void ApplyThermostat () { RMat mc, mt; VecR vt, waB, wvB; real s1, s2, vFac; int n; s1 = s2 = 0.; DO_MOL { VSAdd (vt, mol[n].rv, 0.5 * deltaT, mol[n].ra); s1 += VDot (vt, mol[n].ra); s2 += VLenSq (vt); VSAdd (vt, mol[n].wv, 0.5 * deltaT, mol[n].wa); MVMulT (wvB, mol[n].rMatT.u, vt); MVMulT (waB, mol[n].rMatT.u, mol[n].wa); s1 += VWDot (mInert, wvB, waB); s2 += VWLenSq (mInert, wvB); } vFac = - s1 / s2; DO_MOL { VSAdd (vt, mol[n].rv, 0.5 * deltaT, mol[n].ra); VVSAdd (mol[n].ra, vFac, vt); VSAdd (vt, mol[n].wv, 0.5 * deltaT, mol[n].wa); VVSAdd (mol[n].wa, vFac, vt); } }
void ComputeForces () { VecR dr; real fcVal, rr, rrCut, rri, rri3; int j1, j2, n; rrCut = Sqr (rCut); DO_MOL VZero (mol[n].ra); uSum = 0.; virSum = 0.; for (j1 = 0; j1 < nMol - 1; j1 ++) { for (j2 = j1 + 1; j2 < nMol; j2 ++) { VSub (dr, mol[j1].r, mol[j2].r); VWrapAll (dr); rr = VLenSq (dr); if (rr < rrCut) { rri = 1. / rr; rri3 = Cube (rri); fcVal = 48. * rri3 * (rri3 - 0.5) * rri; VVSAdd (mol[j1].ra, fcVal, dr); VVSAdd (mol[j2].ra, - fcVal, dr); uSum += 4. * rri3 * (rri3 - 1.) + 1.; virSum += fcVal * rr; } } } }
void ComputeSiteForces () { VecR dr, shift; real fcVal, rr, rrCut, rri, rri3, uVal; int j1, j2, m1, m2, ms1, ms2, n, typeSum; rrCut = Sqr (rCut); for (n = 0; n < nMol * sitesMol; n ++) VZero (site[n].f); uSum = 0.; for (m1 = 0; m1 < nMol - 1; m1 ++) { for (m2 = m1 + 1; m2 < nMol; m2 ++) { VSub (dr, mol[m1].r, mol[m2].r); VZero (shift); VShiftAll (dr); VVAdd (dr, shift); rr = VLenSq (dr); if (rr < rrCut) { ms1 = m1 * sitesMol; ms2 = m2 * sitesMol; for (j1 = 0; j1 < sitesMol; j1 ++) { for (j2 = 0; j2 < sitesMol; j2 ++) { typeSum = mSite[j1].typeF + mSite[j2].typeF; if (mSite[j1].typeF == mSite[j2].typeF || typeSum == 5) { VSub (dr, site[ms1 + j1].r, site[ms2 + j2].r); VVAdd (dr, shift); rr = VLenSq (dr); rri = 1. / rr; switch (typeSum) { case 2: rri3 = Cube (rri); uVal = 4. * rri3 * (rri3 - 1.); fcVal = 48. * rri3 * (rri3 - 0.5) * rri; break; case 4: uVal = 4. * bCon * sqrt (rri); fcVal = uVal * rri; break; case 5: uVal = -2. * bCon * sqrt (rri); fcVal = uVal * rri; break; case 6: uVal = bCon * sqrt (rri); fcVal = uVal * rri; break; } VVSAdd (site[ms1 + j1].f, fcVal, dr); VVSAdd (site[ms2 + j2].f, - fcVal, dr); uSum += uVal; } } } } } } }
void ComputeForcesDipoleF () { VecR vc, vn, vs; real fMult, gr, gs, gu, pc, ps, sumC, sumS, t, w; int n, nvv, nx, ny, nz; gu = 2. * M_PI * dipoleInt / Cube (region.x); gr = 4. * M_PI * gu / region.x; gs = 2. * gu; EvalSinCos (); w = Sqr (M_PI / (region.x * alpha)); for (nz = 0; nz <= fSpaceLimit; nz ++) { for (ny = - fSpaceLimit; ny <= fSpaceLimit; ny ++) { for (nx = - fSpaceLimit; nx <= fSpaceLimit; nx ++) { VSet (vn, nx, ny, nz); nvv = VLenSq (vn); if (nvv == 0 || nvv > Sqr (fSpaceLimit)) continue; fMult = 2. * exp (- w * nvv) / nvv; if (nz == 0) fMult *= 0.5; sumC = sumS = 0.; DO_MOL { VSet (vc, tCos[abs (nx)][n].x, tCos[abs (ny)][n].y, tCos[nz][n].z); VSet (vs, tSin[abs (nx)][n].x, tSin[abs (ny)][n].y, tSin[nz][n].z); if (nx < 0) vs.x = - vs.x; if (ny < 0) vs.y = - vs.y; pc = vc.x * vc.y * vc.z - vc.x * vs.y * vs.z - vs.x * vc.y * vs.z - vs.x * vs.y * vc.z; ps = vs.x * vc.y * vc.z + vc.x * vs.y * vc.z + vc.x * vc.y * vs.z - vs.x * vs.y * vs.z; sumC += VDot (vn, mol[n].s) * pc; sumS += VDot (vn, mol[n].s) * ps; } DO_MOL { VSet (vc, tCos[abs (nx)][n].x, tCos[abs (ny)][n].y, tCos[nz][n].z); VSet (vs, tSin[abs (nx)][n].x, tSin[abs (ny)][n].y, tSin[nz][n].z); if (nx < 0) vs.x = - vs.x; if (ny < 0) vs.y = - vs.y; pc = vc.x * vc.y * vc.z - vc.x * vs.y * vs.z - vs.x * vc.y * vs.z - vs.x * vs.y * vc.z; ps = vs.x * vc.y * vc.z + vc.x * vs.y * vc.z + vc.x * vc.y * vs.z - vs.x * vs.y * vs.z; t = gr * fMult * VDot (vn, mol[n].s) * (sumC * ps - sumS * pc); VVSAdd (mol[n].ra, t, vn); t = gs * fMult * (sumC * pc + sumS * ps); VVSAdd (mol[n].sa, - t, vn); } uSum += gu * fMult * (Sqr (sumC) + Sqr (sumS)); } } } }
void LeapfrogStep (int part) { int n; if (part == 1) { DO_MOL { VVSAdd (mol[n].rv, 0.5 * deltaT, mol[n].ra); VVSAdd (mol[n].r, deltaT, mol[n].rv); } } else {
void InitCoords () { VecR c, gap; int j, n, nx, ny, nz; VDiv (gap, region, initUcell); n = 0; for (nz = 0; nz < initUcell.z; nz ++) { for (ny = 0; ny < initUcell.y; ny ++) { for (nx = 0; nx < initUcell.x; nx ++) { VSet (c, nx + 0.25, ny + 0.25, nz + 0.25); VMul (c, c, gap); VVSAdd (c, -0.5, region); for (j = 0; j < 4; j ++) { mol[n].r = c; if (j != 3) { if (j != 0) mol[n].r.x += 0.5 * gap.x; if (j != 1) mol[n].r.y += 0.5 * gap.y; if (j != 2) mol[n].r.z += 0.5 * gap.z; } ++ n; } } } } }
void LeapfrogStep (int part) { RMat mc, mt; VecR t; int n; if (part == 1) { DO_MOL { VVSAdd (mol[n].wv, 0.5 * deltaT, mol[n].wa); VVSAdd (mol[n].rv, 0.5 * deltaT, mol[n].ra); } DO_MOL { VSCopy (t, 0.5 * deltaT, mol[n].wv); BuildStepRmatT (&mc, &t); MulMat (mt.u, mc.u, mol[n].rMatT.u, 3); mol[n].rMatT = mt; } DO_MOL VVSAdd (mol[n].r, deltaT, mol[n].rv); } else {
void ComputeDipoleAccel () { real t; int n; DO_MOL { t = VDot (mol[n].sa, mol[n].s) + mInert * VLenSq (mol[n].sv); VVSAdd (mol[n].sa, - t, mol[n].s); VScale (mol[n].sa, 1. / mInert); } }
void ComputeForcesDipoleR () { VecR dr, w; real a1, a2, a3, alpha2, d, irPi, rr, rrCut, rri, sr1, sr2, ss, t; int j1, j2, n; rrCut = Sqr (0.5 * region.x); irPi = 1. / sqrt (M_PI); alpha2 = Sqr (alpha); DO_MOL VZero (mol[n].sa); for (j1 = 0; j1 < nMol - 1; j1 ++) { for (j2 = j1 + 1; j2 < nMol; j2 ++) { VSub (dr, mol[j1].r, mol[j2].r); VWrapAll (dr); rr = VLenSq (dr); if (rr < rrCut) { d = sqrt (rr); rri = 1. / rr; t = 2. * dipoleInt * alpha * exp (- alpha2 * rr) * rri * irPi; a1 = dipoleInt * erfc (alpha * d) * rri / d + t; a2 = 3. * a1 * rri + 2. * alpha2 * t; a3 = 5. * a2 * rri + 4. * Sqr (alpha2) * t; ss = VDot (mol[j1].s, mol[j2].s); sr1 = VDot (mol[j1].s, dr); sr2 = VDot (mol[j2].s, dr); VSSAdd (w, sr2, mol[j1].s, sr1, mol[j2].s); t = (a2 * ss - a3 * sr1 * sr2); VSSAdd (w, t, dr, a2, w); VVAdd (mol[j1].ra, w); VVSub (mol[j2].ra, w); VVSAdd (mol[j1].sa, - a1, mol[j2].s); VVSAdd (mol[j1].sa, a2 * sr2, dr); VVSAdd (mol[j2].sa, - a1, mol[j1].s); VVSAdd (mol[j2].sa, a2 * sr1, dr); uSum += a1 * ss - a2 * sr1 * sr2; } } } uSum -= 2. * dipoleInt * Cube (alpha) * nMol * irPi / 3.; }
void InitCoords () { VecR c, gap; int n, nx, ny, nz; VDiv (gap, region, initUcell); n = 0; for (nz = 0; nz < initUcell.z; nz ++) { for (ny = 0; ny < initUcell.y; ny ++) { for (nx = 0; nx < initUcell.x; nx ++) { VSet (c, nx + 0.5, ny + 0.5, nz + 0.5); VMul (c, c, gap); VVSAdd (c, -0.5, region); mol[n].r = c; ++ n; } } } }
void ApplyThermostat () { real s1, s2, vFac; VecR w; int n; s1 = s2 = 0.; DO_MOL { s1 += VDot (mol[n].rv, mol[n].ra); s2 += VLenSq (mol[n].rv); } DO_MOL { ComputeAngVel (n, &w); s1 += VDot (w, mol[n].torq); s2 += VWLenSq (mInert, w); } vFac = - s1 / s2; DO_MOL { VVSAdd (mol[n].ra, vFac, mol[n].rv); QSAdd (mol[n].qa, mol[n].qa, vFac, mol[n].qv); } }