|
|
|
@ -1,525 +0,0 @@
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
|
|
|
http://lammps.sandia.gov, Sandia National Laboratories
|
|
|
|
|
Steve Plimpton, sjplimp@sandia.gov
|
|
|
|
|
|
|
|
|
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
|
|
|
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
|
|
|
|
certain rights in this software. This software is distributed under
|
|
|
|
|
the GNU General Public License.
|
|
|
|
|
|
|
|
|
|
See the README file in the top-level LAMMPS directory.
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
Contributing authors: Paul Crozier (SNL)
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
#include "math.h"
|
|
|
|
|
#include "stdio.h"
|
|
|
|
|
#include "stdlib.h"
|
|
|
|
|
#include "string.h"
|
|
|
|
|
#include "pair_dsmc.h"
|
|
|
|
|
#include "atom.h"
|
|
|
|
|
#include "comm.h"
|
|
|
|
|
#include "force.h"
|
|
|
|
|
#include "memory.h"
|
|
|
|
|
#include "error.h"
|
|
|
|
|
#include "domain.h"
|
|
|
|
|
#include "update.h"
|
|
|
|
|
#include "random_mars.h"
|
|
|
|
|
#include "limits.h"
|
|
|
|
|
|
|
|
|
|
using namespace LAMMPS_NS;
|
|
|
|
|
|
|
|
|
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
|
|
|
|
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
PairDSMC::PairDSMC(LAMMPS *lmp) : Pair(lmp)
|
|
|
|
|
{
|
|
|
|
|
single_enable = 0;
|
|
|
|
|
|
|
|
|
|
total_number_of_collisions = 0;
|
|
|
|
|
max_particles = max_particle_list = 0;
|
|
|
|
|
next_particle = NULL;
|
|
|
|
|
random = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
PairDSMC::~PairDSMC()
|
|
|
|
|
{
|
|
|
|
|
if (allocated) {
|
|
|
|
|
memory->destroy(setflag);
|
|
|
|
|
memory->destroy(cutsq);
|
|
|
|
|
memory->destroy(sigma);
|
|
|
|
|
memory->destroy(cut);
|
|
|
|
|
memory->destroy(V_sigma_max);
|
|
|
|
|
memory->destroy(particle_list);
|
|
|
|
|
memory->destroy(first);
|
|
|
|
|
memory->destroy(number);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete [] next_particle;
|
|
|
|
|
delete random;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void PairDSMC::compute(int eflag, int vflag)
|
|
|
|
|
{
|
|
|
|
|
double **x = atom->x;
|
|
|
|
|
double *mass = atom->mass;
|
|
|
|
|
int *type = atom->type;
|
|
|
|
|
int nlocal = atom->nlocal;
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i <= atom->ntypes; ++i)
|
|
|
|
|
for (int j = 0; j < total_ncells; ++j) {
|
|
|
|
|
first[i][j] = -1;
|
|
|
|
|
number[i][j] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (atom->nmax > max_particles) {
|
|
|
|
|
delete [] next_particle;
|
|
|
|
|
max_particles = atom->nmax;
|
|
|
|
|
next_particle = new int[max_particles];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// find each particle's cell and sort by type
|
|
|
|
|
// assume a constant volume and shape simulation domain
|
|
|
|
|
// skip particle if outside processor domain
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < nlocal; ++i) {
|
|
|
|
|
int xcell = static_cast<int>((x[i][0] - domain->boxlo[0])/cellx);
|
|
|
|
|
int ycell = static_cast<int>((x[i][1] - domain->boxlo[1])/celly);
|
|
|
|
|
int zcell = static_cast<int>((x[i][2] - domain->boxlo[2])/cellz);
|
|
|
|
|
|
|
|
|
|
if ((xcell < 0) or (xcell > ncellsx-1) or
|
|
|
|
|
(ycell < 0) or (ycell > ncellsy-1) or
|
|
|
|
|
(zcell < 0) or (zcell > ncellsz-1)) continue;
|
|
|
|
|
|
|
|
|
|
int icell = xcell + ycell*ncellsx + zcell*ncellsx*ncellsy;
|
|
|
|
|
itype = type[i];
|
|
|
|
|
next_particle[i] = first[itype][icell];
|
|
|
|
|
first[itype][icell] = i;
|
|
|
|
|
number[itype][icell]++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int icell = 0; icell < total_ncells; ++icell) {
|
|
|
|
|
|
|
|
|
|
for (itype = 1; itype <= atom->ntypes; ++itype) {
|
|
|
|
|
number_of_A = number[itype][icell];
|
|
|
|
|
if (number_of_A > max_particle_list) {
|
|
|
|
|
max_particle_list = number_of_A;
|
|
|
|
|
memory->grow(particle_list,atom->ntypes+1,max_particle_list,
|
|
|
|
|
"pair:particle_list");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int m = first[itype][icell];
|
|
|
|
|
for (int k = 0; k < number_of_A; k++) {
|
|
|
|
|
particle_list[itype][k] = m;
|
|
|
|
|
m = next_particle[m];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (itype = 1; itype <= atom->ntypes; ++itype) {
|
|
|
|
|
imass = mass[itype];
|
|
|
|
|
number_of_A = number[itype][icell];
|
|
|
|
|
|
|
|
|
|
for (jtype = itype; jtype <= atom->ntypes; ++jtype) {
|
|
|
|
|
jmass = mass[jtype];
|
|
|
|
|
number_of_B = number[jtype][icell];
|
|
|
|
|
|
|
|
|
|
reduced_mass = imass*jmass/(imass + jmass);
|
|
|
|
|
total_mass = imass + jmass;
|
|
|
|
|
jmass_tmass = jmass/total_mass;
|
|
|
|
|
imass_tmass = imass/total_mass;
|
|
|
|
|
|
|
|
|
|
// if necessary, recompute V_sigma_max values
|
|
|
|
|
|
|
|
|
|
if (recompute_vsigmamax_stride &&
|
|
|
|
|
(update->ntimestep % recompute_vsigmamax_stride == 0))
|
|
|
|
|
recompute_V_sigma_max(icell);
|
|
|
|
|
|
|
|
|
|
// # of collisions to perform for itype-jtype pairs
|
|
|
|
|
|
|
|
|
|
double &Vs_max = V_sigma_max[itype][jtype];
|
|
|
|
|
double num_of_collisions_double = number_of_A * number_of_B *
|
|
|
|
|
weighting * Vs_max * update->dt / vol;
|
|
|
|
|
|
|
|
|
|
if ((itype == jtype) and number_of_B)
|
|
|
|
|
num_of_collisions_double *=
|
|
|
|
|
0.5 * double(number_of_B - 1) / double(number_of_B);
|
|
|
|
|
|
|
|
|
|
int num_of_collisions =
|
|
|
|
|
convert_double_to_equivalent_int(num_of_collisions_double);
|
|
|
|
|
|
|
|
|
|
if (num_of_collisions > number_of_A)
|
|
|
|
|
error->warning("Pair dsmc: num_of_collisions > number_of_A",0);
|
|
|
|
|
if (num_of_collisions > number_of_B)
|
|
|
|
|
error->warning("Pair dsmc: num_of_collisions > number_of_B",0);
|
|
|
|
|
|
|
|
|
|
// perform collisions on pairs of particles in icell
|
|
|
|
|
|
|
|
|
|
for (int k = 0; k < num_of_collisions; k++) {
|
|
|
|
|
if ((number_of_A < 1) or (number_of_B < 1)) break;
|
|
|
|
|
int ith_A = static_cast<int>(random->uniform()*number_of_A);
|
|
|
|
|
int jth_B = static_cast<int>(random->uniform()*number_of_B);
|
|
|
|
|
int i = particle_list[itype][ith_A];
|
|
|
|
|
int j = particle_list[jtype][jth_B];
|
|
|
|
|
if (i == j) {
|
|
|
|
|
k--;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
double probability = V_sigma(i,j)/Vs_max;
|
|
|
|
|
if (probability > random->uniform()) scatter_random(i,j,icell);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
allocate all arrays
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void PairDSMC::allocate()
|
|
|
|
|
{
|
|
|
|
|
allocated = 1;
|
|
|
|
|
int n = atom->ntypes;
|
|
|
|
|
|
|
|
|
|
memory->create(setflag,n+1,n+1,"pair:setflag");
|
|
|
|
|
for (int i = 1; i <= n; i++)
|
|
|
|
|
for (int j = i; j <= n; j++)
|
|
|
|
|
setflag[i][j] = 0;
|
|
|
|
|
|
|
|
|
|
memory->create(cutsq,n+1,n+1,"pair:cutsq");
|
|
|
|
|
|
|
|
|
|
memory->create(cut,n+1,n+1,"pair:cut");
|
|
|
|
|
memory->create(sigma,n+1,n+1,"pair:sigma");
|
|
|
|
|
memory->create(V_sigma_max,n+1,n+1,"pair:V_sigma_max");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
global settings
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void PairDSMC::settings(int narg, char **arg)
|
|
|
|
|
{
|
|
|
|
|
if (narg != 6) error->all("Illegal pair_style command");
|
|
|
|
|
|
|
|
|
|
cut_global = 0.0;
|
|
|
|
|
max_cell_size = force->numeric(arg[0]);
|
|
|
|
|
seed = force->inumeric(arg[1]);
|
|
|
|
|
weighting = force->numeric(arg[2]);
|
|
|
|
|
T_ref = force->numeric(arg[3]);
|
|
|
|
|
recompute_vsigmamax_stride = force->inumeric(arg[4]);
|
|
|
|
|
vsigmamax_samples = force->inumeric(arg[5]);
|
|
|
|
|
|
|
|
|
|
// initialize Marsaglia RNG with processor-unique seed
|
|
|
|
|
|
|
|
|
|
if (max_cell_size <= 0.0) error->all("Illegal pair_style command");
|
|
|
|
|
if (seed <= 0) error->all("Illegal pair_style command");
|
|
|
|
|
if (random) delete random;
|
|
|
|
|
random = new RanMars(lmp,seed + comm->me);
|
|
|
|
|
|
|
|
|
|
kT_ref = force->boltz*T_ref;
|
|
|
|
|
|
|
|
|
|
// reset cutoffs that have been explicitly set
|
|
|
|
|
|
|
|
|
|
if (allocated) {
|
|
|
|
|
int i,j;
|
|
|
|
|
for (i = 1; i <= atom->ntypes; i++)
|
|
|
|
|
for (j = i+1; j <= atom->ntypes; j++)
|
|
|
|
|
if (setflag[i][j]) cut[i][j] = cut_global;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
set coeffs for one or more type pairs
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void PairDSMC::coeff(int narg, char **arg)
|
|
|
|
|
{
|
|
|
|
|
if (narg < 3 || narg > 4) error->all("Incorrect args for pair coefficients");
|
|
|
|
|
if (!allocated) allocate();
|
|
|
|
|
|
|
|
|
|
int ilo,ihi,jlo,jhi;
|
|
|
|
|
force->bounds(arg[0],atom->ntypes,ilo,ihi);
|
|
|
|
|
force->bounds(arg[1],atom->ntypes,jlo,jhi);
|
|
|
|
|
|
|
|
|
|
double sigma_one = force->numeric(arg[2]);
|
|
|
|
|
|
|
|
|
|
double cut_one = cut_global;
|
|
|
|
|
if (narg == 4) cut_one = force->numeric(arg[3]);
|
|
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
for (int i = ilo; i <= ihi; i++) {
|
|
|
|
|
for (int j = MAX(jlo,i); j <= jhi; j++) {
|
|
|
|
|
sigma[i][j] = sigma_one;
|
|
|
|
|
cut[i][j] = cut_one;
|
|
|
|
|
setflag[i][j] = 1;
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (count == 0) error->all("Incorrect args for pair coefficients");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
init specific to this pair style
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void PairDSMC::init_style()
|
|
|
|
|
{
|
|
|
|
|
ncellsx = ncellsy = ncellsz = 1;
|
|
|
|
|
while (((domain->boxhi[0] - domain->boxlo[0])/ncellsx) > max_cell_size)
|
|
|
|
|
ncellsx++;
|
|
|
|
|
while (((domain->boxhi[1] - domain->boxlo[1])/ncellsy) > max_cell_size)
|
|
|
|
|
ncellsy++;
|
|
|
|
|
while (((domain->boxhi[2] - domain->boxlo[2])/ncellsz) > max_cell_size)
|
|
|
|
|
ncellsz++;
|
|
|
|
|
|
|
|
|
|
cellx = (domain->boxhi[0] - domain->boxlo[0])/ncellsx;
|
|
|
|
|
celly = (domain->boxhi[1] - domain->boxlo[1])/ncellsy;
|
|
|
|
|
cellz = (domain->boxhi[2] - domain->boxlo[2])/ncellsz;
|
|
|
|
|
|
|
|
|
|
if (comm->me == 0) {
|
|
|
|
|
if (screen) fprintf(screen,"DSMC cell size = %g x %g x %g\n",
|
|
|
|
|
cellx,celly,cellz);
|
|
|
|
|
if (logfile) fprintf(logfile,"DSMC cell size = %g x %g x %g\n",
|
|
|
|
|
cellx,celly,cellz);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
total_ncells = ncellsx*ncellsy*ncellsz;
|
|
|
|
|
vol = cellx*celly*cellz;
|
|
|
|
|
|
|
|
|
|
memory->create(particle_list,atom->ntypes+1,0,"pair:particle_list");
|
|
|
|
|
memory->create(first,atom->ntypes+1,total_ncells,"pair:first");
|
|
|
|
|
memory->create(number,atom->ntypes+1,total_ncells,"pair:number");
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i <= atom->ntypes; i++)
|
|
|
|
|
for (int j = 1; j <= atom->ntypes; j++)
|
|
|
|
|
V_sigma_max[i][j] = 0.0;
|
|
|
|
|
|
|
|
|
|
two_pi = 8.0*atan(1.0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
init for one type pair i,j and corresponding j,i
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
double PairDSMC::init_one(int i, int j)
|
|
|
|
|
{
|
|
|
|
|
if (setflag[i][j] == 0) cut[i][j] = 0.0;
|
|
|
|
|
return cut[i][j];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
proc 0 writes to restart file
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void PairDSMC::write_restart(FILE *fp)
|
|
|
|
|
{
|
|
|
|
|
write_restart_settings(fp);
|
|
|
|
|
|
|
|
|
|
int i,j;
|
|
|
|
|
for (i = 1; i <= atom->ntypes; i++)
|
|
|
|
|
for (j = i; j <= atom->ntypes; j++) {
|
|
|
|
|
fwrite(&setflag[i][j],sizeof(int),1,fp);
|
|
|
|
|
if (setflag[i][j]) {
|
|
|
|
|
fwrite(&sigma[i][j],sizeof(double),1,fp);
|
|
|
|
|
fwrite(&cut[i][j],sizeof(double),1,fp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
proc 0 reads from restart file, bcasts
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void PairDSMC::read_restart(FILE *fp)
|
|
|
|
|
{
|
|
|
|
|
read_restart_settings(fp);
|
|
|
|
|
allocate();
|
|
|
|
|
|
|
|
|
|
int i,j;
|
|
|
|
|
int me = comm->me;
|
|
|
|
|
for (i = 1; i <= atom->ntypes; i++)
|
|
|
|
|
for (j = i; j <= atom->ntypes; j++) {
|
|
|
|
|
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
|
|
|
|
|
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
|
|
|
|
|
if (setflag[i][j]) {
|
|
|
|
|
if (me == 0) {
|
|
|
|
|
fread(&sigma[i][j],sizeof(double),1,fp);
|
|
|
|
|
fread(&cut[i][j],sizeof(double),1,fp);
|
|
|
|
|
}
|
|
|
|
|
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
|
|
|
|
|
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
proc 0 writes to restart file
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void PairDSMC::write_restart_settings(FILE *fp)
|
|
|
|
|
{
|
|
|
|
|
fwrite(&cut_global,sizeof(double),1,fp);
|
|
|
|
|
fwrite(&max_cell_size,sizeof(double),1,fp);
|
|
|
|
|
fwrite(&seed,sizeof(int),1,fp);
|
|
|
|
|
fwrite(&offset_flag,sizeof(int),1,fp);
|
|
|
|
|
fwrite(&mix_flag,sizeof(int),1,fp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
proc 0 reads from restart file, bcasts
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void PairDSMC::read_restart_settings(FILE *fp)
|
|
|
|
|
{
|
|
|
|
|
if (comm->me == 0) {
|
|
|
|
|
fread(&cut_global,sizeof(double),1,fp);
|
|
|
|
|
fread(&max_cell_size,sizeof(double),1,fp);
|
|
|
|
|
fread(&seed,sizeof(int),1,fp);
|
|
|
|
|
fread(&offset_flag,sizeof(int),1,fp);
|
|
|
|
|
fread(&mix_flag,sizeof(int),1,fp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
|
|
|
|
|
MPI_Bcast(&max_cell_size,1,MPI_DOUBLE,0,world);
|
|
|
|
|
MPI_Bcast(&seed,1,MPI_INT,0,world);
|
|
|
|
|
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
|
|
|
|
|
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
|
|
|
|
|
|
|
|
|
|
// initialize Marsaglia RNG with processor-unique seed
|
|
|
|
|
// same seed that pair_style command initially specified
|
|
|
|
|
|
|
|
|
|
if (random) delete random;
|
|
|
|
|
random = new RanMars(lmp,seed + comm->me);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
rezero and recompute the V_sigma_max values this timestep for use during
|
|
|
|
|
the next nrezero timesteps
|
|
|
|
|
-------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
void PairDSMC::recompute_V_sigma_max(int icell)
|
|
|
|
|
{
|
|
|
|
|
int i,j,k;
|
|
|
|
|
double Vsigma_max = 0;
|
|
|
|
|
|
|
|
|
|
if (number_of_A && number_of_B) {
|
|
|
|
|
for (k = 0; k < vsigmamax_samples; k++) {
|
|
|
|
|
i = particle_list[itype]
|
|
|
|
|
[static_cast<int>(random->uniform()*number_of_A)];
|
|
|
|
|
j = particle_list[jtype]
|
|
|
|
|
[static_cast<int>(random->uniform()*number_of_B)];
|
|
|
|
|
if (i == j) continue;
|
|
|
|
|
Vsigma_max = MAX(Vsigma_max,V_sigma(i,j));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
V_sigma_max[itype][jtype] = Vsigma_max;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
VHS model
|
|
|
|
|
compute the velocity vector difference between i and j and multiply by
|
|
|
|
|
their combined collision cross section, sigma, for neutral-neutral
|
|
|
|
|
collisions using the Variable Hard Sphere model
|
|
|
|
|
-------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
double PairDSMC::V_sigma(int i, int j)
|
|
|
|
|
{
|
|
|
|
|
double relative_velocity_sq,relative_velocity,pair_sigma;
|
|
|
|
|
double delv[3];
|
|
|
|
|
double *vi = atom->v[i];
|
|
|
|
|
double *vj = atom->v[j];
|
|
|
|
|
|
|
|
|
|
subtract3d(vi,vj,delv);
|
|
|
|
|
relative_velocity_sq = dot3d(delv,delv);
|
|
|
|
|
relative_velocity = sqrt(relative_velocity_sq);
|
|
|
|
|
|
|
|
|
|
// from Bird eq 4.63, and omega=0.67
|
|
|
|
|
// (omega - 0.5) = 0.17
|
|
|
|
|
// 1/GAMMA(2.5 - omega) = 1.06418029298371
|
|
|
|
|
|
|
|
|
|
if (relative_velocity_sq != 0.0)
|
|
|
|
|
pair_sigma = sigma[itype][jtype]*
|
|
|
|
|
pow(kT_ref/(0.5*reduced_mass*relative_velocity_sq),0.17) *
|
|
|
|
|
1.06418029298371;
|
|
|
|
|
else
|
|
|
|
|
pair_sigma = 0.0;
|
|
|
|
|
|
|
|
|
|
return relative_velocity*pair_sigma;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
generate new velocities for collided particles
|
|
|
|
|
-------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
void PairDSMC::scatter_random(int i, int j, int icell)
|
|
|
|
|
{
|
|
|
|
|
double mag_delv,cos_phi,cos_squared,r,theta;
|
|
|
|
|
double delv[3],vcm[3];
|
|
|
|
|
double *vi = atom->v[i];
|
|
|
|
|
double *vj = atom->v[j];
|
|
|
|
|
|
|
|
|
|
subtract3d(vi,vj,delv);
|
|
|
|
|
if (itype == jtype) mag_delv = sqrt(dot3d(delv,delv))*0.5;
|
|
|
|
|
else mag_delv = sqrt(dot3d(delv,delv));
|
|
|
|
|
|
|
|
|
|
cos_phi = 1.0 - (2.0*random->uniform());
|
|
|
|
|
cos_squared = MIN(1.0,cos_phi*cos_phi);
|
|
|
|
|
r = sqrt(1.0 - cos_squared);
|
|
|
|
|
delv[0] = cos_phi*mag_delv;
|
|
|
|
|
theta = two_pi*random->uniform();
|
|
|
|
|
delv[1] = r*mag_delv*cos(theta);
|
|
|
|
|
delv[2] = r*mag_delv*sin(theta);
|
|
|
|
|
|
|
|
|
|
if (itype == jtype) {
|
|
|
|
|
vcm[0] = (vi[0]+vj[0])*0.5;
|
|
|
|
|
vcm[1] = (vi[1]+vj[1])*0.5;
|
|
|
|
|
vcm[2] = (vi[2]+vj[2])*0.5;
|
|
|
|
|
vi[0] = vcm[0] + delv[0];
|
|
|
|
|
vi[1] = vcm[1] + delv[1];
|
|
|
|
|
vi[2] = vcm[2] + delv[2];
|
|
|
|
|
vj[0] = vcm[0] - delv[0];
|
|
|
|
|
vj[1] = vcm[1] - delv[1];
|
|
|
|
|
vj[2] = vcm[2] - delv[2];
|
|
|
|
|
} else {
|
|
|
|
|
vcm[0] = vi[0]*imass_tmass + vj[0]*jmass_tmass;
|
|
|
|
|
vcm[1] = vi[1]*imass_tmass + vj[1]*jmass_tmass;
|
|
|
|
|
vcm[2] = vi[2]*imass_tmass + vj[2]*jmass_tmass;
|
|
|
|
|
vi[0] = vcm[0] + delv[0]*jmass_tmass;
|
|
|
|
|
vi[1] = vcm[1] + delv[1]*jmass_tmass;
|
|
|
|
|
vi[2] = vcm[2] + delv[2]*jmass_tmass;
|
|
|
|
|
vj[0] = vcm[0] - delv[0]*imass_tmass;
|
|
|
|
|
vj[1] = vcm[1] - delv[1]*imass_tmass;
|
|
|
|
|
vj[2] = vcm[2] - delv[2]*imass_tmass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
total_number_of_collisions++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
This method converts the double supplied by the calling function into
|
|
|
|
|
an int, which is returned. By adding a random number between 0 and 1
|
|
|
|
|
to the double before converting it to an int, we ensure that,
|
|
|
|
|
statistically, we round down with probability identical to the
|
|
|
|
|
remainder and up the rest of the time. So even though we're using an
|
|
|
|
|
integer, we're statistically matching the exact expression represented
|
|
|
|
|
by the double.
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
int PairDSMC::convert_double_to_equivalent_int(double input_double)
|
|
|
|
|
{
|
|
|
|
|
if (input_double > INT_MAX)
|
|
|
|
|
error->all("Tried to convert a double to int, but input_double > INT_MAX");
|
|
|
|
|
|
|
|
|
|
int output_int = static_cast<int>(input_double + random->uniform());
|
|
|
|
|
return output_int;
|
|
|
|
|
}
|