Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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);
                }
            }
        }
Esempio n. 4
0
        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);
                }
            }
        }
Esempio n. 5
0
        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);
            }
        }
Esempio n. 6
0
        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;
                    }
                }
            }
        }