Merzbild.jl internal API reference
The public API functions are exported by the module
Particle indexing
Merzbild.map_cont_index — Function
map_cont_index(particle_indexer, i)Maps a continuous index in the range [0, n_local-1] to an index in the particle array given a ParticleIndexer instance describing how particle indices are split across 2 groups.
Positional arguments
particle_indexer: theParticleIndexerinstancei: the index to map
map_cont_index(pia, cell, species, i)Maps a continuous index in the range [0, n_local-1] to an index in the particle array for particles of a specific species in a specific cell.
Positional arguments
pia: theParticleIndexerArrayinstancecell: the index of the cell in which the particles are locatedspecies: the index of the particles' speciesi: the index to map
Merzbild.update_particle_indexer_new_particle! — Function
update_particle_indexer_new_particle!(pia, cell, species)Update a ParticleIndexerArray instance when a particle of a given species in a given cell is created. This places the particle index in the 2-nd group of particle indices in the ParticleIndexer instance.
Positional arguments
pia: theParticleIndexerArrayinstancecell: the index of the cell in which the particle is createdspecies: the index of the species of which the particle is created
Base.getindex — Function
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! — Function
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 — Function
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! — Function
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)
Merzbild.add_particle! — Function
add_particle!(pv::ParticleVector{D1}, position, w, v::SVector{3,Float64}, x::SVector{D2,Float64}) where {D1,D2}Create a new particle in a ParticleVector instance at position position. The ParticleIndexer/ParticleIndexerArray instances should be updated independently. See update_particle_buffer_new_particle! for more information regarding how the buffer of the ParticleVector is updated. This should not be used to update an existing particle. Particles at positions before position should exist in the ParticleVector array. Any components of x that exceed the x dimension of pv are discarded.
Positional arguments
pv:ParticleVectorinstanceposition: the position in theindexvector to which to write the index of the new particlew: the computational weight of the particle to createv: the velocity of the particle to create
Merzbild.update_particle_buffer_new_particle! — Function
update_particle_buffer_new_particle!(pv::ParticleVector{D}, position) where DUpdate the buffer in a ParticleVector instance when a new particle is created. This writes the index of the new particle (the last index stored in the active part of the buffer) to the index vector at position position, and reduces the length of the active part of the buffer by 1.
Positional arguments
pv:ParticleVectorinstanceposition: the position in theindexvector to which to write the index of the new particle
update_particle_buffer_new_particle!(pv::ParticleVector{D}, pia, species) where DUpdate the buffer in a ParticleVector instance when a new particle is created at the end of the particle array, and reduces the length of the active part of the buffer by 1. This assumes that the pia structure has already an updated particle count (that accounts for the newly created particle), as the index of the new particle taken from the buffer is written to pv.index.[pia.index_last[species]].
Positional arguments
pv:ParticleVectorinstancepia: theParticleIndexerArrayinstancespecies: the index of the species of which a new particle is created
Merzbild.update_buffer_index_new_particle! — Function
update_buffer_index_new_particle!(pv::ParticleVector{D}, pia, cell, species) where DUpdate a ParticleIndexerArray and the buffer in a ParticleVector instance when a particle of a given species in a given cell is created. The particle index is added to the second group of particles pointed to by the ParticleIndexer. See the documentation of update_particle_indexer_new_particle! and update_particle_buffer_new_particle!
Positional arguments
pv:ParticleVectorinstancepia: theParticleIndexerArrayinstancecell: the index of the cell in which the particle is createdspecies: the index of the species of which the particle is created
Merzbild.delete_particle! — Function
delete_particle!(pv::ParticleVector{D}, pia, cell, species, i) where DDelete particle with index i of species species in cell cell and update the particle indexers and buffers accordingly. This changes the ordering of the non-deleted particles in the cell.
Positional arguments
pv:ParticleVectorinstancepia: theParticleIndexerArrayinstancecell: the index of the cell in which the particle is deletedspecies: the index of the species of which the particle is deletedi: the index of the particle to delete
Merzbild.delete_particle_end! — Function
delete_particle_end!(pv::ParticleVector{D}, pia, cell, species) where DDelete the last particle of species species in cell cell: if particles are present in the 2nd group of the indices stored in the ParticleIndexer instance, it will delete the last particle in that group; otherwise it will delete the last particle in the 1st group of particles pointed to by the ParticleIndexer instance. If no particles are present in the cell, the function does nothing. This does not set the value of the contiguous field of pia to false even if pia becomes discontinuous; this has to be done outside of this function.
Positional arguments
pv:ParticleVectorinstancepia: theParticleIndexerArrayinstancecell: the index of the cell in which the particle is deletedspecies: the index of the species of which the particle is deleted
Merzbild.delete_particle_end_group1! — Function
delete_particle_end_group1!(pv::ParticleVector{D}, pia, cell, species) where DDelete particle with index pia.indexer[cell, species].end1of speciesspeciesin cellcelland update the particle indexers and buffers accordingly (i.e. delete the last particle in the 1st group of particles of a given species in a given cell). This also sets the weight of the deleted particle to 0. If no particles are present in the 1st group of particles, the function does nothing. This does not set the value of thecontiguousfield ofpiatofalseeven ifpia` becomes discontinuous; this has to be done outside of this function.
Positional arguments
pv:ParticleVectorinstancepia: theParticleIndexerArrayinstancecell: the index of the cell in which the particle is deletedspecies: the index of the species of which the particle is deleted
Merzbild.delete_particle_end_group2! — Function
delete_particle_end_group2!(pv::ParticleVector{D}, pia, cell, species) where DDelete particle with index pia.indexer[cell, species].end2of speciesspeciesin cellcelland update the particle indexers and buffers accordingly (i.e. delete the last particle in the 2nd group of the particles of a given species in a given cell). This also sets the weight of the deleted particle to 0. If no particles are present in the 2nd group of particles, the function does nothing. This does not set the value of thecontiguousfield ofpiatofalseeven ifpia` becomes discontinuous; this has to be done outside of this function.
Positional arguments
pv:ParticleVectorinstancepia: theParticleIndexerArrayinstancecell: the index of the cell in which the particle is deletedspecies: the index of the species of which the particle is deleted
Merzbild.delete_batch_end! — Function
delete_batch_end!(pv::ParticleVector{D}, pia, cell, species, n) where DDelete the last n particles of species species in cell cell: first any particles in the 2nd group of the indices stored in the ParticleIndexer instance will be deleted; followed by particles in the 1st group of particles pointed to by the ParticleIndexer instance (starting at the end of each group) If no particles are present in the cell, the function does nothing. This does not set the value of the contiguous field of pia to false even if pia becomes discontinuous; this has to be done outside of this function. This updates the indexing, the buffer, n_total and index_last. It is equivalent to calling delete_particle_end! n times, but does the bookkeeping once for the whole batch and resolves index_last with at most one scan over the cells. Note: this assumes that n <= n_group1 + n_group2.
Positional arguments
pv:ParticleVectorinstancepia: theParticleIndexerArrayinstancecell: the index of the cell in which the particle is deletedspecies: the index of the species of which the particle is deleted
Merzbild.delete_batch_end_group1! — Function
delete_batch_end_group1!(pv::ParticleVector{D}, indexer, n) where DDelete n particles from the end of the 1st group of particles of a given species in a given cell indexed by indexer and update the particle indexer and buffer accordingly. This also sets the weight of the deleted particles to 0. If n is 0, the function does nothing. This does not set the value of the contiguous field of pia to false even if pia becomes discontinuous; this has to be done outside of this function. Note: 1) This does not check that n is not larger than the number of particles in the 1st group of particles.
- This also does not update
index_lastorn_total; usedelete_batch_end!to have those updated.
Positional arguments
pv:ParticleVectorinstanceindexer: theParticleIndexerinstancen: the number of particles to delete
Merzbild.delete_batch_end_group2! — Function
delete_batch_end_group2!(pv::ParticleVector{D}, indexer, n) where DDelete n particles from the end of the 2nd group of particles of a given species in a given cell indexed by indexer and update the particle indexer and buffer accordingly. This also sets the weight of the deleted particles to 0. If n is 0, the function does nothing. This does not set the value of the contiguous field of pia to false even if pia becomes discontinuous; this has to be done outside of this function. Note: 1) This does not check that n is not larger than the number of particles in the 2nd group of particles of species in the cell. 2) This also does not update index_last or n_total; use delete_batch_end! to have those updated.
Positional arguments
pv:ParticleVectorinstanceindexer: theParticleIndexerinstancen: the number of particles to delete
Merzbild.find_index_last_after_group1_delete! — Function
find_index_last_after_group1_delete!(pia, cell, species)Find and set the new value of pia.index_last[species] after the 1st group of particles of species species in cell cell has been emptied whilst holding the last index. Only the 1st groups of the cells before cell are searched, since a 1st group holding the last index implies that no 2nd group is populated; failing that, index_last is set to 0.
Positional arguments
pia: theParticleIndexerArrayinstancecell: the index of the cell the particles were deleted fromspecies: the index of the species the particles were deleted from
Merzbild.find_index_last_after_group2_delete! — Function
find_index_last_after_group2_delete!(pia, cell, species)Find and set the new value of pia.index_last[species] after the 2nd group of particles of species species in cell cell has been emptied whilst holding the last index. Cells before cell are searched for a non-empty 2nd group; failing that, all cells are searched for a non-empty 1st group; failing that, index_last is set to 0.
Positional arguments
pia: theParticleIndexerArrayinstancecell: the index of the cell the particles were deleted fromspecies: the index of the species the particles were deleted from
Loading species and interaction data
Merzbild.compute_mu_ref — Function
compute_mu_ref(m_AB, vhs_o, vhs_Tref, vhs_d)Compute reference viscosity for the VHS model.
Positional arguments
m_AB: average mass of colliding particlesvhs_o: exponent for the VHS potentialvhs_Tref: reference temperature for the VHS potentialvhs_d: diameter for the VHS potential
Returns
- Reference viscosity
Merzbild.compute_vss_mu_ref_factor — Function
compute_vss_mu_ref_factor(vss_alpha)Compute the factor $(\alpha + 1)(\alpha + 2) / (6\alpha)$ by which the VHS reference viscosity has to be multiplied to obtain the VSS reference viscosity for the same total cross-section. It is the inverse of the ratio of the VSS and VHS viscosity cross-sections $\sigma_\mu = \sigma_T (1 - \langle\cos^2\chi\rangle)$, and is equal to 1 for $\alpha = 1$ (isotropic scattering).
Positional arguments
vss_alpha: VSS exponent (alpha)
Returns
- the reference viscosity correction factor
References
- G.A. Bird, Eq. (4.63), Molecular gas dynamics and the direct simulation of gas flows, Clarendon Press, Oxford, 1994.
Merzbild.interaction_from_toml — Function
interaction_from_toml(m1, m2, interaction_toml)Construct an Interaction instance from the masses of the two species and the dictionary of the interaction parameters of the species pair, as read from an interaction data TOML file.
The elastic scattering model is given by the optional model key (see Merzbild.parse_scattering_model); if it is not present, the VHS model is used. Both models require the vhs_d, vhs_o, and vhs_Tref keys, with the VSS model additionally requiring the vss_alpha key.
Positional arguments
m1: molecular mass of the first speciesm2: molecular mass of the second speciesinteraction_toml: dictionary of the interaction parameters of the species pair
Returns
- the constructed
Interactioninstance
Throws
KeyError if a parameter required by the scattering model is not found in the dictionary, ArgumentError if the scattering model is not recognized.
Sampling
Merzbild.UnitDVGrid — Type
UnitDVGridStores information about a uniform discrete 3-dimensional velocity grid with extent $[-1.0,1.0]\times[-1.0,1.0]\times[-1.0,1.0]$.
Fields
nx: number of cells in x directionny: number of cells in y directionnz: number of cells in z directiondx: grid spacing in x directiondy: grid spacing in y directiondz: grid spacing in z directionvx_grid:Vectorof grid nodes in x directionvy_grid:Vectorof grid nodes in y directionvz_grid:Vectorof grid nodes in z direction
Merzbild.DVGrid — Type
DVGridStores information about a uniform discrete 3-dimensional symmetric velocity grid with extent $[-v_{x,max},v_{x,max}]\times[-v_{y,max},v_{y,max}]\times[-v_{z,max},v_{z,max}]$.
Fields
base_grid: the underlying unit (non-scaled)UnitDVGriduniform gridvx_max: extent of the grid in the x directionvy_max: extent of the grid in the y directionvz_max: extent of the grid in the z directiondx: grid spacing in x directiondy: grid spacing in y directiondz: grid spacing in z directionvx_grid:Vectorof grid nodes in x directionvy_grid:Vectorof grid nodes in y directionvz_grid:Vectorof grid nodes in z direction
Merzbild.VDF — Type
VDFStores the values of a function evaluated on 3-dimensional velocity grid.
Fields
nx: the number of grid elements in the x directionny: the number of grid elements in the y directionnz: the number of grid elements in the z directionw: the 3-dimensional array of values
Merzbild.sample_bkw! — Function
sample_bkw!(rng, particles::ParticleVector{D}, nparticles, offset, m, T, v0) where DSample particle velocities from the BKW distribution with temperature T for a species with mass m at t=0 and add a velocity offset. Note: This does not update the particle weights, positions, or any indexing structures.
Positional arguments
rng: the random number generatorparticles: theVector-like structure holding the particlesnparticles: the number of particles to sampleoffset: offset the starting position for writing the sampled particles to theparticlesarraym: species' massT: temperaturev0: the 3-dimensional velocity to add to the sampled velocities
sample_bkw!(rng, particles::ParticleVector{D}, nparticles, m, T, v0) where DSample particles' velocities from the BKW distribution with temperature T for a species with mass m at t=0 and add a velocity offset. This does not update the particle weights, positions, or any indexing structures. The sampled particles are written to the start of the particles array.
Positional arguments
rng: the random number generatorparticles: theVector-like structure holding the particlesnparticles: the number of particles to samplem: species' massT: temperaturev0: the 3-dimensional velocity to add to the sampled velocities
Merzbild.evaluate_distribution_on_grid! — Function
evaluate_distribution_on_grid!(vdf, distribution_function, grid, w_total, cutoff_v; normalize=true)Evaluate 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 can be re-normalized so that the distribution has the prescribed computational weight/density.
Positional arguments
vdf: TheVDFinstance where the evaluated values will be storeddistribution_function: the distribution function to be evaluated which takes the x, y, and z velocities as parametersgrid: theDVGridon which the distribution function is evaluatedw_total: the total weight used in the re-normalizationcutoff_v: the radius of the sphere used to cut off high velocities: on grid points outside the sphere the VDF will be 0
Keyword arguments
normalize: iftrue, the resulting values of the VDF will be renormalized so that their sum is equal tow_total
Merzbild.sample_maxwellian! — Function
sample_maxwellian!(rng, particles::ParticleVector{D}, nparticles, offset, m, T, v0)Sample nparticles particles from a Maxwellian with temperature T for a species with mass m and add a velocity offset. Note: This does not update the particle weights, positions, or any indexing structures.
Positional arguments
rng: the random number generatorparticles: theVector-like structure holding the particlesnparticles: the number of particles to sampleoffset: offset the starting position for writing the sampled particles to theparticlesarraym: species' massT: temperaturev0: the 3-dimensional velocity to add to the sampled velocities
Collision computations
Merzbild.norm3 — Function
norm3(v)Compute the Euclidean norm of a 3-component vector.
Bit-for-bit identical to LinearAlgebra.norm(v), but cheaper in hot loops. It must stay outside any @muladd block: contracting the sum of squares into muladd changes the result by up to 0.3 ulp relative to norm, which is enough to break the bit-exact reference-solution tests.
Positional arguments
v: the 3-component vector
Returns
The Euclidean norm of v.
Merzbild.compute_n_coll_single_species — Function
compute_n_coll_single_species(rng, collision_factors, np, Δt, V)Compute the non-integer number of collisions between particles of same species.
Positional arguments
rng: the random number generatorcollision_factors: theCollisionFactorsholding the estimate of $(\sigma g w)_{max}$ for the species in question in the cellnp: number of particles in the cellΔt: timestepV: cell volume
Returns
The non-integer number of collisions.
compute_n_coll_single_species(rng, collision_factors_swpm, np, w_max, G, Δt, V)Compute the non-integer number of collisions between particles of same species for use in the SWPM method.
Positional arguments
rng: the random number generatorcollision_factors: theCollisionFactorsSWPMinstance holding the estimate of $(\sigma g)_{max}$ for the species in question in the cellnp: number of particles in the cellw_max: the maximum computational weight of the particles in the cellG: non-negative value defining the weight transfer functionΔt: timestepV: cell volume
Returns
The non-integer number of collisions.
Merzbild.compute_n_coll_two_species — Function
compute_n_coll_two_species(rng, collision_factors, np1, np2, Δt, V)Compute number of collisions between particles of different species
Positional arguments
rng: the random number generatorcollision_factors: theCollisionFactorsholding the estimate of $(\sigma g w)_{max}$ for the species in question in the cellnp1: number of particles of the first species in the cellnp2: number of particles of the second species in the cellΔt: timestepV: cell volume
Returns
The non-integer number of collisions.
Merzbild.collide_2particles! — Function
collide_2particles!(rng, model, collision_data, collision_factors, interaction, pa_i::Particle{D}, pa_k::Particle{D},
particles_1::ParticleVector{D}, particles_2::ParticleVector{D}, pia, cell, species1, species2; dw_tol=1e-16) where DCollide two particles elastically using the elastic scattering model model. Particles can be of same or different species. If particles' weights differ by less than dw_tol, an equal-weight collision is performed and no particles are split.
Positional arguments
rng: the random number generatormodel: theAbstractScatteringModelsingleton for the scattering modelcollision_data:CollisionDatainstance used for storing collisional quantitiescollision_factors: theCollisionFactorsholding the estimate of $(\sigma g w)_{max}$ for the species in question in the cellinteraction: theInteractioninstance for the colliding speciesparticles_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
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
Merzbild.collide_2particles_equal_weight! — Function
collide_2particles_equal_weight!(rng, model, collision_data, collision_factors, interaction, pa_i::Particle{D}, pa_k::Particle{D}) where DCollide two particles elastically using the elastic scattering model model, assuming equal weights - no particle splitting is performed even if weights are unequal. Particles can be of same or different species.
Positional arguments
rng: the random number generatormodel: theAbstractScatteringModelsingleton for the scattering modelcollision_data:CollisionDatainstance used for storing collisional quantitiescollision_factors: theCollisionFactorsholding the estimate of $(\sigma g w)_{max}$ for the species in question in the cellinteraction: theInteractioninstance for the colliding speciespa_i: the first particle being collidedpa_k: the second particle being collided
Merzbild.compute_vhs_factor — Function
compute_vhs_factor(vhs_Tref, vhs_d, vhs_o, m_r)Compute interaction-specific factor $\pi D_{VHS}^2 (2 T_{ref,VHS}/m_r)^{(\omega_{VHS} - 0.5)} \frac{1}{\Gamma(2.5 - \omega_{VHS})}$.
Positional arguments
vhs_Tref: reference temperature for the VHS potentialvhs_d: diameter for the VHS potentialvhs_o: exponent for the VHS potentialm_r: collision-reduced mass
Returns
- computed VHS cross-section factor
Merzbild.compute_com! — Function
compute_com!(collision_data::CollisionData, interaction::Interaction, p1, p2)Compute center of mass velocity of two particles.
Positional arguments
collision_data: theCollisionDatainstance where the computed velocity will be storedinteraction: theInteractioninstance for the species of the colliding particlesp1: the first particlep2: the second particle
Merzbild.compute_g! — Function
compute_g!(collision_data::CollisionData, p1, p2)Compute relative velocity (vector and its magnitude) of two particles.
Positional arguments
collision_data: theCollisionDatainstance where the computed velocity will be storedp1: the first particlep2: the second particle
Merzbild.compute_g_new_ionization! — Function
compute_g_new_ionization!(collision_data, interaction, E_i, energy_splitting)Compute post-ionization magnitudes of the relative velocities of the impacting and newly created electrons.
Positional arguments
collision_data: theCollisionDatainstance where the computed velocity will be storedinteraction: theInteractioninstance for the electron-neutral interaction which produced the ionE_i: ionization energy of the neutral species in electron-voltenergy_splitting: how the energy is divided among the electrons: ifElectronEnergySplitEqual, the energy is split equally, ifElectronEnergySplitZeroE, one electron takes all of the energy
Merzbild.scatter! — Function
scatter!(rng, model, collision_data, interaction, p1, p2)Scatter two particles using the scattering law of the elastic scattering model: isotropic scattering (Merzbild.scatter_vhs!) for the VHS model, VSS scattering (Merzbild.scatter_vss!) for the VSS model.
Positional arguments
rng: the random number generatormodel: theAbstractScatteringModelsingleton for the scattering modelcollision_data: theCollisionDatainstance which stores the center-of-mass velocity and the pre-collisional relative velocity of the particles, and to which the new post-collisional velocity will be writteninteraction: theInteractioninstance for the colliding particlesp1: the first colliding particlep2: the second colliding particle
Merzbild.scatter_vhs! — Function
scatter_vhs!(rng, collision_data, interaction, p1, p2)Scatter two particles using VHS (isotropic) scattering.
Positional arguments
rng: the random number generatorcollision_data: theCollisionDatainstance to which stores the center-of-mass velocity, the magnitude of the pre-collisional relative velocity of the particles and to which the new post-collisional velocity will be writteninteraction: theInteractioninstance for the colliding particlesp1: the first colliding particlep2: the second colliding particle
Merzbild.scatter_vss! — Function
scatter_vss!(rng, collision_data, interaction, p1, p2)Scatter two particles using VSS (anisotropic) scattering. The cosine of the deflection angle $\chi$ (the angle between the pre- and post-collisional relative velocities) is sampled as $\cos\chi = 2 R^{1/\alpha} - 1$, where $R$ is a uniformly distributed random number and $\alpha$ is the VSS exponent of the interaction; the azimuthal angle $\varepsilon$ is sampled uniformly in $[0, 2\pi)$. The post-collisional relative velocity is then computed by rotating the pre-collisional one.
The power $R^{1/\alpha}$ is evaluated as exp2(vss_inv_alpha * log2(R)) for the same reason as in Merzbild.sigma_vhs.
If the relative velocity is nearly aligned with the x-axis, the rotation is performed in the $(y,z)$ plane instead, as the general expressions become ill-conditioned.
Positional arguments
rng: the random number generatorcollision_data: theCollisionDatainstance which stores the center-of-mass velocity, the pre-collisional relative velocity of the particles (vector and magnitude), and to which the new post-collisional velocity will be writteninteraction: theInteractioninstance for the colliding particlesp1: the first colliding particlep2: the second colliding particle
References
- G.A. Bird, Eq. (2.22), Molecular gas dynamics and the direct simulation of gas flows, Clarendon Press, Oxford, 1994.
- K. Koura, H. Matsumoto, Variable soft sphere molecular model for inverse-power-law or Lennard-Jones potential. Phys. Fluids A, 1991.
Merzbild.scatter_electron_vhs! — Function
scatter_electron_vhs!(rng, particle_electron, g_new)Scatter an electron using VHS (isotropic) scattering and re-scale its relative velocity to g_new. This DOES NOT add the velocity of the center of mass to the electron.
Positional arguments
rng: the random number generatorparticle_electron: the electron particle to scatter off of the neutral particleg_new: the magnitude of the post-collisional relative velocity
Merzbild.scatter_ionization_electrons_and_ion! — Function
scatter_ionization_electrons_and_ion!(rng, collision_data, p_e1, p_e2, p_ion, mass_ratio)Scatter electrons and ion after an ionization reaction using VHS (isotropic) scattering.
Positional arguments
rng: the random number generatorcollision_data: theCollisionDatainstance to which stores the center-of-mass velocity the magnitude of the pre-collisional relative velocity of the electron and the neutral, and the post-collisional magnitudes of the velocities of the electronsp_e1: the first electron particle to scatter off of the neutralp_e2: the second electron particle to scatter off of the neutralp_ion: the ion produced in the ionization reactionmass_ratio: ratio of the electron mass to the ion mass
References
- K. Nanbu, Eqns. (47)-(53b), IEEE Trans. Plasma. Sci., 2000
Merzbild.sigma — Function
sigma(model, interaction, g)Compute the total elastic collision cross-section for a given scattering model. The VSS model uses the same power law as the VHS model.
Positional arguments
model: theAbstractScatteringModelsingleton tag of the scattering modelinteraction: theInteractioninstanceg: the relative velocity of the collision
Returns
The value of the computed cross-section.
Merzbild.sigma_vhs — Function
sigma_vhs(interaction, g)Computes the VHS cross-section.
The power law is evaluated as exp2(vhs_exp * log2(g)) rather than g^vhs_exp: Float64^Float64 carries the logarithm in double-double precision so that the result stays below 1 ulp for any exponent, which costs roughly twice the work. Since vhs_exp is a small fixed exponent, the plain decomposition is accurate to ~2 ulp.
Positional arguments
interaction: theInteractioninstanceg: the relative velocity of the collision
Returns
The value of the computed cross-section.
Merzbild.@scattering_barrier — Macro
@scattering_barrier model callTurn the Merzbild.ScatteringModel enum value model into the corresponding scattering model singleton and insert it into the function call call as the second positional argument (that is, directly after rng).
The macro expands into an if/elseif chain with a literal singleton in each arm, so that each arm is a separate call with a concrete singleton type. This acts as a function barrier: the branch is taken once per call of a collision routine, and everything below it is compiled for one fixed model, with the cross-section and scattering functions inlined and no dispatch left in the collision loop.
Example
@scattering_barrier interaction_l.model ntc!(rng, collision_factors, collision_data, interaction, particles, pia, cell, species, Δt, V; dw_tol=dw_tol)Merzbild.SCATTERING_MODEL_TAGS — Constant
Tuple of all (enum value, singleton tag) pairs of the implemented elastic scattering models, used by Merzbild.@scattering_barrier to generate the enum-to-tag conversion. Any newly added scattering model has to be listed here.
Merzbild.parse_scattering_model — Function
parse_scattering_model(name)Convert the name of an elastic scattering model, as written in an interaction data TOML file, to the corresponding Merzbild.ScatteringModel enum value. The comparison is case-insensitive; the recognized names are "VHS" and "VSS".
Positional arguments
name: the name of the scattering model
Returns
The ScatteringModel enum value.
Throws
ArgumentError if the model name is not recognized.
Merzbild.compute_tabulated_cs_constant_continuation — Function
compute_tabulated_cs_constant_continuation(tabulated_cs_data, E_coll)Compute an energy-dependent cross-section from tabulated data using linear interpolation. If the energy is smaller than the minimum energy used for the tabulation, return first element of the table; if energy is larger than the maximum energy used for the tabulation, return last element of the table.
Positional arguments
tabulated_cs_data: aTabulatedCSDatainstance with the tabulated energies and cross-section valuesE_coll: the collision energy for which to compute the cross-section
Returns
The value of the cross-section.
Merzbild.compute_tabulated_cs_zero_continuation — Function
compute_tabulated_cs_zero_continuation(tabulated_cs_data, E_coll)Compute an energy-dependent cross-section from tabulated data using linear interpolation. If the energy is outside of the range of energies used for the tabulation, returns 0.0.
Positional arguments
tabulated_cs_data: aTabulatedCSDatainstance with the tabulated energies and cross-section valuesE_coll: the collision energy for which to compute the cross-section
Returns
The value of the cross-section.
Merzbild.compute_cross_sections_only! — Function
compute_cross_sections_only!(computed_cs, interaction, g, electron_neutral_interactions, neutral_species_index, extend::CSExtend)Compute electron-impact ionization and excitation cross-sections, and electron-neutral elastic scattering crosss-sections, and return collision energy in eV. Here neutral_species_index is the index of the neutral species being considered in the overall array of the Species instances that includes all species in the simulation and was used to construct the ElectronNeutralInteractions instance.
Positional arguments
computed_cs: the vector ofComputedCrossSectioninstances in which the computed values will be storedinteraction: theInteractioninstance describing the electron-neutral interaction being consideredg: the magnitude of the relative collision velocityelectron_neutral_interactions: theElectronNeutralInteractionsinstance storing the tabulated cross-section dataneutral_species_index: the index of the neutral species being considered
Returns
The electron-neutral collision energy in eV.
Merzbild.compute_cross_sections! — Function
compute_cross_sections!(computed_cs, interaction, g, electron_neutral_interactions, neutral_species_index; extend::CSExtend=CSExtendConstant)Compute electron-impact ionization and excitation cross-sections, electron-neutral elastic scattering cross-sections, total collision cross-section, probabilities of the different processes, and return collision energy in eV. Here neutral_species_index is the index of the neutral species being considered in the overall array of the Species instances that includes all species in the simulation and was used to construct the ElectronNeutralInteractions instance. Out-of-tabulation-range values are treated according to what extend method is used.
Positional arguments
computed_cs: the vector ofComputedCrossSectioninstances in which the computed values will be storedinteraction: theInteractioninstance describing the electron-neutral interaction being consideredg: the magnitude of the relative collision velocityelectron_neutral_interactions: theElectronNeutralInteractionsinstance storing the tabulated cross-section dataneutral_species_index: the index of the neutral species being considered
Keyword arguments
extend: enum ofCSExtendtype that sets how out-of-range energy values are treated when computing cross-sections
Returns
The electron-neutral collision energy in eV.
Merzbild.get_cs_total — Function
get_cs_total(electron_neutral_interactions, computed_cs, neutral_species_index)Get the value of a computed total collision cross-section for electron-neutral interactions. Here neutral_species_index is the index of the neutral species being considered in the overall array of the Species instances that includes all species in the simulation and was used to construct the ElectronNeutralInteractions instance.
Positional arguments
electron_neutral_interactions: theElectronNeutralInteractionsinstance storing the tabulated cross-section datacomputed_cs: the vector ofComputedCrossSectioninstances holding the computed cross-section valuesneutral_species_index: the index of the neutral species being considered
Returns
The value of the total collision cross-section.
Merzbild.get_cs_elastic — Function
get_cs_elastic(electron_neutral_interactions, computed_cs, neutral_species_index)Get the value of a computed electron-neutral elastic scattering cross-section. Here neutral_species_index is the index of the neutral species being considered in the overall array of the Species instances that includes all species in the simulation and was used to construct the ElectronNeutralInteractions instance.
Positional arguments
electron_neutral_interactions: theElectronNeutralInteractionsinstance storing the tabulated cross-section datacomputed_cs: the vector ofComputedCrossSectioninstances holding the computed cross-section valuesneutral_species_index: the index of the neutral species being considered
Returns
The value of the elastic scattering cross-section.
Merzbild.get_cs_ionization — Function
get_cs_ionization(electron_neutral_interactions, computed_cs, neutral_species_index)Get the value of a computed electron-impact ionization cross-section. Here neutral_species_index is the index of the neutral species being considered in the overall array of the Species instances that includes all species in the simulation and was used to construct the ElectronNeutralInteractions instance.
Positional arguments
electron_neutral_interactions: theElectronNeutralInteractionsinstance storing the tabulated cross-section datacomputed_cs: the vector ofComputedCrossSectioninstances holding the computed cross-section valuesneutral_species_index: the index of the neutral species being considered
Returns
The value of the electron-impact ionization scattering cross-section.
Merzbild.get_ionization_threshold — Function
get_ionization_threshold(electron_neutral_interactions, neutral_species_index)Get the ionization threshold energy. Here neutral_species_index is the index of the neutral species being considered in the overall array of the Species instances that includes all species in the simulation and was used to construct the ElectronNeutralInteractions instance.
Positional arguments
electron_neutral_interactionstheElectronNeutralInteractionsinstance storing the tabulated cross-section dataneutral_species_index: the index of the neutral species being considered
Returns
The ionization threshold energy of a specific neutral species.
Merzbild.get_electron_energy_split — Function
get_electron_energy_split(electron_neutral_interactions, neutral_species_index)Get the way electron energy is split during ionization for a specific electron-neutral interaction. Here neutral_species_index is the index of the neutral species being considered in the overall array of the Species instances that includes all species in the simulation and was used to construct the ElectronNeutralInteractions instance.
Positional arguments
electron_neutral_interactionstheElectronNeutralInteractionsinstance storing the tabulated cross-section dataneutral_species_index: the index of the neutral species being considered
Returns
The ElectronEnergySplit value for the specific electron-neutral interaction.
Fokker-Planck computations
Merzbild.sample_normal_rands! — Function
sample_normal_rands!(rng, collision_data_fp, n_local)Sample 3*n_local normally distributed random numbers (with mean 0 and variance 1), one for each velocity component, and write them to a CollisionDataFP instance.
Positional arguments
rng: the random number generatorcollision_data_fp:CollisionDataFPinstance used for storing collisional quantitiesn_local: the number of particles to sample the numbers for
Merzbild.scale_norm_rands! — Function
scale_norm_rands!(collision_data_fp, particles, indexer, local_w)Scale sampled normally distributed random numbers velocity component-wise, so that their weight-averaged means for each component are exactly 0, and their weight-averaged variances are exactly 1. Weighting by the particles' computational weights is required so that the Langevin step conserves momentum (and hence energy) exactly for variable-weight particles; for equal-weight particles this reduces to the plain (unweighted) normalization.
Positional arguments
collision_data_fp:CollisionDataFPinstance used for storing collisional quantitiesparticles:ParticleVectorof the particles being collidedindexer: theParticleIndexerfor the cell/species being collided (pia.indexer[cell, species])local_w: the total computational weight of the particles in the cell
Merzbild.compute_relaxation_time — Function
compute_relaxation_time(interaction, species_data, species, V, es_old, local_w)Compute the relaxation time for a single-species flow, as given by $\tau = 2\mu / p$.
Positional arguments
interaction: theInteractioninstance for the self-interaction of the species in questionspecies_data: the vector ofSpeciesDataspecies: the index of the species for which collisions are performedV: cell volumees_old: the total kinetic energy of the particles in the cell, divided by the species' molecular masslocal_w: the total computational weight of the particles in the cell
Returns
The elastic collision relaxation time.
Electron-neutral interactions
Merzbild.TabulatedCSData — Type
TabulatedCSDataStructure for storing tabulated cross-section data as a function of relative collision energy
Fields
n_vals: number of values storedE: array of relative collision energiessigma: array of cross-section values at these energiesΔE: how much energy is lost (gained) in the collision in case it is inelastic
Merzbild.ElasticScattering — Type
ElasticScatteringStructure to hold data on an elastic scattering cross-section.
Fields
data: aTabulatedCSDatainstance holding the cross-section valuesscattering: theScatteringLawmodel for the scattering of the particles
Merzbild.ExcitationSink — Type
ExcitationSinkStructure to hold data on electron-impact electronic excitation cross-sections for a specific species.
Fields
n_reactions: number of electron-impact electronic excitation reactionsdata: an array ofTabulatedCSDatainstances (of lengthn_reactions) holding the cross-section values for each reactionscattering: theScatteringLawmodel for the scattering of the particles
Merzbild.Ionization — Type
IonizationStructure to hold data on an electron-impact ionization cross-section.
Fields
data: aTabulatedCSDatainstance holding the cross-section valuesscattering: theScatteringLawmodel for the scattering of the electronssplit: theElectronEnergySplitmodel for energy splitting across the primary and secondary electrons
Merzbild.find_species_in_db — Function
Find a chemical species in an LXCat-format XML; returns the first instance of the species found and the id of the "Groups" element in which the species was found. The following conditions need to be satisfied for a tuple (i,j) for it to be returned: tag(xml_data[i]) == "Groups" and attributes(xml_data[i][j])["id"] == species_name.
Positional arguments
xml_data: the LXCat-format XML data to be searchedspecies_name: the name of the species to search for
Returns
Tuple (i,j) denoting the index of the group and group element in which the species is located
Merzbild.load_elastic_data — Function
load_elastic_data(xml_data)Load electron-neutral elastic scattering data from the part of an LXCat-format XML file for a specific species. The following should hold for the data to be loaded: tag(xml_data[i]) == "Processes", attributes(xml_data[i][j])["type"] == "Ionization". This will load the first set of data found for the ionization process.
Positional arguments
xml_data: the LXCat-format XML data to be searched
Returns
TabulatedCSData structure containing the electron-neutral elastic scattering cross-section data.
Throws
DataMissingException if data not found or not all required data present.
Merzbild.load_ionization_data — Function
load_ionization_data(xml_data)Load electron-impact ionization data from the part of an LXCat-format XML file for a specific species. The following should hold for the data to be loaded: tag(xml_data[i]) == "Processes", attributes(xml_data[i][j])["type"] == "Ionization". This will load the first set of data found for the ionization process.
Positional arguments
xml_data: the LXCat-format XML data to be searched
Returns
TabulatedCSData structure containing the electron-impact ionization cross-section data.
Throws
DataMissingException if data not found or not all required data present.
Merging
Merzbild.GridCell — Type
GridCell{D}Struct for keeping track of merging-related quantities in a velocity grid cell with a D-dimensional position vector.
Fields
np: number of particles in cellw: total computational weight of particles in cellv_mean: mean velocity of particles in cellv_std_sq: variance of velocity of particles in cellx_mean: mean position of particles in cellx_std_sq: variance of position of particles in cellparticle_index1: index of first particle in the cell (first as in the first particle that is found to belong to the cell)particle_index2: index of second particle in the cell (second as in the second particle that is found to belong to the cell)w1: the post-merge weight to assign to the first particle in the cellw2: the post-merge weight to assign to the second particle in the cellv1: the post-merge velocity to assign to the first particle in the cellv2: the post-merge velocity to assign to the second particle in the cellx1: the post-merge position to assign to the first particle in the cellx2: the post-merge position to assign to the second particle in the cell
Merzbild.compute_velocity_extent! — Function
compute_velocity_extent!(merging_grid::GridN2Merge{D}, cell, species, species_data, phys_props::PhysProps) where DCompute extent of velocity grid based on temperature in the cell.
Positional arguments:
merging_grid: the grid merging (GridN2Merge) instance for which to compute the extentcell: the index of the cell in which the temperature was computedspecies: the index of the species for which the temperature was computedspecies_data: the array ofSpeciesdataphys_props: thePhysPropsinstance containing the computed temperature
compute_velocity_extent!(merging_grid::GridN2Merge{D}, vx_extent, vy_extent, vz_extent) where DCompute extent of velocity grid based on explicitly set extents.
Positional arguments:
merging_grid: the grid merging (GridN2Merge) instance for which to compute the extentvx_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
Merzbild.compute_grid_index — Function
compute_grid_index(merging_grid::GridN2Merge{D}, v) where DCompute index of cell on the merging grid in which a velocity is located (the last 8 indices correspond to the velocity octants outside the grid).
Positional arguments:
merging_grid: the grid merging (GridN2Merge) instance defining the velocity space gridv: the velocity vector
Returns:
Index of cell on the merging grid.
Merzbild.clear_merging_grid! — Function
clear_merging_grid!(merging_grid::GridN2Merge{D}) where DResets all data for a merging grid instance.
Positional arguments:
merging_grid: the grid merging (GridN2Merge) instance defining the velocity space grid
Merzbild.compute_grid! — Function
compute_grid!(merging_grid::GridN2Merge{D}, particles::ParticleVector{D}, pia, cell, species) where DCompute all the required cell properties for a grid-based merge.
Positional arguments:
merging_grid: the grid merging (GridN2Merge) instance defining the velocity space gridparticles: theParticleVectorinstance of the particles to be mergedpia: theParticleIndexerArrayinstancecell: the cell indexspecies: the species index
Merzbild.compute_new_particles! — Function
compute_new_particles!(rng, merging_grid::GridN2Merge{D}, particles::ParticleVector{D}, pia, cell, species) where DCompute new particles based on the grid cell properties without checking particle locations. So particles may end up outside of 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 index
compute_new_particles!(rng, merging_grid::GridN2Merge{D}, particles::ParticleVector{D}, pia, cell, species, grid::Grid1DUniform) where DCompute new particles based on the grid cell properties; placing out-of-domain particles 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 indexgrid: theGrid1DUniformgrid
compute_new_particles!(rng, octree::OctreeMerge{D,2}, particles::ParticleVector{D}, pia, cell, species) where DCompute post-merge particles with particles based on octree bin properties without checking or setting particle locations (for spatially homogeneous merging). N:2 merging in each bin.
Positional arguments:
rng: the random number generator instanceoctree: theOctreeMergeinstanceparticles: theParticleVectorinstance of the particles to be mergedpia: theParticleIndexerArrayinstancecell: the cell indexspecies: the species index
compute_new_particles!(rng, octree::OctreeMerge{D,2}, particles::ParticleVector{D}, pia, cell, species, grid::Grid1DUniform) where DCompute post-merge particles particles based on octree bin properties; placing out-of-domain particles back into the domain. N:2 merging in each bin.
Positional arguments:
rng: the random number generator instanceoctree: theOctreeMergeinstanceparticles: theParticleVectorinstance of the particles to be mergedpia: theParticleIndexerArrayinstancecell: the cell indexspecies: the species indexgrid: theGrid1DUniformgrid
compute_new_particles!(rng, octree::OctreeMerge{D,1}, particles::ParticleVector{D}, pia, cell, species) where DCompute post-merge particles with particles based on octree bin properties without checking or setting particle locations (for spatially homogeneous merging). N:1 merging in each bin. It computes properties of all particles. And after the first merge, it scales the particles' velocities based on these properties to achieve conservation.
Positional arguments:
rng: the random number generator instanceoctree: theOctreeMergeinstanceparticles: theParticleVectorinstance of 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
compute_new_particles!(rng, octree::OctreeMerge{D,1}, particles::ParticleVector{D}, pia, cell, species, grid::Grid1DUniform) where DCompute post-merge particles with particles based on octree bin properties, N:1 merging in each bin; placing out-of-domain particles back into the domain.. It computes properties of all particles. And after the first merge, it scales the particles based on these properties to achieve conservation.
Positional arguments:
rng: the random number generator instanceoctree: theOctreeMergeinstanceparticles: theParticleVectorinstance of 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
Merzbild.write_back_to_particles! — Function
write_back_to_particles!(octree::OctreeMerge{D,M}, particles::ParticleVector{D}, pia, cell, species) where {D,M}Write back merged particles to the particle array (0D case - position of particles not set). It will only be used in the function computenewparticles! without a grid argument, which means no boundary handling is needed.
Positional arguments:
octree: 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 merged
Returns
The current particle index after writing.
write_back_to_particles!(octree::OctreeMerge{D,M}, particles::ParticleVector{D}, pia, cell, species, grid::Grid1DUniform) where {D,M}Write back merged particles to the particle array with boundary clamping (1D case). Particles positioned outside the grid boundaries (grid.min_x, grid.max_x) are clamped to the boundary. It will only be used in the function computenewparticles! with grid::Grid1DUniform argument.
Positional arguments:
octree: 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 mergedgrid: theGrid1DUniforminstance
Returns
The current particle index after writing.
Merzbild.variance_scaling_rel_tol — Constant
Relative tolerance below which a post-merge variance is treated as having collapsed to zero, see variance_scaling.
Merzbild.variance_scaling — Function
variance_scaling(var_before::SVector{N,Float64}, var_post::SVector{N,Float64}) where NScale the the components of a variance vector var_before by the square root of the ratio of the components of it and a vector var_post, checking for zero/negative values in var_post and non-finite values in the scaling factor.
A component of var_post is treated as zero if it is not larger than variance_scaling_rel_tol times the corresponding component of var_before, and a scaling factor of 1.0 is returned for it. A plain var_post > 0.0 check is not enough: when all post-merge particles collapse onto the mean (e.g. an N:1 merge of a single octree bin), var_post is zero only in exact arithmetic, and is in practice a round-off residue of order eps()^2 * var_before. Scaling by sqrt(var_before / var_post) would then amplify that residue by ~1/eps() and destroy the conservation of the mean, instead of restoring a variance that cannot be restored by scaling in the first place.
Positional arguments
var_before: variance vector components of which to scalevar_post: variance vector components by which to scale
Merzbild.vx_sign — Function
vx_sign(octant)Return sign of velocity vx of an octant in velocity space.
Positional arguments
octant: index of the octant in velocity space
Returns
Sign of the x-velocity corresponding to the octant.
Merzbild.vy_sign — Function
vy_sign(octant)Return sign of velocity vy of an octant in velocity space.
Positional arguments
octant: index of the octant in velocity space
Returns
Sign of the y-velocity corresponding to the octant.
Merzbild.vz_sign — Function
vz_sign(octant)Return sign of velocity vz of an octant in velocity space.
Positional arguments
octant: index of the octant in velocity space
Returns
Sign of the z-velocity corresponding to the octant
Merzbild.base_multi_index_moments — Function
base_multi_index_moments()Base multi indices corresponding to conservation of mass, momentum, and energy components.
Positional arguments
None
Returns
A vector of multi-indices (3-tuples) which corresponding to mass, momentum, and directional energy.
Merzbild.compute_w_total_v0! — Function
compute_w_total_v0!(nnls_merging, particles::ParticleVector{D}, pia, cell, species) where DCompute total computational weight of particles and mean velocity, as well as velocity bounds of the set of particles in each velocity direction.
Positional arguments
nnls_merging: theNNLSMergeinstance where the computed values will be storedparticles: theParticleVectorinstance containing the particles that are being mergedpia: theParticleIndexerArrayinstancecell: the index of the grid cell in which particles are being mergedspecies: the index of the species being merged
Merzbild.fill_powers! — Function
fill_powers!(powers, v, v0)Fill a table of the powers of the components of the centered velocity / position vector v - v0, so that powers[j, e+1] holds (v[j] - v0[j])^e. Only the first size(powers, 1) components are considered, and powers up to size(powers, 2) - 1 are computed. Evaluating the moments off such a table avoids the runtime-exponent ^ calls that dominate the cost of building the LHS matrix.
Positional arguments
powers: the table of powers to fillv: the velocity / position vectorv0: the mean velocity / position vector
Merzbild.ccm_vel — Function
ccm_vel(vel_powers, mim)Compute an unweighted central velocity moment from a table of powers filled by fill_powers!.
Positional arguments
vel_powers: the table of powers of the centered velocity componentsmim: the 3-dimensional multi-index
Returns
Computed unweighted central moment.
Merzbild.ccm_pos — Function
ccm_pos(pos_powers, mim, D)Compute an unweighted central spatial moment from a table of powers filled by fill_powers!. Only the first D components of the multi-index are used, matching the dimensionality of the particle position vectors.
Positional arguments
pos_powers: the table of powers of the centered position componentsmim: the 3-dimensional multi-indexD: the dimensionality of the position vectors
Returns
Computed unweighted central moment.
Merzbild.compute_lhs_and_rhs! — Function
compute_lhs_and_rhs!(nnls_merging::NNLSMerge{D}, lhs_matrix, vel_pos_matrix, particles::ParticleVector{D}, pia, cell, species) where DCompute LHS matrix and RHS vector for NNLS merging. Returns the pre-merge number of particles.
Positional arguments
nnls_merging: theNNLSMergeinstance where the RHS vector will be storedlhs_matrix: the matrix of sizen_total_conserved x n_particles, wheren_total_conservedis the number of conserved moments andn_particlesis the pre-merge number of particles- any fictitious particles
vel_pos_matrix: the matrix of size6 x n_particles, wheren_particlesis the pre-merge number of particles- any fictitious particles, where their velocities and positions will be stored
particles: theParticleVectorinstance containing the particles that are being mergedpia: theParticleIndexerArrayinstancecell: the index of the grid cell in which particles are being mergedspecies: the index of the species being merged
Returns
The pre-merge number of particles.
Merzbild.compute_lhs_and_rhs_rate_preserving! — Function
compute_lhs_and_rhs_rate_preserving!(nnls_merging::NNLSMerge{D}, lhs_matrix, vel_pos_matrix,
interaction, electron_neutral_interactions, computed_cs,
particles::ParticleVector{D}, pia, cell, species, neutral_species_index, extend) where DCompute LHS matrix and RHS vector for the rate-preserving NNLS merging (for electrons). Approximate elastic scattering and electron-impact ionization rates are conserved.
Positional arguments
nnls_merging: theNNLSMergeinstance where the RHS vector will be storedlhs_matrix: the matrix of sizen_total_conserved x n_particles, wheren_total_conservedis the number of conserved moments andn_particlesis the pre-merge number of particles- any fictitious particles
vel_pos_matrix: the matrix of size6 x n_particles, wheren_particlesis the pre-merge number of particles- any fictitious particles, where their velocities and positions will be stored
interaction: 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 that are being 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.extend: enum ofCSExtendtype that sets how out-of-range energy values are treated when computing cross-sections
compute_lhs_and_rhs_rate_preserving!(nnls_merging::NNLSMerge{D}, lhs_matrix, vel_pos_matrix,
interaction, electron_neutral_interactions, computed_cs,
particles::ParticleVector{D}, particles_neutral::ParticleVector{D}, pia, cell, species, neutral_species_index, extend) where DCompute LHS matrix and RHS vector for the rate-preserving NNLS merging (for electrons). Exact elastic scattering and electron-impact ionization rates are conserved.
Positional arguments
nnls_merging: theNNLSMergeinstance where the RHS vector will be storedlhs_matrix: the matrix of sizen_total_conserved x n_particles, wheren_total_conservedis the number of conserved moments andn_particlesis the pre-merge number of particles- any fictitious particles
vel_pos_matrix: the matrix of size6 x n_particles, wheren_particlesis the pre-merge number of particles- any fictitious particles, where their velocities and positions will be stored
interaction: 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 that are being mergedparticles_neutrals: theParticleVectorinstance containing the neutral collision partner particlespia: 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.extend: enum ofCSExtendtype that sets how out-of-range energy values are treated when computing cross-sections
Merzbild.scale_lhs_rhs_variance! — Function
scale_lhs_rhs_variance!(nnls_merging::NNLSMerge{D}, lhs_matrix, lhs_ncols) where DScale the LHS and RHS of the NNLS system using the computed variances of the particles velocities in the $x$, $y$, $z$ directions. If any of the variances is smaller than 1e-6, then $v_{ref}$ is used. Each moment with multi-index (i,j,k) is scaled by $(1/Ev[1])^{i}(1/Ev[2])^{j}(1/Ev[3])^{k}$.
Positional arguments
nnls_merging: theNNLSMergeinstancelhs_matrix: the matrix of the LHSlhs_ncols: number of columns in the LHS matrix
Merzbild.scale_lhs_rhs_vref! — Function
scale_lhs_rhs_vref!(nnls_merging::NNLSMerge{D}, lhs_matrix, lhs_ncols) where DScale the LHS and RHS of the NNLS system using the reference velocity $v_{ref}$. Each moment is scaled by $(1/v_{ref})^{n_{tot}}$, where $n_{tot}$ is the total order of the moment (i.e. for a moment with multi-index (i,j,k) the total order is i+j+k).
Positional arguments
nnls_merging: theNNLSMergeinstancelhs_matrix: the matrix of the LHSlhs_ncols: number of columns in the LHS matrix
Merzbild.scale_lhs_rhs_spatial_variance! — Function
scale_lhs_rhs_spatial_variance!(nnls_merging::NNLSMerge{D}, lhs_matrix, lhs_ncols) where DScale the spatial moments in the LHS and RHS of the NNLS system using the computed variances of the particles positions in the $x$, $y$, $z$ directions. If any of the variances is smaller than 1e-6, then no scaling is done. Each spatial moment with multi-index (i,j,k) is scaled by $(1/Ex[1])^{i}(1/Ex[2])^{j}(1/Ex[3])^{k}$, for non-3-dimensional particle vectors only the first D components are considered and scaled.
Positional arguments
nnls_merging: theNNLSMergeinstancelhs_matrix: the matrix of the LHSlhs_ncols: number of columns in the LHS matrix
Merzbild.scale_lhs_rhs! — Function
scale_lhs_rhs!(nnls_merging::NNLSMerge{D}, lhs_matrix, scaling, lhs_ncols) where DScale the LHS and RHS of the NNLS system using either the reference velocity or the computed variances of the velocity in each direction.
Positional arguments
nnls_merging: theNNLSMergeinstancelhs_matrix: the matrix of the LHSscaling: how to scale entries (:vrefor:variance)lhs_ncols: number of columns in the LHS matrix
Merzbild.scale_lhs_rhs_rate_preserving! — Function
scale_lhs_rhs_rate_preserving!(nnls_merging, lhs_matrix, ref_k_elastic, ref_k_ion, scaling, lhs_ncols) where DScale the LHS and RHS of the NNLS system for the rate-preserving electron merging using the reference velocity $v_{ref}$ and reference elastic scattering and ionization cross-sections. Each moment is scaled by $(1/v_{ref})^{n_{tot}}$, where $n_{tot}$ is the total order of the moment (i.e. for a moment with multi-index (i,j,k) the total order is i+j+k). The entries in the LHS and RHS corresponding to the rates are scaled by ref_k_elastic, ref_k_ion.
Positional arguments
nnls_merging: theNNLSMergeinstancelhs_matrix: the matrix of the LHSref_k_elastic: the reference elastic collision rate coefficientref_k_ion: the reference ionization rate coefficientscaling: how to scale entries (:vrefor:variance)lhs_ncols: number of columns in the LHS matrix
Merzbild.compute_post_merge_particles_nnls! — Function
compute_post_merge_particles_nnls!(nnls_merging::NNLSMerge{3}, x::Vector{Float64}, particles::ParticleVector{3},
pia, cell, species, lhs_ncols,
vel_pos_matrix,
max_err, w_threshold, work_index, column_norms)Compute post-merge particles based on the solution of the NNLS problem. This will replace the particles with the post-merge ones and delete any extraneous particles.
Positional arguments
nnls_merging: theNNLSMergeinstancex: the solution vector of the NNLS systemparticles: theParticleVectorinstance containing the particles that are being mergedpia: theParticleIndexerArrayinstancecell: the index of the grid cell in which particles are being mergedspecies: the index of the species being mergedlhs_ncols: the number of columns in the LHS matrixvel_pos_matrix: the matrix of size6 x n_particles, wheren_particlesis the pre-merge number of particles- any fictitious particles, where their velocities and positions will be stored
max_err: maximum allowed value of the residual of the NNLS systemw_threshold: the relative (w.r.t the total computational weight of the particles being merge) value of the computational weight below which particles are discardedwork_index: the index of theNNLSWorkspaceused to solve the NNLS systemcolumn_norms: the vector of the column-wise norms of the LHS matrix
compute_post_merge_particles_nnls!(nnls_merging::NNLSMerge{2}, x::Vector{Float64}, particles::ParticleVector{2},
pia, cell, species, lhs_ncols,
vel_pos_matrix,
max_err, w_threshold, work_index, column_norms)Compute post-merge particles based on the solution of the NNLS problem. This will replace the particles with the post-merge ones and delete any extraneous particles.
Positional arguments
nnls_merging: theNNLSMergeinstancex: the solution vector of the NNLS systemparticles: theParticleVectorinstance containing the particles that are being mergedpia: theParticleIndexerArrayinstancecell: the index of the grid cell in which particles are being mergedspecies: the index of the species being mergedlhs_ncols: the number of columns in the LHS matrixvel_pos_matrix: the matrix of size6 x n_particles, wheren_particlesis the pre-merge number of particles- any fictitious particles, where their velocities and positions will be stored
max_err: maximum allowed value of the residual of the NNLS systemw_threshold: the relative (w.r.t the total computational weight of the particles being merge) value of the computational weight below which particles are discardedwork_index: the index of theNNLSWorkspaceused to solve the NNLS systemcolumn_norms: the vector of the column-wise norms of the LHS matrix
compute_post_merge_particles_nnls!(nnls_merging::NNLSMerge{1}, x::Vector{Float64}, particles::ParticleVector{1},
pia, cell, species, lhs_ncols,
vel_pos_matrix,
max_err, w_threshold, work_index, column_norms)Compute post-merge particles based on the solution of the NNLS problem. This will replace the particles with the post-merge ones and delete any extraneous particles.
Positional arguments
nnls_merging: theNNLSMergeinstancex: the solution vector of the NNLS systemparticles: theParticleVectorinstance containing the particles that are being mergedpia: theParticleIndexerArrayinstancecell: the index of the grid cell in which particles are being mergedspecies: the index of the species being mergedlhs_ncols: the number of columns in the LHS matrixvel_pos_matrix: the matrix of size6 x n_particles, wheren_particlesis the pre-merge number of particles- any fictitious particles, where their velocities and positions will be stored
max_err: maximum allowed value of the residual of the NNLS systemw_threshold: the relative (w.r.t the total computational weight of the particles being merge) value of the computational weight below which particles are discardedwork_index: the index of theNNLSWorkspaceused to solve the NNLS systemcolumn_norms: the vector of the column-wise norms of the LHS matrix
compute_post_merge_particles_nnls!(nnls_merging::NNLSMerge{1}, x::Vector{Float64}, particles::ParticleVector{1},
pia, cell, species, lhs_ncols,
vel_pos_matrix,
max_err, w_threshold, work_index, column_norms)Compute post-merge particles based on the solution of the NNLS problem. This will replace the particles with the post-merge ones and delete any extraneous particles.
Positional arguments
nnls_merging: theNNLSMergeinstancex: the solution vector of the NNLS systemparticles: theParticleVectorinstance containing the particles that are being mergedpia: theParticleIndexerArrayinstancecell: the index of the grid cell in which particles are being mergedspecies: the index of the species being mergedlhs_ncols: the number of columns in the LHS matrixvel_pos_matrix: the matrix of size6 x n_particles, wheren_particlesis the pre-merge number of particles- any fictitious particles, where their velocities and positions will be stored
max_err: maximum allowed value of the residual of the NNLS systemw_threshold: the relative (w.r.t the total computational weight of the particles being merge) value of the computational weight below which particles are discardedwork_index: the index of theNNLSWorkspaceused to solve the NNLS systemcolumn_norms: the vector of the column-wise norms of the LHS matrix
Merzbild.OctreeCell — Type
OctreeCellStruct holding computed bin properties needed for refinement of an octree bin.
Fields
np: number of particles in cellw: total computational weight of particles in cellv_min: vector of the per-component lower bounds of the velocities in the cellv_max: vector of the per-component upper bounds of the velocities in the celldepth: level of refinement the cell is atcan_be_refined: whether the cell can be refined further
Merzbild.OctreeFullCell — Type
OctreeFullCell{D,M}Struct holding computed bin properties required to merge the particles in a bin down to M particles.
Fields
v_mean: mean velocity of particles in cellv_std_sq: variance of velocity of particles in cellx_mean: mean position of particles in cellx_std_sq: variance of position of particles in cellparticle_indices: indices of particles in the cellweights: the post-merge weights to assign to the particles in the cellvelocities: the post-merge velocities to assign to the particles in the cellpositions: the post-merge positions to assign to the particles in the cell
Merzbild.fill_bins — Function
fill_bins(Nbins)Fill the octree bins structs with zero data, used as a utility function for initialization.
Positional arguments:
Nbins: number ofOctreeCellbins to create
Returns: An array of Nbins OctreeCell instances filled with zeros.
Merzbild.fill_full_bins — Function
fill_full_bins(::Val{D}, ::Val{M}, Nbins) where {D,M}Fill the octree bins full structs with zero data, used as a utility function for initialization.
Positional arguments:
D: dimension of position vectors of particles to be mergedM: number of post-merge particles in each binNbins: number ofOctreeFullCellbins to create
Returns: An array of Nbins OctreeFullCell instances filled with zeros.
Merzbild.clear_octree! — Function
clear_octree!(octree)Reset octree before doing a new merge.
Positional arguments:
octree: theOctreeMergeinstance
Merzbild.resize_octree_buffers! — Function
resize_octree_buffers!(octree, n_particles)Check and resize octree buffers if needed to accommodate a larger number of particles. The size of the buffers is set to n_particles + DELTA_PARTICLES if the their sizes are smaller than n_particles.
Positional arguments:
octree: theOctreeMergeinstancen_particles: the current number of particles being merged
Merzbild.compute_octant — Function
compute_octant(particle_v, v_middle)Compute octant of particle velocity relative to a v_middle` The order of the octants is:
1. - - -2. + - -3. - + -4. + + -5. - - +6. + - +7. - + +8. + + +Positional arguments:
particle_v: the velocity of the particlev_middle: the velocity relative to which the octant is computed
Returns:
The octant number
Merzbild.bin_bounds_inherit! — Function
bin_bounds_inherit!(octree, bin_id, v_min_parent, v_max_parent, v_middle, octant)Compute new bin bounds of one of the 8 octant sub-bins inheriting bounds of parent bin. The order of the octants is
1. - - -2. + - -3. - + -4. + + -5. - - +6. + - +7. - + +8. + + +Positional arguments:
octree: theOctreeMergeinstancebin_id: the index of the bin for which the velocity bounds are being recomputedv_min_parent: the velocity vector of the lower bound of the velocities of the parent binv_max_parent: the velocity vector of the upper bound of the velocities of the parent binv_middle: the velocity across which the split is being performedoctant: the octant of the parent bin to which this bin corresponds
Merzbild.bin_bounds_recompute! — Function
bin_bounds_recompute!(octree, bin_id, bs, be, particles::ParticleVector{D}) where DRecompute bin bounds based on particle velocities by setting them to the smallest and largest velocities of the particles in each velocity direction.
Positional arguments:
octree: theOctreeMergeinstancebin_id: the index of the bin for which the velocity bounds are being recomputedbs: index of the first particle in binbe: index of the last particle in binparticles: theParticleVectorinstance of the particles to be merged
Merzbild.compute_v_mean! — Function
compute_v_mean!(octree, bs, be, particles::ParticleVector{D}) where DCompute mean velocity of particles in a bin.
Positional arguments:
octree: theOctreeMergeinstancebs: index of the first particle in binbe: index of the last particle in binparticles: theParticleVectorinstance of the particles to be merged
Merzbild.compute_v_median! — Function
compute_v_median!(octree, bs, be, particles::ParticleVector{D}) where DCompute median velocity of particles in a bin. NOTE: allocates memory and is probably not fully correct!
Positional arguments:
octree: theOctreeMergeinstancebs: index of the first particle in binbe: index of the last particle in binparticles: theParticleVectorinstance of the particles to be merged
Merzbild.get_new_bin_id — Function
get_new_bin_id(i, bin_id, Nbins)Get index of a newly created bin once a bin with index bin_id is split into 8 sub-bins. The bin_id index is re-used for the 1-st sub-bin, and the other 7 sub-bins are tacked onto the end of the list of bins (so they have indices Nbins + 1, Nbins + 2, ..., where Nbins was the total number of octree bins before the split).
Positional arguments
i: index of sub-octant (ranging from 1 to 8) of the split bin for which to return a new bin indexbin_id: index of bin being splitNbins: total number of octree bins before the split
Returns
Index of a newly created bin corresponding to a bin created from sub-octant i of bin bin_id.
Merzbild.split_bin! — Function
split_bin!(octree::OctreeMerge{D,M}, bin_id, particles::ParticleVector{D}) where {D,M}Sort particles into sub-bins of a bin with index bin_id (by splitting it into octants), keeping track of which sub-bins particles end up in. Also sets the velocity bounds of the new bins.
Positional arguments:
octree: theOctreeMergeinstancebin_id: octree bin indexparticles: theParticleVectorinstance of the particles to be merged
Merzbild.compute_bin_props! — Function
compute_bin_props!(octree::OctreeMerge{D,M}, bin_id, particles::ParticleVector{D}) where {D,M}Compute properties in a bin required for merging: total computational weight, mean velocity and position, standard deviation of particle velocities and positions.
Positional arguments:
octree: theOctreeMergeinstancebin_id: octree bin indexparticles: theParticleVectorinstance of the particles to be merged
Merzbild.get_bin_post_merge_np — Function
get_bin_post_merge_np(octree::OctreeMerge{D,M}, bin_id) where {D,M}Get number of post-merge particles in a bin: M if the number of particles in the bin is >= M, otherwise the number of particles in the bin is returned.
Positional arguments:
octree: theOctreeMergeinstancebin_id: octree bin index
Returns
The number of post-merge particles in a single octree bin (0, 1, or 2).
Merzbild.init_octree! — Function
init_octree!(octree::OctreeMerge{D,M}, particles::ParticleVector{D}, pia, cell, species) where {D,M}Initialize the top bin in an octree by copying particle indices and setting bin bounds.
Positional arguments
octree: 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 merged
Merzbild.compute_octree! — Function
compute_octree!(octree::OctreeMerge{D,M}, particles::ParticleVector{D}, target_np) where {D,M}Perform refinement of an octree for N:2 merging until target number of particles reached or nothing left to refine.
Positional arguments
octree: theOctreeMergeinstanceparticles: theParticleVectorinstance containing the particles to be 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
Grids
Merzbild.Cell1D — Type
Cell1DCell element of a 1-D grid
Fields
xlo: coordinate of the left end of the elementxhi: coordinate of the right end of the elementV: cell volumeinv_V: inverse of cell volume
Merzbild.Cell1D — Method
Cell1D(xlo, xhi, V)Create cell of 1-D uniform grid
Positional arguments
xlo: coordinate of the left end of the elementxhi: coordinate of the right end of the elementV: cell volume
Merzbild.get_cell — Function
get_cell(grid1duniform::Grid1DUniform, x_pos::SVector{D,Float64}) where DFind in which cell of a 1-D uniform grid the coordinate is located
Positional arguments
grid1duniform: the 1-D uniform gridx_pos: the D-dimensional coordinate vector for which the cell index is to be determined (only the first component is used)
Returns
Index of cell the particle is located in
Particle movement
Merzbild.convect_single_particle! — Function
convect_single_particle!(rng, grid::Grid1DUniform, bc_list, particle::Particle{D}, species, Δt) where DConvect a singe particle 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)particle: the particle to be convectedspecies: the index of the species being convectedΔt: the convection timestep
convect_single_particle!(rng, grid::Grid1DUniform, bc_list, particle::Particle{D}, species, surf_props::SurfProps, mass, Δt) where DConvect a singe particle on a 1-D uniform grid, updating surface properties if it collides with a wall.
Positional arguments
rng: the random number generatorgrid: the grid on which the convection is performedbc_list: theTupleof boundary conditions (left and right wall)particle: the particle to be convectedspecies: the index of the species being convectedsurf_props: theSurfPropsstruct where the computed surface properties will be storedmass: the molecular mass of the speciesΔt: the convection timestep
Merzbild.convect_single_particle_periodic! — Function
convect_single_particle_periodic!(grid::Grid1DUniform, particle::Particle{D}, Δt) where DConvect a singe particle on a 1-D uniform grid assuming a periodic grid.
Positional arguments
grid: the grid on which the convection is performedparticle: the particle to be convectedΔt: the convection timestep
Merzbild.set_x — Function
set_x(x::SVector{D,Float64}, val::Float64) where DSet the x component of a Particle position vector.
Positional arguments
x: position vectorval: value to write in the 1-st component of the position vector
Returns
New position vector.
Particle-in-Cell
Merzbild.AbstractFieldBC1D — Type
AbstractFieldBC1DAbstract type for boundary conditions imposed on the electrostatic field in 1-D simulations. Not to be confused with AbstractBC, which describes particle-surface interaction.
Merzbild.poisson_unknowns — Function
poisson_unknowns(n_cells, bc_left, bc_right)Compute the number of unknowns of the discrete 1-D Poisson system and the offset between the index of an unknown and the index of the corresponding node, for a given pair of boundary conditions. Throws an error for the boundary condition combinations which are not admissible (Neumann on both sides, which is singular and leaves no way of fixing the gauge, and a periodic boundary condition paired with a non-periodic one).
Positional arguments
n_cells: number of cells of the gridbc_left: theAbstractFieldBC1Dboundary condition on the left boundarybc_right: theAbstractFieldBC1Dboundary condition on the right boundary
Returns
Tuple of the number of unknowns and the node offset.
Merzbild.set_neumann_diagonal_left! — Function
set_neumann_diagonal_left!(poisson_solver, bc_left)Replace the first row of the discrete Poisson matrix by the finite-volume integration over the left half-cell if the left boundary condition is a Neumann one, otherwise do nothing. The diagonal entry is halved with respect to an interior row, as the control volume of the boundary node is $\Delta x / 2$.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancebc_left: theAbstractFieldBC1Dboundary condition on the left boundary
Merzbild.set_neumann_diagonal_right! — Function
set_neumann_diagonal_right!(poisson_solver, bc_right)Replace the last row of the discrete Poisson matrix by the finite-volume integration over the right half-cell if the right boundary condition is a Neumann one, otherwise do nothing. The diagonal entry is halved with respect to an interior row, as the control volume of the boundary node is $\Delta x / 2$.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancebc_right: theAbstractFieldBC1Dboundary condition on the right boundary
Merzbild.factorize_poisson! — Function
factorize_poisson!(poisson_solver)Pre-compute the forward elimination of the tridiagonal matrix of the Thomas algorithm and store the inv_m, cp, and a_inv_m coefficients. These depend only on the matrix and not on the right-hand side, so with a fixed matrix only the right-hand side recurrence and the back substitution have to be performed per solve.
This assumes that the matrix never changes during a simulations, i.e. PIC grid and BC types are fixed (the prescribed values of the potential/electric fields at Dirichlet/Neumann BCs can vary).
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstance to be factorized
Merzbild.poisson_rhs_left! — Function
poisson_rhs_left!(poisson_solver, field_props, bc_left)Apply the correction of the first row of the right-hand side of the discrete Poisson system stemming from the left boundary condition: for a Dirichlet boundary condition, the eliminated known value of the potential in the boundary node is added to the right-hand side; for a Neumann boundary condition, the row is that of the finite-volume integration over the left half-cell, with a halved charge density and the prescribed value of the electric field.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancefield_props: theElectrostaticFieldPropsinstance holding the charge densitybc_left: theAbstractFieldBC1Dboundary condition on the left boundary
Merzbild.poisson_rhs_right! — Function
poisson_rhs_right!(poisson_solver, field_props, bc_right)Apply the correction of the last row of the right-hand side of the discrete Poisson system stemming from the right boundary condition, mirroring poisson_rhs_left!.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancefield_props: theElectrostaticFieldPropsinstance holding the charge densitybc_right: theAbstractFieldBC1Dboundary condition on the right boundary
Merzbild.assemble_poisson_rhs! — Function
assemble_poisson_rhs!(poisson_solver, field_props)Assemble the right-hand side of the discrete Poisson system from the charge density stored in field_props, applying the boundary corrections. In the periodic case, the mean charge density over the unique nodes is subtracted (otherwise the singular periodic system has no solution at all) and stored in field_props.net_charge_density; a non-zero value of the latter means that the simulation carries a net charge, which is unphysical in a periodic domain.
The charge density is not modified.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancefield_props: theElectrostaticFieldPropsinstance holding the charge density
Merzbild.solve_tridiagonal! — Function
solve_tridiagonal!(poisson_solver)Solve the tridiagonal system using the pre-computed factorization of the matrix (see factorize_poisson!) and the right-hand side stored in poisson_solver.rhs, storing the result in poisson_solver.x.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstance
Merzbild.apply_gauge! — Function
apply_gauge!(poisson_solver, field_props)Shift the potential in the unique nodes 1:n_cells of a periodic domain so that its mean is zero. On a periodic uniform grid this gauge is identical to requiring a zero mean of the cell-averaged potential, as each unique node contributes to exactly two cells.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancefield_props: theElectrostaticFieldPropsinstance holding the potential
Merzbild.finalize_potential_left! — Function
finalize_potential_left!(field_props, bc_left)Write the known value of the potential into the left boundary node for a Dirichlet boundary condition; for a Neumann boundary condition the boundary node is an unknown of the system and nothing is done.
Positional arguments
field_props: theElectrostaticFieldPropsinstance holding the potentialbc_left: theAbstractFieldBC1Dboundary condition on the left boundary
Merzbild.finalize_potential_right! — Function
finalize_potential_right!(field_props, bc_right)Write the known value of the potential into the right boundary node for a Dirichlet boundary condition, mirroring finalize_potential_left!.
Positional arguments
field_props: theElectrostaticFieldPropsinstance holding the potentialbc_right: theAbstractFieldBC1Dboundary condition on the right boundary
Merzbild.finalize_potential! — Function
finalize_potential!(poisson_solver, field_props)Write the values of the potential which are not part of the tridiagonal solution into the nodes: the prescribed values for Dirichlet boundary conditions, and, in the periodic case, the pinned value $\phi = 0$ in node n_cells (which has to be written every timestep, as a stale value left over from the previous timestep would corrupt both the gauge and the electric field in the neighbourhood of that node), followed by the gauge shift and the mirroring of node 1 into the last node.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancefield_props: theElectrostaticFieldPropsinstance holding the potential
Merzbild.electric_field_left! — Function
electric_field_left!(poisson_solver, field_props, bc_left)Compute the x-component of the electric field in the left boundary node: a one-sided difference of the potential for a Dirichlet boundary condition, and the prescribed value for a Neumann boundary condition.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancefield_props: theElectrostaticFieldPropsinstance holding the potential and the electric fieldbc_left: theAbstractFieldBC1Dboundary condition on the left boundary
Merzbild.electric_field_right! — Function
electric_field_right!(poisson_solver, field_props, bc_right)Compute the x-component of the electric field in the right boundary node: a one-sided difference of the potential for a Dirichlet boundary condition, and the prescribed value for a Neumann boundary condition.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancefield_props: theElectrostaticFieldPropsinstance holding the potential and the electric fieldbc_right: theAbstractFieldBC1Dboundary condition on the right boundary
Merzbild.compute_electric_field! — Function
compute_electric_field!(poisson_solver, field_props)Compute the x-component of the electric field $E_x = -d\phi/dx$ in the nodes from the potential, using central differences in the interior nodes and the boundary condition-specific treatment of the boundary nodes.
Positional arguments
poisson_solver: thePoissonSolver1DUniforminstancefield_props: theElectrostaticFieldPropsinstance holding the potential and the electric field
Particle-surface interactions
Merzbild.AbstractBC — Type
AbstractBCAbstract type for boundary conditions
Merzbild.specular_reflection_x! — Function
specular_reflection_x!(particle, Δt)Perform specular reflection of a particle in the x direction.
Positional arguments
particle: theParticleinstance for which the velocity is reflectedΔt: the time left for the particle to move
Returns
Unchanged value of Δt.
Merzbild.diffuse_reflection_x! — Function
diffuse_reflection_x!(rng, particle, wall_reflection_v_sq, wall_normal_sign, wall_v, Δt)Perform diffuse reflection of a particle, assuming the wall is orthogonal to the x axis.
Positional arguments
rng: the random number generatorparticle: theParticleinstance for which the velocity is reflectedwall_reflection_v_sq: the squared thermal velocity of the species reflected at the wall temperaturewall_normal_sign: sign of the wall normalwall_v: wall velocity vectorΔt: the time left for the particle to move
Returns
Unchanged value of Δt.
Merzbild.update_surface_incident! — Function
update_surface_incident!(particle, species, surf_props, surface_element_id)Update surface properties for surface element surface_element_id for an incident particle.
Positional arguments
particle: the particle hitting the surface before its velocity is updatedspecies: the species of the particlesurf_props: theSurfPropsinstancesurface_element_id: id of the surface element which the particle has impacted
Merzbild.update_surface_reflected! — Function
update_surface_reflected!(particle, species, surf_props, surface_element_id)Update surface properties for surface element surface_element_id for a reflected particle.
Positional arguments
particle: the particle hitting the surface after its velocity is updatedspecies: the species of the particlesurf_props: theSurfPropsinstancesurface_element_id: id of the surface element which the particle has impacted
Merzbild.surface_props_scale! — Function
surface_props_scale!(species, species_data, surf_props, Δt)Scale computed surface properties using the molecular mass of species, the inverse of the timestep, and the inverse surface area.
Positional arguments
species: the species of the particlespecies_data: the vector ofSpeciesDataof the chemical species in the flowsurf_props: theSurfPropsinstanceΔt: the timestep over which the surface properties were computed
Merzbild.apply_bc! — Function
apply_bc!(rng, particle::Particle{D}, wallbc::MaxwellWallBC1D, surface_normal::SVector{3,Float64}, Δt) where DApply a Maxwell 1D boundary condition.
Positional arguments
rng: the random number generatorparticle: theParticleinstance for which the velocity is reflectedwallbc: theMaxwellWallBC1Dinstancesurface_normal: the vector of the surface normalΔt: the time left for the particle to move
Returns
Unchanged value of Δt.
apply_bc!(rng, particle::Particle{D}, wallbc::FullyDiffuseBC1D, surface_normal::SVector{3,Float64}, Δt) where DApply a fully diffuse 1D boundary condition.
Positional arguments
rng: the random number generatorparticle: theParticleinstance to which the boundary condition is appliedwallbc: theFullyDiffuseBC1Dinstancesurface_normal: the vector of the surface normalΔt: the time left for the particle to move
Returns
Unchanged value of Δt.
apply_bc!(rng, particle::Particle{D}, wallbc::FullySpecularBC1D, surface_normal::SVector{3,Float64}, Δt) where DApply a fully specular 1D boundary condition.
Positional arguments
rng: the random number generatorparticle: theParticleinstance to which the boundary condition is appliedwallbc: theFullySpecularBC1Dinstancesurface_normal: the vector of the surface normalΔt: the time left for the particle to move
Returns
Unchanged value of Δt.
Merzbild.apply_bc_dispatched! — Function
apply_bc_dispatched!(rng, particle::Particle{D}, bcs::Tuple, i::Int, surface_normal::SVector{3,Float64}, Δt::Float64) where DGenerates a function that dispatches to the correct boundary condition function based on the index i. For use in a particle convection routine.
Positional arguments:
rng: the random number generatorparticle: theParticleinstance for which the boundary condition is appliedbcs: Tuple of boundary conditionsi: index of boundary condition to applysurface_normal: the vector of the surface normalΔt: the time left for the particle to move
Returns
Potentially changed value of Δt.
I/O
Merzbild.AbstractNCDataHolder — Type
AbstractNCDataHolderAbstract type that holds NetCDF-output related data for I/O
Parallel computations
Merzbild.swap_particles_true_index! — Function
swap_particles_true_index!(pv1::ParticleVector{D}, pv2::ParticleVector{D}, i, j) where DSwap particles pv1.particles[i] and pv2.particles[j] in two ParticleVector instances. This does not update any associated indices or buffers. This uses the underlying ("true") indices of the particles.
Positional arguments
pv1: the firstParticleVectorpv2: the secondParticleVectori: the underlying index of the particle inpv1j: the underlying index of the particle inpv2
Merzbild.swap_particles! — Function
swap_particles!(pv1::ParticleVector{D}, pv2::ParticleVector{D}, i, j) where DSwap particles pv1[i] and pv2[j] in two ParticleVector instances. This does not update any associated indices or buffers.
Positional arguments
pv1: the firstParticleVectorpv2: the secondParticleVectori: index of the particle inpv1j: index of the particle inpv2
Merzbild.update_swap_indexing! — Function
update_swap_indexing!(chunk_exchanger, pia_chunks, species, i, j, s_ci_ij, e_ci_ij, s_ji, n_swap)Updates index bookkeeping in chunk_exchanger for particles that were swapped from chunk i to chunk j.
After particles are swapped, this function records where in chunk j those particles from chunk i were placed, cell by cell. It does not perform the actual swapping. For correct bookkeeping it thus needs to be called twice, with all arguments dependent on i and j symmetrically swapped.
Positional arguments
chunk_exchanger: theChunkExchangerinstance to track post-swap and post-push indicespia_chunks: Vector ofParticleIndexerArrayinstances for each chunkspecies: the particle species being redistributedi: source chunk indexj: destination chunk indexs_ci_ij: start cell index in chunkifor the swape_ci_ij: end cell index in chunkifor the swaps_ji: starting index in chunkj's particle array where swapped particles from chunkiwere placedn_swap: total number of particles that were successfully swapped
Returns
s_ci_ij2: the last cell index in the iteration (i.e., where the last particle was swapped)offset_ij: number of particles swapped froms_ci_ij2, useful if the swap was interrupted mid-cell
Merzbild.push_particles! — Function
push_particles!(chunk_exchanger, particles_chunks::Vector{Vector{ParticleVector{D}}}, pia_chunks, species, i, j, offset_ij, s_ci_ij2, e_ci_ij) where DPushes particles of the specified species from chunk i to the end of chunk j, handling partial (unfinished) swaps.
This function finalizes a particle redistribution process between two spatial chunks in a parallel or chunked particle simulation. It ensures all remaining particles from chunk i that need to be moved to chunk j are properly transferred and indexed, even if the previous transfer process via swapping particles was interrupted mid-cell. This also updates the buffer of the source ParticleVector as particles are removed from it.
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 chunkspecies: the particle species being redistributedi: Source chunk indexj: Destination chunk indexoffset_ij: number of particles already transferred from a cell where swapping was performed but incomplete (0 if no incomplete swapping)s_ci_ij2: cell index in chunkiwhere the swapping was interrupted, or where the push should start in case no swapping was performede_ci_ij: final cell index to transfer from chunkito chunkj
Merzbild.push_particles_to_end! — Function
push_particles_to_end!(pv_i::ParticleVector{D}, pv_j::ParticleVector{D}, s2, e2, offset) where DCopy the particles pv_i[s2+offset:e2+offset] to the positions s2:e2 of pv_j, taking new particles in pv_j from its buffer, and adding the freed particles of pv_i to its buffer. This does not update any ParticleIndexer/ParticleIndexerArray indexing.
Positional arguments
pv_i: the sourceParticleVectorpv_j: the destinationParticleVectors2: first index inpv_jto write toe2: last index inpv_jto write tooffset: offset between the indices inpv_jand the indices of the particles inpv_i
Constants
Merzbild.c_light — Constant
Speed of light, m/s
Merzbild.eV — Constant
Electron-Volt, K
Merzbild.eV_J — Constant
Electron-Volt, J
Merzbild.eV_J_inv — Constant
1.0/eV[J], 1/J (or equivalent to how much 1 J is equal to expressed in eV)
Merzbild.twopi — Constant
$2 \pi$
Merzbild.e_mass_div_electron_volt — Constant
Electron mass divided by 1 eV, kg/J
Merzbild.direction_signs — Constant
Positive and negative direction signs
Merzbild.q_e — Constant
Elementary charge, C
Misc
Merzbild.create_position_vector_D — Function
create_position_vector_D(rng, ::Val{D}, xlo, xhi, ylo, yhi, zlo, zhi) where DHelper function to create D-dimensional position vectors for particle sampling in a 0/1/2/3-dimensional box with extent xlo:xhi, ylo:yhi, zlo:zhi; positions are uniformly distributed.
Positional arguments
rng: the random number generator::Val{D}: the dimension of the position vectorxlo- lower x-extent of the boxxhi- upper x-extent of the boxylo- lower y-extent of the boxyhi- upper y-extent of the boxzlo- lower z-extent of the boxzhi- upper z-extent of the box
Merzbild.compute_thermal_velocity — Function
compute_thermal_velocity(m, T)Compute the thermal velocity $\sqrt(2kT/m)$.
Positional arguments
m: the molecular mass of the speciesT: the temperature
Returns
The thermal velocity
Merzbild.binary_search — Function
binary_search(x, val)Binary search for value val in a sorted array x. Finds the position mid such that x[mid] < val < x[mid+1].
Positional arguments
x: the sorted array to be searchedval: the value to search for
Returns
-1ifval < x[1]0ifval > x[end]- Otherwise, returns the index
midsatisfyingx[mid] < val < x[mid+1]
Merzbild.linear_interpolation — Function
linear_interpolation(x, y, val, pos, lower_limit, upper_limit)Perform linear interpolation of a tabulated function y(x), given a parameter value val, a sorted array of values of x and corresponding values of y, as well as the index of the closest values of x to val. In case val is outside of the limits of x, return placeholder values. That is, given that x[pos] < val < x[pos+1], we want to interpolate y(val) given that y[x[pos]] = y[pos], y[x[pos+1]] = y[pos+1].
Positional arguments
x: the vector of values of the parameter of the function to be interpolatedy: the vector of the corresponding function valuesval: the value of the parameter at which the function is to be interpolatedpos: the index of the element inxsuch thatx[pos] < val < x[pos+1], or-1ifval < x[1],0ifval > x[end]lower_limit: the value to return ifval < x[1]upper_limit: the value to return ifval > x[end]
Returns
- The linearly interpolated value of
y(val)ifx[1] <= val <= x[end] lower_limit, ifval < x[1]upper_limit, ifval > x[end]
Merzbild.compute_mixed_moment — Function
compute_mixed_moment(particles, pia, cell, species, powers; sum_scaler=1.0, res_scaler=1.0)Compute mixed velocity moment of particles in a cell: $\sum_i w_i v_{x,i}^{p_x} v_{y,i}^{p_y} v_{z,i}^{p_z}$.
Positional arguments
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 computedpowers: aVectorof the powers to which the x-, y-, and z-components of the velocity are to be raised
Keyword arguments
sum_scaler: during the summation over the particles, scale each summand by this factor potentially reduce round-off issuesres_scaler: scaling factor by which to multiply the result at the end
Merzbild.scale_columns! — Function
scale_columns!(matrix, column_norms)Scale the columns of the matrix to have unit L2 norm and store the inverse of the original norm in a vector.
Positional arguments
matrix: the matrix of the LHScolumn_norms: the vector in which to store the computed inverses of the original column-wise norms
NNLS
Merzbild.solve! — Function
Algorithm NNLS: NONNEGATIVE LEAST SQUARES
The original version of this code was developed by Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory 1973 JUN 15, and published in the book "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. Revised FEB 1995 to accompany reprinting of the book by SIAM.
GIVEN AN M BY N MATRIX, A, AND AN M-VECTOR, B, COMPUTE AN N-VECTOR, X, THAT SOLVES THE LEAST SQUARES PROBLEM A * X = B SUBJECT TO X .GE. 0
Merzbild.construct_householder! — Function
CONSTRUCTION AND/OR APPLICATION OF A SINGLE HOUSEHOLDER TRANSFORMATION.. Q = I + U*(U**T)/B
The original version of this code was developed by Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory 1973 JUN 12, and published in the book "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. Revised FEB 1995 to accompany reprinting of the book by SIAM.
Merzbild.fastview — Function
UnsafeVectorView only works for isbitstype types. For other types, we're already allocating lots of memory elsewhere, so creating a new View is fine.
This function looks type-unstable, but the isbitstype(T) test can be evaluated by the compiler, so the result is actually type-stable.
Fallback for non-contiguous arrays, for which UnsafeVectorView does not make sense.
Merzbild.solve_triangular_system! — Function
The original version of this code was developed by Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory 1973 JUN 15, and published in the book "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. Revised FEB 1995 to accompany reprinting of the book by SIAM.
Merzbild.UnsafeVectorView — Type
Views in Julia still allocate some memory (since they need to keep a reference to the original array). This type allocates no memory and does no bounds checking. Use it with caution.
Merzbild.orthogonal_rotmat — Function
COMPUTE ORTHOGONAL ROTATION MATRIX.. The original version of this code was developed by Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory 1973 JUN 12, and published in the book "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. Revised FEB 1995 to accompany reprinting of the book by SIAM.
COMPUTE.. MATRIX (C, S) SO THAT (C, S)(A) = (SQRT(A2+B2)) (-S,C) (-S,C)(B) ( 0 ) COMPUTE SIG = SQRT(A2+B2) SIG IS COMPUTED LAST TO ALLOW FOR THE POSSIBILITY THAT SIG MAY BE IN THE SAME LOCATION AS A OR B .
Merzbild.apply_householder! — Function
CONSTRUCTION AND/OR APPLICATION OF A SINGLE HOUSEHOLDER TRANSFORMATION.. Q = I + U*(U**T)/B
The original version of this code was developed by Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory 1973 JUN 12, and published in the book "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. Revised FEB 1995 to accompany reprinting of the book by SIAM.
Merzbild.apply_householder_sweep! — Function
apply_householder_sweep!(A::Matrix{T}, up::T, ju, nsetp, m, idx, iz1, iz2) where TApply the Householder transformation held in rows nsetp:m of column ju of A to rows nsetp:m of every column in set Z, i.e. the columns idx[iz1], ..., idx[iz2].
This is a batched replacement for calling apply_householder! once per column. It is equivalent to that loop, but the reflector scalars (the up * u[1] sign test and the reciprocal 1 / (up * u[1])) are the same for every column, so they are computed once outside the column loop instead of once per column, and the columns are processed four at a time so that the reflector stays in registers and the four dot products overlap.
Positional arguments
A: the matrix being triangularizedup: the first component of the Householder vector, as returned byconstruct_householder!ju: index of the column holding the Householder vectornsetp: number of columns already moved to set P (the transformation acts on rowsnsetp:m)m: number of rows ofAidx: the index vector of the NNLS workspaceiz1,iz2: the range of positions inidxholding the set-Z columns