Exemple #1
0
        public void command(int narg, string[] args)
        {
            string[] arg = new string[narg];
            Array.Copy(args, 1, arg, 0, narg);
            if (narg < 1)
            {
                sparta.error.all("Illegal run command");
            }

            if (sparta.grid.exist == 0)
            {
                sparta.error.all("Run command before grid is defined");
            }
            if (sparta.grid.exist_ghost == 0)
            {
                sparta.error.all("Run command before grid ghost cells are defined");
            }

            bigint nsteps_input = Int64.Parse(arg[0]);

            // parse optional args

            int    uptoflag = 0;
            int    startflag = 0;
            int    stopflag = 0;
            bigint start = 0, stop = 0;
            int    preflag = 1;
            int    postflag = 1;
            int    nevery = 0;
            int    ncommands = 0;
            int    first = 0, last = 0;

            int iarg = 1;

            while (iarg < narg)
            {
                switch (arg[iarg])
                {
                case "upto":
                    if (iarg + 1 > narg)
                    {
                        sparta.error.all("Illegal run command");
                    }
                    uptoflag = 1;
                    iarg    += 1;
                    break;

                case "start":
                    if (iarg + 2 > narg)
                    {
                        sparta.error.all("Illegal run command");
                    }
                    startflag = 1;
                    start     = Int64.Parse(arg[iarg + 1]);
                    iarg     += 2;
                    break;

                case "stop":
                    if (iarg + 2 > narg)
                    {
                        sparta.error.all("Illegal run command");
                    }
                    stopflag = 1;
                    stop     = Int64.Parse(arg[iarg + 1]);
                    iarg    += 2;
                    break;

                case "pre":
                    if (iarg + 2 > narg)
                    {
                        sparta.error.all("Illegal run command");
                    }
                    if (string.Equals(arg[iarg + 1], "no"))
                    {
                        preflag = 0;
                    }
                    else if (string.Equals(arg[iarg + 1], "yes"))
                    {
                        preflag = 1;
                    }
                    else
                    {
                        sparta.error.all("Illegal run command");
                    }
                    iarg += 2;
                    break;

                case "post":
                    if (iarg + 2 > narg)
                    {
                        sparta.error.all("Illegal run command");
                    }
                    if (string.Equals(arg[iarg + 1], "no"))
                    {
                        postflag = 0;
                    }
                    else if (string.Equals(arg[iarg + 1], "yes"))
                    {
                        postflag = 1;
                    }
                    else
                    {
                        sparta.error.all("Illegal run command");
                    }
                    iarg += 2;

                    // all remaining args are commands
                    // first,last = arg index of first/last commands
                    // set ncommands = 0 if single command and it is NULL
                    break;

                case "every":
                    if (iarg + 3 > narg)
                    {
                        sparta.error.all("Illegal run command");
                    }
                    nevery = int.Parse(arg[iarg + 1]);
                    if (nevery <= 0)
                    {
                        sparta.error.all("Illegal run command");
                    }
                    first     = iarg + 2;
                    last      = narg - 1;
                    ncommands = last - first + 1;
                    if (ncommands == 1 && string.Equals(arg[first], "NULL"))
                    {
                        ncommands = 0;
                    }
                    iarg = narg;
                    break;

                default:
                    sparta.error.all("Illegal run command");
                    break;
                }
            }
            int nsteps;

            if (uptoflag == 0)
            {
                if (nsteps_input < 0 || nsteps_input > MAXSMALLINT)
                {
                    sparta.error.all("Invalid run command N value");
                }
                nsteps = Convert.ToInt32(nsteps_input);
            }
            else
            {
                bigint delta = nsteps_input - sparta.update.ntimestep;
                if (delta < 0 || delta > MAXSMALLINT)
                {
                    sparta.error.all("Invalid run command upto value");
                }
                nsteps = Convert.ToInt32(delta);
            }

            // error check

            if (startflag != 0)
            {
                if (start < 0 || start > MAXBIGINT)
                {
                    sparta.error.all("Invalid run command start/stop value");
                }
                if (start > sparta.update.ntimestep)
                {
                    sparta.error.all("Run command start value is after start of run");
                }
            }
            if (stopflag != 0)
            {
                if (stop < 0 || stop > MAXBIGINT)
                {
                    sparta.error.all("Invalid run command start/stop value");
                }
                if (stop < sparta.update.ntimestep + nsteps)
                {
                    sparta.error.all("Run command stop value is before end of run");
                }
            }

            // if nevery, make copies of arg strings that are commands
            // required because re-parsing commands via input.one() will wipe out args

            string[] commands = null;
            if (nevery != 0 && ncommands > 0)
            {
                commands  = new string[ncommands];
                ncommands = 0;
                for (int i = first; i <= last; i++)
                {
                    int n = arg[i].Length + 1;
                    commands[ncommands] = string.Copy(arg[i]);
                    ncommands++;
                }
            }

            // perform a single run
            // use start/stop to set begin/end step
            // if pre or 1st run, do System init/setup,
            //   else just init timer and setup output
            // if post, do full Finish, else just print time

            sparta.update.runflag = 1;

            if (nevery == 0)
            {
                sparta.update.nsteps    = nsteps;
                sparta.update.firststep = sparta.update.ntimestep;
                sparta.update.laststep  = sparta.update.ntimestep + nsteps;
                if (sparta.update.laststep < 0 || sparta.update.laststep > MAXBIGINT)
                {
                    sparta.error.all("Too many timesteps");
                }

                if (startflag != 0)
                {
                    sparta.update.beginstep = start;
                }
                else
                {
                    sparta.update.beginstep = sparta.update.firststep;
                }
                if (stopflag != 0)
                {
                    sparta.update.endstep = stop;
                }
                else
                {
                    sparta.update.endstep = sparta.update.laststep;
                }

                if (preflag != 0 || sparta.update.first_update == 0)
                {
                    sparta.init();
                    sparta.update.setup();
                }
                else
                {
                    sparta.output.setup(0);
                }

                sparta.timer.init();
                sparta.timer.barrier_start((int)Timer.Enum1.TIME_LOOP);
                sparta.update.run(nsteps);
                sparta.timer.barrier_stop((int)Timer.Enum1.TIME_LOOP);

                Finish finish = new Finish(sparta);
                finish.end(postflag, 0.0);

                // perform multiple runs optionally interleaved with invocation command(s)
                // use start/stop to set begin/end step
                // if pre or 1st iteration of multiple runs, do System init/setup,
                //   else just init timer and setup output
                // if post or last iteration, do full Finish, else just print time
            }
        }
Exemple #2
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);
                }
            }
        }