Ejemplo n.º 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;
            }
        }
Ejemplo n.º 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;
        }
Ejemplo n.º 3
0
        public static void LoadSim(StreamReader f, DPDSim sim)
        {
            parse_dpd_sim(f, sim);

            //
            // How many bonds and angles do we need, given the molecule definitions?
            //
            int N_bonds  = 0;
            int N_angles = 0;

            foreach (var mol in sim.molecule_types)
            {
                N_bonds  += mol.count * mol.bond_k.Count;
                N_angles += mol.count * mol.angle_k.Count;
            }

            Array.Resize(ref sim.bond_site_indices, N_bonds * 2);
            Array.Resize(ref sim.bond_eq, N_bonds);
            Array.Resize(ref sim.bond_k, N_bonds);

            Array.Resize(ref sim.angle_site_indices, N_angles * 3);
            Array.Resize(ref sim.angle_eq, N_angles);
            Array.Resize(ref sim.angle_k, N_angles);

            //
            // Populate system bond and angle arrays using molecule definitions and counts
            //
            int sys_bond_upto   = 0;
            int sys_angle_upto  = 0;
            int sys_molecule_id = 0;
            int offset          = 0; // start index into system sites for the current molecule

            foreach (var mol in sim.molecule_types)
            {
                for (var mol_inst = 0; mol_inst < mol.count; mol_inst++)
                {
                    var N = mol.bond_k.Count;
                    for (var bi = 0; bi < N; bi++)
                    {
                        var i = offset + mol.bond_site_indices[(bi * 2) + 0];
                        var j = offset + mol.bond_site_indices[(bi * 2) + 1];

                        var b_eq = mol.bond_eq[bi];
                        var b_k  = mol.bond_k[bi];

                        sim.bond_site_indices[sys_bond_upto * 2 + 0] = i - 1; // -1 : unit based index -> zero based index
                        sim.bond_site_indices[sys_bond_upto * 2 + 1] = j - 1;
                        sim.bond_eq[sys_bond_upto] = b_eq;
                        sim.bond_k[sys_bond_upto]  = b_k;

                        sys_bond_upto++;
                    }

                    N = mol.angle_k.Count;
                    for (var ai = 0; ai < N; ai++)
                    {
                        var i = offset + mol.angle_site_indices[(ai * 3) + 0];
                        var j = offset + mol.angle_site_indices[(ai * 3) + 1];
                        var k = offset + mol.angle_site_indices[(ai * 3) + 2];

                        var a_eq = mol.angle_eq[ai];
                        var a_k  = mol.angle_k[ai];

                        sim.angle_site_indices[sys_angle_upto * 3 + 0] = i - 1; // -1 : unit based index -> zero based index
                        sim.angle_site_indices[sys_angle_upto * 3 + 1] = j - 1;
                        sim.angle_site_indices[sys_angle_upto * 3 + 2] = k - 1;
                        sim.angle_eq[sys_angle_upto] = a_eq;
                        sim.angle_k[sys_angle_upto]  = a_k;

                        sys_angle_upto++;
                    }

                    N = mol.site_internal_ids.Count;
                    for (var i = 0; i < N; i++)
                    {
                        sim.molecule_ids[offset + i] = sys_molecule_id;
                    }

                    sys_molecule_id++;
                    offset += mol.site_internal_ids.Count; // update current site offset for bond indices.
                }
            }

            //
            // Nonbonded exclusion lists; used in nonbonded force calculations.
            // MaxExclusionEntries suggested to be 4.
            // Only bonds used here; angles also trivial via i,k sites of angle i-j-k.
            //
            var MaxExclusions = DPDSim.MaxExclusionEntries;

            Array.Resize(ref sim.exclude, sim.site_ids.Length * MaxExclusions);
            for (var i = 0; i < sim.exclude.Length; i++)
            {
                sim.exclude[i] = -1;
            }
            for (var bi = 0; bi < sim.bond_k.Length; bi++)
            {
                var i = sim.bond_site_indices[(bi * 2) + 0];
                var j = sim.bond_site_indices[(bi * 2) + 1];

                // i exclusion entry for j
                var l = 0;
                while (l < MaxExclusions && sim.exclude[(i * MaxExclusions) + l] != -1)
                {
                    l++;
                }
                if (l >= MaxExclusions)
                {
                    DPDError("Too few exclusion entries defined (1); increase DPDsim.MaxExclusionEntries");
                }
                sim.exclude[(i * MaxExclusions) + l] = j;

                // j exclusion entry for i
                l = 0;
                while (l < MaxExclusions && sim.exclude[(j * MaxExclusions) + l] != -1)
                {
                    l++;
                }
                if (l >= MaxExclusions)
                {
                    DPDError("Too few exclusion entries defined (2); increase DPDsim.MaxExclusionEntries");
                }
                sim.exclude[(j * MaxExclusions) + l] = i;
            }

            sim.ZeroNetMomentum();

            //
            // Should we initialize the system velocities, or leave the existing values?
            //
            if (sim.step_no < 1)
            {
                Console.WriteLine("step_no < 1, assuming system initialisation required; site velocities set from a Gaussian distribution.");
                sim.step_no = 1;
                sim.SetInitialVelocities();
            }

            //
            // Wrap particle positions that lie outside the periodic cell
            //
            {
                for (var i = 0; i < sim.site_ids.Length; i++)
                {
                    var j = i * 3;
                    var x = sim.r[j + 0];
                    var y = sim.r[j + 1];
                    var z = sim.r[j + 2];
                    VecMinimumImage(x, y, z, ref x, ref y, ref z, ref sim.cell);
                    sim.r[j + 0] = x;
                    sim.r[j + 1] = y;
                    sim.r[j + 2] = z;
                }
            }

            //
            // Link cell data only needs to be set up once if the cell is constant
            //
            sim.SetupCells();

            //
            // Calculate friction coefficient from sigma; sigma^2 = 2*fric*kBT
            //
            sim.fric = (sim.sigma * sim.sigma) / (2.0 * sim.target_kBT);

            //
            // Initialize ran1() with the seed provided
            //
            Ran1.ran1(ref sim.ran1_value);
        }