public double erot(int isp, double temp_thermal, RanPark erandom) { double eng, a, erm, b; if (sparta.collide == null || sparta.collide.rotstyle == (int)Enum2.NONE) { return(0.0); } if (species[isp].rotdof < 2) { return(0.0); } if (species[isp].rotdof == 2) { eng = -Math.Log(erandom.uniform()) * sparta.update.boltz * temp_thermal; } else { a = 0.5 * sparta.particle.species[isp].rotdof - 1.0; while (true) { // energy cut-off at 10 kT erm = 10.0 * erandom.uniform(); b = Math.Pow(erm / a, a) * Math.Exp(a - erm); if (b > erandom.uniform()) { break; } } eng = erm * sparta.update.boltz * temp_thermal; } return(eng); }
public double evib(int isp, double temp_thermal, RanPark erandom) { double eng, a, erm, b; int vibstyle = (int)Enum2.NONE; if (sparta.collide != null) { vibstyle = sparta.collide.vibstyle; } if (vibstyle == (int)Enum2.NONE || species[isp].vibdof < 2) { return(0.0); } eng = 0.0; if (vibstyle == (int)Enum2.DISCRETE && species[isp].vibdof == 2) { int ivib = Convert.ToInt32(-Math.Log(erandom.uniform()) * temp_thermal / sparta.particle.species[isp].vibtemp); eng = ivib * sparta.update.boltz * sparta.particle.species[isp].vibtemp; } else if (vibstyle == (int)Enum2.SMOOTH || species[isp].vibdof >= 2) { if (species[isp].vibdof == 2) { eng = -Math.Log(erandom.uniform()) * sparta.update.boltz * temp_thermal; } else if (species[isp].vibdof > 2) { a = 0.5 * sparta.particle.species[isp].vibdof - 1; while (true) { // energy cut-off at 10 kT erm = 10.0 * erandom.uniform(); b = Math.Pow(erm / a, a) * Math.Exp(a - erm); if (b > erandom.uniform()) { break; } } eng = erm * sparta.update.boltz * temp_thermal; } } return(eng); }
public void command(int narg, string[] args) { string[] arg = new string[narg]; Array.Copy(args, 1, arg, 0, narg); if (sparta.domain.box_exist == 0) { sparta.error.all("Cannot create grid before simulation box is defined"); } if (sparta.grid.exist != 0) { sparta.error.all("Cannot create grid when grid is already defined"); } sparta.grid.exist = 1; if (narg < 3) { sparta.error.all("Illegal create_grid command"); } int nx = int.Parse(arg[0]); int ny = int.Parse(arg[1]); int nz = int.Parse(arg[2]); if (nx < 1 || ny < 1 || nz < 1) { sparta.error.all("Illegal create_grid command"); } if (sparta.domain.dimension == 2 && nz != 1) { sparta.error.all("Create_grid nz value must be 1 for a 2d simulation"); } // optional args dimension = sparta.domain.dimension; int nlevels = 1; int bstyle = (int)Enum1.NONE; int px = 0; int py = 0; int pz = 0; int order = 0; int inside = (int)Enum3.ANY; int iarg = 3; while (iarg < narg) { if (string.Equals(arg[iarg], "level")) { if (iarg + 8 > narg) { sparta.error.all("Illegal create_grid command"); } if (bstyle != (int)Enum1.NONE && bstyle != (int)Enum1.LEVEL) { sparta.error.all("Illegal create_grid command"); } bstyle = (int)Enum1.LEVEL; if (int.Parse(arg[iarg + 1]) != nlevels + 1) { sparta.error.all("Illegal create_grid command"); } nlevels++; iarg += 8; } else if (string.Equals(arg[iarg], "region")) { if (iarg + 6 > narg) { sparta.error.all("Illegal create_grid command"); } if (bstyle != (int)Enum1.NONE && bstyle != (int)Enum1.LEVEL) { sparta.error.all("Illegal create_grid command"); } bstyle = (int)Enum1.LEVEL; if (int.Parse(arg[iarg + 1]) != nlevels + 1) { sparta.error.all("Illegal create_grid command"); } if (sparta.domain.find_region(arg[iarg + 2]) < 0) { sparta.error.all("Create_grid region ID does not exist"); } nlevels++; iarg += 6; } else if (string.Equals(arg[iarg], "stride")) { if (iarg + 2 > narg) { sparta.error.all("Illegal create_grid command"); } if (bstyle != (int)Enum1.NONE) { sparta.error.all("Illegal create_grid command"); } bstyle = (int)Enum1.STRIDE; if (string.Equals(arg[iarg + 1], "xyz")) { order = (int)Enum2.XYZ; } else if (string.Equals(arg[iarg + 1], "xzy")) { order = (int)Enum2.XZY; } else if (string.Equals(arg[iarg + 1], "yxz")) { order = (int)Enum2.YXZ; } else if (string.Equals(arg[iarg + 1], "yzx")) { order = (int)Enum2.YZX; } else if (string.Equals(arg[iarg + 1], "zxy")) { order = (int)Enum2.ZXY; } else if (string.Equals(arg[iarg + 1], "zyx")) { order = (int)Enum2.ZYX; } else { sparta.error.all("Illegal create_grid command"); } iarg += 2; } else if (string.Equals(arg[iarg], "clump")) { if (iarg + 2 > narg) { sparta.error.all("Illegal create_grid command"); } if (bstyle != (int)Enum1.NONE) { sparta.error.all("Illegal create_grid command"); } bstyle = (int)Enum1.CLUMP; if (string.Equals(arg[iarg + 1], "xyz")) { order = (int)Enum2.XYZ; } else if (string.Equals(arg[iarg + 1], "xzy")) { order = (int)Enum2.XZY; } else if (string.Equals(arg[iarg + 1], "yxz")) { order = (int)Enum2.YXZ; } else if (string.Equals(arg[iarg + 1], "yzx")) { order = (int)Enum2.YZX; } else if (string.Equals(arg[iarg + 1], "zxy")) { order = (int)Enum2.ZXY; } else if (string.Equals(arg[iarg + 1], "zyx")) { order = (int)Enum2.ZYX; } else { sparta.error.all("Illegal create_grid command"); } iarg += 2; } else if (string.Equals(arg[iarg], "block")) { if (iarg + 4 > narg) { sparta.error.all("Illegal create_grid command"); } if (bstyle != (int)Enum1.NONE) { sparta.error.all("Illegal create_grid command"); } bstyle = (int)Enum1.BLOCK; if (string.Equals(arg[iarg + 1], "*")) { px = 0; } else { px = int.Parse(arg[iarg + 1]); } if (string.Equals(arg[iarg + 2], "*")) { py = 0; } else { py = int.Parse(arg[iarg + 2]); } if (string.Equals(arg[iarg + 3], "*")) { pz = 0; } else { pz = int.Parse(arg[iarg + 3]); } iarg += 4; } else if (string.Equals(arg[iarg], "random")) { if (iarg + 1 > narg) { sparta.error.all("Illegal create_grid command"); } if (bstyle != (int)Enum1.NONE) { sparta.error.all("Illegal create_grid command"); } bstyle = (int)Enum1.RANDOM; iarg += 1; } else if (string.Equals(arg[iarg], "inside")) { if (iarg + 2 > narg) { sparta.error.all("Illegal create_grid command"); } if (string.Equals(arg[iarg + 1], "any")) { inside = (int)Enum3.ANY; } else if (string.Equals(arg[iarg + 1], "all")) { inside = (int)Enum3.ALL; } else { sparta.error.all("Illegal create_grid command"); } iarg += 2; } else { sparta.error.all("Illegal create_grid command"); } } if (bstyle == (int)Enum1.NONE) { bstyle = (int)Enum1.LEVEL; } // partition domain across procs, only for BLOCK style if (bstyle == (int)Enum1.BLOCK) { procs2grid(nx, ny, nz, ref px, ref py, ref pz); if (px * py * pz != sparta.comm.nprocs) { sparta.error.all("Bad grid of processors for create_grid"); } } // create root parent cell // treat first 3 args as if specified as "level 1 * * * Nx Ny Nz" sparta.mpi.MPI_Barrier(sparta.world); double time1 = sparta.mpi.MPI_Wtime(); int level = 1; int xlo, xhi, ylo, yhi, zlo, zhi; xlo = xhi = ylo = yhi = zlo = zhi = 1; iarg = 3; Region region = null; // loop over levels // new level determines assignment of previous-level cells // to be parent cells vs child cells // parent cells are those which are further partitioned by new level // child cells are those that are not // add all cells in previous level as either parent or child cells // if this is last level, also add all current level cells as child cells int me = sparta.comm.me; int nprocs = sparta.comm.nprocs; bigint count = 0; int pnx, pny, pnz, ix, iy, iz, nbits, pflag, proc; cellint m, nth = 0, idgrandparent, idparent, idchild; double[] lo = new double[3], hi = new double[3]; Grid.ParentCell p; while (true) { // add previous level cells as parent or child cells // loop over all parent cells to find ones two levels up // use their info to generate parent or child cells at previous level // decision on parent vs child in previous level depends on // pxyz lo/hi bounds in this level // or on whether parent is in/out of region if (level == 1) { sparta.grid.add_parent_cell(0, -1, nx, ny, nz, sparta.domain.boxlo, sparta.domain.boxhi); } else { int nparent1 = sparta.grid.nparent; int prevlevel = level - 2; for (int igrandparent = 0; igrandparent < nparent1; igrandparent++) { if (sparta.grid.pcells[igrandparent].level != prevlevel) { continue; } p = sparta.grid.pcells[igrandparent]; idgrandparent = p.id; nbits = p.nbits; pnx = p.nx; pny = p.ny; pnz = p.nz; m = 0; for (iz = 0; iz < pnz; iz++) { for (iy = 0; iy < pny; iy++) { for (ix = 0; ix < pnx; ix++) { m++; idparent = idgrandparent | (m << nbits); sparta.grid.id_child_lohi(igrandparent, m, lo, hi); if (region != null) { pflag = cell_in_region(lo, hi, region, inside); } else { pflag = 1; if (ix + 1 < xlo || ix + 1 > xhi) { pflag = 0; } if (iy + 1 < ylo || iy + 1 > yhi) { pflag = 0; } if (iz + 1 < zlo || iz + 1 > zhi) { pflag = 0; } } if (pflag != 0) { sparta.grid.add_parent_cell(idparent, igrandparent, nx, ny, nz, lo, hi); } else { if (count % nprocs == me) { sparta.grid.add_child_cell(idparent, igrandparent, lo, hi); } count++; } } } } } } // final level, add current level cells as child cells // loop over all parent cells to find ones at previous level // use their info to generate my child cells at this level // if BSTYLE is set, there is only 1 level, create proc's cells directly if (level == nlevels) { Grid.ParentCell[] pcells = sparta.grid.pcells; int nparent2 = sparta.grid.nparent; int prevlevel = level - 1; for (int iparent = 0; iparent < nparent2; iparent++) { if (pcells[iparent].level != prevlevel) { continue; } p = pcells[iparent]; idparent = p.id; nbits = p.nbits; nx = p.nx; ny = p.ny; nz = p.nz; if (bstyle == (int)Enum1.LEVEL) { cellint ntotal = (cellint)nx * ny * nz; int firstproc = (int)count % nprocs; cellint ifirst = me - firstproc + 1; if (ifirst <= 0) { ifirst += nprocs; } for (m = ifirst; m <= ntotal; m += nprocs) { idchild = idparent | (m << nbits); sparta.grid.id_child_lohi(iparent, m, lo, hi); sparta.grid.add_child_cell(idchild, iparent, lo, hi); } count += ntotal; // loop over all child cells // convert M to Nth based on order // assign each cell to proc based on Nth and STRIDE or CLUMP } else if (bstyle == (int)Enum1.STRIDE || bstyle == (int)Enum1.CLUMP) { cellint ntotal = (cellint)nx * ny * nz; for (m = 0; m < ntotal; m++) { ix = m % nx; iy = (m / nx) % ny; iz = m / (nx * ny); if (order == (int)Enum2.XYZ) { nth = (cellint)iz * nx * ny + iy * nx + ix; } else if (order == (int)Enum2.XZY) { nth = (cellint)iy * nx * nz + iz * nx + ix; } else if (order == (int)Enum2.YXZ) { nth = (cellint)iz * ny * nx + ix * ny + iy; } else if (order == (int)Enum2.YZX) { nth = (cellint)ix * ny * nz + iz * ny + iy; } else if (order == (int)Enum2.ZXY) { nth = (cellint)iy * nz * nx + ix * nz + iz; } else if (order == (int)Enum2.ZYX) { nth = (cellint)ix * nz * ny + iy * nz + iz; } nth++; if (bstyle == (int)Enum1.STRIDE) { proc = nth % nprocs; } else { proc = Convert.ToInt32(1.0 * nth / ntotal * nprocs); } if (proc != me) { continue; } idchild = idparent | (nth << nbits); sparta.grid.id_child_lohi(iparent, nth, lo, hi); sparta.grid.add_child_cell(idchild, iparent, lo, hi); } count += ntotal; // loop over subset of cells in my BLOCK } else if (bstyle == (int)Enum1.BLOCK) { int ipx = me % px; int ipy = (me / px) % py; int ipz = me / (px * py); int ixstart = Convert.ToInt32(1.0 * ipx / px * nx); int ixstop = Convert.ToInt32(1.0 * (ipx + 1) / px * nx); int iystart = Convert.ToInt32(1.0 * ipy / py * ny); int iystop = Convert.ToInt32(1.0 * (ipy + 1) / py * ny); int izstart = Convert.ToInt32(1.0 * ipz / pz * nz); int izstop = Convert.ToInt32(1.0 * (ipz + 1) / pz * nz); for (iz = izstart; iz < izstop; iz++) { for (iy = iystart; iy < iystop; iy++) { for (ix = ixstart; ix < ixstop; ix++) { m = (cellint)iz * nx * ny + iy * nx + ix; m++; idchild = idparent | (m << nbits); sparta.grid.id_child_lohi(iparent, m, lo, hi); sparta.grid.add_child_cell(idchild, iparent, lo, hi); } } } } else if (bstyle == (int)Enum1.RANDOM) { RanPark random = new RanPark(sparta.update.ranmaster.uniform()); cellint ntotal = (cellint)nx * ny * nz; for (m = 0; m < ntotal; m++) { proc = Convert.ToInt32(nprocs * random.uniform()); if (proc != me) { continue; } idchild = idparent | ((m + 1) << nbits); sparta.grid.id_child_lohi(iparent, m + 1, lo, hi); sparta.grid.add_child_cell(idchild, iparent, lo, hi); } count += ntotal; } } break; } if (level == nlevels) { break; } // args for next level // levels must be in ascending order starting at beginning of arg list level++; if (string.Equals(arg[iarg], "level")) { bounds(arg[iarg + 2], nx, ref xlo, ref xhi); bounds(arg[iarg + 3], ny, ref ylo, ref yhi); bounds(arg[iarg + 4], nz, ref zlo, ref zhi); nx = int.Parse(arg[iarg + 5]); ny = int.Parse(arg[iarg + 6]); nz = int.Parse(arg[iarg + 7]); iarg += 8; } else if (string.Equals(arg[iarg], "region")) { int iregion = sparta.domain.find_region(arg[iarg + 2]); region = sparta.domain.regions[iregion]; nx = int.Parse(arg[iarg + 3]); ny = int.Parse(arg[iarg + 4]); nz = int.Parse(arg[iarg + 5]); iarg += 6; } else { sparta.error.all("Illegal create_grid command"); } if (nx < 1 || ny < 1 || nz < 1) { sparta.error.all("Illegal create_grid command"); } if (dimension == 2) { if (zlo != 1 || zhi != 1 || nz != 1) { sparta.error.all("Illegal create_grid command"); } } } // set grandparent flag for all parent cells Grid.ParentCell[] pcells1 = sparta.grid.pcells; int nparent = sparta.grid.nparent; for (int i = 1; i < nparent; i++) { pcells1[pcells1[i].iparent].grandparent = 1; } // invoke grid methods to complete grid setup if (nprocs == 1 || bstyle == (int)Enum1.CLUMP || bstyle == (int)Enum1.BLOCK) { sparta.grid.clumped = 1; } else { sparta.grid.clumped = 0; } sparta.mpi.MPI_Barrier(sparta.world); double time2 = sparta.mpi.MPI_Wtime(); sparta.grid.setup_owned(); sparta.grid.acquire_ghosts(); sparta.grid.find_neighbors(); sparta.grid.check_uniform(); sparta.comm.reset_neighbors(); sparta.mpi.MPI_Barrier(sparta.world); double time3 = sparta.mpi.MPI_Wtime(); // stats double time_total = time3 - time1; if (sparta.comm.me == 0) { string str1 = string.Format("Created {0:G} child grid cells\n", sparta.grid.ncell); string str2 = string.Format(" parent cells = {0}\n", sparta.grid.nparent); string str3 = string.Format(" CPU time = {0:G} secs\n", time_total); string str4 = string.Format(" create/ghost percent = {0:G6} {1:G6}\n", 100.0 * (time2 - time1) / time_total, 100.0 * (time3 - time2) / time_total); if (sparta.screen != null) { Console.WriteLine(str1 + str2 + str3 + str4); StreamWriter sw = new StreamWriter(sparta.screen); sw.Write(str1); sw.Write(str2); sw.Write(str3); sw.Write(str4); } if (sparta.logfile != null) { StreamWriter sw1 = new StreamWriter(sparta.logfile); sw1.Write(str1); sw1.Write(str2); sw1.Write(str3); sw1.Write(str4); } } }
public void command(int narg, string[] args, int outflag = 1) { string[] arg = new string[narg]; Array.Copy(args, 1, arg, 0, narg); if (sparta.grid.exist == 0) { sparta.error.all("Cannot balance grid before grid is defined"); } if (narg < 1) { sparta.error.all("Illegal balance_grid command"); } int order = 0, bstyle = 0; int px = 0, py = 0, pz = 0; int rcbwt = 0, rcbflip = 0; if (string.Equals(arg[0], "none")) { if (narg != 1) { sparta.error.all("Illegal balance_grid command"); } bstyle = (int)Enum1.NONE; } else if (string.Equals(arg[0], "stride")) { if (narg != 2) { sparta.error.all("Illegal balance_grid command"); } bstyle = (int)Enum1.STRIDE; if (string.Equals(arg[1], "xyz")) { order = (int)Enum2.XYZ; } else if (string.Equals(arg[1], "xzy")) { order = (int)Enum2.XZY; } else if (string.Equals(arg[1], "yxz")) { order = (int)Enum2.YXZ; } else if (string.Equals(arg[1], "yzx")) { order = (int)Enum2.YZX; } else if (string.Equals(arg[1], "zxy")) { order = (int)Enum2.ZXY; } else if (string.Equals(arg[1], "zyx")) { order = (int)Enum2.ZYX; } else { sparta.error.all("Illegal balance_grid command"); } } else if (string.Equals(arg[0], "clump")) { if (narg != 2) { sparta.error.all("Illegal balance_grid command"); } bstyle = (int)Enum1.CLUMP; if (string.Equals(arg[1], "xyz")) { order = (int)Enum2.XYZ; } else if (string.Equals(arg[1], "xzy")) { order = (int)Enum2.XZY; } else if (string.Equals(arg[1], "yxz")) { order = (int)Enum2.YXZ; } else if (string.Equals(arg[1], "yzx")) { order = (int)Enum2.YZX; } else if (string.Equals(arg[1], "zxy")) { order = (int)Enum2.ZXY; } else if (string.Equals(arg[1], "zyx")) { order = (int)Enum2.ZYX; } else { sparta.error.all("Illegal balance_grid command"); } } else if (string.Equals(arg[0], "block")) { if (narg != 4) { sparta.error.all("Illegal balance_grid command"); } bstyle = (int)Enum1.BLOCK; if (string.Equals(arg[1], "*")) { px = 0; } else { px = int.Parse(arg[1]); } if (string.Equals(arg[2], "*")) { py = 0; } else { py = int.Parse(arg[2]); } if (string.Equals(arg[3], "*")) { pz = 0; } else { pz = int.Parse(arg[3]); } } else if (string.Equals(arg[0], "random")) { if (narg != 1) { sparta.error.all("Illegal balance_grid command"); } bstyle = (int)Enum1.RANDOM; } else if (string.Equals(arg[0], "proc")) { if (narg != 1) { sparta.error.all("Illegal balance_grid command"); } bstyle = (int)Enum1.PROC; } else if (string.Equals(arg[0], "rcb")) { if (narg != 2 && narg != 3) { sparta.error.all("Illegal balance_grid command"); } bstyle = (int)Enum1.BISECTION; if (string.Equals(arg[1], "cell")) { rcbwt = (int)Enum3.CELL; } else if (string.Equals(arg[1], "part")) { rcbwt = (int)Enum3.PARTICLE; } else { sparta.error.all("Illegal balance_grid command"); } // undocumented optional 3rd arg // rcbflip = 3rd arg = 1 forces rcb.compute() to flip sign // of all grid cell "dots" to force totally different // assignment of grid cells to procs and induce // complete rebalance data migration rcbflip = 0; if (narg == 3) { rcbflip = int.Parse(arg[2]); } } else { sparta.error.all("Illegal balance_grid command"); } // error check on methods only allowed for a uniform grid if (bstyle == (int)Enum1.STRIDE || bstyle == (int)Enum1.CLUMP || bstyle == (int)Enum1.BLOCK) { if (sparta.grid.uniform == 0) { sparta.error.all("Invalid balance_grid style for non-uniform grid"); } } // re-assign each of my local child cells to a proc // only assign unsplit and split cells // do not assign sub-cells since they migrate with their split cell // set nmigrate = # of cells that will migrate to a new proc // reset proc field in cells for migrating cells // style NONE performs no re-assignment sparta.mpi.MPI_Barrier(sparta.world); double time1 = sparta.mpi.MPI_Wtime(); Grid.ChildCell[] cells = sparta.grid.cells; Grid.ChildInfo[] cinfo = sparta.grid.cinfo; int nglocal = sparta.grid.nlocal; int nprocs = sparta.comm.nprocs; int newproc; int nmigrate = 0; if (bstyle == (int)Enum1.STRIDE) { cellint idm1, ix, iy, iz, nth = 0; cellint nx = sparta.grid.unx; cellint ny = sparta.grid.uny; cellint nz = sparta.grid.unz; for (int icell = 0; icell < nglocal; icell++) { if (cells[icell].nsplit <= 0) { continue; } idm1 = cells[icell].id - 1; ix = idm1 % nx; iy = (idm1 / nx) % ny; iz = idm1 / (nx * ny); if (order == (int)Enum2.XYZ) { nth = iz * nx * ny + iy * nx + ix; } else if (order == (int)Enum2.XZY) { nth = iy * nx * nz + iz * nx + ix; } else if (order == (int)Enum2.YXZ) { nth = iz * ny * nx + ix * ny + iy; } else if (order == (int)Enum2.YZX) { nth = ix * ny * nz + iz * ny + iy; } else if (order == (int)Enum2.ZXY) { nth = iy * nz * nx + ix * nz + iz; } else if (order == (int)Enum2.ZYX) { nth = ix * nz * ny + iy * nz + iz; } newproc = nth % nprocs; if (newproc != cells[icell].proc) { nmigrate++; } cells[icell].proc = newproc; } } else if (bstyle == (int)Enum1.BLOCK) { cellint idm1, ix, iy, iz; int ipx, ipy, ipz; int nx = sparta.grid.unx; int ny = sparta.grid.uny; int nz = sparta.grid.unz; procs2grid(nx, ny, nz, ref px, ref py, ref pz); if (px * py * pz != nprocs) { sparta.error.all("Bad grid of processors for balance_grid block"); } for (int icell = 0; icell < nglocal; icell++) { if (cells[icell].nsplit <= 0) { continue; } idm1 = cells[icell].id - 1; ix = idm1 % nx; iy = (idm1 / nx) % ny; iz = idm1 / (nx * ny); ipx = ix * px / nx; ipy = iy * py / ny; ipz = iz * pz / nz; newproc = ipz * px * py + ipy * px + ipx; if (newproc != cells[icell].proc) { nmigrate++; } cells[icell].proc = newproc; } } else if (bstyle == (int)Enum1.RANDOM) { RanPark random = new RanPark(sparta.update.ranmaster.uniform()); double seed = sparta.update.ranmaster.uniform(); random.reset(seed, sparta.comm.me, 100); for (int icell = 0; icell < nglocal; icell++) { if (cells[icell].nsplit <= 0) { continue; } newproc = Convert.ToInt32(nprocs * random.uniform()); if (newproc != cells[icell].proc) { nmigrate++; } cells[icell].proc = newproc; } //delete random; } else if (bstyle == (int)Enum1.BISECTION) { RCB rcb = new RCB(sparta); double[,] x = new double[nglocal, 3]; double[] lo, hi; int nbalance = 0; for (int icell = 0; icell < nglocal; icell++) { if (cells[icell].nsplit <= 0) { continue; } lo = cells[icell].lo; hi = cells[icell].hi; x[nbalance, 0] = 0.5 * (lo[0] + hi[0]); x[nbalance, 1] = 0.5 * (lo[1] + hi[1]); x[nbalance, 2] = 0.5 * (lo[2] + hi[2]); nbalance++; } double[] wt; if (rcbwt == (int)Enum3.PARTICLE) { sparta.particle.sort(); int zero = 0; int n; wt = new double[nglocal]; nbalance = 0; for (int icell = 0; icell < nglocal; icell++) { if (cells[icell].nsplit <= 0) { continue; } n = cinfo[icell].count; if (n != 0) { wt[nbalance++] = n; } else { wt[nbalance++] = ZEROPARTICLE; zero++; } } } else { wt = new double[nglocal]; } rcb.compute(nbalance, x, wt, rcbflip); rcb.invert(); nbalance = 0; int[] sendproc = rcb.sendproc; for (int icell = 0; icell < nglocal; icell++) { if (cells[icell].nsplit <= 0) { continue; } cells[icell].proc = sendproc[nbalance++]; } nmigrate = nbalance - rcb.nkeep; } // set clumped of not, depending on style // NONE style does not change clumping if (nprocs == 1 || bstyle == (int)Enum1.CLUMP || bstyle == (int)Enum1.BLOCK || bstyle == (int)Enum1.BISECTION) { sparta.grid.clumped = 1; } else if (bstyle != (int)Enum1.NONE) { sparta.grid.clumped = 0; } sparta.mpi.MPI_Barrier(sparta.world); double time2 = sparta.mpi.MPI_Wtime(); // sort particles // NOTE: not needed again if rcbwt = PARTICLE for bstyle = BISECTION ?? sparta.particle.sort(); sparta.mpi.MPI_Barrier(sparta.world); double time3 = sparta.mpi.MPI_Wtime(); // invoke init() so all grid cell info, including collide & fixes, // is ready to migrate // for init, do not require surfs be assigned collision models // this allows balance call early in script, e.g. from ReadRestart // migrate grid cells and their particles to new owners // invoke grid methods to complete grid setup int ghost_previous = sparta.grid.exist_ghost; sparta.domain.boundary_collision_check = 0; sparta.surf.surf_collision_check = 0; sparta.init(); sparta.domain.boundary_collision_check = 1; sparta.surf.surf_collision_check = 1; sparta.grid.unset_neighbors(); sparta.grid.remove_ghosts(); sparta.comm.migrate_cells(nmigrate); sparta.mpi.MPI_Barrier(sparta.world); double time4 = sparta.mpi.MPI_Wtime(); sparta.grid.setup_owned(); sparta.grid.acquire_ghosts(); if (ghost_previous != 0) { sparta.grid.reset_neighbors(); } else { sparta.grid.find_neighbors(); } sparta.comm.reset_neighbors(); // reallocate per grid arrays in per grid dumps for (int i = 0; i < sparta.output.ndump; i++) { sparta.output.dump[i].reset_grid(); } sparta.mpi.MPI_Barrier(sparta.world); double time5 = sparta.mpi.MPI_Wtime(); // stats on balance operation // only print if outflag = 1 // some callers suppress output, e.g. ReadRestart bigint count = nmigrate; bigint nmigrate_all = 0; sparta.mpi.MPI_Allreduce(ref count, ref nmigrate_all, 1, MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world); double time_total = time5 - time1; if (sparta.comm.me == 0 && outflag != 0) { string str1 = string.Format("Balance grid migrated {0} cells\n", nmigrate_all); string str2 = string.Format(" CPU time = {0:G} secs\n", time_total); string str3 = string.Format(" reassign/sort/migrate/ghost percent = {0:G6} {1:G6} {2:G6} {3:G6}\n", 100.0 * (time2 - time1) / time_total, 100.0 * (time3 - time2) / time_total, 100.0 * (time4 - time3) / time_total, 100.0 * (time5 - time4) / time_total); Console.WriteLine(str1 + str2 + str3); if (sparta.screen != null) { new StreamWriter(sparta.screen).WriteLine(str1 + str2 + str3); //fprintf(screen, "Balance grid migrated " BIGINT_FORMAT " cells\n", // nmigrate_all); //fprintf(screen, " CPU time = %g secs\n", time_total); //fprintf(screen, " reassign/sort/migrate/ghost percent = %g %g %g %g\n", // 100.0 * (time2 - time1) / time_total, 100.0 * (time3 - time2) / time_total, // 100.0 * (time4 - time3) / time_total, 100.0 * (time5 - time4) / time_total); } if (sparta.logfile != null) { new StreamWriter(sparta.logfile).WriteLine(str1 + str2 + str3); } } }
protected RanPark random; // RNG for particle reflection void diffuse(Particle.OnePart p, double[] norm) { // specular reflection // reflect incident v around norm if (random.uniform() > acc) { MathExtra.reflect3(p.v, norm); // diffuse reflection // vrm = most probable speed of species, eqns (4.1) and (4.7) // vperp = velocity component perpendicular to surface along norm, eqn (12.3) // vtan12 = 2 velocity components tangential to surface // tangent1 = component of particle v tangential to surface, // check if tangent1 = 0 (normal collision), set randomly // tangent2 = norm x tangent1 = orthogonal tangential direction // tangent12 are both unit vectors } else { double[] tangent1 = new double[3], tangent2 = new double[3]; List <Particle.Species> species = sparta.particle.species; int ispecies = p.ispecies; double vrm = Math.Sqrt(2.0 * sparta.update.boltz * twall / species[ispecies].mass); double vperp = vrm * Math.Sqrt(-Math.Log(random.uniform())); double theta = MyConst.MY_2PI * random.uniform(); double vtangent = vrm * Math.Sqrt(-Math.Log(random.uniform())); double vtan1 = vtangent * Math.Sin(theta); double vtan2 = vtangent * Math.Cos(theta); double[] v = p.v; double dot = MathExtra.dot3(v, norm); double beta_un, normalized_distbn_fn; tangent1[0] = v[0] - dot * norm[0]; tangent1[1] = v[1] - dot * norm[1]; tangent1[2] = v[2] - dot * norm[2]; if (MathExtra.lensq3(tangent1) == 0.0) { tangent2[0] = random.uniform(); tangent2[1] = random.uniform(); tangent2[2] = random.uniform(); MathExtra.cross3(norm, tangent2, tangent1); } MathExtra.norm3(tangent1); MathExtra.cross3(norm, tangent1, tangent2); // add in translation or rotation vector if specified // only keep portion of vector tangential to surface element if (trflag != 0) { double vxdelta, vydelta, vzdelta; if (tflag != 0) { vxdelta = vx; vydelta = vy; vzdelta = vz; double adot = vxdelta * norm[0] + vydelta * norm[1] + vzdelta * norm[2]; if (Math.Abs(adot) > 0.001) { adot /= vrm; do { do { beta_un = (6.0 * random.uniform() - 3.0); } while (beta_un + adot < 0.0); normalized_distbn_fn = 2.0 * (beta_un + adot) / (adot + Math.Sqrt(adot * adot + 2.0)) * Math.Exp(0.5 + (0.5 * adot) * (adot - Math.Sqrt(adot * adot + 2.0)) - beta_un * beta_un); } while (normalized_distbn_fn < random.uniform()); vperp = beta_un * vrm; } } else { double[] x = p.x; vxdelta = wy * (x[2] - pz) - wz * (x[1] - py); vydelta = wz * (x[0] - px) - wx * (x[2] - pz); vzdelta = wx * (x[1] - py) - wy * (x[0] - px); double adot = vxdelta * norm[0] + vydelta * norm[1] + vzdelta * norm[2]; vxdelta -= adot * norm[0]; vydelta -= adot * norm[1]; vzdelta -= adot * norm[2]; } v[0] = vperp * norm[0] + vtan1 * tangent1[0] + vtan2 * tangent2[0] + vxdelta; v[1] = vperp * norm[1] + vtan1 * tangent1[1] + vtan2 * tangent2[1] + vydelta; v[2] = vperp * norm[2] + vtan1 * tangent1[2] + vtan2 * tangent2[2] + vzdelta; // no translation or rotation } else { v[0] = vperp * norm[0] + vtan1 * tangent1[0] + vtan2 * tangent2[0]; v[1] = vperp * norm[1] + vtan1 * tangent1[1] + vtan2 * tangent2[1]; v[2] = vperp * norm[2] + vtan1 * tangent1[2] + vtan2 * tangent2[2]; } p.erot = sparta.particle.erot(ispecies, twall, random); p.evib = sparta.particle.evib(ispecies, twall, random); } }
protected List <Particle.OnePart> elist; // list of ambipolar electrons // for one grid cell or pair of groups in cell //inline void addgroup(int igroup, int n) //{ // if (ngroup[igroup] == maxgroup[igroup]) // { // maxgroup[igroup] += DELTAPART; // memory.grow(glist[igroup], maxgroup[igroup], "collide:grouplist"); // } // glist[igroup][ngroup[igroup]++] = n; //} public void collisions_one(int NEARCP) { int i, j, k, m, n, ip, np; int nattempt, reactflag; double attempt, volume; Particle.OnePart?ipart = null, jpart = null, kpart = null; // loop over cells I own Grid.ChildInfo[] cinfo = sparta.grid.cinfo; Particle.OnePart[] particles = sparta.particle.particles; int[] next = sparta.particle.next; for (int icell = 0; icell < nglocal; icell++) { np = cinfo[icell].count; if (np <= 1) { continue; } if (NEARCP != 0) { if (np > max_nn) { //realloc_nn(np, nn_last_partner); nn_last_partner = new int[np]; } //memset(nn_last_partner, 0, np * sizeof(int)); } ip = cinfo[icell].first; volume = cinfo[icell].volume / cinfo[icell].weight; if (volume == 0.0) { sparta.error.one("Collision cell volume is zero"); } // setup particle list for this cell if (np > npmax) { npmax = np + DELTAPART; //memory.destroy(plist); //memory.create(plist, npmax, "collide:plist"); plist = new int[npmax]; } n = 0; while (ip >= 0) { plist[n++] = ip; ip = next[ip]; } // attempt = exact collision attempt count for a pair of groups // nattempt = rounded attempt with RN attempt = attempt_collision(icell, np, volume); nattempt = Convert.ToInt32(attempt); if (nattempt == 0) { continue; } nattempt_one += nattempt; // perform collisions // select random pair of particles, cannot be same // test if collision actually occurs for (m = 0; m < nattempt; m++) { i = (int)(np * random.uniform()); if (NEARCP != 0) { j = find_nn(i, np); } else { j = (int)(np * random.uniform()); while (i == j) { j = (int)(np * random.uniform()); } } ipart = particles[plist[i]]; jpart = particles[plist[j]]; // test if collision actually occurs // continue to next collision if no reaction if (test_collision(icell, 0, 0, ipart.Value, jpart.Value) == 0) { continue; } if (NEARCP != 0) { nn_last_partner[i] = j + 1; nn_last_partner[j] = i + 1; } // if recombination reaction is possible for this IJ pair // pick a 3rd particle to participate and set cell number density // unless boost factor turns it off, or there is no 3rd particle if (recombflag != 0 && recomb_ijflag[ipart.Value.ispecies, jpart.Value.ispecies] != 0) { //if (random.uniform() > sparta.react.recomb_boost_inverse) // sparta.react.recomb_species = -1; //else if (np <= 2) // sparta.react.recomb_species = -1; //else //{ // k = (int)(np * random.uniform()); // while (k == i || k == j) k = (int)(np * random.uniform()); // sparta.react.recomb_part3 = particles[plist[k]]; // sparta.react.recomb_species = sparta.react.recomb_part3.ispecies; // sparta.react.recomb_density = np * sparta.update.fnum / volume; //} Console.WriteLine("Collide collisions_one(). react"); } // perform collision and possible reaction setup_collision(ipart.Value, jpart.Value); reactflag = perform_collision(ref ipart, ref jpart, ref kpart); ncollide_one++; if (reactflag != 0) { nreact_one++; } else { continue; } // if jpart destroyed, delete from plist // also add particle to deletion list // exit attempt loop if only single particle left if (jpart == null) { if (ndelete == maxdelete) { maxdelete += DELTADELETE; //memory.grow(dellist, maxdelete, "collide:dellist"); dellist = new int[maxdelete]; } dellist[ndelete++] = plist[j]; np--; plist[j] = plist[np]; if (NEARCP != 0) { nn_last_partner[j] = nn_last_partner[np]; } if (np < 2) { break; } } // if kpart created, add to plist // kpart was just added to particle list, so index = nlocal-1 // particle data structs may have been realloced by kpart if (kpart != null) { if (np == npmax) { npmax = np + DELTAPART; //memory.grow(plist, npmax, "collide:plist"); plist = new int[npmax]; } if (NEARCP != 0) { set_nn(np); } plist[np++] = sparta.particle.nlocal - 1; particles = sparta.particle.particles; } } } }