Collision routine
Rather than analyzing the individual trajectories of any particle, a collision can generally occur for each pair of particles which are within the same sub-cell.
The collision rate within a cell is calculated as follows: The product of the relative velocity and the corresponding cross section multiplied with the time step spans a cylindrical volume. The ratio of this volume and the cell volume is the collision probability :
Thus, if we assume that the collision cross section and all relative velocities are constant, the number of expected collisions in one cell between two species A and B can be simply calculated by:
The additional parameters in this equation are:
- = The number of simulation particles of species A and B within the cell
- = The scaling factor between real and simulated particle number (which is assumed to be the same for species A and B, here)
NTC algorithm
In reality, all relative velocities and corresponding cross sections are different. In this case, the so called "NTC-Method"1 is applied, which is a variation of the acceptance-reject method of statistics: For each collision type, the maximum product is determined from the sampled data of . Then, the number of pair selections is determined as maximum possible collisions in one cell (i. e. assumed that the product is maximal for all possible collision pairs in one cell):
In the follwing, collision pairs are randomly selected within the sub-cell. The actual relativ velocity and energy is calculated from:
For a selected collision pair, the collision is actually performed, if the following random experiment holds:
where is a random number in [0, 1].
General NTC implementation with reaction products
We denote as the mean product of relative velocity and cross section of a collision type within one cell. Further, we have species A with weighting factor , species B with weighting factor and reaction product C with weighting factor . It shall be assumed that . Further, in the current simulation volume, there may be a scaling factor for all weighting factors. Under these conditions, the physical number of collisions within a cell becomes:
To determine the number of collisions occurring for the simulation particles, this quantity is to be divided by their respective weighting factor or and by :
With , the quantity
is identical with NR_Preselect in the PICMC code,
and is denoted as
F1_Postselect. F1_Postselect is the probability that the
post-collision velocities are applied to the first species with the
heigher statistical weigth. The corresponding factor F2_Postselect for
the lightweigth species is 1.0. If we now have reaction products of
species C the number of reaction products created by the collision
becomes:
For , multiple reaction products are created for each collision, if only a fraction of of the collisions result into a reaction product.
Within the PICMC code this is handled in the following functions:
void DSMC_Volume::pvm_set_collision(...)void DSMC_Volume::collision()
In void DSMC_Volume::pvm_set_collision(...) the above described pre-
and postcollision selection factors are defined as follows:
// picmc.cxx line 3376 ff
void DSMC_Volume::pvm_set_collision(int i1, int cflag1,
int i2, int cflag2,
double max_eV,
double alpha, double thresh_eV,
int nrp, int *rp, int ncs, double *cs) {
/* ... */
double &NR1 = DSMC_Base::pp[i1].nreal,
&NR2 = DSMC_Base::pp[i2].nreal;
plist -> NR_Preselect = (NR1 > NR2) ? NR1 : NR2;
plist -> F1_Postselect = (NR1 > NR2) ? NR2/NR1 : 1.0;
plist -> F2_Postselect = (NR1 > NR2) ? 1.0 : NR1/NR2;
/* ... */
}
Generally, the post-collision selection factor for species A/B can be written as:
The generation of reaction products can be found in
DSMC_Volume::collision(...), here the most relevant lines are as
follows:
/* ... */
minnr = minnr = pp[spec_1].nreal*pp[spec_2].nreal / plist->NR_Preselect;
/* ... */
if(pp[plist->rp[i]].nreal < minnr) {
for(j = 0; j < (minnr/pp[plist->rp[i]].nreal); j++)
p3d[plist->rp[i]]->insert(x, y, z, vx, vy, vz, 0.0, icell);
//statistical handling of reminder if nreal not whole-numbered
if(random.fetch() < ((minnr/pp[plist->rp[i]].nreal) - j + 1))
p3d[plist->rp[i]]->insert(x, y, z, vx, vy, vz, 0.0, icell);
} else {
if(random.fetch() < (minnr/pp[plist->rp[i]].nreal))
p3d[plist->rp[i]]->insert(x, y, z, vx, vy, vz, 0.0, icell);
}
/* ... */
Handling of frozen species
In some scenarios, species can be frozen, i. e. they are loaded into memory and take part within the collision but do not move themselfes. Also, any post-collision velocity is not applied to frozen species. An example is a transport simulation using the species where are frozen. The purpose of such a simulation is to split the time scales in order to speed up the simulation. In an RF parallel plate plasma with the considered species, the population of and becomes stable already after a few microseconds, while the stabilization time of the population (as reaction product from dissociation of ) is larger by many orders of magnitude. Given the species A and B, then for a frozen species B the collision numbers as described above become:
Now, it turns out that computation time can be saved by using
instead of as NR_Preselect. In
this case, also the post-collision production factor of collision
products is modified, the number of collision products becomes:
i. e. the collision selection factor is now instead of . In the above mentioned PICMC code this is handled automatically. However this is problematic, if is much higher than 1 - in our current example, we have and . Thus, the creation of reaction products is a very rare incident in the PICMC simulation, but if this incident occurs, reaction products are created at once!
As a correction, the pre-selection factor has to be chosen in a way, that one collision product is generated for each collision:
The post-collision selection factors are determined as stated above. If multiple reation products occur, the minimum of their weighting factors should be inserted in the denominator. Now, a simple way to speed up the computation is to increase the weighting factor of the reaction product.
The frozen species are treated in
DSMC_Volume::pvm_set_collision(...) as follows.
// picmc.cxx line 3376 ff
void DSMC_Volume::pvm_set_collision(int i1, int cflag1,
int i2, int cflag2,
double max_eV,
double alpha, double thresh_eV,
int nrp, int *rp, int ncs, double *cs) {
/* ... */
double &NR1 = DSMC_Base::pp[i1].nreal,
&NR2 = DSMC_Base::pp[i2].nreal;
plist -> NR_Preselect = (NR1 > NR2) ? NR1 : NR2;
plist -> F1_Postselect = (NR1 > NR2) ? NR2/NR1 : 1.0;
plist -> F2_Postselect = (NR1 > NR2) ? 1.0 : NR1/NR2;
double NR_tmp,
NR_RP = (NR1 > NR2) ? NR1 : NR2;
int irp;
for(irp=0; irp<nrp; ++irp) {
NR_tmp = DSMC_Base::pp[rp[irp]].nreal;
if (NR_tmp < NR_RP) NR_RP = NR_tmp;
}
if(plist->cflag1 & 0x02) {
plist -> NR_Preselect = NR1 * NR2 / NR_RP;
plist -> F1_Postselect = 0.0; // frozen
plist -> F2_Postselect = NR_RP/NR2;
}
if(plist->cflag2 & 0x02) {
plist -> NR_Preselect = NR1 * NR2 / NR_RP;
plist -> F1_Postselect = NR_RP/NR1;
plist -> F2_Postselect = 0.0; // frozen
}
/* ... */
}