bool _computeForceRaw(Real3D& force12, Real3D& force32, const Real3D& r12, const Real3D& r32, real _theta0) const { real dist12_sqr = r12.sqr(); real dist32_sqr = r32.sqr(); real dist12_magn = sqrt(dist12_sqr); real dist32_magn = sqrt(dist32_sqr); real dU_dtheta, a11, a12, a22; real inv_dist1232 = 1.0/(dist12_magn * dist32_magn); real cos_theta = r12 * r32 * inv_dist1232; if(cos_theta < -1.0) cos_theta = -1.0; else if(cos_theta > 1.0) cos_theta = 1.0; real sin_theta = sqrt(1.0 - cos_theta * cos_theta); dU_dtheta = - KpK * (acos(cos_theta) - _theta0) / sin_theta; a11 = dU_dtheta * cos_theta / dist12_sqr; a12 = -dU_dtheta * inv_dist1232; a22 = dU_dtheta * cos_theta / dist32_sqr; force12 = a11 * r12 + a12 * r32; force32 = a22 * r32 + a12 * r12; return true; }
inline real AngularUniquePotentialTemplate< Derived >:: computeEnergy(const Real3D& r12, const Real3D& r32, real theta0) const { real dist12Sqr = r12.sqr(); real dist32Sqr = r32.sqr(); real cos_theta = r12 * r32 / (sqrt(dist12Sqr) * sqrt(dist32Sqr)); return computeEnergy(acos(cos_theta), theta0); }
inline real AngularUniquePotentialTemplate< Derived >:: _computeEnergy(const Real3D& r12, const Real3D& r32, real theta0) const { real dist12_sqr = r12.sqr(); real dist32_sqr = r32.sqr(); if (dist12_sqr >= cutoffSqr || dist32_sqr >= cutoffSqr ) return 0.0; else{ real cos_theta = r12 * r32 / (sqrt(dist12_sqr) * sqrt(dist32_sqr)); return _computeEnergy(acos(cos_theta), theta0); } }
bool _computeForce(Real3D& force, const Particle &p1, const Particle &p2) const { Real3D dist = p1.position() - p2.position(); real r2 = dist.sqr(); if (r2>rc2) return true; real r = sqrt(r2); real qq = p1.q()*p2.q(); real ffactor = prefactor*qq* (1.0/(r*r2) + B1); force = dist * ffactor; return true; }
real _computeEnergyDeriv(const Particle& p1, const Particle& p2) const { Real3D dist = p1.position() - p2.position(); real distSqr = dist.sqr(); if (distSqr>rc2) return 0.0; if (checkTIpair(p1.id(),p2.id())) { real qq = p1.q()*p2.q(); real dhdl = -1.0 * prefactor * qq * (1.0 / sqrt(distSqr) - B1_half*distSqr -crf); return dhdl; } else { return 0.0; } }
python::list MeanSquareInternalDist::compute() const{ python::list pyli; System& system = getSystemRef(); //creating vector which stores particleIDs for each CPU vector<longint> localIDs; // localIDs is a vector with PID of particles in each CPU and it contains whole chains for (map<size_t,int>::const_iterator itr=idToCpu.begin(); itr!=idToCpu.end(); ++itr) { size_t i = itr->first; int whichCPU = itr->second; if(system.comm->rank()==whichCPU){ localIDs.push_back(i); } } sort(localIDs.begin(), localIDs.end()); //sorts entries from low to high - should not be necessary as long as the above iterator iterates in ascending order according to the keys // MSID calculation int M = getListSize(); //number of snapshots/configurations real intdist_sum = 0; int N_chains = localIDs.size() / chainlength; // N_chains is number of chains in this cpu and chainlength is a global variable from ConfigsParticleDecomp.hpp for (int n=1; n<chainlength;n++){ // loop over chainlength real intdist = 0.0; for (int j=0; j<N_chains;j++){ real sumdistsq = 0.0 ; for (int i=j*chainlength; i<(j*chainlength)+chainlength-n;i++){ Real3D pos1 = getConf(M-1)->getCoordinates(localIDs[i]); // compute the MSID of the last added snapshot Real3D pos2 = getConf(M-1)->getCoordinates(localIDs[i+n]); // compute the MSID of the last added snapshot Real3D delta = pos2 - pos1; //vector with the distances from i to chainlength-n sumdistsq += delta.sqr();// dx*dx+dy*dy+dz*dz } intdist += sumdistsq/real(chainlength-n); //sum of the internal distances (chainlength-n) of the chains in this cpu } boost::mpi::reduce(*system.comm, intdist, intdist_sum, std::plus<real>(), 0); if (system.comm->rank() == 0) { int chains_total = num_of_part / chainlength; pyli.append( intdist_sum / real(chains_total)); } } return pyli; }
real _computeEnergy(const Particle& p1, const Particle& p2) const { Real3D dist = p1.position() - p2.position(); real distSqr = dist.sqr(); if (distSqr>rc2) return 0.0; real qq = p1.q()*p2.q(); /* Note: this implementation counts minus integral of the force as energy which is not the same as the full electrostatic energy See the original paper Tironi et al J.Chem.Phys 102, 13, 1995 for details*/ real energy = prefactor*qq * (1.0 / sqrt(distSqr) - B1_half*distSqr -crf); return energy; }
bool _computeForce(Real3D& force, const Particle &p1, const Particle &p2) const { Real3D dist = p1.position() - p2.position(); real r2 = dist.sqr(); if (r2>rc2) return true; real r = sqrt(r2); real qq = p1.q()*p2.q(); if (checkTIpair(p1.id(),p2.id())) { qq *= complLambdaTI; //(1-lambda)*qAi*qAj } real ffactor = prefactor*qq* (1.0/(r*r2) + B1); force = dist * ffactor; return true; }
real _computeEnergy(const Particle& p1, const Particle& p2) const { Real3D dist = p1.position() - p2.position(); real distSqr = dist.sqr(); if (distSqr>rc2) return 0.0; real qq = p1.q()*p2.q(); if (checkTIpair(p1.id(),p2.id())) { qq *= complLambdaTI; //(1-lambda)*qAi*qAj } /* Note: this implementation counts minus integral of the force as energy which is not the same as the full electrostatic energy See the original paper Tironi et al, J. Chem. Phys. 102 , 5451 (1995) for details*/ real energy = prefactor*qq * (1.0 / sqrt(distSqr) - B1_half*distSqr -crf); return energy; }
void _computeForceRaw(Real3D& force1, Real3D& force2, Real3D& force3, Real3D& force4, const Real3D& r21, const Real3D& r32, const Real3D& r43, const real _phi0) const { Real3D retF[4]; Real3D rijjk = r21.cross(r32); // [r21 x r32] Real3D rjkkn = r32.cross(r43); // [r32 x r43] real rijjk_sqr = rijjk.sqr(); real rjkkn_sqr = rjkkn.sqr(); real rijjk_abs = sqrt(rijjk_sqr); real rjkkn_abs = sqrt(rjkkn_sqr); real inv_rijjk = 1.0 / rijjk_abs; real inv_rjkkn = 1.0 / rjkkn_abs; // cosine between planes real cos_phi = (rijjk * rjkkn) * (inv_rijjk * inv_rjkkn); if (cos_phi > 1.0) cos_phi = 1.0; else if (cos_phi < -1.0) cos_phi = -1.0; real coef1 = (-2.0) * K * (cos_phi - cos(_phi0)); real A1 = inv_rijjk * inv_rjkkn; real A2 = inv_rijjk * inv_rijjk; real A3 = inv_rjkkn * inv_rjkkn; Real3D p3232 ( prod(r32,r32) ); Real3D p3243 ( prod(r32,r43) ); Real3D p2132 ( prod(r21,r32) ); Real3D p2143 ( prod(r21,r43) ); Real3D p2121 ( prod(r21,r21) ); Real3D p4343 ( prod(r43,r43) ); // we have 4 particles 1,2,3,4 for(int l=0; l<4; l++){ Real3D B1, B2, B3; for(int i=0; i<3; i++){ B1[i]= r21[i] * ( p3232[i] * (d(l,2)-d(l,3)) + p3243[i] * (d(l,2)-d(l,1)) ) + r32[i] * ( p2132[i] * (d(l,3)-d(l,2)) + p3243[i] * (d(l,1)-d(l,0)) ) + r43[i] * ( p2132[i] * (d(l,2)-d(l,1)) + p3232[i] * (d(l,0)-d(l,1)) ) + 2.0 * r32[i] * p2143[i] * (d(l,1)-d(l,2)); B2[i]= 2.0 * r21[i] * ( p3232[i] * (d(l,1)-d(l,0)) + p2132[i] * (d(l,1)-d(l,2)) ) + 2.0 * r32[i] * ( p2121[i] * (d(l,2)-d(l,1)) + p2132[i] * (d(l,0)-d(l,1))); B3[i]= 2.0 * r43[i] * ( p3232[i] * (d(l,3)-d(l,2)) + p3243[i] * (d(l,1)-d(l,2)) ) + 2.0 * r32[i] * ( p4343[i] * (d(l,2)-d(l,1)) + p3243[i] * (d(l,2)-d(l,3))); } retF[l] = coef1 * ( A1*B1 - 0.5*cos_phi*(A2*B2 + A3*B3) ); } force1 = retF[0]; force2 = retF[1]; force3 = retF[2]; force4 = retF[3]; }
void Rattle::applyPositionConstraints() { int iteration = 0; bool done = false; real dt = integrator->getTimeStep(); System& system = getSystemRef(); const bc::BC& bc = *getSystemRef().bc; // boundary conditions boost::unordered_map<longint, Real3D> currPosition; boost::unordered_map<longint, Real3D> currVelocity; boost::unordered_map<longint, bool> movedLastTime; //was this particle moved last time? boost::unordered_map<longint, bool> movingThisTime; //is the particle being moved this time? if (oldPos.size() == 0) {return;} //no rigid bonds on this node //loop over bonds on this node OldPos::iterator it; for (it=oldPos.begin(); it != oldPos.end(); it++ ) { longint pidHyd = it->first; longint pidHeavy = constrainedBonds[pidHyd].pidHeavy; //In the maps below, the values for each key pidHeavy may be initialised more than, if pidHeavy is involved in more than one constrained bond. This is not a problem movedLastTime[pidHyd] = true; movedLastTime[pidHeavy] = true; movingThisTime[pidHyd] = false; movingThisTime[pidHeavy] = false; currPosition[pidHyd] = system.storage->lookupAdrATParticle(pidHyd)->getPos(); currPosition[pidHeavy] = system.storage->lookupAdrATParticle(pidHeavy)->getPos(); currVelocity[pidHyd] = system.storage->lookupAdrATParticle(pidHyd)->getV(); currVelocity[pidHeavy] = system.storage->lookupAdrATParticle(pidHeavy)->getV(); } //constraint interations while (!done && iteration < maxit) { done = true; //loop over constrained bonds on this cpu for (it=oldPos.begin(); it != oldPos.end(); it++) { //get pids of the two particles in this bond longint a = it->first; //pidHyd longint b = constrainedBonds[a].pidHeavy; if (movedLastTime[a] || movedLastTime[b]) { //compare current distance to desired constraint distance Real3D pab; bc.getMinimumImageVectorBox(pab,currPosition[a],currPosition[b]); //a-b, current positions which change during iterations real pabsq = pab.sqr(); real constraint_absq = constrainedBonds[a].constraintDist2; real diffsq = pabsq - constraint_absq; if (fabs(diffsq) > (constraint_absq*tol) ) { //get ab vector before unconstrained position update Real3D rab; bc.getMinimumImageVectorBox(rab,oldPos[a].second,oldPos[a].first); //pos at time t (end of last timestep), a-b; real rab_dot_pab = rab * pab; //r_ab(t) * r_ab,curr(t+dt) if (rab_dot_pab < (constraint_absq*rptol)) { //i.e. if angle is too large std::ostringstream msg; msg << "Constraint failure in RATTLE" << std::endl; throw std::runtime_error( msg.str() ); } real rma = constrainedBonds[a].invmassHyd; real rmb = constrainedBonds[a].invmassHeavy; real gab = diffsq / (2.0 * (rma + rmb) * rab_dot_pab); //direct constraint along bond vector at end of previous timestep Real3D displ = gab * rab; currPosition[a] -= rma * displ; currPosition[b] += rmb * displ; displ /= dt; currVelocity[a] -= rma * displ; currVelocity[b] += rmb * displ; movingThisTime[a] = true; movingThisTime[b] = true; done = false; } } } boost::unordered_map<longint, bool>::iterator it3; for (it3 = movedLastTime.begin(); it3 != movedLastTime.end(); it3++) { longint id = it3->first; movedLastTime[id] = movingThisTime[id]; movingThisTime[id] = false; } iteration += 1; } if (!done) { std::ostringstream msg; msg << "Too many position constraint iterations in Rattle" << std::endl; throw std::runtime_error( msg.str() ); } //store new values for positions boost::unordered_map<longint, Real3D>::iterator it2; for (it2 = currPosition.begin(); it2 != currPosition.end(); it2++) { longint id = it2->first; Particle* p = system.storage->lookupAdrATParticle(id); p->position() = currPosition[id]; p->velocity() = currVelocity[id]; } }