// // 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; } }
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; }
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); }