Example #1
0
        public void compute_line_normal(int nstart, int n)
        {
            int p1, p2;

            double[] z = new double[3], delta = new double[3], norm = new double[3];

            z[0] = 0.0; z[1] = 0.0; z[2] = 1.0;

            int m = nstart;

            for (int i = 0; i < n; i++)
            {
                p1 = lines[m].p1;
                p2 = lines[m].p2;
                MathExtra.sub3(pts[p2].x, pts[p1].x, delta);
                MathExtra.cross3(z, delta, norm);
                MathExtra.norm3(norm);
                norm[2] = 0.0;
                Line line = lines[m];
                line.norm    = new double[3];
                line.norm[0] = norm[0];
                line.norm[1] = norm[1];
                line.norm[2] = norm[2];
                lines[m]     = line;

                m++;
            }
        }
Example #2
0
        //public double axi_line_size(int);
        public double tri_size(int m, out double len)
        {
            double[] delta12 = new double[3], delta13 = new double[3],
            delta23 = new double[3], cross = new double[3];

            MathExtra.sub3(pts[tris[m].p2].x, pts[tris[m].p1].x, delta12);
            MathExtra.sub3(pts[tris[m].p3].x, pts[tris[m].p1].x, delta13);
            MathExtra.sub3(pts[tris[m].p3].x, pts[tris[m].p2].x, delta23);
            len = Math.Min(MathExtra.len3(delta12), MathExtra.len3(delta13));
            len = Math.Min(len, MathExtra.len3(delta23));

            MathExtra.cross3(delta12, delta13, cross);
            double area = 0.5 * MathExtra.len3(cross);

            return(area);
        }
Example #3
0
        public void compute_tri_normal(int nstart, int n)
        {
            int p1, p2, p3;

            double[] delta12 = new double[3], delta13 = new double[3];

            int m = nstart;

            for (int i = 0; i < n; i++)
            {
                p1 = tris[m].p1;
                p2 = tris[m].p2;
                p3 = tris[m].p3;
                MathExtra.sub3(pts[p2].x, pts[p1].x, delta12);
                MathExtra.sub3(pts[p3].x, pts[p1].x, delta13);
                MathExtra.cross3(delta12, delta13, tris[m].norm);
                MathExtra.norm3(tris[m].norm);
                m++;
            }
        }
Example #4
0
        public void end(int flag, double time_multiple_runs)
        {
            int i;

            int[]  histo = new int[10];
            int    loopflag, statsflag, timeflag, histoflag;
            double time, tmp = 0, ave = 0, max = 0, min = 0;
            double time_loop = 0, time_other = 0;

            int me = 0, nprocs = 0;

            sparta.mpi.MPI_Comm_rank(sparta.world, ref me);
            sparta.mpi.MPI_Comm_size(sparta.world, ref nprocs);

            // choose flavors of statistical output
            // flag = 0 = just loop summary
            // flag = 1 = dynamics or minimization

            loopflag  = 1;
            statsflag = timeflag = histoflag = 0;
            if (flag == 1)
            {
                statsflag = timeflag = histoflag = 1;
            }

            // loop stats
            // time_multiple_runs used for moves/CPU/proc statistic below

            if (loopflag != 0)
            {
                time_other = sparta.timer.array[(int)EnumTime.Time_LOOP] -
                             (sparta.timer.array[(int)EnumTime.Time_MOVE] + sparta.timer.array[(int)EnumTime.Time_COLLIDE] +
                              sparta.timer.array[(int)EnumTime.Time_SORT] + sparta.timer.array[(int)EnumTime.Time_COMM] +
                              sparta.timer.array[(int)EnumTime.Time_MODIFY] + sparta.timer.array[(int)EnumTime.Time_OUTPUT]);

                time_loop = sparta.timer.array[(int)EnumTime.Time_LOOP];
                sparta.mpi.MPI_Allreduce(ref time_loop, ref tmp, 1, MPI.MPI_DOUBLE, MPI.MPI_SUM, sparta.world);
                time_loop = tmp / nprocs;

                if (time_multiple_runs == 0.0)
                {
                    time_multiple_runs = time_loop;
                }
                else
                {
                    tmp = time_multiple_runs;
                    sparta.mpi.MPI_Allreduce(ref tmp, ref time_multiple_runs, 1, MPI.MPI_DOUBLE, MPI.MPI_SUM, sparta.world);
                    time_multiple_runs /= nprocs;
                }
            }

            // recalculate nglobal

            Int64 n = sparta.particle.nlocal;

            sparta.mpi.MPI_Allreduce(ref n, ref sparta.particle.nglobal, 1, MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world);

            // overall loop time

            if (me == 0)
            {
                string str = string.Format("Loop time of {0} on {1} procs for {2} steps with {3} particles\n", time_loop, nprocs, sparta.update.nsteps, sparta.particle.nglobal);
                Console.WriteLine(str);
                if (sparta.screen != null)
                {
                    new StreamWriter(sparta.screen).WriteLine(str);
                }
                if (sparta.logfile != null)
                {
                    new StreamWriter(sparta.logfile).WriteLine(str);
                }
            }

            // cummulative stats over entire run

            if (statsflag != 0)
            {
                Int64 nmove_total = 0, ntouch_total = 0, ncomm_total = 0;
                Int64 nboundary_total = 0, nexit_total = 0;
                Int64 nscheck_total = 0, nscollide_total = 0, nsreact_total = 0;
                Int64 nattempt_total = 0;
                Int64 ncollide_total = 0;
                Int64 nreact_total   = 0;
                int   stuck_total    = 0;

                sparta.mpi.MPI_Allreduce(ref sparta.update.nmove_running, ref nmove_total, 1,
                                         MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world);
                sparta.mpi.MPI_Allreduce(ref sparta.update.ntouch_running, ref ntouch_total, 1,
                                         MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world);
                sparta.mpi.MPI_Allreduce(ref sparta.update.ncomm_running, ref ncomm_total, 1,
                                         MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world);
                sparta.mpi.MPI_Allreduce(ref sparta.update.nboundary_running, ref nboundary_total, 1,
                                         MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world);
                sparta.mpi.MPI_Allreduce(ref sparta.update.nexit_running, ref nexit_total, 1,
                                         MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world);
                sparta.mpi.MPI_Allreduce(ref sparta.update.nscheck_running, ref nscheck_total, 1,
                                         MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world);
                sparta.mpi.MPI_Allreduce(ref sparta.update.nscollide_running, ref nscollide_total, 1,
                                         MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world);
                sparta.mpi.MPI_Allreduce(ref sparta.surf.nreact_running, ref nsreact_total, 1,
                                         MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world);
                if (sparta.collide != null)
                {
                    sparta.mpi.MPI_Allreduce(ref sparta.collide.nattempt_running, ref nattempt_total, 1,
                                             MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world);
                    sparta.mpi.MPI_Allreduce(ref sparta.collide.ncollide_running, ref ncollide_total, 1,
                                             MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world);
                    sparta.mpi.MPI_Allreduce(ref sparta.collide.nreact_running, ref nreact_total, 1,
                                             MPI.MPI_LONG_LONG, MPI.MPI_SUM, sparta.world);
                }
                sparta.mpi.MPI_Allreduce(ref sparta.update.nstuck, ref stuck_total, 1, MPI.MPI_INT, MPI.MPI_SUM, sparta.world);

                double pms, pmsp, ctps, cis, pfc, pfcwb, pfeb, schps, sclps, srps, caps, cps, rps;
                pms       = pmsp = ctps = cis = pfc = pfcwb = pfeb =
                    schps = sclps = srps = caps = cps = rps = 0.0;

                Int64 elapsed = sparta.update.ntimestep - sparta.update.first_running_step;
                if (elapsed != 0)
                {
                    pms = 1.0 * nmove_total / elapsed;
                }

                if (nmove_total != 0)
                {
                    pmsp  = 1.0 * nmove_total / time_multiple_runs / nprocs;
                    ctps  = 1.0 * ntouch_total / nmove_total;
                    cis   = 1.0 * sparta.update.niterate_running / elapsed;
                    pfc   = 1.0 * ncomm_total / nmove_total;
                    pfcwb = 1.0 * nboundary_total / nmove_total;
                    pfeb  = 1.0 * nexit_total / nmove_total;
                    schps = 1.0 * nscheck_total / nmove_total;
                    sclps = 1.0 * nscollide_total / nmove_total;
                    srps  = 1.0 * nsreact_total / nmove_total;
                    caps  = 1.0 * nattempt_total / nmove_total;
                    cps   = 1.0 * ncollide_total / nmove_total;
                    rps   = 1.0 * nreact_total / nmove_total;
                }

                string str;

                if (me == 0)
                {
                    str  = "\n";
                    str += string.Format("Particle moves    = {0} {1}\n",
                                         nmove_total, MathExtra.num2str(nmove_total));
                    str += string.Format("Cells touched     = {0} {1}\n",
                                         ntouch_total, MathExtra.num2str(ntouch_total));
                    str += string.Format("Particle comms    = {0} {1}\n",
                                         ncomm_total, MathExtra.num2str(ncomm_total));
                    str += string.Format("Boundary collides = {0} {1}\n",
                                         nboundary_total, MathExtra.num2str(nboundary_total));
                    str += string.Format("Boundary exits    = {0} {1}\n",
                                         nboundary_total, MathExtra.num2str(nexit_total));
                    str += string.Format("SurfColl checks   = {0} {1}\n",
                                         nscheck_total, MathExtra.num2str(nscheck_total));
                    str += string.Format("SurfColl occurs   = {0} {1}\n",
                                         nscollide_total, MathExtra.num2str(nscollide_total));
                    str += string.Format("Surf reactions    = {0} {1}\n",
                                         nsreact_total, MathExtra.num2str(nsreact_total));
                    str += string.Format("Collide attempts  = {0} {1}\n",
                                         nattempt_total, MathExtra.num2str(nattempt_total));
                    str += string.Format("Collide occurs    = {0} {1}\n",
                                         ncollide_total, MathExtra.num2str(ncollide_total));
                    str += string.Format("Gas reactions     = {0} {1}\n",
                                         nreact_total, MathExtra.num2str(nreact_total));
                    str += string.Format("Particles stuck   = {0}\n", stuck_total);

                    str += string.Format("\n");
                    str += string.Format("Particle-moves/CPUsec/proc: {0}\n", pmsp);
                    str += string.Format("Particle-moves/step: {0}\n", pms);
                    str += string.Format("Cell-touches/particle/step: {0}\n", ctps);
                    str += string.Format("Particle comm iterations/step: {0}\n", cis);
                    str += string.Format("Particle fraction communicated: {0}\n", pfc);
                    str += string.Format("Particle fraction colliding with boundary: {0}\n", pfcwb);
                    str += string.Format("Particle fraction exiting boundary: {0}\n", pfeb);
                    str += string.Format("Surface-checks/particle/step: {0}\n", schps);
                    str += string.Format("Surface-collisions/particle/step: {0}\n", sclps);
                    str += string.Format("Surface-reactions/particle/step: {0}\n", srps);
                    str += string.Format("Collision-attempts/particle/step: {0}\n", caps);
                    str += string.Format("Collisions/particle/step: {0}\n", cps);
                    str += string.Format("Gas-reactions/particle/step: {0}\n", rps);
                    Console.WriteLine(str);
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine(str);
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine(str);
                    }
                }
            }

            // timing breakdowns

            if (timeflag != 0)
            {
                if (me == 0)
                {
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine("\n");
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine("\n");
                    }
                }

                time = sparta.timer.array[(int)EnumTime.Time_MOVE];
                sparta.mpi.MPI_Allreduce(ref time, ref tmp, 1, MPI.MPI_DOUBLE, MPI.MPI_SUM, sparta.world);
                time = tmp / nprocs;
                if (me == 0)
                {
                    Console.WriteLine("Move  time (%%) = {0} ({1})\n",
                                      time, time / time_loop * 100.0);
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine("Move  time (%%) = {0} ({1})\n",
                                                                  time, time / time_loop * 100.0);
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine("Move  time (%%) = {0} ({1})\n",
                                                                   time, time / time_loop * 100.0);
                    }
                }

                time = sparta.timer.array[(int)EnumTime.Time_COLLIDE];
                sparta.mpi.MPI_Allreduce(ref time, ref tmp, 1, MPI.MPI_DOUBLE, MPI.MPI_SUM, sparta.world);
                time = tmp / nprocs;
                if (me == 0)
                {
                    Console.WriteLine("Coll  time (%%) = {0} ({1})\n",
                                      time, time / time_loop * 100.0);
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine("Coll  time (%%) = {0} ({1})\n",
                                                                  time, time / time_loop * 100.0);
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine("Coll  time (%%) = {0} ({1})\n",
                                                                   time, time / time_loop * 100.0);
                    }
                }

                time = sparta.timer.array[(int)EnumTime.Time_SORT];
                sparta.mpi.MPI_Allreduce(ref time, ref tmp, 1, MPI.MPI_DOUBLE, MPI.MPI_SUM, sparta.world);
                time = tmp / nprocs;
                if (me == 0)
                {
                    Console.WriteLine("Sort  time (%%) = {0} ({1})\n",
                                      time, time / time_loop * 100.0);
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine("Sort  time (%%) = {0} ({1})\n",
                                                                  time, time / time_loop * 100.0);
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine("Sort  time (%%) = {0} ({1})\n",
                                                                   time, time / time_loop * 100.0);
                    }
                }

                time = sparta.timer.array[(int)EnumTime.Time_COMM];
                sparta.mpi.MPI_Allreduce(ref time, ref tmp, 1, MPI.MPI_DOUBLE, MPI.MPI_SUM, sparta.world);
                time = tmp / nprocs;
                if (me == 0)
                {
                    Console.WriteLine("Comm  time (%%) = {0} ({1})\n",
                                      time, time / time_loop * 100.0);
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine("Comm  time (%%) = {0} ({1})\n",
                                                                  time, time / time_loop * 100.0);
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine("Comm  time (%%) = {0} ({1})\n",
                                                                   time, time / time_loop * 100.0);
                    }
                }

                time = sparta.timer.array[(int)EnumTime.Time_MODIFY];
                sparta.mpi.MPI_Allreduce(ref time, ref tmp, 1, MPI.MPI_DOUBLE, MPI.MPI_SUM, sparta.world);
                time = tmp / nprocs;
                if (me == 0)
                {
                    Console.WriteLine("Modfy time (%%) = {0} ({1})\n",
                                      time, time / time_loop * 100.0);
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine("Modfy time (%%) = {0} ({1})\n",
                                                                  time, time / time_loop * 100.0);
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine("Modfy time (%%) = {0} ({1})\n",
                                                                   time, time / time_loop * 100.0);
                    }
                }

                time = sparta.timer.array[(int)EnumTime.Time_OUTPUT];
                sparta.mpi.MPI_Allreduce(ref time, ref tmp, 1, MPI.MPI_DOUBLE, MPI.MPI_SUM, sparta.world);
                time = tmp / nprocs;
                if (me == 0)
                {
                    Console.WriteLine("Outpt time (%%) = {0} ({1})\n",
                                      time, time / time_loop * 100.0);
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine("Outpt time (%%) = {0} ({1})\n",
                                                                  time, time / time_loop * 100.0);
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine("Outpt time (%%) = {0} ({1})\n",
                                                                   time, time / time_loop * 100.0);
                    }
                }

                time = time_other;
                sparta.mpi.MPI_Allreduce(ref time, ref tmp, 1, MPI.MPI_DOUBLE, MPI.MPI_SUM, sparta.world);
                time = tmp / nprocs;
                if (me == 0)
                {
                    Console.WriteLine("Other time (%%) = {0} ({1})\n",
                                      time, time / time_loop * 100.0);
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine("Other time (%%) = {0} ({1})\n",
                                                                  time, time / time_loop * 100.0);
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine("Other time (%%) = {0} ({1})\n",
                                                                   time, time / time_loop * 100.0);
                    }
                }
            }

            // histograms

            if (histoflag != 0)
            {
                if (me == 0)
                {
                    Console.WriteLine("\n");
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine("\n");
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine("\n");
                    }
                }

                tmp = sparta.particle.nlocal;
                stats(1, ref tmp, ref ave, ref max, ref min, 10, ref histo);
                if (me == 0)
                {
                    string str = string.Format("Particles: {0} ave {1} max {2} min\n", ave, max, min);
                    str += "Histogram:";
                    for (int a = 0; a < 10; a++)
                    {
                        str += string.Format(" {0}", histo[a]);
                    }
                    str += "\n";
                    Console.WriteLine(str);
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine(str);
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine(str);
                    }
                }

                tmp = sparta.grid.nlocal;
                stats(1, ref tmp, ref ave, ref max, ref min, 10, ref histo);
                if (me == 0)
                {
                    string str = string.Format("Cells:     {0} ave {1} max {2} min\n", ave, max, min);
                    str += "Histogram:";
                    for (int a = 0; a < 10; a++)
                    {
                        str += string.Format(" {0}", histo[a]);
                    }
                    str += "\n";
                    Console.WriteLine(str);
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine(str);
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine(str);
                    }
                }

                tmp = sparta.grid.nghost;
                stats(1, ref tmp, ref ave, ref max, ref min, 10, ref histo);
                if (me == 0)
                {
                    string str = string.Format("GhostCell: {0} ave {1} max {2} min\n", ave, max, min);
                    str += "Histogram:";
                    for (int a = 0; a < 10; a++)
                    {
                        str += string.Format(" {0}", histo[a]);
                    }
                    str += "\n";
                    Console.WriteLine(str);
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine(str);
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine(str);
                    }
                }

                tmp = sparta.grid.nempty;
                stats(1, ref tmp, ref ave, ref max, ref min, 10, ref histo);
                if (me == 0)
                {
                    string str = string.Format("EmptyCell: {0} ave {1} max {2} min\n", ave, max, min);
                    str += "Histogram:";
                    for (int a = 0; a < 10; a++)
                    {
                        str += string.Format(" {0}", histo[a]);
                    }
                    str += "\n";
                    Console.WriteLine(str);
                    if (sparta.screen != null)
                    {
                        new StreamWriter(sparta.screen).WriteLine(str);
                    }
                    if (sparta.logfile != null)
                    {
                        new StreamWriter(sparta.logfile).WriteLine(str);
                    }
                }
            }

            if (sparta.logfile != null)
            {
                sparta.logfile.Flush();
            }
        }
Example #5
0
 //public void quad_corner_point(int, double*, double*, double*);
 //public void hex_corner_point(int, double*, double*, double*);
 public double line_size(int m)
 {
     double[] delta = new double[3];
     MathExtra.sub3(pts[lines[m].p2].x, pts[lines[m].p1].x, delta);
     return(MathExtra.len3(delta));
 }
Example #6
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);
            }
        }