Source code for pyMETHES.config

#  Copyright (c) 2020 ETH Zurich

"""
Module for the Config class of the simulation.
"""

# Import Packages
import json5
import json
from typing import Union
import scipy.constants as csts

num = Union[int, float]


[docs]class Config: """ Configuration class for the Monte-Carlo simulation. The configuration can be loaded from, or saved to, json or json5 files. Alternatively, it can be provided as, or exported to, a (nested) dictionary. The gas number density is not a configuration parameter, but a cached property of the Config class, which is computed from the pressure and temperature. Attributes: gases (list): sum formulae of gases paths_to_cross_section_files (list): paths to the cross section files in txt format fractions (list): proportions of the gases in the gas mixture max_cross_section_energy (float): maximum cross section energy (eV) output_directory (str): path to the output directory EN (float): E/N ratio in (Td) _pressure (float): gas pressure in Pa _temperature (float): gas temperature in K _gas_number_density (float): gas number density in m-3 num_e_initial (int): initial number of electrons initial_pos_electrons (list): initial position [x, y, z] of the electrons' center of mass initial_std_electrons (list): initial broadening of gaussian distributed electrons in x, y and z direction num_energy_bins (int): number of energy bins to group the electrons for the energy distribution energy_sharing_factor (float): energy sharing factor for ionization collisions isotropic_scattering (bool): scattering: isotropic (true), non-isotropic according to Vahedi et al. (false) conserve (bool): conservation of the number of electrons num_e_max (int): maximum allowed electron number (when it is reached, the number of electrons is then conserved until simulation ends) w_tol (float): tolerance on the flux drift velocity. simulation ends when w_err/w < w_tol DN_tol (float): tolerance on the flux diffusion coefficient. simulation ends when DN_err/w < DN_tol num_col_max (int): maximum number of collisions during the simulation, simulation ends when it is reached """
[docs] def __init__(self, config: Union[str, dict]): """ Instantiate the config. Args: config (str, dict): path to a json or json5 config file, or dictionary. """ if isinstance(config, str): if config.endswith('.json5'): with open(config, "r") as json_file: config = json5.load(json_file) elif config.endswith('.json'): with open(config, "r") as json_file: config = json.load(json_file) else: raise ValueError(f"Configuration file '{config}' has invalid extension." " Extensions '.json' or '.json5' are expected.") # gases input_gases = config['input_gases'] self.paths_to_cross_section_files: (str, list) = \ input_gases['paths_to_cross_section_files'] self.gases: (str, list) = input_gases['gases'] self.fractions: (float, list) = input_gases['fractions'] self.max_cross_section_energy: num = input_gases['max_cross_section_energy'] # output output = config['output'] self.output_directory: str = output['output_directory'] self.base_name: str = output['base_name'] self.save_simulation_pickle: bool = output['save_simulation_pickle'] self.save_temporal_evolution: bool = output['save_temporal_evolution'] self.save_swarm_parameters: bool = output['save_swarm_parameters'] self.save_energy_distribution: bool = output['save_energy_distribution'] # physical conditions physical_conditions = config['physical_conditions'] self.EN: num = physical_conditions['EN'] self._pressure: num = physical_conditions['pressure'] self._temperature: num = physical_conditions['temperature'] self._gas_number_density = None # initial state initial_state = config['initial_state'] self.num_e_initial: int = int(initial_state['num_e_initial']) self.initial_pos_electrons: list = initial_state['initial_pos_electrons'] self.initial_std_electrons: list = initial_state['initial_std_electrons'] # simulation settings simulation = config['simulation_settings'] self.num_energy_bins: int = simulation['num_energy_bins'] self.energy_sharing_factor: num = simulation['energy_sharing_factor'] self.isotropic_scattering: bool = simulation['isotropic_scattering'] self.conserve: bool = simulation['conserve'] self.num_e_max: int = int(simulation['num_e_max']) # end conditions end_conditions = config['end_conditions'] self.w_tol: float = end_conditions['w_tol'] self.DN_tol: float = end_conditions['DN_tol'] self.num_col_max: int = int(end_conditions['num_col_max'])
@property def gas_number_density(self) -> float: if self._gas_number_density is None: self._gas_number_density = \ self.pressure / (csts.Boltzmann * self.temperature) return self._gas_number_density @property def pressure(self) -> float: return self._pressure @pressure.setter def pressure(self, value: float): """ Pressure setter. If a new value is set, resets the cache for the gas number density. :param value: pressure in Pascal """ self._pressure = value self._gas_number_density = None @property def temperature(self) -> float: return self._temperature @temperature.setter def temperature(self, value: float) -> None: """ Temperature setter. If a new value is set, resets the cache for the gas number density. :param value: temperature in Kelvin """ self._temperature = value self._gas_number_density = None
[docs] def to_dict(self) -> dict: """ Returns the current configuration as a dictionary. Returns: dict of configuration """ return { 'input_gases': { 'gases': self.gases, 'paths_to_cross_section_files': self.paths_to_cross_section_files, 'fractions': self.fractions, 'max_cross_section_energy': self.max_cross_section_energy, }, 'output': { 'output_directory': self.output_directory, 'base_name': self.base_name, 'save_simulation_pickle': self.save_simulation_pickle, 'save_temporal_evolution': self.save_temporal_evolution, 'save_swarm_parameters': self.save_swarm_parameters, 'save_energy_distribution': self.save_energy_distribution, }, 'physical_conditions': { 'EN': self.EN, 'pressure': self.pressure, 'temperature': self.temperature, }, 'initial_state': { 'num_e_initial': self.num_e_initial, 'initial_pos_electrons': self.initial_pos_electrons, 'initial_std_electrons': self.initial_std_electrons, }, 'simulation_settings': { 'num_energy_bins': self.num_energy_bins, 'energy_sharing_factor': self.energy_sharing_factor, 'isotropic_scattering': self.isotropic_scattering, 'conserve': self.conserve, 'num_e_max': self.num_e_max, }, 'end_conditions': { 'w_tol': self.w_tol, 'DN_tol': self.DN_tol, 'num_col_max': self.num_col_max, } }
[docs] def save_json5(self, path: str = 'config.json5') -> None: """ Saves the current configuration to a json5 file. Args: path (str): path including the file name and extension, example: 'data/config.json5' """ with open(path, "w") as config_file: json5.dump(self.to_dict(), config_file, indent=2)
[docs] def save_json(self, path: str = 'config.json') -> None: """ Saves the current configuration to a json file. Args: path (str): path including the file name and extension, example: 'data/config.json' """ with open(path, "w") as config_file: json.dump(self.to_dict(), config_file, indent=2)