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