示例#1
0
# MCC collisions
cross_sec_direc = '../../../../warpx-data/MCC_cross_sections/He/'
mcc_electrons = picmi.MCCCollisions(
    name='coll_elec',
    species=electrons,
    background_density=N_INERT,
    background_temperature=T_INERT,
    background_mass=ions.mass,
    scattering_processes={
        'elastic' : {
            'cross_section' : cross_sec_direc+'electron_scattering.dat'
        },
        'excitation1' : {
            'cross_section': cross_sec_direc+'excitation_1.dat',
            'energy' : 19.82
        },
        'excitation2' : {
            'cross_section': cross_sec_direc+'excitation_2.dat',
            'energy' : 20.61
        },
        'ionization' : {
            'cross_section' : cross_sec_direc+'ionization.dat',
            'energy' : 24.55,
            'species' : ions
        },
    }
)

mcc_ions = picmi.MCCCollisions(
    name='coll_ion',
示例#2
0
    def __init__(self,
                 electron_species,
                 ion_species,
                 T_INERT,
                 P_INERT=None,
                 N_INERT=None,
                 scraper=None,
                 **kwargs):
        """Initialize MCC parameters.

        Arguments:
            electron_species (picmi.Species): Species that will be producing the
                ions via impact ionization. This will normally be electrons.
            ion_species (picmi.Species): Ion species generated from ionization
                events. Charge state should be specified during Species
                construction. Also used to obtain the neutral mass.
            T_INERT (float): Temperature for injected ions in
                Kelvin.
            P_INERT (float): Pressure of the neutral "target" for
                impact ionization, in Torr. Assumed to be such that the density
                is much larger than both the electron and ion densities, so that
                the neutral dynamics can be ignored. Cannot be specified if
                N_INERT is specified.
            N_INERT (float): Neutral gas density in m^-3. Cannot be specified
                if P_INERT is specified.
            scraper (pywarpx.ParticleScraper): The particle scraper is
                instructed to save pid's for number of MCC events.
            **kwargs that can be included:
            exclude_collisions (list): A list of collision types to exclude.
        """
        self.electron_species = electron_species
        self.ion_species = ion_species
        self.T_INERT = T_INERT
        self.N_INERT = N_INERT
        self.P_INERT = P_INERT

        self.name = kwargs.get(
            'name',
            f"mcc_{self.electron_species.name}_{self.ion_species.name}")

        self.exclude_collisions = kwargs.get("exclude_collisions", None)
        if self.exclude_collisions is None:
            self.exclude_collisions = []

        if self.N_INERT is not None:
            # N and P cannot both be specified
            if self.P_INERT is not None:
                raise ValueError("Must specify N_INERT or P_INERT, not both")
            # if N is not None and P is None, everything is all good
        # N and P cannot both be unspecified
        elif self.P_INERT is None:
            raise ValueError("Must specify one of N_INERT or P_INERT")
        # set N using ideal gas law if only P is specified
        else:
            self.N_INERT = (mwxutil.ideal_gas_density(self.P_INERT,
                                                      self.T_INERT))

        self.scraper = scraper

        # Use environment variable if possible, otherwise look one
        # directory up from warpx
        path_name = os.environ.get(
            "MCC_CROSS_SECTIONS_DIR",
            os.path.join(mwxutil.mewarpx_dir,
                         "../../../warpx-data/MCC_cross_sections"))
        path_name = os.path.join(path_name, self.ion_species.particle_type)
        # include all collision processes that match species
        file_paths = glob.glob(os.path.join(path_name, "*.dat"))

        elec_collision_types = {
            "electron_scattering": "elastic",
            "excitation_1": "excitation1",
            "excitation_2": "excitation2",
            "ionization": "ionization",
        }
        ion_collision_types = {
            "ion_scattering": "elastic",
            "ion_back_scatter": "back",
            "charge_exchange": "charge_exchange"
        }
        required_energy = {
            "He": {
                "excitation_1": 19.82,
                "excitation_2": 20.61,
                "ionization": 24.55
            },
            "Ar": {
                "excitation_1": 11.5,
                "ionization": 15.7596112
            },
            "Xe": {
                "excitation_1": 8.315,
                "ionization": 12.1298431
            }
        }

        # build scattering process dictionaries
        elec_scattering_processes = {}
        ion_scattering_processes = {}

        for path in file_paths:
            file_name = os.path.basename(path)
            coll_key = file_name.split('.dat')[0]

            # exclude collision type if specified
            if coll_key in self.exclude_collisions:
                continue

            # if electron process
            if coll_key in elec_collision_types:
                coll_type = elec_collision_types[coll_key]
                scatter_dict = {"cross_section": path}
                # add energy if needed
                ion = self.ion_species.particle_type
                if coll_key in required_energy[ion]:
                    scatter_dict["energy"] = required_energy[ion][coll_key]
                # specify species for ionization
                if coll_key == "ionization":
                    scatter_dict["species"] = self.ion_species
                elec_scattering_processes[coll_type] = scatter_dict

            # if ion process
            elif coll_key in ion_collision_types:
                coll_type = ion_collision_types[coll_key]
                scatter_dict = {"cross_section": path}
                ion_scattering_processes[coll_type] = scatter_dict

            else:
                raise ValueError(
                    f"{path}: filename not recognized as an MCC cross-section "
                    "file. Please move outside this folder or end with "
                    "something other than .dat if it is not a cross-section "
                    "file.")

        # raise an error if no scattering processes exist
        if (not elec_scattering_processes) and (not ion_scattering_processes):
            raise ValueError(
                "No scattering processes for electron or ion species.")

        if mwxrun.simulation.collisions is None:
            mwxrun.simulation.collisions = []

        if elec_scattering_processes:
            self.electron_mcc = picmi.MCCCollisions(
                name=f'coll_{self.electron_species.name}',
                species=self.electron_species,
                background_density=self.N_INERT,
                background_temperature=self.T_INERT,
                background_mass=self.ion_species.mass,
                scattering_processes=elec_scattering_processes)
            mwxrun.simulation.collisions.append(self.electron_mcc)

        if ion_scattering_processes:
            self.ion_mcc = picmi.MCCCollisions(
                name=f'coll_{self.ion_species.name}',
                species=self.ion_species,
                background_density=self.N_INERT,
                background_temperature=self.T_INERT,
                scattering_processes=ion_scattering_processes)
            mwxrun.simulation.collisions.append(self.ion_mcc)

        # add E_total PID to both species
        self.electron_species.add_pid("E_total")
        self.ion_species.add_pid("E_total")

        callbacks.installbeforecollisions(self._get_particle_data_before)
        callbacks.installaftercollisions(self._get_particle_data_after)
示例#3
0
    def setup_run(self):
        """Setup simulation components."""

        #######################################################################
        # Set geometry and boundary conditions                                #
        #######################################################################

        self.grid = picmi.Cartesian1DGrid(
            number_of_cells=[self.nz],
            warpx_max_grid_size=128,
            lower_bound=[0],
            upper_bound=[self.gap],
            lower_boundary_conditions=['dirichlet'],
            upper_boundary_conditions=['dirichlet'],
            lower_boundary_conditions_particles=['absorbing'],
            upper_boundary_conditions_particles=['absorbing'],
            warpx_potential_hi_z=self.voltage,
        )

        #######################################################################
        # Field solver                                                        #
        #######################################################################

        self.solver = picmi.ElectrostaticSolver(grid=self.grid,
                                                method='Multigrid',
                                                required_precision=1e-12,
                                                warpx_self_fields_verbosity=0)

        #######################################################################
        # Particle types setup                                                #
        #######################################################################

        self.electrons = picmi.Species(
            particle_type='electron',
            name='electrons',
            initial_distribution=picmi.UniformDistribution(
                density=self.plasma_density,
                rms_velocity=[
                    np.sqrt(constants.kb * self.elec_temp / constants.m_e)
                ] * 3,
            ))
        self.ions = picmi.Species(
            particle_type='He',
            name='he_ions',
            charge='q_e',
            mass=self.m_ion,
            initial_distribution=picmi.UniformDistribution(
                density=self.plasma_density,
                rms_velocity=[
                    np.sqrt(constants.kb * self.gas_temp / self.m_ion)
                ] * 3,
            ))

        #######################################################################
        # Collision  initialization                                           #
        #######################################################################

        cross_sec_direc = '../../../../warpx-data/MCC_cross_sections/He/'
        mcc_electrons = picmi.MCCCollisions(
            name='coll_elec',
            species=self.electrons,
            background_density=self.gas_density,
            background_temperature=self.gas_temp,
            background_mass=self.ions.mass,
            scattering_processes={
                'elastic': {
                    'cross_section':
                    cross_sec_direc + 'electron_scattering.dat'
                },
                'excitation1': {
                    'cross_section': cross_sec_direc + 'excitation_1.dat',
                    'energy': 19.82
                },
                'excitation2': {
                    'cross_section': cross_sec_direc + 'excitation_2.dat',
                    'energy': 20.61
                },
                'ionization': {
                    'cross_section': cross_sec_direc + 'ionization.dat',
                    'energy': 24.55,
                    'species': self.ions
                },
            })

        mcc_ions = picmi.MCCCollisions(
            name='coll_ion',
            species=self.ions,
            background_density=self.gas_density,
            background_temperature=self.gas_temp,
            scattering_processes={
                'elastic': {
                    'cross_section': cross_sec_direc + 'ion_scattering.dat'
                },
                'back': {
                    'cross_section': cross_sec_direc + 'ion_back_scatter.dat'
                },
                # 'charge_exchange' : {
                #    'cross_section' : cross_sec_direc+'charge_exchange.dat'
                # }
            })

        #######################################################################
        # Initialize simulation                                               #
        #######################################################################

        self.sim = picmi.Simulation(
            solver=self.solver,
            time_step_size=self.dt,
            max_steps=self.max_steps,
            warpx_collisions=[mcc_electrons, mcc_ions],
            warpx_load_balance_intervals=self.max_steps // 5000,
            verbose=self.test)

        self.sim.add_species(self.electrons,
                             layout=picmi.GriddedLayout(
                                 n_macroparticle_per_cell=[self.seed_nppc],
                                 grid=self.grid))
        self.sim.add_species(self.ions,
                             layout=picmi.GriddedLayout(
                                 n_macroparticle_per_cell=[self.seed_nppc],
                                 grid=self.grid))

        #######################################################################
        # Add diagnostics for the CI test to be happy                         #
        #######################################################################

        field_diag = picmi.FieldDiagnostic(
            name='diag1',
            grid=self.grid,
            period=0,
            data_list=['rho_electrons', 'rho_he_ions'],
            write_dir='.',
            warpx_file_prefix='Python_background_mcc_1d_plt')
        self.sim.add_diagnostic(field_diag)