Merzbild.jl public API reference
Particles
Merzbild.Particle — Type
Particle{D}A structure to store information about a single particle with a D-dimensional position vector.
Fields
w: the computational weight of the particlev: the 3-dimensional velocity vector of the particlex: the D-dimensional position of the particle
Merzbild.ParticleVector — Type
ParticleVector{D}The structure used to store particles, sort and keep track of particle indices, and keep track of unused particles. The lengths of the particles, index, cell, and buffer vectors are all the same (and stay the same during resizing of a ParticleVector instance). Only the first nbuffer elements of the buffer vector store indices of the actually unused particles. D determines the dimension of the particles' position vectors.
Accessing ParticleVector{D}[i] will return a Particle{D} instance, with the actual particle returned being ParticleVector.particles[ParticleVector.index[i]].
Fields
particles: the vector of particles of a single speciesindex: the vector of indices of the particles (these are sorted in grid sorting, not the particles themselves)cell: the vector storing information in which cell a particle is located (used in grid sorting routines)buffer: a last-in-first-out (LIFO) queue keeping track of pre-allocated but unused particlesnbuffer: the number of elements in the buffer
Merzbild.ParticleVector — Method
ParticleVector{D}(np) where DCreate an empty ParticleVector{D} instance of length np (all vectors will have length np), filled with particles with weight 0, velocity 0, position 0.
Positional arguments
np: the length of theParticleVector{D}instance to create
Base.getindex — Method
Base.getindex(pv::ParticleVector{D}, i) where DReturns the underlying particle in a ParticleVector instance with index i.
Is usually called as ParticleVector[i].
Positional arguments
pv:ParticleVectorinstancei: the index of the particle to be selected
Base.setindex! — Method
Base.setindex!(pv::ParticleVector{D}, p::Particle{D}, i::Integer) where DSet the underlying particle in a ParticleVector instance with index i to a new particle.
Is usually called as ParticleVector[i] = p.
Positional arguments
pv:ParticleVectorinstancep: theParticleinstance to writei: the index of the particle to be written to
Base.length — Method
Base.length(pv::ParticleVector{D}) where DReturns the length of a ParticleVector instance.
Is usually called as length(ParticleVector).
Positional arguments
pv:ParticleVectorinstance
Base.resize! — Method
Base.resize!(pv::ParticleVector{D}, n::Integer) where DResize a ParticleVector instance, taking care of the indices, buffer, and creating placeholder new particles with weight 0, velocity 0, and position 0.
Positional arguments
pv:ParticleVectorinstancen: the new length of theParticleVectorinstance (i.e. the length of all the vector fields of the instance)
Particle indexing
Merzbild.ParticleIndexer — Type
ParticleIndexerThe structure used to index particles of a given species in a given cell. It is assumed that the particle indices are contiguous; they may be split across two groups of contiguous indices.
Fields
n_local: the number of particles in the cellstart1: the first index in the first group of particle indicesend1: the last index in the first group of particle indicesn_group1: the number of particles in the first group (n_group1 = end1 - start1 + 1)start2: the first index in the second group of particle indices, if no particles are present in the group, it should be <= 0end2: the last index in the second group of particle indicesn_group2: the number of particles in the second group (n_group2 = end2 - start2 + 1, unless no particles are present in the second group)
Merzbild.ParticleIndexer — Method
ParticleIndexer()Create an empty ParticleIndexer. end1 and end2 are set to -1, the other fields are set to 0.
Merzbild.ParticleIndexer — Method
ParticleIndexer(n_particles)Create a ParticleIndexer given a number of particles. All particles are in group 1, with indices starting from 1.
Positional arguments
n_particles: the number of particles
Merzbild.ParticleIndexerArray — Type
ParticleIndexerArrayA structure to store an array of ParticleIndexer instances for each species in each cell. It also stores information about the whether the ParticleIndexer instances for each species are "contiguous". A set of ParticleIndexer instances (for a specific species) are "contiguous" if the following conditions are fulfilled (assuming all cells contain particles and in all cells have both n_group1>0 and n_group2>0, for a more detailed explanation, one is referred to the documentation on contiguous indexing):
pia.indexer[cell,species].end1 + 1 == pia.indexer[cell+1,species].start1,cell = 1,...,n_cells - 1pia.indexer[n_cells,species].end1 + 1 == pia.indexer[1,species].start2pia.indexer[cell,species].end2 + 1 == pia.indexer[cell+1,species].start2,cell = 1,...,n_cells - 1
Fields
n_cells: number of cells being indexedn_species: number of species being indexedindexer: the array of size(n_cells, n_species)(number of grid cells * number of species in the simulation) storing theParticleIndexerinstancesn_total: vector of lengthn_speciesstoring the total number of particles of each speciescontiguous: vector of lengthn_speciesstoring a boolean flag whether the ParticleIndexer instances for a species are "contiguous"index_last: vector of lengthn_speciesstoring the last valid index in the particle array for each species (tracks the highest index used, allowing for non-contiguous indexing when particles are deleted from the middle)
Merzbild.ParticleIndexerArray — Method
ParticleIndexerArray(indexer_arr::Array{ParticleIndexer,2}, n_total)Creates a ParticleIndexerArray from a 2-D array of ParticleIndexer instances.
Positional arguments
indexer_arr: the 2-D array ofParticleIndexerinstancesn_total: the vector of the total number of particles of each species
Merzbild.ParticleIndexerArray — Method
ParticleIndexerArray(n_cells::Integer, n_species::Integer)Create an empty ParticleIndexerArray given the number of cells and species
Positional arguments
n_cells: the number of grid cellsn_species: the number of species
Merzbild.ParticleIndexerArray — Method
ParticleIndexerArray(n_particles::Integer)Create a single-species/single-cell ParticleIndexerArray and set up the indexing for n_particles in group 1 in cell 1.
Positional arguments
n_particles: the number of particles (integer number)
Merzbild.ParticleIndexerArray — Method
ParticleIndexerArray(n_particles::T) where T<:AbstractVectorCreate a multi-species/single-cell ParticleIndexerArray and set up the indexing for n_particles[species] in group 1 in cell 1 for all species.
Positional arguments
n_particles: the number of particles of each species (vector-like)
Merzbild.ParticleIndexerArray — Method
ParticleIndexerArray(grid, species_data::Array{Species})Create an empty multi-species/multi-cell ParticleIndexerArray.
Positional arguments
grid: the simulation gridspecies_data: array ofSpeciesdata for all of the species in the simulation
Merzbild.squash_pia! — Function
squash_pia!(pv::ParticleVector{D}, pia, species) where DRestore the continuity of indices in a ParticleVector and associated ParticleIndexerArray instance for a specific species. If for this species the instance has contiguous == true, nothing will be done.
Positional arguments
pv: theParticleVectorpia: theParticleIndexerArrayinstancespecies: the index of the species for which to restore continuity of indices
squash_pia!(particles, pia)Restore the continuity of indices in a list of ParticleVectors and the associated ParticleIndexerArray instance for all species. If for a specific species the instance has contiguous == true, nothing will be done.
Positional arguments
particles: the list ofParticleVectors for all species in the flowpia: theParticleIndexerArrayinstance
Merzbild.restore_particle_ordering! — Function
restore_particle_ordering!(pv::ParticleVector{D}, inv_map::Vector{Int64}) where DRestore the ordering of particles in a ParticleVector so that pv.index[i] == i. This function ensures that:
- The index array is restored to identity mapping (pv.index[i] == i)
- The buffer contains only unused particle indices in descending order
- Used particles are placed in the first (length(pv.index) - pv.nbuffer) positions
Positional arguments
pv: ParticleVector instance to restore ordering forinv_map: Vector of integers to store inverse map (inv_map[pv.index[i]] == i)
restore_particle_ordering!(pv::ParticleVector{D}, pia, species, inv_map::Vector{Int64}) where DRestore the ordering of particles in a ParticleVector and update the associated ParticleIndexerArray. This function calls restore_particle_ordering! to restore the particle ordering and then updates pia.index_last[species] to reflect the new contiguous indexing.
Positional arguments
pv: ParticleVector instance to restore ordering forpia: ParticleIndexerArray instance to updatespecies: the index of the species for which to update index_lastinv_map: Vector of integers to store inverse map (inv_map[pv.index[i]] == i)
Merzbild.count_disordered_particles — Function
count_disordered_particles(pv::ParticleVector{D}, pia, species) where DCount number of particles of species for which pv.index[i] != i + offset(cell). The larger this count, the less orderly the layout of particles in memory, which can potentially lead to decreased performance. This only considers particles present in the simulation, i.e. i<=pia.n_total[species], assumes contiguous indexing, and that particles are only pointed to by the first group of a ParticleIndexer, which is the case after particles have been sorted.
In case use_offset is false, the value of offset is always 0, so the function simply counts all particles where pv.index[i] != i. If use_offset is set to true, for each cell cell, the offset is whilst iterating over the particles in a cell. So in case the indexing in a cell is simply offset by a constant value, or a subset of indices are offset by a constant value, and particles are still laid out continuously in memory, this provides a more accurate measurement of the degree of fragmentation of the particle array.
Positional arguments
pv: theParticleVectorinstance for which to compute the metricpia: theParticleIndexerArrayinstancespecies: the index of the species for which the metric is computed
Keyword arguments
use_offset: whether to account for cell-specific offsets in the indexing
Returns
The number of particles where the index to the index array and the value of the index array do not coincide.
Merzbild.check_unique_index — Function
check_unique_index(pv::ParticleVector{D}, pia, species) where DTest that for all particles in a simulation, no two indices are the same, i.e. no two particles i and j, i!=j point to the same underlying particle. This function allocates a temporary array and is thus intended for debugging/verifying code and not for efficient simulations. It also checks that any particles present in the buffer are not pointed to by the indexing.
Positional arguments
pv: theParticleVectorinstance for which to check indexingpia: theParticleIndexerArrayinstancespecies: the species for which to check indexing
Returns
If a particle exists to which more than 1 index is pointing, and particles in the buffer ARE NOT pointed to by the indicies, returns (false, n_index), where n_index is the number of indices pointing to the same particle.
If a particle exists to which more than 1 index is pointing, and particles in the buffer ARE pointed to by the indicies, returns (false, -n_index), where n_index is the number of indices pointing to the same particle.
If no particles exist to which more than 1 index is pointing, but a particle in a buffer is pointed to by the indexing, returns (false, -1).
If indexing is correct, returns (true, 0).
Merzbild.check_pia_is_correct — Function
check_pia_is_correct(pia, species)Check that a ParticleIndexerArray instance entries are correct. This means that for each cell for each species, the following should hold: * n_local == n_group1 + n_group2 * if n_group1 > 0, then n_group1 == end1 - start1 + 1 * if n_group1 == 0, then start1 == 0, end1 == -1 * if n_group2 > 0, then n_group2 == end2 - start2 + 1 * if n_group2 == 0, then start2 == 0, end2 == -1 * pia.n_total[species] == sum([pia.indexer[cell, species].n_local for cell in 1:n_cells]) and index_last[species] points to the last index used.
Positional arguments
pia: theParticleIndexerArrayinstance for which to check consistencyspecies: the species for which to check indexing
Returns
If indexing is incorrect in a cell i, returns (false, i).
If the total number of particles as given by cell-wise particle indices is not equal to pia.n_total[species], returns (false, 0).
If index_last[species] < pia.n_total[species], returns (false, -1).
If index_last[species] is not the largest value of the indices pointed to by the groups, returns (false, -2).
If indexing is correct, returns (true, 0).
Merzbild.pretty_print_pia — Function
pretty_print_pia(pia, species)Display a ParticleIndexerArray instance by showing the starting/ending indices of the groups over all cells for a specific species.
Positional arguments
pia: theParticleIndexerArrayinstancespecies: the index of the species for which the indices are displayed
Merzbild.check_unique_buffer — Function
check_unique_buffer(pv::ParticleVector{D}) where DTest that the buffer elements in the active part of a buffer in a ParticleVector instance are unique (active part is pv.buffer[1:pv.nbuffer]). This function allocates a temporary dictionary and is thus intended for debugging/verifying code and not for efficient simulations.
Positional arguments
pv: theParticleVectorinstance for which to check buffer
Returns
If a non-unique index is in the active part of the buffer, the function returns (false, i), where i is the first location at which the non-unique index is encountered for the second time (so if it is present at locations i1, i2, i3, etc., i2 will be returned).
If buffer is correct, returns (true, 0).
Loading species and interaction data
Merzbild.MERZBILD_DATA_PATH — Constant
MERZBILD_DATA_PATHAbsolute path to the data directory bundled with Merzbild.jl, holding the built-in species (particles.toml) and interaction (vhs.toml, pseudo_maxwell.toml, vss.toml) data files. Use it to load bundled data independently of the current working directory, e.g. load_species_data(joinpath(MERZBILD_DATA_PATH, "particles.toml"), "Ar").
Merzbild.Species — Type
SpeciesA structure to store information about a chemical species.
Fields
name: the name of the speciesmass: the molecular mass of the speciescharge: the charge of the species in terms of elementary charge (i.e. 1, -1, etc.)charge_div_mass: the charge of the species divided by its mass, C/kg
Merzbild.Interaction — Type
InteractionStructure to store interaction parameters for a 2-species interaction. The VHS model uses the following power law: $\sigma_{VHS} = C g^(1 - 2 \omega_{VHS})$, where $omega$ is the exponent of the VHS potential, and $C$ is the pre-computed factor: $C = \pi D_{VHS}^2 (2 T_{ref,VHS}/m_r)^{(\omega_{VHS} - 0.5)} \frac{1}{\Gamma(2.5 - \omega_{VHS})}$. The VSS model uses the same power law for the total cross-section, but a different scattering law.
The elastic scattering model is fixed for a species pair and is stored in the model field as a Merzbild.ScatteringModel enum value, so that the array of Interaction instances stays concretely typed.
Fields
m_r: collision-reduced massμ1: relative mass of the first speciesμ2: relative mass of the second speciesvhs_d: diameter for the VHS potentialvhs_o: exponent for the VHS potential (omega)vhs_exp: pre-computed1 - 2 vhs_ovhs_Tref: reference temperature for the VHS potentialvhs_muref: reference viscosity for the VHS potentialvhs_factor: pre-computed factor for calculation of the VHS cross-sectionvss_alpha: exponent of the VSS scattering law (equal to 1.0 for the models with isotropic scattering)vss_inv_alpha: pre-computed1 / vss_alphamodel: theScatteringModelenum value of the elastic scattering model of the species pair
Merzbild.Interaction — Method
Interaction(m1::Float64, m2::Float64, vhs_d::Float64, vhs_o::Float64, vhs_Tref::Float64)Construct an Interaction instance using the VHS model from the masses of the two species and the VHS parameters.
Positional arguments
m1: molecular mass of the first speciesm2: molecular mass of the second speciesvhs_d: VHS diametervhs_o: VHS exponent (omega)vhs_Tref: reference VHS temperature
Merzbild.Interaction — Method
Interaction(::VHS, m1::Float64, m2::Float64, vhs_d::Float64, vhs_o::Float64, vhs_Tref::Float64)Construct an Interaction instance using the VHS model from the masses of the two species and the VHS parameters.
Positional arguments
m1: molecular mass of the first speciesm2: molecular mass of the second speciesvhs_d: VHS diametervhs_o: VHS exponent (omega)vhs_Tref: reference VHS temperature
Merzbild.Interaction — Method
Interaction(::VSS, m1::Float64, m2::Float64, vhs_d::Float64, vhs_o::Float64, vhs_Tref::Float64, vss_alpha::Float64)Construct an Interaction instance using the VSS model from the masses of the two species, the VHS parameters (which define the total cross-section), and the VSS exponent (which defines the scattering law). The reference viscosity is corrected by the factor $(\alpha + 1)(\alpha + 2) / (6\alpha)$ accounting for the anisotropic scattering, see Merzbild.compute_vss_mu_ref_factor.
Positional arguments
m1: molecular mass of the first speciesm2: molecular mass of the second speciesvhs_d: VHS diametervhs_o: VHS exponent (omega)vhs_Tref: reference VHS temperaturevss_alpha: VSS exponent (alpha)
Merzbild.load_species_data — Function
load_species_data(species_filename, species_names)Load a vector of species data (mass, charge, etc.) from a TOML file.
Positional arguments
species_filename: the path to the TOML file containing the dataspecies_names: a list of the names of the species for which to load the data
Returns
Vector of Species filled with data loaded from the file.
load_species_data(species_filename, species_name::String)Load a vector of species data (mass, charge, etc.) from a TOML file for a single species.
Positional arguments
species_filename: the path to the TOML file containing the dataspecies_name: the name of the species for which to load the data
Returns
Vector of Species filled with data loaded from the file.
Merzbild.load_interaction_data — Function
load_interaction_data(interactions_filename, species_data)Load interaction data from a TOML file given a list of species' data (list of Species instances). It will load interaction data for all possible pair-wise interactions of the species in the list.
The resulting 2-D array has the interaction data for Species[i] with Species[k] in position [i,k]. It is not symmetric, as the relative collision masses μ1 and μ2 are swapped when comparing the Interaction instances in positions [i,k] and [k,i]. If no data is found, the function throws an error.
The elastic scattering model of a species pair is set by the optional model key of the pair's entry in the file, defaulting to the VHS model, see Merzbild.interaction_from_toml.
Positional arguments
interactions_filename: the path to the TOML file containing the dataspecies_data: list ofSpeciesinstances for which to search for the interaction data
Returns
- 2-dimensional array of
Interactioninstances of size(n_species, n_species)
Throws
KeyError if interaction data not found in the file.
load_interaction_data(interactions_filename, species_data)Load interaction data from a TOML file given a list of species' data (list of Species instances), filling in dummy VHS data in case no entry is found in the TOML file. Useful for interactions where the VHS model doesn't make sense, for example electron-neutral interactions.
It will load interaction data for all possible pair-wise interactions of the species in the list. The resulting 2-D array has the interaction data for Species[i] with Species[k] in position [i,k]. It is not symmetric, as the relative collision masses μ1 and μ2 are swapped when comparing the Interaction instances in positions [i,k] and [k,i].
The elastic scattering model of a species pair is set by the optional model key of the pair's entry in the file, defaulting to the VHS model, see Merzbild.interaction_from_toml; the dummy data is always filled in using the VHS model.
Positional arguments
interactions_filename: the path to the TOML file containing the dataspecies_data: list ofSpeciesinstances for which to search for the interaction datadummy_vhs_d: value to use for the VHS diameter if no interaction data found in the filedummy_vhs_o: value to use for the VHS exponent if no interaction data found in the filedummy_vhs_Tref: value to use for the VHS reference temperature if no interaction data found in the file
Returns
- 2-dimensional array of
Interactioninstances of size(n_species, n_species)
Merzbild.load_interaction_data_with_dummy — Function
load_interaction_data_with_dummy(interactions_filename, species_data)Load interaction data from a TOML file given a list of species' data (list of Species instances), filling in dummy VHS data in case no entry is found in the TOML file. Useful for interactions where the VHS model doesn't make sense, for example electron-neutral interactions. Uses a value of 1e-10 for the dummy VHS diameter, 1.0 for the dummy VHS exponent, and 273.0 for the dummy VHS reference temperature.
It will load interaction data for all possible pair-wise interactions of the species in the list. The resulting 2-D array has the interaction data for Species[i] with Species[k] in position [i,k]. It is not symmetric, as the relative collision masses μ1 and μ2 are swapped when comparing the Interaction instances in positions [i,k] and [k,i].
Positional arguments
interactions_filename: the path to the TOML file containing the dataspecies_data: list ofSpeciesinstances for which to search for the interaction data
Returns
- 2-dimensional array of
Interactioninstances of size(n_species, n_species)
Merzbild.load_species_and_interaction_data — Function
load_species_and_interaction_data(species_filename, interactions_filename, species_names; fill_dummy=true)Given a list of species' names, load the species and interaction data (filling with dummy data if needed).
Positional arguments
species_filename: the path to the TOML file containing the species' datainteractions_filename: the path to the TOML file containing the interaction dataspecies_name: the name of the species for which to load the data
Keyword arguments
fill_dummy: iftrue, fill interaction data with computed dummy values if no entry found for a species pair in the interaction file
Returns
VectorofSpeciesinstances- 2-dimensional array of
Interactioninstances of size(n_species, n_species)
Elastic scattering models
Merzbild.AbstractScatteringModel — Type
AbstractScatteringModelAbstract type for the elastic scattering models used by the DSMC/SWPM collision routines.
Each concrete model is a zero-field singleton type (VHS, VSS) that is used as a compile-time tag: the total cross-section Merzbild.sigma and the computation of the post-collision velocities Merzbild.scatter! are dispatched on it. As the tag is a zero-size value of a concrete type, it is not stored anywhere and the inner collision loops stay free of branching, dynamic dispatch, and allocations.
The model of a species pair is stored in the corresponding Interaction instance as a Merzbild.ScatteringModel enum value (so that the array of Interaction instances stays concretely typed); the collision routines convert it to the singleton tag exactly once per call, see Merzbild.@scattering_barrier.
Merzbild.VHS — Type
VHSSingleton type tag for the Variable Hard Sphere model: the total cross-section follows the power law $\sigma = C g^{1 - 2\omega}$ and the scattering is isotropic.
Merzbild.VSS — Type
VSSSingleton type tag for the Variable Soft Sphere model: the total cross-section is the same as for the VHS model, but the scattering is anisotropic, with the cosine of the deflection angle sampled as $\cos\chi = 2 R^{1/\alpha} - 1$, where $R$ is a uniformly distributed random number and $\alpha$ is the VSS exponent ($\alpha = 1$ recovers isotropic scattering).
References
- K. Koura, H. Matsumoto, Variable soft sphere molecular model for inverse-power-law or Lennard-Jones potential. Phys. Fluids A, 1991.
Merzbild.ScatteringModel — Type
Sampling
Merzbild.maxwellian — Function
maxwellian(vx, vy, vz, m, T)Evaluate the Maxwell distribution with temperature T for a species with mass m at a velocity (vx, vy, vz)
Positional arguments
vx: x velocityvy: y velocityvz: z velocitym: species' massT: temperature
Merzbild.bkw — Function
bkw(vx, vy, vz, m, T, scaled_time)Evaluate the Bobylev-Krook-Wu (BKW) distribution with temperature T for a species with mass m at a velocity (vx, vy, vz) and scaled time scaled_time
Positional arguments
vx: x velocityvy: y velocityvz: z velocitym: species' massT: temperaturescaled_time: the scaled_time
Merzbild.sample_on_grid! — Function
sample_on_grid!(rng, vdf_func, particles::ParticleVector{D}, nv, m, T, n_total,
xlo, xhi, ylo, yhi, zlo, zhi; v_mult=3.5, cutoff_mult=3.5, noise=0.0,
v_offset=[0.0, 0.0, 0.0])Sample particles by evaluating a distribution on a discrete velocity grid, considering only points inside a sphere of a given radius (the value of the VDF at points outside of the sphere will be 0.0). The values of the VDF at the grid points will then be the computational weights of the particles, and the particles velocities are taken to be the velocities of the corresponding grid nodes (with additional uniformly distributed noise). Note: this can produce a large amount of particles for fine grids (as the number of grid nodes scales as nv^3.) The grid is assumed to have the same number of nodes nv in each direction, and the extent is computed as v_mult * v_thermal, where v_thermal is the thermal velocity $\sqrt(2kT/m)$, and v_mult is a user-defined parameter. The positions of the particles are assumed to be randomly distributed in a cuboid.
Positional arguments
rng: The random number generatorvdf_func: the distribution function to be evaluated which takes the x, y, and z velocities as parametersparticles: theVector-like structure holding the particlesnv: the number of grid nodes in each directionm: the molecular mass of the speciesT: the temperature used to compute the thermal velocityn_total: the total computational weight (number of physical particles) to be sampledxlo: the lower bound of the x coordinates of the particlesxhi: the upper bound of the x coordinates of the particlesylo: the lower bound of the y coordinates of the particlesyhi: the upper bound of the y coordinates of the particleszlo: the lower bound of the z coordinates of the particleszhi: the upper bound of the z coordinates of the particles
Keyword arguments
v_mult: the value by which the thermal velocity is multiplied to compute the extent of the velocity gridcutoff_mult: the value by which the thermal velocity is multiplied to compute the radius for the sphere used to cut-off the higher velocitiesnoise: controls the amount of noise added to the particle velocities (the noise is uniformly distributed on the interval[-noise*dv, noise*dv], wheredvis the grid spacing)v_offset: the streaming velocity vector to be added to the particle velocities
Returns
- The number of particles created
Merzbild.sample_maxwellian_on_grid! — Function
sample_maxwellian_on_grid!(rng, particles::ParticleVector{D}, nv, m, T, n_total,
xlo, xhi, ylo, yhi, zlo, zhi; v_mult=3.5, cutoff_mult=3.5, noise=0.0,
v_offset=[0.0, 0.0, 0.0])Sample particles by evaluating a Maxwellian on a discrete velocity grid, considering only points inside a sphere of a given radius (the value of the VDF at points outside of the sphere will be 0.0). The values of the VDF at the grid points will then be the computational weights of the particles, and the particles velocities are taken to be the velocities of the corresponding grid nodes (with additional uniformly distributed noise). Note: this can produce a large amount of particles for fine grids (as the number of grid nodes scales as nv^3.) The grid is assumed to have the same number of nodes nv in each direction, and the extent is computed as v_mult * v_thermal, where v_thermal is the thermal velocity $\sqrt(2kT/m)$, and v_mult is a user-defined parameter. The positions of the particles are assumed to be randomly distributed in a cuboid.
Positional arguments
rng: The random number generatorparticles: theVector-like structure holding the particlesnv: the number of grid nodes in each directionm: the molecular mass of the speciesT: the temperature used to compute the thermal velocityn_total: the total computational weight (number of physical particles) to be sampledxlo: the lower bound of the x coordinates of the particlesxhi: the upper bound of the x coordinates of the particlesylo: the lower bound of the y coordinates of the particlesyhi: the upper bound of the y coordinates of the particleszlo: the lower bound of the z coordinates of the particleszhi: the upper bound of the z coordinates of the particles
Keyword arguments
v_mult: the value by which the thermal velocity is multiplied to compute the extent of the velocity gridcutoff_mult: the value by which the thermal velocity is multiplied to compute the radius for the sphere used to cut-off the higher velocitiesnoise: controls the amount of noise added to the particle velocities (the noise is uniformly distributed on the interval[-noise*dv, noise*dv], wheredvis the grid spacing)v_offset: the streaming velocity vector to be added to the particle velocities
Returns
The function returns the number of particles created
Merzbild.sample_particles_equal_weight! — Function
sample_particles_equal_weight!(rng, particles, pia, cell, species,
nparticles, m, T, Fnum, xlo, xhi, ylo, yhi, zlo, zhi;
distribution=:Maxwellian, vx0=0.0, vy0=0.0, vz0=0.0)Sample equal-weight particles of a specific species in a specific cell from a distribution. The positions of the particles are assumed to be randomly distributed in a cuboid. Note: this does not work if applied twice in a row to the same cell.
Positional arguments
rng: the random number generatorparticles: theVector-like structure holding the particlespia: theParticleIndexerArraycell: the cell indexspecies: the species indexnparticles: the number of particles to samplem: species' massT: temperatureFnum: the computational weight of the particlesxlo: the lower bound of the x coordinates of the particlesxhi: the upper bound of the x coordinates of the particlesylo: the lower bound of the y coordinates of the particlesyhi: the upper bound of the y coordinates of the particleszlo: the lower bound of the z coordinates of the particleszhi: the upper bound of the z coordinates of the particles
Keyword arguments
distribution: the distribution to sample from (either:Maxwellianor:BKW)vx0: the x-velocity offset to add to the particle velocitiesvy0: the y-velocity offset to add to the particle velocitiesvz0: the z-velocity offset to add to the particle velocities
sample_particles_equal_weight!(rng, grid1duniform, particles, pia, species, species_data, ppc::Integer, T, Fnum)Sample particles from a Maxwellian distribution in each cell of a 1-D uniform grid given the number of particles per cell.
Positional arguments
rng: the random number generatorgrid1duniform: the 1-D uniform gridparticles: theParticleVectorof particlespia: theParticleIndexerArrayspecies: the index of the species to be sampled forspecies_data:VectorofSpeciesdatappc: number of particles per cell to be sampledT: the temperatureFnum: the computational weight of the particles
sample_particles_equal_weight!(rng, grid1duniform, particles, pia, species, species_data, ppc::Integer, T, Fnum, cell_chunk)Sample particles from a Maxwellian distribution in a sequentially ordered subset of cells of a 1-D uniform grid given the number of particles per cell.
Positional arguments
rng: the random number generatorgrid1duniform: the 1-D uniform gridparticles: theParticleVectorof particlespia: theParticleIndexerArrayspecies: the index of the species to be sampled forspecies_data:VectorofSpeciesdatappc: number of particles per cell to be sampledT: the temperatureFnum: the computational weight of the particlescell_chunk: the list of cell indices or range in which to sample particles, should be ordered in increasing order
sample_particles_equal_weight!(rng, grid1duniform, particles, pia, species, species_data, ndens::Float64, T, Fnum)Sample particles from a Maxwellian distribution in each cell in a sequentially ordered subset of cells of a 1-D uniform grid given the target number density. If the computed number of particles is not an integer value, the fractional remainder is used to probabilistically sample an extra particle, so that on average, the expected number density is achieved.
Positional arguments
rng: the random number generatorgrid1duniform: the 1-D uniform gridparticles: theParticleVectorof particlespia: theParticleIndexerArrayspecies: the index of the species to be sampled forspecies_data:VectorofSpeciesdatandens: target number densityT: the temperatureFnum: the computational weight of the particles
sample_particles_equal_weight!(rng, grid1duniform, particles, pia, species, species_data, ndens::Float64, T, Fnum, cell_chunk)Sample particles from a Maxwellian distribution in each cell of 1-D uniform grid given the target number density. If the computed number of particles is not an integer value, the fractional remainder is used to probabilistically sample an extra particle, so that on average, the expected number density is achieved.
Positional arguments
rng: the random number generatorgrid1duniform: the 1-D uniform gridparticles: theParticleVectorof particlespia: theParticleIndexerArrayspecies: the index of the species to be sampled forspecies_data:VectorofSpeciesdatandens: target number densityT: the temperatureFnum: the computational weight of the particlescell_chunk: the list of cell indices or range in which to sample particles, should be ordered in increasing order
Merzbild.sample_particles_phase_box_weighted! — Function
sample_particles_phase_box_weighted!(rng, particles::ParticleVector{D}, pia, cell, species,
nparticles, m, T, n_total, xlo, xhi, ylo, yhi, zlo, zhi;
v_mult=3.5, vx0=0.0, vy0=0.0, vz0=0.0)Sample variable-weight particles of a specific species in a specific cell from a Maxwellian. The velocities are sampled in a uniform box in phase space with extent ±v_mult * v_thermal in each direction, where v_thermal is the thermal velocity $\sqrt(2kT/m)$, and v_mult is a user-defined parameter, and their weights are computed proportional to the value of a Maxwell distribution at temperature T at those velocities. A streaming velocity component can be added to all of the sampled particles' velocities. The positions of the particles are assumed to be randomly distributed in a cuboid.
Positional arguments
rng: the random number generatorparticles: theVector-like structure holding the particlespia: theParticleIndexerArraycell: the cell indexspecies: the species indexnparticles: the number of particles to samplem: species' massT: temperaturen_total: the total computational weight (number of physical particles) to be sampledxlo: the lower bound of the x coordinates of the particlesxhi: the upper bound of the x coordinates of the particlesylo: the lower bound of the y coordinates of the particlesyhi: the upper bound of the y coordinates of the particleszlo: the lower bound of the z coordinates of the particleszhi: the upper bound of the z coordinates of the particles
Keyword arguments
v_mult: the value by which the thermal velocity is multiplied to compute the extent of the velocity boxvx0: the x-velocity offset to add to the particle velocitiesvy0: the y-velocity offset to add to the particle velocitiesvz0: the z-velocity offset to add to the particle velocities
Computing grid and surface macroscopic properties
Merzbild.PhysProps — Type
PhysPropsStructure to store computed physical properties in a physical cell.
Fields
ndens_not_Np: whether thenfield stores number density (iftrue) and not the number of physical particles in a cell (iffalse)n_cells: number of physical cellsn_species: number of specieslpa: length of the particle array (vector of lengthn_species)np: number of particles (array of shape(n_cells, n_species))n: number density or number of physical particles in a cell (array of shape(n_cells, n_species))v: per-species flow velocity in a cell (array of shape(3, n_cells, n_species))T: per-species temperature in a cell (array of shape(n_cells, n_species))
Merzbild.PhysProps — Method
PhysProps(n_cells, n_species; ndens_not_Np=false)Construct physical properties given the number of cells and species.
Positional arguments
n_cells: number of cellsn_species: number of species
Keyword arguments
ndens_not_Np: whether thenfield stores number density (iftrue) and not the number of physical particles in a cell (iffalse)
Merzbild.PhysProps — Method
PhysProps(pia::ParticleIndexerArray; ndens_not_Np=false)Construct physical properties given a ParticleIndexerArray instance,.
Positional arguments
pia: theParticleIndexerArrayinstance
Keyword arguments
ndens_not_Np: whether thenfield stores number density (iftrue) and not the number of physical particles in a cell (iffalse)
Merzbild.SurfProps — Type
SurfPropsStructure to store computed surface properties.
Fields
n_elements: number of surface elementsn_species: number of speciesareas: the vector of surface element areasinv_areas: the vector of the inverse surface element areasnormals: the array of surface element normals with shape(3, n_elements)np: number of particles impacting the surface elements, array of shape(n_elements, n_species)flux_incident: incident mass flux per surface element, array of shape(n_elements, n_species)flux_reflected: reflected mass flux per surface element, array of shape(n_elements, n_species)force: force acting per surface element, array of shape(3, n_elements, n_species)normal_pressure: normal pressure per surface element, array of shape(n_elements, n_species)shear_pressure: shear pressure per surface element, array of shape(3, n_elements, n_species)kinetic_energy_flux: kinetic energy flux per surface element, array of shape(n_elements, n_species)
Merzbild.SurfProps — Method
SurfProps(n_elements, n_species, areas, normals)Construct a struct for holding computed surface properties for n_elements surface elements, n_species species. The surface elements' areas and normals are given by areas and normals, respectively.
Positional arguments
n_elements: number of surface elementsn_species: number of speciesareas: vector of areas of surface elementsnormals: vector of normals to surface elements
Merzbild.SurfProps — Method
SurfProps(pia, grid::Grid1DUniform)Create a SurfProps struct for a 1-D grid, with element 1 corresponding to the left wall and element 2 corresponding to the right wall. The areas of the wall are assumed to be equal to 1, the normals are parallel to the x axis.
Positional arguments
pia: theParticleIndexerArrayinstancegrid: theGrid1DUniformgrid
Merzbild.FluxProps — Type
FluxPropsStructure to store computed flux densities in a physical cell. The kinetic energy flux density of a species is computed as $\frac{m}{2V} \sum_i w_i \mathbf{C}_i C_i^2$, where $\mathbf{C}_i$ is the peculiar velocity of a particle, $m$ is the molecular mass of the species, $V$ is the cell volume. The $k,l$ component of the the momentum flux density tensor is computed as $\frac{m}{2V} \sum_i w_i \C_{i,k} \C_{i,l}$. The $xx$, $yy$, $zz$ components thereof are stored in diagonal_momentum_flux. The $xy$, $xz$, $yz$ components thereof are stored in off_diagonal_momentum_flux.
Fields
n_cells: number of physical cellsn_species: number of specieskinetic_energy_flux: per-species kinetic energy flux in a cell (array of shape(3, n_cells, n_species))diagonal_momentum_flux: diagonal components of the per-species momentum flux tensor in a cell (array of shape(3, n_cells, n_species))off_diagonal_momentum_flux: off-diagonal components of the per-species momentum flux tensor in a cell (array of shape(3, n_cells, n_species))
Merzbild.FluxProps — Method
FluxProps(n_cells, n_species)Construct a FluxProps instance given the number of cells and species.
Positional arguments
n_cells: number of cellsn_species: number of species
Merzbild.FluxProps — Method
FluxProps(pia)Construct a FluxProps instance given a ParticleIndexerArray instance.
Positional arguments
pia: theParticleIndexerArrayinstance
Merzbild.ElectrostaticFieldProps — Type
ElectrostaticFieldPropsStructure to store the electrostatic field quantities on the nodes of a grid. The quantities are node-centered: for a 1D uniform grid with n_cells cells, the nodes are located at $x_j = (j-1) \Delta x$, $j = 1 \dots n_{\textrm{cells}}+1$, so all the vectors are of length n_cells + 1. For a periodic simulation, the last node is the periodic image of the first one, and the values stored in it are mirrored from the first node.
The structure is grid-independent: it stores no reference to a grid or to a Poisson solver.
Fields
n_nodes: number of nodescharge_density: the charge density $\rho$ in the nodes, C/m³ (before a call tonormalize_charge_density!this holds the deposited charge in C and not a density)potential: the electrostatic potential $\phi$ in the nodes, Velectric_field: the x-component of the electric field $E_x$ in the nodes, V/mnet_charge_density: the mean charge density subtracted in the periodic case,0.0otherwise, C/m³
Merzbild.ElectrostaticFieldProps — Method
ElectrostaticFieldProps(n_nodes::Integer)Construct an ElectrostaticFieldProps instance given the number of nodes (and not the number of cells, in contrast to PhysProps(n_cells, n_species)). For a 1-D uniform grid with n_cells cells, the number of nodes is n_cells + 1.
Positional arguments
n_nodes: number of nodes
Merzbild.ElectrostaticFieldProps — Method
ElectrostaticFieldProps(grid::Grid1DUniform)Construct an ElectrostaticFieldProps instance for a 1-D uniform grid, using n_nodes = grid.n_cells + 1 nodes.
Positional arguments
grid: theGrid1DUniformgrid
Merzbild.clear_charge_density! — Function
clear_charge_density!(field_props::ElectrostaticFieldProps)Clear the charge density stored in an ElectrostaticFieldProps instance, leaving the potential and the electric field computed at the previous timestep untouched. This is to be called before the charge of the particles is deposited on the nodes at a new timestep.
Positional arguments
field_props: theElectrostaticFieldPropsinstance for which the charge density is cleared
Merzbild.compute_props! — Function
compute_props!(particles, pia, species_data, phys_props)Compute the physical properties of all species in all cells and store the result in a PhysProps instance. This function does not compute the total moments, even if phys_props.n_moments > 0.
Positional arguments
particles: theVectorofParticleVectors containing all the particles in a simulationpia: theParticleIndexerArrayinstancespecies_data: theVectorofSpeciesDataphys_props: thePhysPropsinstance in which the computed physical properties are stored
Merzbild.compute_props_sorted! — Function
compute_props_sorted!(particles, pia, species_data, phys_props, cell_chunk)Compute the physical properties of all species in a subset of cells and store the result in a PhysProps instance, assuming the particles are sorted. This function does not compute the total moments, even if phys_props.n_moments > 0. Currently this does not compute the length of the particle array.
Positional arguments
particles: theVectorofParticleVectors containing all the particles in a simulationpia: theParticleIndexerArrayinstancespecies_data: theVectorofSpeciesDataphys_props: thePhysPropsinstance in which the computed physical properties are storedcell_chunk: the list of cell indices or range of cell indices in which to compute the properties
compute_props_sorted!(particles, pia, species_data, phys_props)Compute the physical properties of all species in all cells and store the result in a PhysProps instance, assuming the particles are sorted. This function does not compute the total moments, even if phys_props.n_moments > 0. Currently this does not compute the length of the particle array.
Positional arguments
particles: theVectorofParticleVectors containing all the particles in a simulationpia: theParticleIndexerArrayinstancespecies_data: theVectorofSpeciesDataphys_props: thePhysPropsinstance in which the computed physical properties are stored
compute_props_sorted!(particles::Vector{ParticleVector{D}}, pia, species_data, phys_props, grid::G, cell_chunk) where {G<:AbstractGrid,D}Compute the physical properties of all species in a subset of cells and store the result in a PhysProps instance, assuming the particles are sorted. This function does not compute the total moments, even if phys_props.n_moments > 0. If ndens_not_Np is true, the number density will be computed based on the volumes of the grid cells; otherwise, the number of physical particles in each cell will be computed. Currently this does not compute the length of the particle array.
Positional arguments
particles: theVectorofParticleVectors containing all the particles in a simulationpia: theParticleIndexerArrayinstancespecies_data: theVectorofSpeciesDataphys_props: thePhysPropsinstance in which the computed physical properties are storedgrid: the physical gridcell_chunk: the list of cell indices or range of cell indices in which to compute the properties
compute_props_sorted!(particles::Vector{ParticleVector{D}}, pia, species_data, phys_props, grid::G) where {G<:AbstractGrid,D}Compute the physical properties of all species in all cells and store the result in a PhysProps instance, assuming the particles are sorted. This function does not compute the total moments, even if phys_props.n_moments > 0. If ndens_not_Np is true, the number density will be computed based on the volumes of the grid cells; otherwise, the number of physical particles in each cell will be computed. Currently this does not compute the length of the particle array.
Positional arguments
particles: theVectorofParticleVectors containing all the particles in a simulationpia: theParticleIndexerArrayinstancespecies_data: theVectorofSpeciesDataphys_props: thePhysPropsinstance in which the computed physical properties are storedgrid: the physical grid
Merzbild.compute_flux_props! — Function
compute_flux_props!(particles::Vector{ParticleVector{D}}, pia, species_data, phys_props::PhysProps, flux_props::FluxProps, grid::G) where {G<:AbstractGrid,D}Compute the fluxes of all species in all cells and store the result in a FluxProps instance. This uses the pre-computed species-wise mean velocities from a PhysProps instance, which needs to be computed at the same timestep before calling this function. Particles of a cell can be distributed across group1 and group2 of indices pointed to by the ParticleIndexerArray instance, i.e. this function can be used to compute fluxes immediately after collisions (but before convection). In case particles are sorted, compute_flux_props_sorted! will be more efficient.
Positional arguments
particles: theVectorofParticleVectors containing all the particles in a simulationpia: theParticleIndexerArrayinstancespecies_data: theVectorofSpeciesDataphys_props: thePhysPropsinstance computed at the same timestepflux_props: theFluxPropsinstance in which the computed fluxes are storedgrid: the physical grid
Merzbild.compute_flux_props_sorted! — Function
compute_flux_props_sorted!(particles::Vector{ParticleVector{D}}, pia, species_data, phys_props, flux_props, grid::G, cell_chunk) where {G<:AbstractGrid, D}Compute the flux densities of all species in a subset of cells and store the result in a FluxProps instance, assuming the particles are sorted. This uses the pre-computed species-wise mean velocities from a PhysProps instance, which needs to be computed at the same timestep before calling this function for the same subset of cells.
Positional arguments
particles: theVectorofParticleVectors containing all the particles in a simulationpia: theParticleIndexerArrayinstancespecies_data: theVectorofSpeciesDataphys_props: thePhysPropsinstance computed at the same timestep for the same subset of cellsflux_props: theFluxPropsinstance in which the computed fluxes are storedgrid: the physical gridcell_chunk: the list of cell indices or range of cell indices in which to compute the properties
compute_flux_props_sorted!(particles::Vector{ParticleVector{D}}, pia, species_data, phys_props, flux_props, grid::G) where {G<:AbstractGrid,D}Compute the flux densities of all species in all cells and store the result in a FluxProps instance, assuming the particles are sorted. This uses the pre-computed species-wise mean velocities from a PhysProps instance, which needs to be computed at the same timestep before calling this function.
Positional arguments
particles: theVectorofParticleVectors containing all the particles in a simulationpia: theParticleIndexerArrayinstancespecies_data: theVectorofSpeciesDataphys_props: thePhysPropsinstance computed at the same timestepflux_props: theFluxPropsinstance in which the computed fluxes are storedgrid: the physical grid
Merzbild.avg_props! — Function
avg_props!(phys_props_avg::PhysProps, phys_props::PhysProps, n_avg_timesteps)Used to time-average computed physical properties, not including the total moments. For each instantaneous value of a property computed and stored in phys_props, it is divided by n_avg_timesteps and added to phys_props_avg.
Positional arguments
phys_props_avg: thePhysPropsinstance used to store the time-averaged propertiesphys_props: thePhysPropsinstance holding the current values of the properties to be used for the averaging at the current timestepn_avg_timesteps: the number of timesteps over which the averaging is performed
Throws
ErrorException if phys_props_avg computes number density and phys_props computes number of physical particles, or vice versa.
avg_props!(flux_props_avg::FluxProps, flux_props::FluxProps, n_avg_timesteps)Used to time-average computed flux densities. For each instantaneous value of a property computed and stored in flux_props, it is divided by n_avg_timesteps and added to flux_props_avg.
Positional arguments
flux_props_avg: theFluxPropsinstance used to store the time-averaged propertiesflux_props: theFluxPropsinstance holding the current values of the properties to be used for the averaging at the current timestepn_avg_timesteps: the number of timesteps over which the averaging is performed
avg_props!(surf_props_avg::SurfProps, surf_props::SurfProps, n_avg_timesteps)Used to time-average computed surface properties. For each instantaneous value of a property computed and stored in surf_props, it is divided by n_avg_timesteps and added to surf_props_avg.
Positional arguments
surf_props_avg: theSurfPropsinstance used to store the time-averaged propertiessurf_props: theSurfPropsinstance holding the current values of the properties to be used for the averaging at the current timestepn_avg_timesteps: the number of timesteps over which the averaging is performed
Merzbild.clear_props! — Function
clear_props!(phys_props::PhysProps)Clear all data from PhysProps, for use when physical properties are averaged over timesteps and averaging over a new set of timesteps needs to be started.
Positional arguments
phys_props: thePhysPropsinstance to be cleared
clear_props!(flux_props::FluxProps)Clear all data from FluxProps, for use when flux densities are averaged over timesteps and averaging over a new set of timesteps needs to be started.
Positional arguments
flux_props: theFluxPropsinstance to be cleared
clear_props!(field_props::ElectrostaticFieldProps)Clear all data from an ElectrostaticFieldProps instance (the charge density, the potential, and the electric field). For clearing only the charge density in a time loop, use clear_charge_density!.
Positional arguments
field_props: theElectrostaticFieldPropsinstance to be cleared
clear_props!(surf_props::SurfProps)Clear all data from a SurfProps instance, either at the start of a new convection step, or when physical properties are averaged over timesteps and averaging over a new set of timesteps needs to be started.
Positional arguments
surf_props: theSurfPropsinstance to be cleared
Merzbild.compute_moment_scaling! — Function
compute_moment_scaling!(moment_scaling, moment_powers, species, species_data, Tref)Fill the vector moment_scaling with the appropriate scaling based on the Maxwell-Boltzmann distribution for a specific species.
Positional arguments
moment_scaling: vector to be filled with the moment scaling factors (lengthn_moments)moment_powers: vector of moment powers (lengthn_moments)species: the species for which the mixed moment is being computedspecies_data: theVectorofSpeciesDataTref: reference temperature used to compute the total moments of a Maxwellian distribution which are used to scale the total moments
Merzbild.compute_moments! — Function
compute_moments!(moment_values, moment_scaling, moment_powers, particles, pia, cell, species, species_data, phys_props)Fill the vector moment_values with the computed scaled moment values for a single species in a single cell. The values of n (number density or number of physical particles) and v (mean velocity) are taken from phys_props. It's important that function compute_props! must be called before this function, so that the correct nandv`` values are available.
Positional arguments
moment_values: vector to be filled with the computed moment values (lengthn_moments)moment_scaling: vector of precomputed moment scaling factors (lengthn_moments)moment_powers: vector of moment powers (lengthn_moments)particles: theVectorofParticleVectors containing all the particles in a simulationpia: theParticleIndexerArrayinstancecell: the cell in which the moment is being computedspecies: the species for which the mixed moment is being computedspecies_data: theVectorofSpeciesDataphys_props: thePhysPropsinstance in which the computed physical properties are stored
Collisional properties
Merzbild.mean_free_path — Function
mean_free_path(interaction, species, n, T)Compute elastic VHS mean free path for single-species collisions. This also holds for a VSS interaction, as the VSS model uses the same total cross-section as the VHS model.
Positional arguments
interaction: the 2-dimensional array ofInteractioninstances (of shape(n_species, n_species)) of all the pair-wise interactionsspecies: the species for which to compute the mean free pathn: the number densityT: the temperature
Returns
Mean free path.
References
- Eqn. (4.65) in "Molecular Gas Dynamics and the Direct Simulation of Gas Flows" or (D.21) in "Nonequilibrium Gas Dynamics and Molecular Simulation".
Merzbild.mean_collision_frequency — Function
mean_collision_frequency(interaction, species, species_data, n, T)Compute elastic VHS mean collision frequency for single-species collisions. This also holds for a VSS interaction, as the VSS model uses the same total cross-section as the VHS model.
Positional arguments
interactions: the 2-dimensional array ofInteractioninstances (of shape(n_species, n_species)) of all the pair-wise interactionsspecies: the species for which to compute the mean free pathspecies_data: the vector ofSpeciesinstances of the species in the flown: the number densityT: the temperature
Returns
Mean collision frequency.
References
- Eqn. (4.64) in "Molecular Gas Dynamics and the Direct Simulation of Gas Flows"
Merzbild.debye_length — Function
debye_length(n, T)Compute the Debye length $\lambda_D = \sqrt{\varepsilon_0 k_B T / (n q_e^2)}$ of a plasma with singly charged particles with density $n$ at a temperature $T$.
Positional arguments
n: the number density of the charged particlesT: the temperature of the charged particles
Returns
Debye length.
Merzbild.plasma_frequency — Function
plasma_frequency(species, species_data, n)Compute the plasma frequency $\omega_p = \sqrt{n q^2 / (\varepsilon_0 m)}$ of a species with charge $q$ and mass $m$ with a number density $n$.
Positional arguments
species: the species for which to compute the plasma frequencyspecies_data: the vector ofSpeciesinstances of the species in the flown: the number density of the species
Returns
Plasma frequency in rad/s.
Collision computations
Merzbild.CollisionData — Type
CollisionDataStructure to store temporary collision data for a specific collision (relative velocity, collision energy, post-collision velocities, etc.)
Fields
v_com: vector of center-of-mass velocityg: magnitude of relative velocityE_coll: relative translational energy of the colliding particlesE_coll_eV: relative translational energy of the colliding particles in electron-voltg_vec: vector of pre-collisional relative velocityg_vec_new: vector of post-collisional relative velocityg_new_1: magnitude of post-collisional relative velocity of the first particle in the collision pairg_new_2: magnitude of post-collisional relative velocity of the second particle in the collision pair
Merzbild.CollisionData — Method
CollisionData()Create an empty CollisionData instance.
Merzbild.CollisionFactors — Type
CollisionFactorsStructure to store NTC-related collision factors for collisions between particles of two species in a given cell.
Fields
n1: the number of particles of the first species in the celln2: the number of particles of the second species in the cellsigma_g_w_max: estimate of the $(\sigma g w)_{max}$ ($\sigma$ is the total collision cross-section, $g$ is the relative collision velocity, $w$ is the computational weight of the particles)n_coll: number of collisions to be testedn_coll_performed: number of collisions actually performedn_eq_w_coll_performed: number of collisions between particles with equal weights actually performed
Merzbild.CollisionFactors — Method
CollisionFactors()Create an empty CollisionFactors instance (all values set to 0).
Merzbild.CollisionFactorsSWPM — Type
CollisionFactorsSWPMStructure to store SWPM-related collision factors for collisions between particles of two species in a given cell.
Fields
n1: the number of particles of the first species in the celln2: the number of particles of the second species in the cellsigma_g_max: estimate of the $(\sigma g)_{max}$ ($\sigma$ is the total collision cross-section, $g$ is the relative collision velocityn_coll: number of collisions to be testedn_coll_performed: number of collisions actually performed
Merzbild.CollisionFactorsSWPM — Method
CollisionFactorsSWPM()Create an empty CollisionFactorsSWPM instance (all values set to 0).
Merzbild.CollisionDataFP — Type
CollisionDataFPStructure to store temporary collision data for the particle Fokker-Planck approach.
Fields
vel_ave: average velocity of the particles in the cellmean: mean value of the sampled velocitiesstddev: standard deviation of the sampled velocitiesxvel_rand: pre-allocated storage for sampled x-velocity componentsyvel_rand: pre-allocated storage for sampled y-velocity componentszvel_rand: pre-allocated storage for sampled z-velocity components
Merzbild.CollisionDataFP — Method
CollisionDataFP()Create an empty CollisionDataFP instance.
Merzbild.CollisionDataFP — Method
CollisionDataFP(n_particles_in_cell)Create an empty CollisionDataFP instance, pre-allocating the arrays for sampled normal variables for n_particles_in_cell.
Positional arguments
n_particles_in_cell: estimate of expected maximum number of particles in cell
Merzbild.create_collision_factors_array — Function
create_collision_factors_array(n_species)Create a 3-dimensional array of collision factors for all interaction pairs for a 0-D case (1 spatial cell), with shape (n_species,n_species,1).
Positional arguments
n_species: number of species in the flow
Returns
3-dimensional array of CollisionFactors instances with shape (n_species,n_species,1).
create_collision_factors_array(n_species, n_cells)Create a 3-dimensional array of collision factors for all interaction pairs for all cells in the simulation, with shape (n_species,n_species,n_cells).
Positional arguments
n_species: number of species in the flown_cells: number of cells in the simulation
Returns
3-dimensional array of CollisionFactors instances with shape (n_species,n_species,n_cells).
create_collision_factors_array(pia)Create a 3-dimensional array of collision factors for all interaction pairs for all cells in the simulation, with shape (n_species,n_species,n_cells).
Positional arguments
pia: the ParticleIndexerArray instance
Returns
3-dimensional array of CollisionFactors instances with shape (n_species,n_species,n_cells).
create_collision_factors_array(pia, interactions, species_data, T_list, Fnum::Real; mult_factor=1.0)Create a 3-dimensional array of collision factors for all interaction pairs for all cells in the simulation, with shape (n_species,n_species,n_cells). This will fill the array with the estimates $(\sigma g w)_{max}$ for all species in all cells, assuming a constant particle computational weight Fnum, a VHS cross-section, and that the temperature of each species is constant across all cells.
Positional arguments
pia: the ParticleIndexerArray instanceinteractions: the 2-dimensional array ofInteractioninstances (of shape(n_species, n_species)) of all the pair-wise interactionsspecies_data: the vector ofSpeciesinstances of the species in the flowT_list: the list of temperatures of the speciesFnum: the constant computational weight of the particles
Keyword arguments
mult_factor: a factor by which to multiply the result (default value is 1.0)
Returns
3-dimensional array of CollisionFactors instances with shape (n_species,n_species,n_cells) filled with estimated values of $(\sigma g w)_{max}$.
create_collision_factors_array(pia, interactions, species_data, T::Real, Fnum::Real; mult_factor=1.0)Create a 3-dimensional array of collision factors for all interaction pairs for all cells in the simulation, with shape (n_species,n_species,n_cells). This will fill the array with the estimates $(\sigma g w)_{max}$ for all species in all cells, assuming a constant particle computational weight Fnum, a VHS cross-section, and that all species have a single temperature that is constant across all cells.
Positional arguments
pia: the ParticleIndexerArray instanceinteractions: the 2-dimensional array ofInteractioninstances (of shape(n_species, n_species)) of all the pair-wise interactionsspecies_data: the vector ofSpeciesinstances of the species in the flowT: the temperatures of the flowFnum: the constant computational weight of the particles
Keyword arguments
mult_factor: a factor by which to multiply the result (default value is 1.0)
Returns
3-dimensional array of CollisionFactors instances with shape (n_species,n_species,n_cells) filled with estimated values of $(\sigma g w)_{max}$.
Merzbild.create_collision_factors_swpm_array — Function
create_collision_factors_swpm_array(n_species)Create a 3-dimensional array of SWPM collision factors for all interaction pairs for a 0-D case (1 spatial cell), with shape (n_species,n_species,1).
Positional arguments
n_species: number of species in the flow
Returns
3-dimensional array of CollisionFactorsSWPM instances with shape (n_species,n_species,1).
create_collision_factors_swpm_array(n_species, n_cells)Create a 3-dimensional array of SWPM collision factors for all interaction pairs for all cells in the simulation, with shape (n_species,n_species,n_cells).
Positional arguments
n_species: number of species in the flown_cells: number of cells in the simulation
Returns
3-dimensional array of CollisionFactorsSWPM instances with shape (n_species,n_species,n_cells).
create_collision_factors_swpm_array(pia)Create a 3-dimensional array of SWPM collision factors for all interaction pairs for all cells in the simulation, with shape (n_species,n_species,n_cells).
Positional arguments
pia: the ParticleIndexerArray instance
Returns
3-dimensional array of CollisionFactorsSWPM instances with shape (n_species,n_species,n_cells).
create_collision_factors_swpm_array(pia, interactions, species_data, T_list; mult_factor=1.0)Create a 3-dimensional array of SWPM collision factors for all interaction pairs for all cells in the simulation, with shape (n_species,n_species,n_cells). This will fill the array with the estimates $(\sigma g)_{max}$ for all species in all cells, assuming a VHS cross-section, and that the temperature of each species is constant across all cells.
Positional arguments
pia: the ParticleIndexerArray instanceinteractions: the 2-dimensional array ofInteractioninstances (of shape(n_species, n_species)) of all the pair-wise interactionsspecies_data: the vector ofSpeciesinstances of the species in the flowT_list: the list of temperatures of the species
Keyword arguments
mult_factor: a factor by which to multiply the result (default value is 1.0)
Returns
3-dimensional array of CollisionFactorsSWPM instances with shape (n_species,n_species,n_cells) filled with estimated values of $(\sigma g)_{max}$.
create_collision_factors_swpm_array(pia, interactions, species_data, T::Real; mult_factor=1.0)Create a 3-dimensional array of SWPM collision factors for all interaction pairs for all cells in the simulation, with shape (n_species,n_species,n_cells). This will fill the array with the estimates $(\sigma g)_{max}$ for all species in all cells, assuming a VHS cross-section, and that all species have a single temperature that is constant across all cells.
Positional arguments
pia: the ParticleIndexerArray instanceinteractions: the 2-dimensional array ofInteractioninstances (of shape(n_species, n_species)) of all the pair-wise interactionsspecies_data: the vector ofSpeciesinstances of the species in the flowT: the temperatures of the flow
Keyword arguments
mult_factor: a factor by which to multiply the result (default value is 1.0)
Returns
3-dimensional array of CollisionFactorsSWPM instances with shape (n_species,n_species,n_cells) filled with estimated values of $(\sigma g)_{max}$.
Merzbild.create_computed_crosssections — Function
create_computed_crosssections(electron_neutral_interactions)Create a vector of ComputedCrossSections instances for the electron-neutral interactions.
Positional arguments
electron_neutral_interactions: theElectronNeutralInteractionsinstance for which the cross-sections will be computed
Returns
Vector of ComputedCrossSections of length electron_neutral_interactions.n_neutrals.
Merzbild.estimate_sigma_g_w_max — Function
estimate_sigma_g_w_max(interaction, species1, species2, T1, T2, Fnum; mult_factor=1.0)Estimate $(\sigma g w)_{max}$ for a two-species interaction, assuming a constant particle computational weight Fnum and a VHS cross-section. The relative velocity $g$ is estimated as $g = 0.5 (\sqrt{2T_1 k_B / m_1} + \sqrt{2T_2 k_B / m_2})$, where $T_1$ and $m_1$ are the temperature and mass of the first species (species1), and $T_2$ and $m_2$ are the temperature and mass of the second species (species2). This relative velocity estimate is then plugged into the VHS cross-section model to compute $\sigma$. The result is then multiplied by Fnum and an (optional) factor mult_factor. This is also the correct estimate for the VSS model, as it uses the same total cross-section as the VHS model.
Positional arguments
interaction: theInteractioninstance for the interacting speciesspecies1: theSpeciesinstance of the first interacting speciesspecies2: theSpeciesinstance of the second interacting speciesT1: the temperature of the first interacting speciesT2: the temperature of the second interacting speciesFnum: the constant computational weight of the particles
Keyword arguments
mult_factor: a factor by which to multiply the result (default value is 1.0)
Returns
The estimate of $(\sigma g w)_{max}$.
estimate_sigma_g_w_max(interaction, species, T, Fnum; mult_factor=1.0)Estimate $(\sigma g w)_{max}$ for a single-species interaction, assuming a constant particle computational weight Fnum and a VHS cross-section. Uses the same methodology as the estimate for a two-species interaction.
Positional arguments
interaction: theInteractioninstance for the interacting speciesspecies: theSpeciesinstance of the interacting speciesT: the temperature of the interacting speciesFnum: the constant computational weight of the particles
Keyword arguments
mult_factor: a factor by which to multiply the result (default value is 1.0)
Returns
- the estimate of $(\sigma g w)_{max}$
Merzbild.estimate_sigma_g_w_max! — Function
estimate_sigma_g_w_max!(collision_factors, interactions, species_data, T_list, Fnum; mult_factor=1.0)Estimate $(\sigma g w)_{max}$ for all species in all cells, assuming a constant particle computational weight Fnum, a VHS cross-section, and that each species' temperature is constant across all cells. Uses the same methodology as the estimate for a two-species interaction.
Positional arguments
collision_factors: 3-dimensional array ofCollisionFactorsof shape(n_species, n_species, n_cells)interactions: the 2-dimensional array ofInteractioninstances (of shape(n_species, n_species)) of all the pair-wise interactionsspecies_data: the vector ofSpeciesinstances of the species in the flowT_list: the list of temperatures of the speciesFnum: the constant computational weight of the particles
Keyword arguments
mult_factor: a factor by which to multiply the result (default value is 1.0)
estimate_sigma_g_w_max!(collision_factors, interactions, species_data, T_list, Fnum; mult_factor=1.0)Estimate $(\sigma g w)_{max}$ for all species in all cells, assuming species-specific computational weights Fnum, a VHS cross-section, and that each species' temperature is constant across all cells. Uses the same methodology as the estimate for a two-species interaction.
Positional arguments
collision_factors: 3-dimensional array ofCollisionFactorsof shape(n_species, n_species, n_cells)interactions: the 2-dimensional array ofInteractioninstances (of shape(n_species, n_species)) of all the pair-wise interactionsspecies_data: the vector ofSpeciesinstances of the species in the flowT_list: the list of temperatures of the speciesFnum: a list of the computational weights of the species
Keyword arguments
mult_factor: a factor by which to multiply the result (default value is 1.0)
Merzbild.estimate_sigma_g_w_max_ntc_n_e! — Function
estimate_sigma_g_w_max_ntc_n_e!(rng, collision_factors, collision_data, interaction,
n_e_interactions, n_e_cs, particles_n, particles_e,
pia, cell, species_n, species_e, Δt, V; min_coll=5, n_loops=3)Estimate $(\sigma g w)_{max}$ for an electron-neutral interaction by stochastically choosing particle pairs multiple times and computing $(\sigma g w)$ for each pair. The number of collisions is computed using the standard variable-weight NTC formula, the value of min_coll is added to this number, and particles are randomly sampled. The whole procedure is repeated n_loops times, so that an increased value $(\sigma g w)_{max}$ can have an impact on the computed number of pairs to select during the next loop iteration.
Positional arguments
rng: the random number generatorcollision_factors: theCollisionFactorsfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsn_e_interactions: theElectronNeutralInteractionsinstancen_e_cs: a vector ofComputedCrossSectionsinstancesparticles_n:ParticleVectorof the particles of neutral speciesparticles_e:ParticleVectorof the particles of the electron speciespia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies_n: the index of the neutral speciesspecies_e: the index of the electron speciesΔt: timestepV: cell volume
Keyword arguments:
min_coll: the minimum number of pairs to testn_loops: the number of loops to perform (in each loop the number of collisions is computed using the estimated value of $(\sigma g w)_{max}$)extend: enum ofCSExtendtype that sets how out-of-range energy values are treated when computing cross-sections
Merzbild.estimate_sigma_g_max! — Function
estimate_sigma_g_max!(collision_factors::Array{CollisionFactorsSWPM}, interactions, species_data, T_list; mult_factor=1.0)Estimate $(\sigma g)_{max}$ for all species in all cells, assuming a constant particle computational weight Fnum, a VHS cross-section, and that each species' temperature is constant across all cells. Uses the same methodology as the estimate for a two-species interaction.
Positional arguments
collision_factors: 3-dimensional array ofCollisionFactorsSWPMof shape(n_species, n_species, n_cells)interactions: the 2-dimensional array ofInteractioninstances (of shape(n_species, n_species)) of all the pair-wise interactionsspecies_data: the vector ofSpeciesinstances of the species in the flowT_list: the list of temperatures of the species
Keyword arguments
mult_factor: a factor by which to multiply the result (default value is 1.0)
Merzbild.ntc! — Function
ntc!(rng, collision_factors, collision_data, interaction, particles::ParticleVector{D}, pia,
cell, species, Δt, V; dw_tol=1e-16) where DPerform elastic collisions between particles of same species using the NTC algorithm. The elastic scattering model is taken from the Interaction instance of the species pair.
Positional arguments
rng: the random number generatorcollision_factors: theCollisionFactorsfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsparticles:ParticleVectorof the particles being collidedpia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies: the index of the species for which collisions are performedΔt: timestepV: cell volume
Keyword arguments
dw_tol: if weights of particles differ by less than this amount, an equal-weight collision is assumed
and no particle splitting is performed
References
- D.P. Schmidt, C.J. Rutland, A New Droplet Collision Algorithm. J. Comput. Phys, 2000.
ntc!(rng, model::AbstractScatteringModel, collision_factors, collision_data, interaction,
particles::ParticleVector{D}, pia, cell, species, Δt, V; dw_tol=1e-16) where DPerform elastic collisions between particles of same species using the NTC algorithm and the elastic scattering model model, overriding the model stored in the Interaction instance of the species pair.
Positional arguments
rng: the random number generatormodel: theAbstractScatteringModelsingleton for the scattering modelcollision_factors: theCollisionFactorsfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsparticles:ParticleVectorof the particles being collidedpia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies: the index of the species for which collisions are performedΔt: timestepV: cell volume
Keyword arguments
dw_tol: if weights of particles differ by less than this amount, an equal-weight collision is assumed
and no particle splitting is performed
References
- D.P. Schmidt, C.J. Rutland, A New Droplet Collision Algorithm. J. Comput. Phys, 2000.
ntc!(rng, collision_factors, collision_data, interaction,
particles_1::ParticleVector{D}, particles_2::ParticleVector{D}, pia,
cell, species1, species2, Δt, V; dw_tol=1e-16) where DPerform elastic collisions between particles of different species using the NTC algorithm. The elastic scattering model is taken from the Interaction instance of the species pair.
Positional arguments
rng: the random number generatorcollision_factors: theCollisionFactorsfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsparticles_1:ParticleVectorof the particles of the first species being collidedparticles_2:ParticleVectorof the particles of the second species being collidedpia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies1: the index of the first species for which collisions are performedspecies2: the index of the second species for which collisions are performedΔt: timestepV: cell volume
Keyword arguments
dw_tol: if weights of particles differ by less than this amount, an equal-weight collision is assumed
and no particle splitting is performed
References
- D.P. Schmidt, C.J. Rutland, A New Droplet Collision Algorithm. J. Comput. Phys, 2000.
ntc!(rng, model::AbstractScatteringModel, collision_factors, collision_data, interaction,
particles_1::ParticleVector{D}, particles_2::ParticleVector{D}, pia,
cell, species1, species2, Δt, V; dw_tol=1e-16) where DPerform elastic collisions between particles of different species using the NTC algorithm and the elastic scattering model model, overriding the model stored in the Interaction instance of the species pair.
Positional arguments
rng: the random number generatormodel: theAbstractScatteringModelsingleton for the scattering modelcollision_factors: theCollisionFactorsfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsparticles_1:ParticleVectorof the particles of the first species being collidedparticles_2:ParticleVectorof the particles of the second species being collidedpia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies1: the index of the first species for which collisions are performedspecies2: the index of the second species for which collisions are performedΔt: timestepV: cell volume
Keyword arguments
dw_tol: if weights of particles differ by less than this amount, an equal-weight collision is assumed
and no particle splitting is performed
References
- D.P. Schmidt, C.J. Rutland, A New Droplet Collision Algorithm. J. Comput. Phys, 2000.
Merzbild.ntc_equal_weight! — Function
ntc_equal_weight!(rng, collision_factors, collision_data, interaction, particles::ParticleVector{D}, pia,
cell, species, Δt, V) where DPerform elastic collisions between particles of same species using the NTC algorithm. Particle weights are assumed to be equal, and no weight checks/splitting is performed. The elastic scattering model is taken from the Interaction instance of the species pair.
Positional arguments
rng: the random number generatorcollision_factors: theCollisionFactorsfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsparticles:ParticleVectorof the particles being collidedpia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies: the index of the species for which collisions are performedΔt: timestepV: cell volume
References
- G.A. Bird, Molecular gas dynamics and the direct simulation of gas flows, Clarendon Press, Oxford, 1994.
ntc_equal_weight!(rng, model::AbstractScatteringModel, collision_factors, collision_data, interaction,
particles::ParticleVector{D}, pia, cell, species, Δt, V) where DPerform elastic collisions between particles of same species using the NTC algorithm and the elastic scattering model model, overriding the model stored in the Interaction instance of the species pair. Particle weights are assumed to be equal, and no weight checks/splitting is performed.
Positional arguments
rng: the random number generatormodel: theAbstractScatteringModelsingleton for the scattering modelcollision_factors: theCollisionFactorsfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsparticles:ParticleVectorof the particles being collidedpia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies: the index of the species for which collisions are performedΔt: timestepV: cell volume
References
- G.A. Bird, Molecular gas dynamics and the direct simulation of gas flows, Clarendon Press, Oxford, 1994.
ntc_equal_weight!(rng, collision_factors, collision_data, interaction,
particles_1, particles_2, pia,
cell, species1, species2, Δt, V)Perform elastic collisions between particles of different species using the NTC algorithm. Particle weights are assumed to be equal, and no weight checks/splitting is performed. The elastic scattering model is taken from the Interaction instance of the species pair.
Positional arguments
rng: the random number generatorcollision_factors: theCollisionFactorsfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsparticles_1:ParticleVectorof the particles of the first species being collidedparticles_2:ParticleVectorof the particles of the second species being collidedpia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies1: the index of the first species for which collisions are performedspecies2: the index of the second species for which collisions are performedΔt: timestepV: cell volume
References
- G.A. Bird, Molecular gas dynamics and the direct simulation of gas flows, Clarendon Press, Oxford, 1994.
ntc_equal_weight!(rng, model::AbstractScatteringModel, collision_factors, collision_data, interaction,
particles_1, particles_2, pia,
cell, species1, species2, Δt, V)Perform elastic collisions between particles of different species using the NTC algorithm and the elastic scattering model model, overriding the model stored in the Interaction instance of the species pair. Particle weights are assumed to be equal, and no weight checks/splitting is performed.
Positional arguments
rng: the random number generatormodel: theAbstractScatteringModelsingleton for the scattering modelcollision_factors: theCollisionFactorsfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsparticles_1:ParticleVectorof the particles of the first species being collidedparticles_2:ParticleVectorof the particles of the second species being collidedpia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies1: the index of the first species for which collisions are performedspecies2: the index of the second species for which collisions are performedΔt: timestepV: cell volume
References
- G.A. Bird, Molecular gas dynamics and the direct simulation of gas flows, Clarendon Press, Oxford, 1994.
Merzbild.ntc_n_e! — Function
ntc_n_e!(rng, collision_factors, collision_data, interaction,
n_e_interactions, n_e_cs, particles_n, particles_e, particles_ion,
pia, cell, species_n, species_e, species_ion, Δt, V; extend::CSExtend=CSExtendConstant, dw_tol=1e-16)Perform electron-neutral elastic scattering and electron-impact ionization collisions.
Positional arguments
rng: the random number generatorcollision_factors: theCollisionFactorsfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsn_e_interactions: theElectronNeutralInteractionsinstancen_e_cs: a vector ofComputedCrossSectionsinstancesparticles_n:ParticleVectorof the particles of neutral speciesparticles_e:ParticleVectorof the particles of the electron speciesparticles_ion:ParticleVectorof the particles of the ion speciespia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies_n: the index of the neutral speciesspecies_e: the index of the electron speciesspecies_ion: the index of the ion speciesΔt: timestepV: cell volume
Keyword arguments
extend: enum ofCSExtendtype that sets how out-of-range energy values are treated when computing cross-sectionsdw_tol: if weights of particles differ by less than this amount, an equal-weight collision is assumed
and no particle splitting is performed
References
- D.P. Schmidt, C.J. Rutland, A New Droplet Collision Algorithm. J. Comput. Phys, 2000.
Merzbild.ntc_n_e_es! — Function
ntc_n_e_es!(rng, collision_factors, collision_data, interaction,
n_e_interactions, n_e_cs, particles_n, particles_e, particles_ion,
pia, cell, species_n, species_e, species_ion, Δt, V; extend::CSExtend=CSExtendConstant, dw_tol=1e-16)Perform electron-neutral elastic scattering and electron-impact ionization collisions using the event splitting method.
Positional arguments
rng: the random number generatorcollision_factors: theCollisionFactorsfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsn_e_interactions: theElectronNeutralInteractionsinstancen_e_cs: a vector ofComputedCrossSectionsinstancesparticles_n:ParticleVectorof the particles of neutral speciesparticles_e:ParticleVectorof the particles of the electron speciesparticles_ion:ParticleVectorof the particles of the ion speciespia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies_n: the index of the neutral speciesspecies_e: the index of the electron speciesspecies_ion: the index of the ion speciesΔt: timestepV: cell volume
Keyword arguments
extend: enum ofCSExtendtype that sets how out-of-range energy values are treated when computing cross-sectionsdw_tol: if weights of particles differ by less than this amount, an equal-weight collision is assumed
and no particle splitting is performed
References
- G. Oblapenko, D. Goldstein, P. Varghese, C. Moore, Hedging direct simulation Monte Carlo bets via event splitting. J. Comput. Phys, 2022.
- D.P. Schmidt, C.J. Rutland, A New Droplet Collision Algorithm. J. Comput. Phys, 2000.
Merzbild.swpm! — Function
swpm!(rng, collision_factors_swpm, collision_data, interaction, particles::ParticleVector{D}, pia,
cell, species, G, Δt, V)Perform elastic collisions between variable-weight particles of same species using the SWPM algorithm. The elastic scattering model is taken from the Interaction instance of the species pair. During a collision of particles with weights $w_i$, $w_j$, the weights are depleted by $\min(w_i, w_j) / (1+G)$, where $G \geq 0$ is a user-defined parameter.
Positional arguments
rng: the random number generatorcollision_factors_swpm: theCollisionFactorsSWPMfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsparticles:ParticleVectorof the particles being collidedpia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies: the index of the species for which collisions are performedG: non-negative value defining the weight transfer functionΔt: timestepV: cell volume
References
- S. Rjasanow, W.Wagner, Stochastic numerics for the Boltzmann equation. Springer Berlin, Heidelberg, 2005.
swpm!(rng, model::AbstractScatteringModel, collision_factors_swpm, collision_data, interaction,
particles::ParticleVector{D}, pia, cell, species, G, Δt, V)Perform elastic collisions between variable-weight particles of same species using the SWPM algorithm and the elastic scattering model model, overriding the model stored in the Interaction instance of the species pair. During a collision of particles with weights $w_i$, $w_j$, the weights are depleted by $\min(w_i, w_j) / (1+G)$, where $G \geq 0$ is a user-defined parameter.
Positional arguments
rng: the random number generatormodel: theAbstractScatteringModelsingleton tag of the scattering modelcollision_factors_swpm: theCollisionFactorsSWPMfor the species in question in the cellcollision_data:CollisionDatainstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsparticles:ParticleVectorof the particles being collidedpia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies: the index of the species for which collisions are performedG: non-negative value defining the weight transfer functionΔt: timestepV: cell volume
References
- S. Rjasanow, W.Wagner, Stochastic numerics for the Boltzmann equation. Springer Berlin, Heidelberg, 2005.
Fokker-Planck computations
Merzbild.fp_linear! — Function
fp_linear!(rng, collision_data_fp, interaction, particles::ParticleVector{D}, pia, cell, species, species_data, Δt, V) where DModel single-species elastic collisions using a linear Fokker-Planck approximation.
Positional arguments
rng: the random number generatorcollision_data_fp:CollisionDataFPinstance used for storing collisional quantitiesinteraction: 2-dimensional array ofInteractioninstances for all possible species pairsparticles:ParticleVectorof the particles being collidedpia: theParticleIndexerArraycell: the index of the cell in which collisions are performedspecies: the index of the species for which collisions are performedspecies_data: the vector ofSpeciesDataΔt: timestepV: cell volume
References
- M.H. Gorji, M. Torrilhon, P. Jenny, Fokker-Planck model for computational studies of monatomic rarefied gas flows. J. Fluid Mech., 2011.
Electron-neutral interactions
Merzbild.ElectronNeutralInteractions — Type
ElectronNeutralInteractionsStructure to hold data on electron-neutral interactions. The neutral_indexer field is used to obtain the index of the species inside the structure, given an index of the neutral species in the full list of species in the simulation. For example, if we have a following list of species in the simulation: [e-, He, Ar+, He+, Ar], n_neutrals=2, the ElectronNeutralInteractions instance stores data for interactions of electrons with [He, Ar], and neutral_indexer[2] = 1, neutral_indexer[5] = 2.
Fields
n_neutrals: number of neutral species for which the data has been loadedmass_ratios: ratio of electron mass to mass of neutrals; this uses the electron mass as given in theSpeciesinstance, so heavy electrons are possibleneutral_indexer: array that maps indices of neutral species in the full list of species to local indices in theElectronNeutralInteractionsstructureelastic: an array ofElasticScatteringinstances (of lengthn_neutrals) holding the cross-section data on elastic scattering for each neutral speciesionization: an array ofIonizationinstances (of lengthn_neutrals) holding the cross-section data on electron-impact ionization for each neutral speciesexcitation_sink: an array ofExcitationSinkinstances (of lengthn_neutrals) holding the cross-section data on electron-impact electronic excitation for each neutral species
Merzbild.ElectronNeutralInteractions — Method
ElectronNeutralInteractions(species_data, filename, databases, scattering_laws, energy_splits)Load electron-neutral interaction data from an LXCAT format XML file for a set of given neutral species and instantiate a ElectronNeutralInteractions instance.
Positional arguments
species_data: vector ofSpeciesdata for the neutral speciesfilename: path to XML filedatabases: dictionary of(species.name => database)pairs, specifying the name
of the cross-section database in the XML file to use for the species
scattering_laws: vector ofScatteringLawinstances to use for each speciesenergy_splits: vector ofElectronEnergySplitinstances to use for each species
Returns
ElectronNeutralInteractions structure containing the electron-neutral interaction data.
Throws
DataMissingException if data not found or not all required data present.
Merzbild.ComputedCrossSections — Type
ComputedCrossSectionsStructure to hold data on computed cross-sections of electron-neutral interactions for a specific neutral species.
Fields
n_excitations: number of electron-impact excitation reactionscs_total: the computed total cross-section (sum of cross-sections of all processes)cs_elastic: the computed elastic scattering cross-sectioncs_ionization: the computed electron-impact ionization cross-sectioncs_excitation: the computed electron-impact electronic excitation cross-sectionprob_vec: a vector of probabilities of the processes (of length2+n_excitations).prob_vec[1]is the probability of elastic scattering,prob_vec[2]is the probability of electron-impact ionization,prob_vec[3:2+n_excitations]are the probabilities of the electron-impact electronic excitation processescdf_prob_vec: a vector of cumulative probabilities of the processes (of length2+n_excitations), used for sampling a specific process:cfd_prob_vec[1] = 0.0,cfd_prob_vec[n] = cfd_prob_vec[n-1] + prob_vec[n-1], n>1
Merzbild.ElectronEnergySplit — Type
ElectronEnergySplit ElectronEnergySplitEqual=1 ElectronEnergySplitZeroE=2Enum for various splittings of electron energy in electron-impact ionization reactions. ElectronEnergySplitEqual corresponds to energy being shared equally amongst the electrons, ElectronEnergySplitZeroE corresponds to the one-takes-all sharing model.
Merzbild.ScatteringLaw — Type
ScatteringLaw ScatteringIsotropic=1 ScatteringOkhrimovskyy=2Enum for various scattering laws in electron-neutral interactions. ScatteringIsotropic corresponds to isotropic scattering, ScatteringOkhrimovskyy to the scattering model of A. Okhrimovskyy et al., 2002.
Merzbild.CSExtend — Type
CSExtend CSExtendConstant=1 CSExtendZero=2Enum defining how to extend cross-sections in case energy is outside of tabulated range.
Possible values:
CSExtendConstant: continue with closest value in arrayCSExtendZero: continue with zero
Merging
Grid merging
Merzbild.GridN2Merge — Type
GridN2Merge{D}Struct for merging particles with D-dimensional position vectors using a grid in velocity space. Particles in each cell are merged down. Particles outside of the grid are merged based on the octant they are in. So for an N:2 merge one would expect at most 2*(Nx*Ny*Nz+8) post-merge particles, where Nx, Ny, Nz are the number of grid cells in each velocity direction. The grid bounds in each direction can be computed using the mean thermal velocity of the particles and the mean streaming velocity: [v0-extent_multiplier*sqrt(2*k_B*T/m),v0+extent_multiplier*sqrt(2*k_B*T/m)]. Here T is the temperature of the species in question, m is the molecular mass, v0 is the mean velocity and extent_multiplier is a user-defined parameter (3.5 is a reasonable choice) defining the extent of the grid.
Fields
Nx: number of grid cells in x velocity directionNy: number of grid cells in y velocity directionNz: number of grid cells in z velocity directionNyNz: product ofNyandNzNtotal: total number of grid cells (equal toNx*Ny*Nz+8, as we account for the external octants)extent_multiplier: the vector of factors by which to multiply the thermal velocity to determine the grid bounds in each velocity directionextent_v_lower: the lower bounds of the velocity grid in each velocity directionextent_v_upper: the upper bounds of the velocity grid in each velocity directionextent_v_mid:(extent_v_lower + extent_v_upper)/2Δv: the grid cell size in each velocity directionΔv_inv: the inverse grid cell size in each velocity directiondirection_vec: used to store randomly sampled direction signsdirection_vecD: used to store randomly sampled direction signs of length Dcells: vector ofGridCellinstances for each grid cell, as well as the external octants
Merzbild.GridN2Merge — Method
GridN2Merge{D}(Nx::Int, Ny::Int, Nz::Int, extent_multiplier::T) where {D, T <: AbstractArray}Create velocity grid-based merging for particles with D-dimensional position vectors.
Positional arguments
Nx: number of cells in vx directionNy: number of cells in vy directionNz: number of cells in vz directionextent_multiplier: the vector of factors by which to multiply the thermal velocity to determine the grid bounds
in each velocity direction
Merzbild.GridN2Merge — Method
GridN2Merge{D}(N::Int, extent_multiplier::T) where {D, T <: AbstractArray}Create velocity grid-based merging for particles with D-dimensional position vectors with an equal number of cells in each direction.
Positional arguments
N: number of cells in each velocity directionextent_multiplier: the vector of factors by which to multiply the thermal velocity to determine the grid bounds
in each velocity direction
Merzbild.GridN2Merge — Method
GridN2Merge{D}(Nx::Int, Ny::Int, Nz::Int, extent_multiplier::Float64) where DCreate velocity grid-based merging for particles with D-dimensional position vectors with equal extent multipliers in each direction.
Positional arguments
Nx: number of cells in vx directionNy: number of cells in vy directionNz: number of cells in vz directionextent_multiplier: the factor by which to multiply the thermal velocity to determine the grid bounds
in each velocity direction
Merzbild.GridN2Merge — Method
GridN2Merge{D}(Nx::Int, Ny::Int, Nz::Int,
extent_multiplier_x::Float64,
extent_multiplier_y::Float64,
extent_multiplier_z::Float64) where DCreate velocity grid-based for merging particles with D-dimensional position vectors
Positional arguments
Nx: number of cells in vx directionNy: number of cells in vy directionNz: number of cells in vz directionextent_multiplier_x: the factor by which to multiply the thermal velocity to determine the grid bounds
in the x-velocity direction
extent_multiplier_y: the factor by which to multiply the thermal velocity to determine the grid bounds
in the y-velocity direction
extent_multiplier_z: the factor by which to multiply the thermal velocity to determine the grid bounds
in the z-velocity direction
Merzbild.GridN2Merge — Method
GridN2Merge{D}(N::Int, extent_multiplier::Float64) where DCreate velocity grid-based merging for particles with D-dimensional position vectors with an equal number of cells in each direction and equal extent multipliers in each direction.
Positional arguments
N: number of cells in each velocity directionextent_multiplier: the factor by which to multiply the thermal velocity to determine the grid bounds
in each velocity direction
Merzbild.GridN2Merge — Method
GridN2Merge(N::Int, extent_multiplier::T) where T <: AbstractArrayCreate velocity grid-based merging for particles with 3-dimensional position vectors with an equal number of cells in each direction.
Positional arguments
N: number of cells in each velocity directionextent_multiplier: the vector of factors by which to multiply the thermal velocity to determine the grid bounds
in each velocity direction
Merzbild.GridN2Merge — Method
GridN2Merge(Nx::Int, Ny::Int, Nz::Int, extent_multiplier::Float64)Create velocity grid-based merging for particles with 3-dimensional position vectors with equal extent multipliers in each direction.
Positional arguments
Nx: number of cells in vx directionNy: number of cells in vy directionNz: number of cells in vz directionextent_multiplier: the factor by which to multiply the thermal velocity to determine the grid bounds
in each velocity direction
Merzbild.GridN2Merge — Method
GridN2Merge(Nx::Int, Ny::Int, Nz::Int,
extent_multiplier_x::Float64,
extent_multiplier_y::Float64,
extent_multiplier_z::Float64)Create velocity grid-based merging for particles with 3-dimensional position vectors.
Positional arguments
Nx: number of cells in vx directionNy: number of cells in vy directionNz: number of cells in vz directionextent_multiplier_x: the factor by which to multiply the thermal velocity to determine the grid bounds
in the x-velocity direction
extent_multiplier_y: the factor by which to multiply the thermal velocity to determine the grid bounds
in the y-velocity direction
extent_multiplier_z: the factor by which to multiply the thermal velocity to determine the grid bounds
in the z-velocity direction
Merzbild.merge_grid_based! — Function
merge_grid_based!(rng, merging_grid::GridN2Merge{D}, particles::ParticleVector{D}, pia, cell, species, species_data, phys_props::PhysProps) where DMerge particles using a velocity grid-based merging approach. A Cartesian grid in velocity space is used to group particles together (particles outside of the grid are group by velocity octant), and in each cell/octant, particles are merged down to 2 particles. The extent of the grid is based on the temperature for the species in question in the physical grid cell being considered, as stored in the phys_props parameter.
Positional arguments:
rng: the random number generator instancemerging_grid: the grid merging (GridN2Merge) instance defining the velocity space gridparticles: theParticleVectorinstance of the particles to be mergedpia: theParticleIndexerArrayinstancecell: the cell indexspecies: the species indexspecies_data: the array ofSpeciesdataphys_props: thePhysPropsinstance containing the computed temperature
References
- M. Vranic, T. Grismayer, J.L. Martins, R.A. Fonseca, L.O. Silva, Particle merging algorithm for PIC codes. Comput. Phys. Comm., 2015.
- G. Oblapenko, D. Goldstein, P. Varghese, C. Moore, A velocity space hybridization-based Boltzmann equation solver. J. Comput. Phys, 2020.
merge_grid_based!(rng, merging_grid::GridN2Merge{D}, particles::ParticleVector{D}, pia, cell, species, species_data, vx_extent, vy_extent, vz_extent)Merge particles using a velocity grid-based merging approach. A Cartesian grid in velocity space is used to group particles together (particles outside of the grid are group by velocity octant), and in each cell/octant, particles are merged down to 2 particles. The extent of the grid is specified explicitly.
Positional arguments:
rng: the random number generator instancemerging_grid: the grid merging (GridN2Merge) instance defining the velocity space gridparticles: theParticleVectorinstance of the particles to be mergedpia: theParticleIndexerArrayinstancecell: the cell indexspecies: the species indexspecies_data: the array ofSpeciesdatavx_extent: lower and upper bounds of the grid extent in the x velocity directionvy_extent: lower and upper bounds of the grid extent in the y velocity directionvz_extent: lower and upper bounds of the grid extent in the z velocity direction
References
- M. Vranic, T. Grismayer, J.L. Martins, R.A. Fonseca, L.O. Silva, Particle merging algorithm for PIC codes. Comput. Phys. Comm., 2015.
- G. Oblapenko, D. Goldstein, P. Varghese, C. Moore, A velocity space hybridization-based Boltzmann equation solver. J. Comput. Phys, 2020.
merge_grid_based!(rng, merging_grid::GridN2Merge{D}, particles::ParticleVector{D}, pia, cell, species, species_data, phys_props::PhysProps, grid::Grid1DUniform) where DMerge particles using a velocity grid-based merging approach. A Cartesian grid in velocity space is used to group particles together (particles outside of the grid are group by velocity octant), and in each cell/octant, particles are merged down to 2 particles. The extent of the grid is based on the temperature for the species in question in the physical grid cell being considered, as stored in the phys_props parameter. If particle positions end up outside of the simulation domain, the particles are placed back into the domain.
Positional arguments:
rng: the random number generator instancemerging_grid: the grid merging (GridN2Merge) instance defining the velocity space gridparticles: theParticleVectorinstance of the particles to be mergedpia: theParticleIndexerArrayinstancecell: the cell indexspecies: the species indexspecies_data: the array ofSpeciesdataphys_props: thePhysPropsinstance containing the computed temperaturegrid: theGrid1DUniformgrid
References
- M. Vranic, T. Grismayer, J.L. Martins, R.A. Fonseca, L.O. Silva, Particle merging algorithm for PIC codes. Comput. Phys. Comm., 2015.
- G. Oblapenko, D. Goldstein, P. Varghese, C. Moore, A velocity space hybridization-based Boltzmann equation solver. J. Comput. Phys, 2020.
merge_grid_based!(rng, merging_grid::GridN2Merge{D}, particles::ParticleVector{D}, pia, cell, species, species_data, vx_extent, vy_extent, vz_extent, grid::Grid1DUniform) where DMerge particles using a velocity grid-based merging approach. A Cartesian grid in velocity space is used to group particles together (particles outside of the grid are group by velocity octant), and in each cell/octant, particles are merged down to 2 particles. The extent of the grid is specified explicitly. If particle positions end up outside of the simulation domain, the particles are placed back into the domain.
Positional arguments:
rng: the random number generator instancemerging_grid: the grid merging (GridN2Merge) instance defining the velocity space gridparticles: theParticleVectorinstance of the particles to be mergedpia: theParticleIndexerArrayinstancecell: the cell indexspecies: the species indexspecies_data: the array ofSpeciesdatavx_extent: lower and upper bounds of the grid extent in the x velocity directionvy_extent: lower and upper bounds of the grid extent in the y velocity directionvz_extent: lower and upper bounds of the grid extent in the z velocity directiongrid: theGrid1DUniformgrid
References
- M. Vranic, T. Grismayer, J.L. Martins, R.A. Fonseca, L.O. Silva, Particle merging algorithm for PIC codes. Comput. Phys. Comm., 2015.
- G. Oblapenko, D. Goldstein, P. Varghese, C. Moore, A velocity space hybridization-based Boltzmann equation solver. J. Comput. Phys, 2020.
Merzbild.GridN2Merge — Method
GridN2Merge(N::Int, extent_multiplier::Float64)Create velocity grid-based merging for particles with 3-dimensional position vectors with an equal number of cells in each direction and equal extenr multipliers in each direction.
Positional arguments
N: number of cells in each velocity directionextent_multiplier: the factor by which to multiply the thermal velocity to determine the grid bounds
in each velocity direction
NNLS merging
Merzbild.NNLSMerge — Type
NNLSMerge{D}Struct for keeping track of merging-related quantities for NNLS-based merging of particles with D-dimensional position vectors.
Fields
v0: vector of the mean velocity of the particlesx0: D-dimensional vector of the mean position of the particlesvref: reference velocity magnitude for scalinginv_vref: inverse of reference velocity magnitude for scalingEv: vector of standard deviation of velocities of particlesEx: vector of standard deviation of positions of particlesw_total: total computational of the particlesscalev: vector of values used to scale the velocity of particlesscalex: vector of values used to scale the positions of particlesn_total_conserved: total number of moments conservedn_moments_vel: number of velocity moments to preserverhs_vector: vector of computed momentsrow_scale: scratch vector of the row-wise scaling factors applied to the LHS matrixmim: vector of 3-tuples of multi-indices for the velocity moments to preservetot_order: vector of total orders of the velocity moments to preservevel_powers: scratch table of powers of the centered velocity components of a particlen_moments_pos: number of spatial moments to preservemim_pos: vector of 3-tuples of multi-indices for the spatial moments to preservetot_order_pos: vector of total orders of the spatial moments to preservepos_powers: scratch table of powers of the centered position components of a particlepos_i_x: index of the spatial moment corresponding to preservation of the center of mass in the x directionpos_i_y: index of the spatial moment corresponding to preservation of the center of mass in the y directionpos_i_z: index of the spatial moment corresponding to preservation of the center of mass in the z directionlhs_matrix_ncols_start: the number of columns in the first pre-allocated matrixlhs_matrix_ncols_end: the number of columns in the last pre-allocated matrixcolumn_norms: vector of vectors of the column-wise inverse norms of the LHS matricesvel_pos_matrices: vector of matrices of size(3+D)xNpthat store the velocities and positions of the particlescolumn_norms_scratch: column-wise inverse norms used when the number of columns is outside the pre-allocated rangevel_pos_matrix_scratch: velocities and positions used when the number of columns is outside the pre-allocated rangework: Vector ofNNLSWorkspaceinstances
Merzbild.NNLSMerge — Method
NNLSMerge{D}(multi_index_moments, init_np; rate_preserving=false, multi_index_moments_pos=[], matrix_ncol_nprealloc=0) where DCreate NNLS-based merging. Mass, momentum, directional energy are always conserved: if not in the list multi_index_moments of moments to preserve, the corresponding moment multi-indices will be added automatically. These indices are (0,0,0) for mass, (1,0,0), (0,1,0), (0,0,1) for momentum, and (2,0,0), (0,2,0), (0,0,2) for directional energies. Spatial moments can be preserved by setting multi_index_moments_pos. If multi_index_moments_pos is non-empty, it is currently left to the user to include any relevant 1st order moments (corresponding center of mass conservation) i.e. (1, 0, 0), (0, 1, 0), (0, 0, 1); otherwise the corresponding spatial moments including higher-order ones will not be conserved. By default, a single NNLSWorkspace is pre-allocated for the system. The number of columns in the LHS matrix is the number of particles to be merged (+ any fictitious particles); so it cannot be fixed in advance. By setting matrix_ncol_nprealloc to a value larger than 0, one can pre-allocate a range of workspaces with a fixed number of columns spanning [init_np, init_np+matrix_ncol_nprealloc]. In this case, matrix_ncol_nprealloc+2 NNLSWorkspace instances are pre-allocated, with the last one being used in case the number of columns is not in the range (its LHS matrix is then re-allocated on the fly, but only when the number of columns differs from the previous call). Vectors column_norms and vel_pos_matrices are also then pre-allocated, holding respectively the inverses of the column-wise norms of the LHS matrices used for their scaling, and the particle velocities and positions. Outside the pre-allocated range the column_norms_scratch / vel_pos_matrix_scratch buffers are used instead; these grow as needed and are re-used across calls.
Positional arguments
multi_index_moments: vector of mixed moments to preserve of the form[(i1, j1, k1), (i2, j2, k2), ...]`init_np: assumption on pre-merge number of particles to pre-allocate memory for
Keyword arguments:
rate_preserving: used for rate-preserving merging of electrons, preserves approximate elastic collision and ionization ratesmulti_index_moments_pos: list of spatial moments to preservematrix_ncol_nprealloc: number of NNLS workspaces with a fixed number of columns to pre-allocate
Throws
ArgumentError: if any of moment powers is negative
Merzbild.NNLSMerge — Method
NNLSMerge(multi_index_moments, init_np; rate_preserving=false, multi_index_moments_pos=[], matrix_ncol_nprealloc=0)Create NNLS-based merging for particles with a 3-dimensional position vector. Mass, momentum, directional energy are always conserved: if not in the list multi_index_moments of moments to preserve, the corresponding moment multi-indices will be added automatically. These indices are (0,0,0) for mass, (1,0,0), (0,1,0), (0,0,1) for momentum, and (2,0,0), (0,2,0), (0,0,2) for directional energies. Spatial moments can be preserved by setting multi_index_moments_pos. If multi_index_moments_pos is non-empty, it is currently left to the user to include any relevant 1st order moments (corresponding center of mass conservation) i.e. (1, 0, 0), (0, 1, 0), (0, 0, 1); otherwise the corresponding spatial moments including higher-order ones will not be conserved. By default, a single NNLSWorkspace is pre-allocated for the system. The number of columns in the LHS matrix is the number of particles to be merged (+ any fictitious particles); so it cannot be fixed in advance. By setting matrix_ncol_nprealloc to a value larger than 0, one can pre-allocate a range of workspaces with a fixed number of columns spanning [init_np, init_np+matrix_ncol_nprealloc]. In this case, matrix_ncol_nprealloc+2 NNLSWorkspace instances are pre-allocated, with the last one being used in case the number of columns is not in the range (its LHS matrix is then re-allocated on the fly, but only when the number of columns differs from the previous call). Vectors column_norms and vel_pos_matrices are also then pre-allocated, holding respectively the inverses of the column-wise norms of the LHS matrices used for their scaling, and the particle velocities and positions. Outside the pre-allocated range the column_norms_scratch / vel_pos_matrix_scratch buffers are used instead; these grow as needed and are re-used across calls.
Positional arguments
multi_index_moments: vector of mixed moments to preserve of the form[(i1, j1, k1), (i2, j2, k2), ...]`init_np: assumption on pre-merge number of particles to pre-allocate memory for
Keyword arguments:
rate_preserving: used for rate-preserving merging of electrons, preserves approximate elastic collision and ionization ratesmulti_index_moments_pos: list of spatial moments to preservematrix_ncol_nprealloc: number of NNLS workspaces with a fixed number of columns to pre-allocate
Throws
ArgumentError: if any of moment powers is negative
Merzbild.compute_multi_index_moments — Function
compute_multi_index_moments(n)Compute all mixed moment multi-indices of total order up to n, i.e. all 3-tuples (i,j,k)such thati+j+k <= n`.
Positional arguments
n: maximum total order
Returns
Vector of 3-tuples of moment multi-indices.
Merzbild.merge_nnls_based! — Function
merge_nnls_based!(rng, nnls_merging::NNLSMerge{D}, particles::ParticleVector{D}, pia, cell, species;
vref=1.0, scaling=:variance,
max_err=1e-11, iteration_mult=2, w_threshold=0.0) where DPerform NNLS-based merging. The NNLS system is scaled to improve numerical stability, the scaling algorithm is set by the scaling parameter. Even if scaling is done using the computed variances, vref might be used in case those variances are small.
Positional arguments
rng: the random number generator instancennls_merging: theNNLSMergeinstanceparticles: theParticleVectorinstance containing the particles to be mergedpia: theParticleIndexerArrayinstancecell: the index of the grid cell in which particles are being mergedspecies: the index of the species being merged
Keyword arguments
vref: the reference velocity used to scale the velocitiesscaling: how to scale entries in the LHS and RHS of the NNLS system - either based on the reference velocityvref(scaling=:vref) or on the computed variances in each direction (scaling=:variance)max_err: maximum allowed value of the residual of the NNLS systemiteration_mult: the number by which the number of columns of the NNLS system matrix is multiplied, this gives the maximum number of iterations of the NNLS algorithmw_threshold: any particles with a relative weight smaller than this value will be discarded (and the weight of the remaining particles re-scaled)
Returns
If the residual exceeds max_err or the number of non-zero (or smaller than w_threshold) elements in the solution vector is equal to the original number of particles, -1 is returned to signify a failure of the merging algorithm.
References
- G. Oblapenko, M. Torrilhon, Moment-preserving particle merging via non-negative least squares. arXiv preprint, 2026.
Merzbild.merge_nnls_based_rate_preserving! — Function
merge_nnls_based_rate_preserving!(rng, nnls_merging::NNLSMerge{D},
interaction, electron_neutral_interactions, computed_cs,
particles::ParticleVector{D}, pia, cell, species, neutral_species_index,
ref_cs_elastic, ref_cs_ion; scaling=:variance,
vref=1.0, max_err=1e-11,
iteration_mult=2,
extend::CSExtend=CSExtendConstant) where DPerform NNLS-based merging of electrons that conserves approximate elastic scattering and electron-impact ionization rates. The NNLS system is scaled to improve numerical stability, the scaling algorithm is set by the scaling parameter. Even if scaling is done using the computed variances, vref might be used in case those variances are small.
The reference velocity is also used in conjunction with the reference cross-sections to scale the parts of the NNLS matrix and RHS corresponding to conservation of electron-neutral collision rates. The reference rate is computed as $\sigma_{r,ref} v_{ref}$, where $\sigma_{r,ref}$ is the reference process cross-section. In case scaling==:variance, the reference velocity for the computation of reference rates is computed as $v_{ref} = \sqrt{E_x^2 + E_y^2 + E_z^2}$, where $E_x$, $E_y$, $E_z$ are the variances of the velocity in the corresponding directions.
Positional arguments
rng: the random number generator instancennls_merging: theNNLSMergeinstanceinteraction: theInteractioninstance describing the electron-neutral interaction being consideredelectron_neutral_interactions: theElectronNeutralInteractionsinstance storing the tabulated cross-section data used to compute the ratescomputed_cs: the vector ofComputedCrossSectioninstances in which the computed values will be storedparticles: theParticleVectorinstance containing the particles to be mergedpia: theParticleIndexerArrayinstancecell: the index of the grid cell in which particles are being mergedspecies: the index of the species being mergedneutral_species_index: the index of the neutral species which is the collision partner in the electron-neutral collisions for which approximate rates are being preserved.ref_cs_elastic: the reference elastic scattering cross-section used to scale the ratesref_cs_ion: the reference electron-impact ionization cross-section used to scale the rates
Keyword arguments
vref: the reference velocity used to scale the velocities in the case ofscaling=:vrefscaling: how to scale entries in the LHS and RHS of the NNLS system - either based on the reference velocityvref(scaling=:vref) or on the computed variances in each direction (scaling=:variance)max_err: maximum allowed value of the residual of the NNLS systemiteration_mult: the number by which the number of columns of the NNLS system matrix is multiplied, this gives the maximum number of iterations of the NNLS algorithmw_threshold: any particles with a relative weight smaller than this value will be discarded (and the weight of the remaining particles re-scaled)extend: enum ofCSExtendtype that sets how out-of-range energy values are treated when computing cross-sections
Returns
If the residual exceeds max_err or the number of non-zero (or smaller than w_threshold) elements in the solution vector is equal to the original number of particles, -1 is returned to signify a failure of the merging algorithm.
References
- G. Oblapenko, M. Torrilhon, Moment-preserving particle merging via non-negative least squares. arXiv preprint, 2026.
merge_nnls_based_rate_preserving!(rng, nnls_merging::NNLSMerge{D},
interaction, electron_neutral_interactions, computed_cs,
particles::ParticleVector{D}, particles_neutral::ParticleVector{D}, pia, cell, species, neutral_species_index,
ref_cs_elastic, ref_cs_ion; vref=1.0, scaling=:variance,
max_err=1e-11,
iteration_mult=2, w_threshold=0.0,
extend::CSExtend=CSExtendConstant) where DPerform NNLS-based merging of electrons that conserves exact elastic scattering and electron-impact ionization rates for one specific neutral species. The NNLS system is scaled to improve numerical stability, the scaling algorithm is set by the scaling parameter. Even if scaling is done using the computed variances, vref might be used in case those variances are small.
The reference velocity is also used in conjunction with the reference cross-sections to scale the parts of the NNLS matrix and RHS corresponding to conservation of electron-neutral collision rates. The reference rate is computed as $\sigma_{r,ref} v_{ref}$, where $\sigma_{r,ref}$ is the reference process cross-section. In case scaling==:variance, the reference velocity for the computation of reference rates is computed as $v_{ref} = \sqrt{E_x^2 + E_y^2 + E_z^2}$, where $E_x$, $E_y$, $E_z$ are the variances of the velocity in the corresponding directions.
Positional arguments
rng: the random number generator instancennls_merging: theNNLSMergeinstanceinteraction: theInteractioninstance describing the electron-neutral interaction being consideredelectron_neutral_interactions: theElectronNeutralInteractionsinstance storing the tabulated cross-section data used to compute the ratescomputed_cs: the vector ofComputedCrossSectioninstances in which the computed values will be storedparticles: theParticleVectorinstance containing the particles to be mergedparticles_neutral: theParticleVectorinstance containing the neutral collision partner particles (they are not affected by the merge)pia: theParticleIndexerArrayinstancecell: the index of the grid cell in which particles are being mergedspecies: the index of the species being mergedneutral_species_index: the index of the neutral species which is the collision partner in the electron-neutral collisions for which approximate rates are being preserved.ref_cs_elastic: the reference elastic scattering cross-section used to scale the ratesref_cs_ion: the reference electron-impact ionization cross-section used to scale the rates
Keyword arguments
vref: the reference velocity used to scale the velocities in the case ofscaling=:vrefscaling: how to scale entries in the LHS and RHS of the NNLS system - either based on the reference velocityvref(scaling=:vref) or on the computed variances in each direction (scaling=:variance)max_err: maximum allowed value of the residual of the NNLS systemiteration_mult: the number by which the number of columns of the NNLS system matrix is multiplied, this gives the maximum number of iterations of the NNLS algorithmw_threshold: any particles with a relative weight smaller than this value will be discarded (and the weight of the remaining particles re-scaled)extend: enum ofCSExtendtype that sets how out-of-range energy values are treated when computing cross-sections
Returns
If the residual exceeds max_err or the number of non-zero (or smaller than w_threshold) elements in the solution vector is equal to the original number of particles, -1 is returned to signify a failure of the merging algorithm.
References
- G. Oblapenko, M. Torrilhon, Moment-preserving particle merging via non-negative least squares. arXiv preprint, 2026.
Octree merging
Merzbild.OctreeBinSplit — Type
OctreeBinSplit OctreeBinMidSplit=1 OctreeBinMeanSplit=2 OctreeBinMedianSplit=3Enum defining how the velocity along which the bin is split is chosen.
Possible values:
OctreeBinMidSplit: the bin is split along the middle velocityOctreeBinMeanSplit: the bin is split along the mean velocity of the particles in the binOctreeBinMedianSplit: the bin is split along the median velocity of the particles in the bin
Merzbild.OctreeInitBin — Type
OctreeInitBin OctreeInitBinMinMaxVel=1 OctreeInitBinMinMaxVelSym=2 OctreeInitBinC=3Enum defining how the bounds of the initial bin are computed.
Possible values:
OctreeInitBinMinMaxVel: the minimum and maximum velocities of the particles being merged are used to compute the boundsOctreeInitBinMinMaxVelSym: the minimum and maximum velocities of the particles being merged are used to compute the bounds, but the bounds are then symmetrized in each velocity direction:[-max(abs(min_v), abs(max_v)), max(abs(min_v), abs(max_v))]OctreeInitBinC: the initial bounds are set to[-c, c]in each direction, wherec`` speed of light
Merzbild.OctreeBinBounds — Type
OctreeBinBounds OctreeBinBoundsInherit=1 OctreeBinBoundsRecompute=2Enum defining how the bounds of a split sub-octant bin are computed.
Possible values:
OctreeBinBoundsInherit: the splitting velocity and the appropriate bounds of the parent bin are inheritedOctreeBinBoundsRecompute: the bounds are recomputed based on the particles in the bin
Merzbild.OctreeMerge — Type
OctreeMerge{D,M}Struct for N:M Octree merging for particles with D-dimensional position vectors.
Fields
max_Nbins: maximum possible number of binsNbins: number of bins currently usedbins: Vector ofOctreeCellinstances used to compute the properties required for bin refinementfull_bins: Vector ofOctreeFullCell{D,M}instances used to compute the post-merge particles in each binn_particles: total number of particles being mergedbin_start: denotes start of indices of particles in biniin theparticle_indexes_sortedarraybin_end: denotes end of indices of particles in biniin theparticle_indexes_sortedarrayparticle_indexes_sorted: Vector of particle indices of the particles being mergedparticle_octants: Vector of particle octants for each particle used during radix sortparticles_sort_output: Vector of integer indices used to store particle indices during radix sortparticle_in_bin_counter:MVectorof size 8, stores the number of particles in each binnonempty_counter:MVectorof size 8, stores the number of particles in each non-empty bin (the octants to which these bins correspond to are innonempty_bins)nonempty_bins:MVectorof size 8, a sequential list of non-empty octantsndens_counter:MVectorof size 8, used in bin splitting, stores number density in each (non-empty) binbin_bounds_compute: enum ofOctreeBinBoundstype defining whether bin bounds are fully defined by the parent bin and splitting velocity (vel_middle), or whether they are recomputed for each new sub-octant binsplit: enum ofOctreeBinSplittype defining how bins are splitvel_middle: used to store the velocity along which a bin is split into octantsv_min_parent: used in bin splitting to store the vector of the per-component lower bounds of the velocities in the cellv_max_parent: used in bin splitting to store the vector of the per-component upper bounds of the velocities in the celldirection_vec3: used to store randomly sampled direction signs, of length 3direction_vecD: used to store randomly sampled direction signs, of length Dinit_bin_bounds: enum ofOctreeInitBintype defining how the bounds of the top-level bin are setmax_depth: maximum allowed depth of a bintotal_post_merge_np: used to keep track of number of post-merge particlesv_mean: used to store mean velocity for conservative N:1 mergingx_mean: used to store mean position for conservative N:1 mergingv_var_before: used to store pre-merge variance of velocity for conservative N:1 mergingx_var_before: used to store pre-merge variance of position for conservative N:1 mergingv_mean_post: used to store post-merge mean velocity for conservative N:1 mergingx_mean_post: used to store post-merge mean position for conservative N:1 mergingv_var_post: used to store post-merge variance of velocity for conservative N:1 mergingx_var_post: used to store post-merge variance of position for conservative N:1 merging
Merzbild.OctreeMerge — Method
OctreeMerge{D,M}(split::OctreeBinSplit; init_bin_bounds=OctreeInitBinMinMaxVel, bin_bounds_compute=OctreeBinBoundsInherit,
max_Nbins=4096, max_depth=10)Create an Octree N:M merging instance for particles with D-dimensional position vectors.
Positional arguments:
split: a enum ofOctreeBinSplittype which tells how to split a bin into sub-bins
Keyword arguments:
init_bin_bounds: a enum ofOctreeInitBintype which defines how the bounds of the top-level bin are setbin_bounds_compute: a enum ofOctreeBinBoundstype which defines whether the bounds of sub-bins are recomputed based on the minimum/maximum velocities of the particles in those sub-bins, or the bounds are inherited from the bin that was splitmax_Nbins: maximum number of bins allowed (this only counts leaf-level bins)max_depth: maximum depth of a sub-bin starting from the top-level bin containing all particles (which has a depth of 0)
Returns: OctreeMerge instance with everything set to 0.
Merzbild.OctreeMerge — Method
OctreeMerge(split::OctreeBinSplit; init_bin_bounds=OctreeInitBinMinMaxVel, bin_bounds_compute=OctreeBinBoundsInherit,
max_Nbins=4096, max_depth=10)Create an Octree N:2 merging instance for particles with 3-dimensional position vectors.
Positional arguments:
split: a enum ofOctreeBinSplittype which tells how to split a bin into sub-bins
Keyword arguments:
init_bin_bounds: a enum ofOctreeInitBintype which defines how the bounds of the top-level bin are setbin_bounds_compute: a enum ofOctreeBinBoundstype which defines whether the bounds of sub-bins are recomputed based on the minimum/maximum velocities of the particles in those sub-bins, or the bounds are inherited from the bin that was splitmax_Nbins: maximum number of bins allowed (this only counts leaf-level bins)max_depth: maximum depth of a sub-bin starting from the top-level bin containing all particles (which has a depth of 0)
Returns: OctreeMerge instance with everything set to 0.
Merzbild.merge_octree! — Function
merge_octree!(rng, octree::OctreeMerge{D,M}, particles::ParticleVector{D}, pia, cell, species, target_np) where {D,M}Perform octree N:M merging without checking whether particle positions end up outside of the simulation domain.
Positional arguments
rng: the random number generator instanceoctree: theOctreeMergeinstanceparticles: theParticleVectorinstance containing the particles to be mergedpia: theParticleIndexerArrayinstancecell: the index of the grid cell in which particles are being mergedspecies: the index of the species being mergedtarget_np: the target post-merge number of particles; the post-merge number of particles will not exceed this value but may be not exactly equal to it
References
- R.S. Martin, J.-L. Cambier, Octree particle management for DSMC and PIC simulations. J. Comput. Phys., 2016.
merge_octree!(rng, octree::OctreeMerge{D,M}, particles::ParticleVector{D}, pia, cell, species, target_np, grid::Grid1DUniform) where {D,M}Perform octree N:M merging, checking whether particle positions end up outside of the simulation domain, and placing them back into the domain if needed.
Positional arguments
rng: the random number generator instanceoctree: theOctreeMergeinstanceparticles: theParticleVectorinstance containing the particles to be mergedpia: theParticleIndexerArrayinstancecell: the index of the grid cell in which particles are being mergedspecies: the index of the species being mergedtarget_np: the target post-merge number of particles; the post-merge number of particles will not exceed this value but may be not exactly equal to itgrid: theGrid1DUniformgridR.S. Martin, J.-L. Cambier, Octree particle management for DSMC and PIC simulations. J. Comput. Phys., 2016.
Roulette merging
Merzbild.merge_roulette! — Function
merge_roulette!(rng, particles::ParticleVector{D}, pia, cell, species, target_np) where DPerform roulette merging - delete random particles until target number of particles is reached, and re-weight remaining particles to conserve number density.
Positional arguments
rng: the random number generator instanceparticles: theParticleVectorinstance containing the particles to be mergedpia: theParticleIndexerArrayinstancecell: the index of the grid cell in which particles are being mergedspecies: the index of the species being mergedtarget_np: the target post-merge number of particles
Keyword arguments
conservative: iftrue, the post-merge particles' velocities will be corrected to ensure conservation of momentum and energy
References
- J. Watrous, D.B. Seidel, C.H. Moore, W. McDoniel, Improvements to Particle Merge Algorithms for Sandia National Laboratories Plasma Physics Modeling Code, EMPIRE. Presentation, 2023.
Grids and particle sorting
Merzbild.AbstractGrid — Type
AbstractGridAbstract grid type
Merzbild.Grid1DUniform — Type
Grid1DUniform1-D Uniform grid for a domain $[0,L]$
Fields
L: length of the domainn_cells: number of cellsΔx: cell sizeinv_Δx: inverse of cell sizecells:VectorofCell1Delementsmin_x: minimum allowedxcoordinate for particles (slightly larger than $0$)max_x: maximum allowedxcoordinate for particles (slightly smaller than $L$)surface_normals: vector of surface normals (1st element corresponds to the left wall, 2nd to the right wall)
Merzbild.Grid1DUniform — Method
Grid1DUniform(L, nx; wall_offset=1e-12)Create 1-D uniform grid for a domain $[0, L]$ with nx cells
Positional arguments
L: length of the domainnx: number of cells
Keyword arguments
wall_offset: specifies a small relative offset from the walls so that particles never end up with a coordinate of exactly $0$ or $L$, otherwise some sorting routines may produce cell indices outside of the1:nxrange. The offset is computed asΔx * wall_offset, whereΔxis the cell size.
Merzbild.GridSortInPlace — Type
GridSortInPlaceStruct for in-place sorting of particles.
The occ_lo/occ_hi fields record the first and last cell holding particles, as recorded by the most recent sorting call performed with this instance, to be used for multi-threaded simulations with particle exchange between threads. They describe that call only, and are meant to be consumed right after it, by update_occupancy_bounds!; a GridSortInPlace shared between species or ParticleIndexerArray instances therefore holds the bounds of whichever was sorted last. They are 1/n_cells before the first sort.
Fields
cell_counts: scratch vector used to count the number of particles in each cell and to compute the resulting offsetssorted_indices: vector to store sorted particle indicesocc_lo: first cell holding particles during the last sortocc_hi: last cell holding particles during the last sort
Merzbild.GridSortInPlace — Method
GridSortInPlace(n_cells::Integer, n_particles::Integer)Create a GridSortInPlace instance given a number of grid cells and number of particles.
Positional arguments
n_cells: the number of grid cellsn_particles: the (expected) number of particles in the simulation (to pre-allocate thesorted_indicesvector) - it is recommended to set this to the maximum expected number of particles in the simulation to avoid resizing of arrays during a simulation
Merzbild.GridSortInPlace — Method
GridSortInPlace(grid::G, n_particles::Integer) where {G<:AbstractGrid}Create a GridSortInPlace instance given a grid and number of particles.
Positional arguments
grid: the grid on which to sort the particlesn_particles: the (expected) number of particles in the simulation (to pre-allocate thesorted_indicesvector) - it is recommended to set this to the maximum expected number of particles in the simulation to avoid resizing of arrays during a simulation
Merzbild.sort_particles! — Function
sort_particles!(gridsort::GridSortInPlace, grid, particles::ParticleVector{D}, pia, species) where DSort particles on a grid using an in-place sorting algorithm. The pia instance is allowed to have non-contiguous indices (arising for example from merging). This function assumes that at the start of the sorting, it is not known in which cell each particle is located, and therefore the cell for each particle has to be determined (by calling get_cell).
The first and last cell holding particles are recorded in the GridSortInPlace instance, for use in update_occupancy_bounds!.
Positional arguments
gridsort: theGridSortInPlacestructuregrid: the grid (should have ann_cellsfield, and aget_cellfunction has to be defined for the grid type)particles: theParticleVectorof particles to be sortedpia: theParticleIndexerArrayinstancespecies: the index of the species being sorted
sort_particles!(gridsort::GridSortInPlace, particles, pia, species)Sort particles on a grid using an in-place sorting algorithm. The pia instance is allowed to have non-contiguous indices (arising for example from merging). This function assumes that at the start of the sorting, it is known in which cell each particle is located.
The first and last cell holding particles are recorded in the GridSortInPlace instance, for use in update_occupancy_bounds!.
Positional arguments
gridsort: theGridSortInPlacestructureparticles: theParticleVectorof particles to be sortedpia: theParticleIndexerArrayinstancespecies: the index of the species being sorted
Particle movement
Merzbild.convect_particles! — Function
convect_particles!(rng, grid::Grid1DUniform, bc_list, particles::ParticleVector{D}, pia, species, species_data, Δt) where DConvect particles on a 1-D uniform grid.
Positional arguments
rng: the random number generatorgrid: the grid on which the convection is performedbc_list: theTupleof boundary conditions (left and right wall)particles: theParticleVectorof particles to be convectedpia: theParticleIndexerArrayinstancespecies: the index of the species being convectedspecies_data: the vector ofSpeciesdataΔt: the convection timestep
convect_particles!(rng, grid::Grid1DUniform, bc_list, surf_props::SurfProps, particles::ParticleVector{D}, pia, species, species_data, Δt) where DConvect particles on a 1-D uniform grid, computing surface properties if particles hit a surface.
Positional arguments
rng: the random number generatorgrid: the grid on which the convection is performedbc_list: theTupleof boundary conditions (left and right wall)particles: theParticleVectorof particles to be convectedpia: theParticleIndexerArrayinstancespecies: the index of the species being convectedspecies_data: the vector ofSpeciesdatasurf_props: theSurfPropsstruct where the computed surface properties will be storedΔt: the convection timestep
Merzbild.convect_particles_periodic! — Function
convect_particles_periodic!(grid::Grid1DUniform, particles::ParticleVector{D}, pia, species, Δt) where DConvect particles on a 1-D uniform grid assuming a periodic grid.
Positional arguments
grid: the grid on which the convection is performedparticles: theParticleVectorof particles to be convectedpia: theParticleIndexerArrayinstancespecies: the index of the species being convectedΔt: the convection timestep
Merzbild.convect_particles_and_compute_cell! — Function
convect_particles_and_compute_cell!(rng, grid::Grid1DUniform, bc_list, particles::ParticleVector{D}, pia, species, species_data, Δt) where DConvect particles on a 1-D uniform grid and write post-convection cell index to particles.cell.
Positional arguments
rng: the random number generatorgrid: the grid on which the convection is performedbc_list: theTupleof boundary conditions (left and right wall)particles: theParticleVectorof particles to be convectedpia: theParticleIndexerArrayinstancespecies: the index of the species being convectedspecies_data: the vector ofSpeciesdataΔt: the convection timestep
convect_particles_and_compute_cell!(rng, grid::Grid1DUniform, bc_list, surf_props::SurfProps, particles::ParticleVector{D}, pia, species, species_data, Δt) where DConvect particles on a 1-D uniform grid and write post-convection cell index to particles.cell, computing surface properties if particles hit a surface.
Positional arguments
rng: the random number generatorgrid: the grid on which the convection is performedbc_list: theTupleof boundary conditions (left and right wall)particles: theParticleVectorof particles to be convectedpia: theParticleIndexerArrayinstancespecies: the index of the species being convectedspecies_data: the vector ofSpeciesdatasurf_props: theSurfPropsstruct where the computed surface properties will be storedΔt: the convection timestep
Merzbild.convect_particles_and_compute_cell_periodic! — Function
convect_particles_and_compute_cell_periodic!(grid::Grid1DUniform, particles::ParticleVector{D}, pia, species, Δt) where DConvect particles on a 1-D uniform grid and write post-convection cell index to particles.cell assuming a periodic grid.
Positional arguments
grid: the grid on which the convection is performedparticles: theParticleVectorof particles to be convectedpia: theParticleIndexerArrayinstancespecies: the index of the species being convectedΔt: the convection timestep
Particle-surface interactions
Merzbild.MaxwellWallBC1D — Type
MaxwellWallBC1D <: AbstractBCA struct to hold information about a Maxwell reflecting wall (mixture of specular and diffuse scattering) orthogonal to the x-axis. This is species-specific, as reflection_velocity_sq is dependent on the species' mass.
Fields
T: temperaturev: wall velocity vectoraccommodation: accommodation coefficient (a value of 0 corresponds to specular reflection, a value of 1 corresponds to purely diffuse reflection) - these are implemented in separate more efficient functions as wellreflection_velocity_sq: pre-computed squared thermal reflection velocity
Merzbild.MaxwellWallBC1D — Method
MaxwellWallBC1D(species, species_data, T::Float64, v, accommodation::Float64)Construct a MaxwellWallBC1D instance for a given species.
Positional arguments
species: index of the species for which to create the BCspecies_data: the list ofSpeciesdataT: wall temperaturev: wall velocity vectoraccommodation: accommodation coefficient
Merzbild.FullyDiffuseBC1D — Type
FullyDiffuseBC1D <: AbstractBCA struct to hold information about a fully diffuse reflecting wall orthogonal to the x-axis. This is species-specific, as reflection_velocity_sq is dependent on the species' mass.
Fields
T: temperaturev: wall velocity vectorreflection_velocity_sq: pre-computed squared thermal reflection velocities
Merzbild.FullyDiffuseBC1D — Method
FullyDiffuseBC1D(species, species_data, T::Float64, v)Construct a FullyDiffuseBC1D instance for a given species.
Positional arguments
species: index of the species for which to create the BCspecies_data: the list ofSpeciesdataT: wall temperaturev: wall velocity vector
Merzbild.FullySpecularBC1D — Type
FullyDiffuseBC1D <: AbstractBCA struct to hold information about a fully specularly reflecting wall orthogonal to the x-axis. Since such reflection simply flips the sign of the particle's x-velocity, no data is stored in the struct.
I/O
Merzbild.write_grid — Function
write_grid(nc_filename, grid::Grid1DUniform; global_attributes=Dict{Any,Any}())Write grid info to a NetCDF file
Positional arguments
nc_filename: path to the NetCDF filegrid: the grid to be written out to a file
Keyword arguments
global_attributes: dictionary of additional global attributes to be written to the netCDF file
Merzbild.IOSkipList — Type
IOSkipListStruct that holds track of which variables are not to be written to NetCDF file for physical properties computed on a grid. If the field value is true, the corresponding physical grid property will not be output to the file.
Fields
skip_length_particle_array: whether the length of the particle array should be skippedskip_number_of_particles: whether the output of the number of particles should be skippedskip_number_density: whether the output of the number density/number of physical particles should be skippedskip_velocity: whether the output of the velocity should be skippedskip_temperature: whether the output of the temperature should be skipped
Merzbild.IOSkipList — Method
IOSkipList(list_of_variables_to_skip)Construct an IOSkipList from a list of variable names. The possible names are: length_particle_array, np or nparticles, ndens, v, T.
Positional arguments
list_of_variables_to_skip: list of variable names to skip
Merzbild.IOSkipList — Method
IOSkipList()Construct an empty IOSkipList.
Merzbild.IOSkipListSurf — Type
IOSkipListSurfStruct that holds track of which variables are not to be written to NetCDF file for computed surface properties. If the field value is true, the corresponding surface property will not be output to the file.
Fields
skip_number_of_particles: whether the output of the number of particles should be skippedskip_fluxes: whether the output of the incident/reflected fluxes should be skippedskip_force: whether the output of the force should be skippedskip_normal_pressure: whether the output of the normal pressure should be skippedskip_shear_pressure: whether the output of the shear pressure should be skippedskip_kinetic_energy_flux: whether the output of the kinetic energy flux should be skipped
Merzbild.IOSkipListSurf — Method
IOSkipListSurf(list_of_variables_to_skip)Construct an IOSkipListSurf from a list of variable names. The possible names are: np or nparticles, fluxes, force, normal_pressure, shear_pressure, kinetic_energy_flux.
Positional arguments
list_of_variables_to_skip: list of variable names to skip
Merzbild.IOSkipListSurf — Method
IOSkipListSurf()Construct an empty IOSkipListSurf
Merzbild.IOSkipListFlux — Type
IOSkipListFluxStruct that holds track of which variables are not to be written to NetCDF file for computed fluxes. If the field value is true, the corresponding flux will not be output to the file.
Fields
skip_kinetic_energy_flux: whether the output of the kinetic energy flux should be skippedskip_diagonal_momentum_flux: whether the output of the diagonal components of the momentum flux tensor should be skippedskip_off_diagonal_momentum_flux: whether the output of the off-diagonal components of the momentum flux tensor should be skipped
Merzbild.IOSkipListFlux — Method
IOSkipListFlux(list_of_variables_to_skip)Construct an IOSkipListFlux from a list of variable names. The possible names are: kinetic_energy_flux, diagonal_momentum_flux, off_diagonal_momentum_flux.
Positional arguments
list_of_variables_to_skip: list of variable names to skip
Merzbild.IOSkipListFlux — Method
IOSkipListFlux()Construct an empty IOSkipListFlux
Merzbild.IOSkipListField — Type
IOSkipListFieldStruct that holds track of which variables are not to be written to NetCDF file for the electrostatic field quantities computed on the nodes of a grid. If the field value is true, the corresponding field quantity will not be output to the file.
Fields
skip_charge_density: whether the output of the charge density should be skippedskip_potential: whether the output of the electrostatic potential should be skippedskip_electric_field: whether the output of the electric field should be skipped
Merzbild.IOSkipListField — Method
IOSkipListField(list_of_variables_to_skip)Construct an IOSkipListField from a list of variable names. The possible names are: rho or charge_density, phi or potential, E or electric_field.
Positional arguments
list_of_variables_to_skip: list of variable names to skip
Merzbild.IOSkipListField — Method
IOSkipListField()Construct an empty IOSkipListField.
Merzbild.NCDataHolder — Type
NCDataHolder <: AbstractNCDataHolderStruct that holds NetCDF-output related data for physical properties (grid properties) I/O.
Fields
filehandle: handle to the open NetCDF filendens_not_Np: whether the number density or the number of physical particles is being outputtimestep_dim: timestep dimension that used to keep track of the number of output stepsv_timestep: variable to hold the simulation timestep number (dimensiontime)v_lpa: variable to hold lengths of particle arrays (dimensionn_species x time)v_np: variable to hold number of particles (dimensionn_cells x n_species x time)v_ndens: variable to hold number density or the number of physical particles (dimensionn_cells x n_species x time)v_v: variable to hold velocity (dimension3 x n_cells x n_species x time)v_T: variable to hold temperature (dimensionn_cells x n_species x time)n_species_1: constant vector[n_species, 1](used for offsets during I/O)n_cells_n_species_1: constant vector[n_cells, n_species, 1](used for offsets during I/O)n_v_n_cells_n_species_1: constant vector[3, n_cells, n_species, 1](used for offsets during I/O)currtimesteps: vector[n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)currtimesteps_1: vector[1, n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)currtimesteps_1_1: vector[1, 1, n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)currtimesteps_1_1_1: vector[1, 1, 1, n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)timestep: vector storing the current simulation timestepskip_list:IOSkipListinstance of variables to skip during output
Merzbild.NCDataHolder — Method
NCDataHolder(nc_filename, names_skip_list, species_data, phys_props; global_attributes=Dict{Any,Any}(), mode=NC_64BIT_OFFSET)Construct a NCDataHolder instance with a list of variables to skip.
Positional arguments
nc_filename: filename to write output tonames_skip_list: list of variable names to skip, seeIOSkipListfor more detailsspecies_data: the vector ofSpeciesdata for the species in the simulationphys_props: thePhysPropsinstance which will be used for the computation and output of physical properties
Keyword arguments
global_attributes: dictionary of any additional attributes to write to the netCDF file as a global attributemode: NetCDF file format mode (default:NC_64BIT_OFFSETfor older and faster format, can useNC_NETCDF4for NetCDF4 format)
Merzbild.NCDataHolder — Method
NCDataHolder(nc_filename, species_data, phys_props; global_attributes=Dict{Any,Any}(), mode=NC_64BIT_OFFSET)Construct a NCDataHolder instance with an empty list of variable to skip,
Positional arguments
nc_filename: filename to write output tospecies_data: the vector ofSpeciesdata for the species in the simulationphys_props: thePhysPropsinstance which will be used for the computation and output of physical properties
Keyword arguments
global_attributes: dictionary of any additional attributes to write to the netCDF file as a global attributemode: NetCDF file format mode (default:NC_64BIT_OFFSETfor older and faster format, can useNC_NETCDF4for NetCDF4 format)
Merzbild.NCDataHolderSurf — Type
NCDataHolderSurfStruct that holds NetCDF-output related data for surface properties I/O.
Fields
filehandle: handle to the open NetCDF filetimestep_dim: timestep dimension that used to keep track of the number of output stepsv_timestep: variable to hold the simulation timestep number (dimensiontime)v_np: variable to hold number of particles that hit the surface (dimensionn_elements x n_species x time)v_flux_incident: variable to hold incident mass flux (dimensionn_elements x n_species x time)v_flux_reflected: variable to hold reflected mass flux (dimensionn_elements x n_species x time)v_force: variable to hold force (dimension3 x n_elements x n_species x time)v_normal_pressure: variable to hold normal pressure (dimensionn_elements x n_species x time)v_shear_pressure: variable to hold shear pressure (dimension3 x n_elements x n_species x time)v_kinetic_energy_flux: variable to hold kinetic energy flux (dimensionn_elements x n_species x time)n_species_1: constant vector[n_species, 1](used for offsets during I/O)n_elements_n_species_1: constant vector[n_elements, n_species, 1](used for offsets during I/O)n_v_n_elements_n_species_1: constant vector[3, n_elements, n_species, 1](used for offsets during I/O)currtimesteps: vector[n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)currtimesteps_1: vector[1, n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)currtimesteps_1_1: vector[1, 1, n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)currtimesteps_1_1_1: vector[1, 1, 1, n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)timestep: vector storing the current simulation timestepskip_list:IOSkipListSurfinstance of variables to skip during output
Merzbild.NCDataHolderSurf — Method
NCDataHolderSurf(nc_filename, names_skip_list, species_data, surf_props; global_attributes=Dict{Any,Any}(), mode=NC_64BIT_OFFSET)Construct a NCDataHolderSurf instance with a list of variables to skip.
Positional arguments
nc_filename: filename to write output tonames_skip_list: list of variable names to skip, seeIOSkipListSurffor more detailsspecies_data: the vector ofSpeciesdata for the species in the simulationsurf_props: theSurfPropsinstance which will be used for the computation and output of surface properties
Keyword arguments
global_attributes: dictionary of any additional attributes to write to the netCDF file as a global attributemode: NetCDF file format mode (default:NC_64BIT_OFFSETfor older and faster format, can useNC_NETCDF4for NetCDF4 format)
Merzbild.NCDataHolderSurf — Method
NCDataHolderSurf(nc_filename, species_data, surf_props; global_attributes=Dict{Any,Any}(), mode=NC_64BIT_OFFSET)Construct a NCDataHolderSurf instance with an empty list of variable to skip.
Positional arguments
Positional arguments
nc_filename: filename to write output tospecies_data: the vector ofSpeciesdata for the species in the simulationsurf_props: theSurfPropsinstance which will be used for the computation and output of surface properties
Keyword arguments
global_attributes: dictionary of any additional attributes to write to the netCDF file as a global attributemode: NetCDF file format mode (default:NC_64BIT_OFFSETfor older and faster format, can useNC_NETCDF4for NetCDF4 format)
Merzbild.NCDataHolderFlux — Type
NCDataHolderFluxStruct that holds NetCDF-output related data for fluxes I/O.
Fields
filehandle: handle to the open NetCDF filetimestep_dim: timestep dimension that used to keep track of the number of output stepsv_timestep: variable to hold the simulation timestep number (dimensiontime)v_kinetic_energy_flux: variable to hold kinetic energy flux (dimension3 x n_elements x n_species x time)v_diagonal_momentum_flux: variable to the diagonal components of the momentum flux tensor (dimension3 x n_elements x n_species x time)v_off_diagonal_momentum_flux: variable to the off-diagonal components of the momentum flux tensor (dimension3 x n_elements x n_species x time)n_v_n_elements_n_species_1: constant vector[3, n_elements, n_species, 1](used for offsets during I/O)currtimesteps: vector[n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)currtimesteps_1_1_1: vector[1, 1, 1, n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)timestep: vector storing the current simulation timestepskip_list:IOSkipListFluxinstance of variables to skip during output
Merzbild.NCDataHolderFlux — Method
NCDataHolderFlux(nc_filename, names_skip_list, species_data, flux_props; global_attributes=Dict{Any,Any}(), mode=NC_64BIT_OFFSET)Construct a NCDataHolderFlux instance with a list of variables to skip.
Positional arguments
nc_filename: filename to write output tonames_skip_list: list of variable names to skip, seeIOSkipListSurffor more detailsspecies_data: the vector ofSpeciesdata for the species in the simulationflux_props: theFluxPropsinstance which will be used for the computation and output of fluxes
Keyword arguments
global_attributes: dictionary of any additional attributes to write to the netCDF file as a global attributemode: NetCDF file format mode (default:NC_64BIT_OFFSETfor older and faster format, can useNC_NETCDF4for NetCDF4 format)
Merzbild.NCDataHolderFlux — Method
NCDataHolderFlux(nc_filename, species_data, flux_props; global_attributes=Dict{Any,Any}(), mode=NC_64BIT_OFFSET)Construct a NCDataHolderFlux instance with an empty list of variable to skip.
Positional arguments
Positional arguments
nc_filename: filename to write output tospecies_data: the vector ofSpeciesdata for the species in the simulationflux_props: theFluxPropsinstance which will be used for the computation and output of fluxes
Keyword arguments
global_attributes: dictionary of any additional attributes to write to the netCDF file as a global attributemode: NetCDF file format mode (default:NC_64BIT_OFFSETfor older and faster format, can useNC_NETCDF4for NetCDF4 format)
Merzbild.NCDataHolderMoments — Type
NCDataHolderMoments <: AbstractNCDataHolderStruct that holds NetCDF-output related data for moments I/O.
Fields
filehandle: handle to the open NetCDF filetimestep_dim: timestep dimension that used to keep track of the number of output stepsv_timestep: variable to hold the simulation timestep number (dimensiontime)v_mompows: variable to hold list of total moment powers (dimensionn_moments)v_moments: variable to hold total moments (dimensionn_moments x n_cells x n_species x time)n_moments: number of momentsn_cells: number of cellsn_species: number of speciesn_moments_n_cells_n_species_1: constant vector[n_moments, n_cells, n_species, 1](used for offsets during I/O)currtimesteps: vector[n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)currtimesteps_1_1_1: vector[1, 1, 1, n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)timestep: vector storing the current simulation timestep
Merzbild.NCDataHolderMoments — Method
NCDataHolderMoments(nc_filename, species_data, n_cells, n_species, moment_powers; global_attributes=Dict{Any,Any}(), mode=NC_64BIT_OFFSET)Construct a NCDataHolderMoments instance.
Positional arguments
nc_filename: filename to write output tospecies_data: the vector ofSpeciesdata for the species in the simulationn_cells: number of cellsn_species: number of speciesmoment_powers: vector of moment powers (e.g.,Int8[2, 4, 6])
Keyword arguments
global_attributes: dictionary of any additional attributes to write to the netCDF file as a global attributemode: NetCDF file format mode (default:NC_64BIT_OFFSETfor older and faster format, can useNC_NETCDF4for NetCDF4 format)
Merzbild.NCDataHolderField — Type
NCDataHolderField <: AbstractNCDataHolderStruct that holds NetCDF-output related data for the I/O of the electrostatic field quantities stored in the nodes of a grid.
Fields
filehandle: handle to the open NetCDF filetimestep_dim: timestep dimension that used to keep track of the number of output stepsv_timestep: variable to hold the simulation timestep number (dimensiontime)v_charge_density: variable to hold the charge density (dimensionn_nodes x time)v_potential: variable to hold the electrostatic potential (dimensionn_nodes x time)v_electric_field: variable to hold the x-component of the electric field (dimensionn_nodes x time)n_nodes: number of nodesn_nodes_1: constant vector[n_nodes, 1](used for offsets during I/O)currtimesteps: vector[n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)currtimesteps_1: vector[1, n_t_output], wheren_t_outputis the current output timestep (i.e. how many times the properties have already been output, not the simulation timestep) (used for offsets during I/O)timestep: vector storing the current simulation timestepskip_list:IOSkipListFieldinstance of variables to skip during output
Merzbild.NCDataHolderField — Method
NCDataHolderField(nc_filename, names_skip_list, field_props; global_attributes=Dict{Any,Any}(), mode=NC_64BIT_OFFSET)Construct a NCDataHolderField instance with a list of variables to skip.
Positional arguments
nc_filename: filename to write output tonames_skip_list: list of variable names to skip, seeIOSkipListFieldfor more detailsfield_props: theElectrostaticFieldPropsinstance which will be used for the output of the field quantities
Keyword arguments
global_attributes: dictionary of any additional attributes to write to the netCDF file as a global attributemode: NetCDF file format mode (default:NC_64BIT_OFFSETfor older and faster format,NC_NETCDF4for NetCDF4 format)
Merzbild.NCDataHolderField — Method
NCDataHolderField(nc_filename, field_props; global_attributes=Dict{Any,Any}(), mode=NC_64BIT_OFFSET)Construct a NCDataHolderField instance with an empty list of variables to skip.
Positional arguments
nc_filename: filename to write output tofield_props: theElectrostaticFieldPropsinstance which will be used for the output of the field quantities
Keyword arguments
global_attributes: dictionary of any additional attributes to write to the netCDF file as a global attributemode: NetCDF file format mode (default:NC_64BIT_OFFSETfor older and faster format,NC_NETCDF4for NetCDF4 format)
Merzbild.write_netcdf — Function
write_netcdf(ds, phys_props::PhysProps, timestep; sync_freq=0)Write computed PhysProps to NetCDF file and synchronize file to disk if necessary.
Positional arguments
ds: theNCDataHolderfor the file to which the output will be writtenphys_props: thePhysPropsinstance containing the computed propertiestimestep: the simulation timestep
Keyword arguments
sync_freq: if larger than 0 and if the number of timesteps output is proportional tosync_freq, the data will be synchronized to disk. If set to 1, will sync data to disk at every timestep at which data is written to the file.
Throws
ErrorException if the NCDataHolder expects number density and the phys_props holds the number of physical particles, or vice versa.
write_netcdf(ds, surf_props::SurfProps, timestep; sync_freq=0)Write SurfProps to a NetCDF file and synchronize file to disk if necessary.
Positional arguments
ds: theNCDataHolderSurffor the file to which the output will be writtensurf_props: theSurfPropsinstance containing the computed propertiestimestep: the simulation timestep
Keyword arguments
sync_freq: if larger than 0 and if the number of timesteps output is proportional tosync_freq, the data will be synchronized to disk. If set to 1, will sync data to disk at every timestep at which data is written to the file.
write_netcdf(ds, flux_props::FluxProps, timestep; sync_freq=0)Write FluxProps to a NetCDF file and synchronize file to disk if necessary.
Positional arguments
ds: theNCDataHolderFluxfor the file to which the output will be writtenflux_props: theFluxPropsinstance containing the computed propertiestimestep: the simulation timestep
Keyword arguments
sync_freq: if larger than 0 and if the number of timesteps output is proportional tosync_freq, the data will be synchronized to disk. If set to 1, will sync data to disk at every timestep at which data is written to the file.
write_netcdf(nc_filename, particles::Vector{ParticleVector{D}}, pia, species_data, species_ids; global_attributes=Dict{Any,Any}(), mode=NC_64BIT_OFFSET)Write particles of species listed in species_ids to a NetCDF file. The particles are written cell-wise, so the ordering is not preserved in case particles are present in the set of indices pointed to by group2 indices. If D==0 (particle position is not tracked), neither the particle position nor the cell index is written to the file.
Positional arguments
nc_filename: filename to write output toparticles: the Vector ofParticleVectorinstances of particles to be writtenpia: theParticleIndexerArrayinstancespecies_data: the vector ofSpeciesdata for the species in the simulationspecies_ids: list of species ids (in range 1:n_species) of species for which to write particle data
Keyword arguments
global_attributes: dictionary of any additional attributes to write to the netCDF file as a global attribute
write_netcdf(ds::NCDataHolderMoments, moments, timestep; sync_freq=0)Write 'moments' to a NetCDF file and synchronize file to disk if necessary.
Positional arguments
ds: theNCDataHolderMomentsfor the file to which the output will be writtenmoments: the moments array (dimensionn_moments x n_cells x n_species)timestep: the simulation timestep
Keyword arguments
sync_freq: if larger than 0 and if the number of timesteps output is proportional tosync_freq, the data will be synchronized to disk. If set to 1, will sync data to disk at every timestep at which data is written to the file.
write_netcdf(ds, field_props::ElectrostaticFieldProps, timestep; sync_freq=0)Write the electrostatic field quantities stored in an ElectrostaticFieldProps instance to a NetCDF file and synchronize file to disk if necessary.
Positional arguments
ds: theNCDataHolderFieldfor the file to which the output will be writtenfield_props: theElectrostaticFieldPropsinstance containing the field quantitiestimestep: the simulation timestep
Keyword arguments
sync_freq: if larger than 0 and if the number of timesteps output is proportional tosync_freq, the data will be synchronized to disk. If set to 1, will sync data to disk at every timestep at which data is written to the file.
Merzbild.close_netcdf — Function
close_netcdf(ds::T) where {T<:AbstractNCDataHolder}Close NetCDF file.
Positional arguments
ds: anAbstractNCDataHolderinstance to close.
Parallel computations
Merzbild.ChunkExchanger — Type
ChunkExchangerStruct used to organize exchange of particles between independent ParticleVector instances for chunked multi-threaded simulations. It is assumed that the cell indices within each chunk are contiguous, i.e. chunk[i+1] = chunk[i]+1.
The indexing for the exchanged groups is stored as arrays of shape (n_chunks, n_cells), and [chunk_id, cell] describes the particles that belong to cell cell and came from particle chunk chunk_id. Group 1 holds the particles that arrived via swapping, group 2 the particles that arrived via pushing, i.e. those added to the end of the particle array. The end of a group is not stored, as it is given by start + n_group - 1 (which is -1 for an empty group, matching the convention used by ParticleIndexer).
The table is self-clearing: every entry written during an exchange is read exactly once, in the same timestep, by the chunk owning the cell, and sort_particles_after_exchange! zeroes it as it reads it. It is therefore already empty at the start of each timestep and does not need to be reset! between timesteps.
The occ_lo/occ_hi fields hold, per chunk, the first and last cell in which the chunk holds any particles. They let exchange_particles! reject a pair of chunks that cannot have anything to exchange without scanning the cells of either chunk. They are updated by update_occupancy_bounds! and start out as the whole grid, i.e. a simulation that never calls it is still correct, just slower.
Fields
n_chunks: number of chunks used in the simulationn_cells: number of grid cells in the simulationstart1: index of the first particle of group 1n_group1: number of particles in group 1start2: index of the first particle of group 2n_group2: number of particles in group 2occ_lo: first cell in which a chunk holds particlesocc_hi: last cell in which a chunk holds particles
Merzbild.ChunkExchanger — Method
ChunkExchanger(chunks, n_cells)Create a ChunkExchanger for length(chunks) chunks and n_cells cell.
Positional arguments
chunks: list of cell chunksn_cells: total number of cells in the simulation
Merzbild.update_occupancy_bounds! — Function
update_occupancy_bounds!(chunk_exchanger, gridsort, pia, chunk_id, species)Update the first and last cell in which chunk chunk_id holds particles of the given species, so that exchange_particles! can reject pairs of chunks with nothing to exchange without scanning any cells.
Must be called after sort_particles! and before exchange_particles!, as it simply copies over the bounds recorded by the sort. If not called, one should set occ_lo to 1 and occ_hi to n_cells in each chunk.
Positional arguments
chunk_exchanger: theChunkExchangerinstance in which to store the boundsgridsort: theGridSortInPlaceused to sort the chunk's particlespia: theParticleIndexerArrayinstance associated with the chunkchunk_id: the chunk for which to update the boundsspecies: the particle species for which the bounds are computed
Merzbild.exchange_particles! — Function
exchange_particles!(chunk_exchanger, particles_chunks::Vector{Vector{ParticleVector{D}}}, pia_chunks, cell_chunks, species, i, j) where DRedistribute particles between chunks i and j based on their spatial cell ownership.
This function ensures each particle resides in the chunk responsible for its current cell. It performs symmetric swaps when possible, and pushes remaining particles if needed. The indexing metadata (chunk_exchanger and pia_chunks) is updated accordingly, and particles pushed to another chunk (not swapped) are added to the buffer for future re-use. The particles before the start of the re-distribution need to be sorted, so that no particles are indexed by the start2:end2 part of a ParticleIndexer. After the operation, the n_total[species] value of pia_chunks[chunk_id] will not include particles that were pushed to another chunk (the appropriate n_group1, start1, end1 values will be set to 0, 0, -1). However indexing should not be relied on until particles are re-sorted, see (sort_particles_after_exchange!)[@ref].
Positional arguments
chunk_exchanger: theChunkExchangerinstance to track post-swap and post-push indicesparticles_chunks: Vector of Vector ofParticleVector(per chunk and per species, i.e.particles_chunks[chunk_id][species]is the correct order of access)pia_chunks: Vector ofParticleIndexerArrayinstances for each chunkcell_chunks: cell ownership list for each chunk, i.e.cell_chunks[chunk_id]is a list of cells belonging to chunkchunk_id; the cells withincell_chunks[chunk_id]should be ordered in increasing order and be continuous: i.e.cell_chunks[chunk_id][i] == cell_chunks[chunk_id][i-1] + 1species: the particle species being redistributedi: index of first chunkj: index of second chunk
exchange_particles!(chunk_exchanger, particles_chunks::Vector{Vector{ParticleVector{D}}}, pia_chunks, cell_chunks, species) where DRedistribute particles between chunks based on their spatial cell ownership.
This function ensures each particle resides in the chunk responsible for its current cell. It performs symmetric swaps when possible, and pushes remaining particles if needed. The indexing metadata (chunk_exchanger and pia_chunks) is updated accordingly, and particles pushed to another chunk (not swapped) are added to the buffer for future re-use. The particles before the start of the re-distribution need to be sorted, so that no particles are indexed by the start2:end2 part of a ParticleIndexer. After the operation, the n_total[species] value of pia_chunks[chunk_id] will not include particles that were pushed to another chunk (the appropriate n_group1, start1, end1 values will be set to 0, 0, -1). However indexing should not be relied on until particles are re-sorted, see (sort_particles_after_exchange!)[@ref].
Positional arguments
chunk_exchanger: theChunkExchangerinstance to track post-swap and post-push indicesparticles_chunks: Vector of Vector ofParticleVector(per chunk and per species, i.e.particles_chunks[chunk_id][species]is the correct order of access)pia_chunks: Vector ofParticleIndexerArrayinstances for each chunkcell_chunks: cell ownership list for each chunk, i.e.cell_chunks[chunk_id]is a list of cells belonging to chunkchunk_id; the cells withincell_chunks[chunk_id]should be ordered in increasing order and be continuous: i.e.cell_chunks[chunk_id][i] == cell_chunks[chunk_id][i-1] + 1species: the particle species being redistributed
Merzbild.sort_particles_after_exchange! — Function
sort_particles_after_exchange!(chunk_exchanger, gridsort, particles::ParticleVector{D}, pia, cell_chunk, species) where DRestore indexing of a ParticleVector and the associated ParticleIndexerArray after particles have been swapped and pushed between chunks.
The first and last cell of the chunk holding particles are recorded in the GridSortInPlace instance, so that update_occupancy_bounds! can be called after this function as well as after sort_particles!.
Positional arguments
chunk_exchanger: theChunkExchangerinstance used to track post-swap and post-push indicesgridsort: TheGridSortInPlaceassociated with the chunkparticles: theParticleVectorfor which to restore the indexingpia: theParticleIndexerArrayinstances associated with the chunkcell_chunk: list or range of cells belonging to the chunkspecies: the particle species being for which the indexing is being restored
Merzbild.reset! — Function
reset!(chunk_exchanger, chunk_id)Reset all indexing of the entries [chunk_id,:] of a chunk_exchanger.
A newly constructed ChunkExchanger is already empty, and sort_particles_after_exchange! clears the entries it reads, so in a time loop that sorts every chunk after every exchange this does not need to be called at all. It is intended for re-using a ChunkExchanger whose indexing was left in an unknown state, e.g. after an exchange that was not followed by a re-sort.
Positional arguments
chunk_exchanger: theChunkExchangerinstancechunk_id: the chunk for which to reset indexing
Merzbild.reduce_surf_props! — Function
reduce_surf_props!(surf_props_target, surf_props_chunks)Sum up the values of the computed surface properties for all SurfProps instances in a surf_props_chunks list and store the sums in surf_props_target.
Positional arguments
surf_props_target: theSurfPropsinstance which will hold the reduced valuessurf_props_chunks: the listSurfPropsinstances to use for the reduction operation
Merzbild.reduce_field_props! — Function
reduce_field_props!(field_props_target, field_props_chunks)Sum the charge deposited in the ElectrostaticFieldProps instances of a field_props_chunks list into field_props_target, which is cleared first. This is used in a multi-threaded simulation, where each thread deposits the particles of the cells it owns into its own ElectrostaticFieldProps instance, since depositing into a shared instance is not thread-safe.
Only the charge density is reduced; the potential and the electric field of the target are left untouched, as they are computed by a single solve_poisson! call afterwards. The charge in the per-thread instances is expected to be the raw deposited charge, so normalize_charge_density! has to be called exactly once, on the target, after the reduction, in serial mode.
Positional arguments
field_props_target: theElectrostaticFieldPropsinstance which will hold the reduced charge densityfield_props_chunks: the list ofElectrostaticFieldPropsinstances to use for the reduction operation
Merzbild.generate_1_factorization — Function
generate_1_factorization(N_chunks)Construct a Vector{Vector{Tuple{Int,Int}}} with the following properties:
- tuple elements
iandjrange from1toN_chunks - tuples
(i,j)and(j,i)are considered equivalent - each tuple
(i,j)(up to equivalency) appears in the result exactly once - in each
Vectorof tuples all numbers are unique - tuples
(i,i)do not appear - the
Vectors of tuples are as long as possible.
This corresponds to a 1-factorization of a complete graph; the resulting Vector of Vectors of Tuples can be iterated over, and particle exchange can be performed between chunks listed in the Tuples in a given Vector using multi-threaded, since each chunk appears at most once in a given vector. This allows to multi-thread the particle exchange step.
Positional arguments
N_chunks: number of chunks
Returns
A Vector of Vectors of Tuples corresponding to the 1-factorization of a complete graph with N_chunks vertices.
Merzbild.LoadBalancerCellQ — Type
LoadBalancerCellQUsed to perform load-balancing in multi-threaded simulations by tracking a per-cell quantity (i.e. number of collisions, number of particles, density, etc.) in a range of cells indexed by cell_start:cell_end and allowing to rebalance the assignment of cells to chunks based on the total quantity per chunk.
Fields
cell_start: index of first cellcell_end: index of last celln_cells: number of cellsn_chunks: number of chunksq:Vectorof lengthn_cellsof per-cell quantity on which balancing is based. Note that this array is 1-indexed.q_total_per_chunk:Vectorof lengthn_chunksholding the sums ofqacross all cells in a chunkq_total: total sum of the per-cell quantity across alln_cellscellschunked_indices: aVector{UnitRange{Int64}}of lengthn_chunksholding the ranges of indices
assigned to each chunk
Merzbild.LoadBalancerCellQ — Method
LoadBalancerCellQ(n_cells, n_chunks)Create a per-cell indicator-based load balancer for n_cells cells and n_chunks chunks. Note: this uses index_chunks, i.e. it is assumed that cell indexing starts from 1 and is contiguous!
Positional arguments
n_cells: number of cellsn_chunks: number of chunks
Keyword arguments
cell_start: index of first cell indexed by theLoadBalancerCellQinstance
Merzbild.update_lb_cellq! — Function
update_lb_cellq!(lb::LoadBalancerCellQ, chunk_id, cell, q; averaging_window=1.0)Update the values of the load-balancing quantity being tracked in a single cell.
Positional arguments
lb: theLoadBalancerCellQinstance to updatechunk_id: the index of the chunk to which the cell belongscell: the index of the cell to updateq: the value of the load-balancing quantity in the cell
Keyword arguments
averaging_window: the time window over which the load-balancing quantity is averaged
(to potentially avoid round-off errors, overflow, or variable time-steps)
Merzbild.rebalance_lb! — Function
rebalance_lb!(lb::LoadBalancerCellQ)Compute new ranges of cell-indices so that each range holds approximately the same total sum of the load-balancing quantity.
Positional arguments
lb: theLoadBalancerCellQinstance on which to perform re-balancing
Merzbild.reset_lb! — Function
reset_lb!(lb::LoadBalancerCellQ)Set all values of the load balancer tracking a per-cell quantity to zero. Indexing is not reset.
Positional arguments
lb: theLoadBalancerCellQinstance to reset
Particle-in-Cell
Merzbild.accelerate_constant_field_x! — Function
accelerate_constant_field_x!(particles, pia, cell, species, species_data, E, Δt)Accelerate particles with a constant electric field in the X direction; no sorting of particles is required since the field is constant.
Positional arguments
particles: vector-like structure of particles to be acceleratedpia: ParticleIndexerArray instancecell: index of the cell in which particles are being acceleratedspecies: index of the species of the particles being acceleratedspecies_data: aVector{Species}instance with the species' dataE: value of the electric field in V/mΔt: timestep for which the acceleration is performed
Merzbild.DirichletFieldBC1D — Type
DirichletFieldBC1D <: AbstractFieldBC1DA boundary condition prescribing the value of the electrostatic potential at a boundary of a 1-D domain. The structure is mutable, so that the value can be changed from within a time loop (for example, to drive an RF electrode: bc_left.ϕ = V0 * sin(2π * f * t)).
Fields
ϕ: the prescribed value of the potential, V
Merzbild.NeumannFieldBC1D — Type
NeumannFieldBC1D <: AbstractFieldBC1DA boundary condition prescribing the x-component of the electric field at a boundary of a 1-D domain (and not the derivative of the potential, given by $d\phi/dx = -E_x$). The structure is mutable, so that the value can be changed from within a time loop (for example, for a dielectric wall accumulating a surface charge $\sigma$: bc_right.E_x = σ / eps_0).
Fields
E_x: the prescribed value of the x-component of the electric field, V/m
Merzbild.PeriodicFieldBC1D — Type
PeriodicFieldBC1D <: AbstractFieldBC1DA periodic boundary condition for the electrostatic field in a 1-D domain. It has to be used on both sides of the domain; as no values are prescribed, no data is stored in the struct.
Merzbild.PoissonSolver1DUniform — Type
PoissonSolver1DUniformStructure holding data used to discretize and solve the 1-D Poisson equation $-\phi'' = \rho / \varepsilon_0$ via second-order finite differences using the Thomas algorithm for tridiagonal matrices.
The field quantities themselves are not stored here, but in an ElectrostaticFieldProps instance. The boundary conditions are type parameters, so that the assembly of the right-hand side is resolved at compile time.
The unknowns are the values of the potential in the nodes which are not prescribed by the boundary conditions; the potential in node node_offset + k is the k-th unknown. The number of unknowns and the node offset depend on the boundary conditions (N = n_nodes, n_cells = N - 1):
| left BC | right BC | unknown nodes | n_unknowns | node_offset |
|---|---|---|---|---|
| Dirichlet | Dirichlet | 2 … N-1 | n_cells - 1 | 1 |
| Neumann | Dirichlet | 1 … N-1 | n_cells | 0 |
| Dirichlet | Neumann | 2 … N | n_cells | 1 |
| Neumann | Neumann | — | — | rejected at construction |
| periodic | periodic | 1 … n_cells-1 | n_cells - 1 | 0 |
Fields
n_nodes: number of nodesn_unknowns: number of unknowns of the tridiagonal systemnode_offset: offset between the index of an unknown and the index of the corresponding nodeΔx: cell sizeinv_Δx: inverse of the cell sizeinv_Δx2: inverse of the squared cell size, used for the Dirichlet right-hand side correctioninv_eps_0: inverse of the vacuum permittivitybc_left: theAbstractFieldBC1Dboundary condition on the left boundarybc_right: theAbstractFieldBC1Dboundary condition on the right boundarya: sub-diagonal of the matrix, witha[1] = 0as it lies outside of the matrix (not used in the solve)b: main diagonal of the matrix (not used in the solve)c: super-diagonal of the matrix, withc[n_unknowns] = 0as it lies outside of the matrix (not used in the solve)cp: pre-computedc[i] / m[i]factorization coefficientsinv_m: pre-computed1 / (b[i] - cp[i-1] * a[i])factorization coefficientsa_inv_m: pre-computed-a[i] / m[i]factorization coefficientsrhs: right-hand side of the tridiagonal systemdp: workspace of the forward sweep of the Thomas algorithmx: solution of the tridiagonal system (values of the potential in the unknown nodes)
Merzbild.PoissonSolver1DUniform — Method
PoissonSolver1DUniform(grid::Grid1DUniform, bc_left::AbstractFieldBC1D, bc_right::AbstractFieldBC1D)Construct a solver of the 1-D Poisson equation on a uniform grid for a given pair of boundary conditions and factorize the resulting tridiagonal matrix.
Neumann boundary conditions on both sides are rejected (the system is singular and no gauge is available), as is a periodic boundary condition paired with a non-periodic one.
Positional arguments
grid: theGrid1DUniformgridbc_left: theAbstractFieldBC1Dboundary condition on the left boundarybc_right: theAbstractFieldBC1Dboundary condition on the right boundary
Merzbild.deposit_charge! — Function
deposit_charge!(grid::Grid1DUniform, particles::ParticleVector, pia, species, species_data, field_props)Deposit the charge of the particles of a single species on the nodes of a 1-D uniform grid using first-order (cloud-in-cell) weighting. The deposited values are accumulated, so the charge density has to be cleared by a call to clear_charge_density! or clear_props! before the first species is deposited, and normalize_charge_density! has to be called exactly once after the last species has been deposited in order to turn the deposited charge into a charge density. Neutral species are skipped.
The particles are assumed to be sorted on the grid. This routine is serial; for a multi-threaded simulation, see the cell_chunk version of the routine and reduce_field_props!.
Positional arguments
grid: theGrid1DUniformgridparticles: theParticleVectorof the particles of the species being depositedpia: theParticleIndexerArrayinstancespecies: the index of the species being depositedspecies_data: theVectorofSpeciesdatafield_props: theElectrostaticFieldPropsinstance in which the deposited charge is stored
deposit_charge!(grid::Grid1DUniform, particles::ParticleVector, pia, species, species_data, field_props, cell_chunk)Deposit the charge of the particles of a single species located in a subset of the cells of a 1-D uniform grid on the nodes of the grid. Note: the particles are assumed to be sorted on the grid.
In a multi-threaded simulation, each thread should deposit the particles of the cells it owns into its own ElectrostaticFieldProps instance; the per-thread instances are then summed into the global one with reduce_field_props!.
Positional arguments
grid: theGrid1DUniformgridparticles: theParticleVectorof the particles of the species being depositedpia: theParticleIndexerArrayinstancespecies: the index of the species being depositedspecies_data: theVectorofSpeciesdatafield_props: theElectrostaticFieldPropsinstance in which the deposited charge is storedcell_chunk: the list of cell indices or range in which the charge of the particles is deposited
deposit_charge!(poisson_solver, grid::Grid1DUniform, particles, pia, species_data, field_props)Clear the charge density, deposit the charge of the particles of all the species on the nodes of a 1-D uniform grid, and normalize the result to a charge density. This is the recommended way of computing the charge density, as it performs the clearing, the deposition, and the normalization in the correct order.
The particles are assumed to be sorted on the grid. This routine is serial.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancegrid: theGrid1DUniformgridparticles: theVectorofParticleVectors containing all the particles in a simulationpia: theParticleIndexerArrayinstancespecies_data: theVectorofSpeciesdatafield_props: theElectrostaticFieldPropsinstance in which the charge density is stored
Merzbild.normalize_charge_density! — Function
normalize_charge_density!(poisson_solver::PoissonSolver1DUniform, field_props)Turn the charge deposited on the nodes of a 1D uniform grid by deposit_charge! into a charge density, by dividing it by the volume of the dual cell of each node. The dual cell of a boundary node is $\Delta x / 2$, so the deposited charge in the boundary nodes is multiplied by 2.
Note that this routine has to be called exactly once per timestep, after all the species have been deposited. The solver is used only to determine the types of the boundary conditions and the cell size.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancefield_props: theElectrostaticFieldPropsinstance holding the deposited charge
normalize_charge_density!(poisson_solver::PoissonSolver1DUniform{PeriodicFieldBC1D, PeriodicFieldBC1D},
field_props)Turn the charge deposited on the nodes of a 1D uniform grid by deposit_charge! into a charge density, by dividing it by the volume of the dual cell of each node; periodic boundary conditions. The charge deposited in the last node is folded into the first node and mirrored back, and the dual cell of every node is $\Delta x$.
Note that this routine has to be called exactly once per timestep, after all the species have been deposited.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstance with periodic BCsfield_props: theElectrostaticFieldPropsinstance holding the deposited charge
Merzbild.solve_poisson! — Function
solve_poisson!(poisson_solver, field_props)Compute the electrostatic potential and the electric field in the nodes from the charge density stored in field_props, by assembling and solving the discrete Poisson system. The charge density is not modified, so repeated calls do not change the result; it is however assumed that the charge density has already been normalized by a call to normalize_charge_density!.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancefield_props: theElectrostaticFieldPropsinstance holding the charge density, the potential, and the electric field
Merzbild.accelerate_electric_field_x! — Function
accelerate_electric_field_x!(grid::Grid1DUniform, particles, pia, cell, species, species_data, field_props, Δt)Accelerate the particles of a species in a single cell of a 1-D uniform grid with the self-consistent electric field stored in the nodes, using first-order (cloud-in-cell) interpolation of the field to the position of a particle. The interpolation uses the same weights as deposit_charge!.
The particles are assumed to be sorted on the grid (so no particles are indexed by group2).
Positional arguments
grid: theGrid1DUniformgridparticles: theParticleVectorof the particles being acceleratedpia: theParticleIndexerArrayinstancecell: index of the cell in which particles are being acceleratedspecies: index of the species of the particles being acceleratedspecies_data: aVector{Species}instance with the species' datafield_props: theElectrostaticFieldPropsinstance holding the electric fieldΔt: timestep for which the acceleration is performed
accelerate_electric_field_x!(grid::Grid1DUniform, particles, pia, species, species_data, field_props, Δt)Accelerate the particles of a species in all cells of a 1-D uniform grid with the self-consistent electric field stored in the nodes.
The particles are assumed to be sorted on the grid.
Positional arguments
grid: theGrid1DUniformgridparticles: theParticleVectorof the particles being acceleratedpia: theParticleIndexerArrayinstancespecies: index of the species of the particles being acceleratedspecies_data: aVector{Species}instance with the species' datafield_props: theElectrostaticFieldPropsinstance holding the electric fieldΔt: timestep for which the acceleration is performed
Constants
Merzbild.k_B — Constant
Boltzmann constant, J/K
Merzbild.eps_0 — Constant
Vacuum permittivity, F/m
Misc
Merzbild.DataMissingException — Type
DataMissingExceptionException for the case of missing tabulated cross-section data
Fields
msg: error message
Merzbild.MERZBILD_SIMULATIONS_PATH — Constant
MERZBILD_SIMULATIONS_PATHAbsolute path to the simulations directory bundled with Merzbild.jl, holding various simulation examples. Use it to run bundled simulations independently of the current working directory, e.g. include(joinpath(MERZBILD_SIMULATIONS_PATH, "0D/BKW/bkw.jl")).
Merzbild.MERZBILD_SCRIPTS_PATH — Constant
MERZBILD_SCRIPTS_PATHAbsolute path to the scripts directory bundled with Merzbild.jl, holding various Python scripts for data post-processing and plotting.