示例#1
0
        //
        // Use Gaussian distribution to set initial velocities.
        //
        public void SetInitialVelocities()
        {
            // 0.5mv**2 = 3/2kBT.
            // v = sqrt( 3kBT / m )

            double factor = Math.Sqrt(3.0 * target_kBT) / 3.0; // divide evenly across degs of freedom for v components

            for (var i = 0; i < site_ids.Length; i++)
            {
                var j = i * 3;

                v[j + 0] = Ran1.gasdev(ref ran1_value) * factor;
                v[j + 1] = Ran1.gasdev(ref ran1_value) * factor;
                v[j + 2] = Ran1.gasdev(ref ran1_value) * factor;
            }
        }
示例#2
0
        private static void nonbonded_pair(int i, int j, double cutsq, double sqrt_dt, DPDSim sim)
        {
            double dx, dy, dz;
            double dx_hat, dy_hat, dz_hat;
            double fx, fy, fz;
            double vx, vy, vz;

            var i_off = i * 3;
            var j_off = j * 3;

            //
            // Ignore bound sites. I should probably check generated code to see this is worth unrolling.
            //
            for (var k = 0; k < DPDSim.MaxExclusionEntries; k++)
            {
                if (sim.exclude[(i * DPDSim.MaxExclusionEntries) + k] == j)
                {
                    return;
                }
            }

            //
            // Difference in particle positions (minimum image convention is applied) and velocities.
            // Try for the early skip, so we don't waste time reading velocities from memory if
            // we don't need to (should also help reduce cache pressure etc).
            //
            dx = sim.r[i_off + 0] - sim.r[j_off + 0];
            dy = sim.r[i_off + 1] - sim.r[j_off + 1];
            dz = sim.r[i_off + 2] - sim.r[j_off + 2];
            VecMinimumImage(dx, dy, dz, ref dx, ref dy, ref dz, ref sim.cell);
            double r_mag = (dx * dx + dy * dy + dz * dz);

            // Avoid sqrt() until we know it's needed, compare squared distances instead
            if (r_mag > cutsq)
            {
                return;
            }

            vx = sim.v[i_off + 0] - sim.v[j_off + 0];
            vy = sim.v[i_off + 1] - sim.v[j_off + 1];
            vz = sim.v[i_off + 2] - sim.v[j_off + 2];

            r_mag  = Math.Sqrt(r_mag);
            dx_hat = dx / r_mag;
            dy_hat = dy / r_mag;
            dz_hat = dz / r_mag;

            double rhat_dot_v = (dx_hat * vx) + (dy_hat * vy) + (dz_hat * vz);

            //
            // Conservative and random weightings are the same, dissipative
            // weight = random weight^2
            //
            double cons_weight = 1.0 - r_mag / sim.rcut;
            double rand_weight = cons_weight;
            double diss_weight = rand_weight * rand_weight;

            //
            // Conservative interaction parameters (interactions defined in kBT)
            //
            double a = sim.interactions[(sim.site_ids[i] * sim.site_types.Count) + sim.site_ids[j]];

            sim.nonbonded_energy += a * (r_mag * ((r_mag / (2.0 * sim.rcut)) - 1) + (sim.rcut / 2.0));

            //
            // Accumulate conservative force
            //
            fx = a * cons_weight * dx_hat;
            fy = a * cons_weight * dy_hat;
            fz = a * cons_weight * dz_hat;

            //
            // Accumulate dissipative force
            //
            fx += -sim.fric * diss_weight * rhat_dot_v * dx_hat;
            fy += -sim.fric * diss_weight * rhat_dot_v * dy_hat;
            fz += -sim.fric * diss_weight * rhat_dot_v * dz_hat;

            //
            // Accumulate random force - gasdev() returns zero mean, unit variance.
            //
            double random_number = (double)Ran1.gasdev(ref sim.ran1_value);

            fx += sim.sigma * rand_weight * random_number * dx_hat / sqrt_dt;
            fx += sim.sigma * rand_weight * random_number * dy_hat / sqrt_dt;
            fx += sim.sigma * rand_weight * random_number * dz_hat / sqrt_dt;

            //
            // Update sim force arrays
            //
            sim.f[i_off + 0] += fx;
            sim.f[i_off + 1] += fy;
            sim.f[i_off + 2] += fz;

            sim.f[j_off + 0] -= fx;
            sim.f[j_off + 1] -= fy;
            sim.f[j_off + 2] -= fz;

            //
            // Pressure tensor contribution
            //
            sim.pressure[0] += dx * fx;
            sim.pressure[1] += dx * fy;
            sim.pressure[2] += dx * fz;

            sim.pressure[3] += dy * fx;
            sim.pressure[4] += dy * fy;
            sim.pressure[5] += dy * fz;

            sim.pressure[6] += dz * fx;
            sim.pressure[7] += dz * fy;
            sim.pressure[8] += dz * fz;

            //
            // Maintain a tally of the number of pair interactions
            //
            sim.ninteractions += 1.0;
        }