void RMSDForceImpl::initialize(ContextImpl& context) { kernel = context.getPlatform().createKernel(CalcRMSDForceKernel::Name(), context); // Check for errors in the specification of particles. const System& system = context.getSystem(); int numParticles = system.getNumParticles(); if (owner.getReferencePositions().size() != numParticles) throw OpenMMException("RMSDForce: Number of reference positions does not equal number of particles in the System"); set<int> particles; for (int i : owner.getParticles()) { if (i < 0 || i >= numParticles) { stringstream msg; msg << "RMSDForce: Illegal particle index for RMSD: "; msg << i; throw OpenMMException(msg.str()); } if (particles.find(i) != particles.end()) { stringstream msg; msg << "RMSDForce: Duplicated particle index for RMSD: "; msg << i; throw OpenMMException(msg.str()); } particles.insert(i); } kernel.getAs<CalcRMSDForceKernel>().initialize(context.getSystem(), owner); }
void CustomNonbondedForceImpl::initialize(ContextImpl& context) { kernel = context.getPlatform().createKernel(CalcCustomNonbondedForceKernel::Name(), context); // Check for errors in the specification of parameters and exclusions. const System& system = context.getSystem(); if (owner.getNumParticles() != system.getNumParticles()) throw OpenMMException("CustomNonbondedForce must have exactly as many particles as the System it belongs to."); if (owner.getUseSwitchingFunction()) { if (owner.getSwitchingDistance() < 0 || owner.getSwitchingDistance() >= owner.getCutoffDistance()) throw OpenMMException("CustomNonbondedForce: Switching distance must satisfy 0 <= r_switch < r_cutoff"); } vector<set<int> > exclusions(owner.getNumParticles()); vector<double> parameters; int numParameters = owner.getNumPerParticleParameters(); for (int i = 0; i < owner.getNumParticles(); i++) { owner.getParticleParameters(i, parameters); if (parameters.size() != numParameters) { stringstream msg; msg << "CustomNonbondedForce: Wrong number of parameters for particle "; msg << i; throw OpenMMException(msg.str()); } } for (int i = 0; i < owner.getNumExclusions(); i++) { int particle1, particle2; owner.getExclusionParticles(i, particle1, particle2); if (particle1 < 0 || particle1 >= owner.getNumParticles()) { stringstream msg; msg << "CustomNonbondedForce: Illegal particle index for an exclusion: "; msg << particle1; throw OpenMMException(msg.str()); } if (particle2 < 0 || particle2 >= owner.getNumParticles()) { stringstream msg; msg << "CustomNonbondedForce: Illegal particle index for an exclusion: "; msg << particle2; throw OpenMMException(msg.str()); } if (exclusions[particle1].count(particle2) > 0 || exclusions[particle2].count(particle1) > 0) { stringstream msg; msg << "CustomNonbondedForce: Multiple exclusions are specified for particles "; msg << particle1; msg << " and "; msg << particle2; throw OpenMMException(msg.str()); } exclusions[particle1].insert(particle2); exclusions[particle2].insert(particle1); } if (owner.getNonbondedMethod() == CustomNonbondedForce::CutoffPeriodic) { Vec3 boxVectors[3]; system.getDefaultPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]); double cutoff = owner.getCutoffDistance(); if (cutoff > 0.5*boxVectors[0][0] || cutoff > 0.5*boxVectors[1][1] || cutoff > 0.5*boxVectors[2][2]) throw OpenMMException("CustomNonbondedForce: The cutoff distance cannot be greater than half the periodic box size."); } kernel.getAs<CalcCustomNonbondedForceKernel>().initialize(context.getSystem(), owner); }
void AmoebaWcaDispersionForceImpl::initialize(ContextImpl& context) { const System& system = context.getSystem(); if (owner.getNumParticles() != system.getNumParticles()) throw OpenMMException("AmoebaWcaDispersionForce must have exactly as many particles as the System it belongs to."); kernel = context.getPlatform().createKernel(CalcAmoebaWcaDispersionForceKernel::Name(), context); kernel.getAs<CalcAmoebaWcaDispersionForceKernel>().initialize(context.getSystem(), owner); }
void RPMDIntegrator::initialize(ContextImpl& contextRef) { if (owner != NULL && &contextRef.getOwner() != owner) throw OpenMMException("This Integrator is already bound to a context"); if (contextRef.getSystem().getNumConstraints() > 0) throw OpenMMException("RPMDIntegrator cannot be used with Systems that include constraints"); context = &contextRef; owner = &contextRef.getOwner(); kernel = context->getPlatform().createKernel(IntegrateRPMDStepKernel::Name(), contextRef); kernel.getAs<IntegrateRPMDStepKernel>().initialize(contextRef.getSystem(), *this); }
void NonbondedForceImpl::initialize(ContextImpl& context) { kernel = context.getPlatform().createKernel(CalcNonbondedForceKernel::Name(), context); // Check for errors in the specification of exceptions. const System& system = context.getSystem(); if (owner.getNumParticles() != system.getNumParticles()) throw OpenMMException("NonbondedForce must have exactly as many particles as the System it belongs to."); if (owner.getUseSwitchingFunction()) { if (owner.getSwitchingDistance() < 0 || owner.getSwitchingDistance() >= owner.getCutoffDistance()) throw OpenMMException("NonbondedForce: Switching distance must satisfy 0 <= r_switch < r_cutoff"); } vector<set<int> > exceptions(owner.getNumParticles()); for (int i = 0; i < owner.getNumExceptions(); i++) { int particle1, particle2; double chargeProd, sigma, epsilon; owner.getExceptionParameters(i, particle1, particle2, chargeProd, sigma, epsilon); if (particle1 < 0 || particle1 >= owner.getNumParticles()) { stringstream msg; msg << "NonbondedForce: Illegal particle index for an exception: "; msg << particle1; throw OpenMMException(msg.str()); } if (particle2 < 0 || particle2 >= owner.getNumParticles()) { stringstream msg; msg << "NonbondedForce: Illegal particle index for an exception: "; msg << particle2; throw OpenMMException(msg.str()); } if (exceptions[particle1].count(particle2) > 0 || exceptions[particle2].count(particle1) > 0) { stringstream msg; msg << "NonbondedForce: Multiple exceptions are specified for particles "; msg << particle1; msg << " and "; msg << particle2; throw OpenMMException(msg.str()); } exceptions[particle1].insert(particle2); exceptions[particle2].insert(particle1); } if (owner.getNonbondedMethod() == NonbondedForce::CutoffPeriodic || owner.getNonbondedMethod() == NonbondedForce::Ewald || owner.getNonbondedMethod() == NonbondedForce::PME) { Vec3 boxVectors[3]; system.getDefaultPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]); double cutoff = owner.getCutoffDistance(); if (cutoff > 0.5*boxVectors[0][0] || cutoff > 0.5*boxVectors[1][1] || cutoff > 0.5*boxVectors[2][2]) throw OpenMMException("NonbondedForce: The cutoff distance cannot be greater than half the periodic box size."); if (owner.getNonbondedMethod() == NonbondedForce::Ewald && (boxVectors[1][0] != 0.0 || boxVectors[2][0] != 0.0 || boxVectors[2][1] != 0)) throw OpenMMException("NonbondedForce: Ewald is not supported with non-rectangular boxes. Use PME instead."); } kernel.getAs<CalcNonbondedForceKernel>().initialize(context.getSystem(), owner); }
void GBSAOBCForceImpl::initialize(ContextImpl& context) { kernel = context.getPlatform().createKernel(CalcGBSAOBCForceKernel::Name(), context); if (owner.getNumParticles() != context.getSystem().getNumParticles()) throw OpenMMException("GBSAOBCForce must have exactly as many particles as the System it belongs to."); if (owner.getNonbondedMethod() == GBSAOBCForce::CutoffPeriodic) { Vec3 boxVectors[3]; context.getSystem().getDefaultPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]); double cutoff = owner.getCutoffDistance(); if (cutoff > 0.5*boxVectors[0][0] || cutoff > 0.5*boxVectors[1][1] || cutoff > 0.5*boxVectors[2][2]) throw OpenMMException("GBSAOBCForce: The cutoff distance cannot be greater than half the periodic box size."); } kernel.getAs<CalcGBSAOBCForceKernel>().initialize(context.getSystem(), owner); }
static double computeShiftedKineticEnergy(ContextImpl& context, vector<double>& inverseMasses, double timeShift, ReferenceConstraintAlgorithm* constraints) { const System& system = context.getSystem(); int numParticles = system.getNumParticles(); vector<RealVec>& posData = extractPositions(context); vector<RealVec>& velData = extractVelocities(context); vector<RealVec>& forceData = extractForces(context); // Compute the shifted velocities. vector<RealVec> shiftedVel(numParticles); for (int i = 0; i < numParticles; ++i) { if (inverseMasses[i] > 0) shiftedVel[i] = velData[i]+forceData[i]*(timeShift*inverseMasses[i]); else shiftedVel[i] = velData[i]; } // Apply constraints to them. if (constraints != NULL) { constraints->setTolerance(1e-4); constraints->applyToVelocities(numParticles, posData, shiftedVel, inverseMasses); } // Compute the kinetic energy. double energy = 0.0; for (int i = 0; i < numParticles; ++i) if (inverseMasses[i] > 0) energy += (shiftedVel[i].dot(shiftedVel[i]))/inverseMasses[i]; return 0.5*energy; }
/** * Compute the kinetic energy of the system, possibly shifting the velocities in time to account * for a leapfrog integrator. */ static double computeShiftedKineticEnergy(ContextImpl& context, vector<double>& masses, double timeShift) { vector<RealVec>& posData = extractPositions(context); vector<RealVec>& velData = extractVelocities(context); vector<RealVec>& forceData = extractForces(context); int numParticles = context.getSystem().getNumParticles(); // Compute the shifted velocities. vector<RealVec> shiftedVel(numParticles); for (int i = 0; i < numParticles; ++i) { if (masses[i] > 0) shiftedVel[i] = velData[i]+forceData[i]*(timeShift/masses[i]); else shiftedVel[i] = velData[i]; } // Apply constraints to them. vector<double> inverseMasses(numParticles); for (int i = 0; i < numParticles; i++) inverseMasses[i] = (masses[i] == 0 ? 0 : 1/masses[i]); extractConstraints(context).applyToVelocities(posData, shiftedVel, inverseMasses, 1e-4); // Compute the kinetic energy. double energy = 0.0; for (int i = 0; i < numParticles; ++i) if (masses[i] > 0) energy += masses[i]*(shiftedVel[i].dot(shiftedVel[i])); return 0.5*energy; }
void CustomIntegrator::initialize(ContextImpl& contextRef) { if (owner != NULL && &contextRef.getOwner() != owner) throw OpenMMException("This Integrator is already bound to a context"); vector<std::string> variableList; set<std::string> variableSet; variableList.insert(variableList.end(), globalNames.begin(), globalNames.end()); variableList.insert(variableList.end(), perDofNames.begin(), perDofNames.end()); for (int i = 0; i < (int) variableList.size(); i++) { string& name = variableList[i]; if (variableSet.find(name) != variableSet.end()) throw OpenMMException("The Integrator defines two variables with the same name: "+name); variableSet.insert(name); if (contextRef.getParameters().find(name) != contextRef.getParameters().end()) throw OpenMMException("The Integrator defines a variable with the same name as a Context parameter: "+name); } set<std::string> globalTargets; globalTargets.insert(globalNames.begin(), globalNames.end()); globalTargets.insert("dt"); for (map<string, double>::const_iterator iter = contextRef.getParameters().begin(); iter != contextRef.getParameters().end(); ++iter) globalTargets.insert(iter->first); for (int i = 0; i < computations.size(); i++) { if (computations[i].type == ComputeGlobal && globalTargets.find(computations[i].variable) == globalTargets.end()) throw OpenMMException("Unknown global variable: "+computations[i].variable); } context = &contextRef; owner = &contextRef.getOwner(); kernel = context->getPlatform().createKernel(IntegrateCustomStepKernel::Name(), contextRef); kernel.getAs<IntegrateCustomStepKernel>().initialize(contextRef.getSystem(), *this); kernel.getAs<IntegrateCustomStepKernel>().setGlobalVariables(contextRef, globalValues); for (int i = 0; i < (int) perDofValues.size(); i++) { if (perDofValues[i].size() == 1) perDofValues[i].resize(context->getSystem().getNumParticles(), perDofValues[i][0]); kernel.getAs<IntegrateCustomStepKernel>().setPerDofVariable(contextRef, i, perDofValues[i]); } }
double CpuCalcForcesAndEnergyKernel::finishComputation(ContextImpl& context, bool includeForce, bool includeEnergy, int groups) { // Sum the forces from all the threads. SumForceTask task(context.getSystem().getNumParticles(), extractForces(context), data); data.threads.execute(task); data.threads.waitForThreads(); return referenceKernel.getAs<ReferenceCalcForcesAndEnergyKernel>().finishComputation(context, includeForce, includeEnergy, groups); }
void VariableLangevinIntegrator::initialize(ContextImpl& contextRef) { if (owner != NULL && &contextRef.getOwner() != owner) throw OpenMMException("This Integrator is already bound to a context"); context = &contextRef; owner = &contextRef.getOwner(); kernel = context->getPlatform().createKernel(IntegrateVariableLangevinStepKernel::Name(), contextRef); kernel.getAs<IntegrateVariableLangevinStepKernel>().initialize(contextRef.getSystem(), *this); }
void Integrator::initialize( ContextImpl &contextRef ) { context = &contextRef; if( context->getSystem().getNumConstraints() > 0 ) { throw OpenMMException( "LTMD Integrator does not support constraints" ); } kernel = context->getPlatform().createKernel( StepKernel::Name(), contextRef ); ( ( StepKernel & )( kernel.getImpl() ) ).initialize( contextRef.getSystem(), *this ); //(dynamic_cast<StepKernel &>( kernel.getImpl() )).initialize( contextRef.getSystem(), *this ); }
void CpuCalcForcesAndEnergyKernel::beginComputation(ContextImpl& context, bool includeForce, bool includeEnergy, int groups) { referenceKernel.getAs<ReferenceCalcForcesAndEnergyKernel>().beginComputation(context, includeForce, includeEnergy, groups); // Convert positions to single precision and clear the forces. InitForceTask task(context.getSystem().getNumParticles(), context, data); data.threads.execute(task); data.threads.waitForThreads(); }
void DrudeLangevinIntegrator::initialize(ContextImpl& contextRef) { if (owner != NULL && &contextRef.getOwner() != owner) throw OpenMMException("This Integrator is already bound to a context"); const DrudeForce* force = NULL; const System& system = contextRef.getSystem(); for (int i = 0; i < system.getNumForces(); i++) if (dynamic_cast<const DrudeForce*>(&system.getForce(i)) != NULL) { if (force == NULL) force = dynamic_cast<const DrudeForce*>(&system.getForce(i)); else throw OpenMMException("The System contains multiple DrudeForces"); } if (force == NULL) throw OpenMMException("The System does not contain a DrudeForce"); context = &contextRef; owner = &contextRef.getOwner(); kernel = context->getPlatform().createKernel(IntegrateDrudeLangevinStepKernel::Name(), contextRef); kernel.getAs<IntegrateDrudeLangevinStepKernel>().initialize(contextRef.getSystem(), *this, *force); }
void MonteCarloAnisotropicBarostatImpl::initialize(ContextImpl& context) { kernel = context.getPlatform().createKernel(ApplyMonteCarloBarostatKernel::Name(), context); kernel.getAs<ApplyMonteCarloBarostatKernel>().initialize(context.getSystem(), owner); Vec3 box[3]; context.getPeriodicBoxVectors(box[0], box[1], box[2]); double volume = box[0][0]*box[1][1]*box[2][2]; for (int i=0; i<3; i++) { volumeScale[i] = 0.01*volume; numAttempted[i] = 0; numAccepted[i] = 0; } init_gen_rand(owner.getRandomNumberSeed(), random); }
void MonteCarloBarostatImpl::initialize(ContextImpl& context) { kernel = context.getPlatform().createKernel(ApplyMonteCarloBarostatKernel::Name(), context); kernel.getAs<ApplyMonteCarloBarostatKernel>().initialize(context.getSystem(), owner); Vec3 box[3]; context.getPeriodicBoxVectors(box[0], box[1], box[2]); double volume = box[0][0]*box[1][1]*box[2][2]; volumeScale = 0.01*volume; numAttempted = 0; numAccepted = 0; int randSeed = owner.getRandomNumberSeed(); // A random seed of 0 means use a unique one if (randSeed == 0) randSeed = osrngseed(); init_gen_rand(randSeed, random); }
double ReferenceIntegrateRPMDStepKernel::computeKineticEnergy(ContextImpl& context, const RPMDIntegrator& integrator) { const System& system = context.getSystem(); int numParticles = system.getNumParticles(); vector<RealVec>& velData = extractVelocities(context); double energy = 0.0; for (int i = 0; i < numParticles; ++i) { double mass = system.getParticleMass(i); if (mass > 0) { RealVec v = velData[i]; energy += mass*(v.dot(v)); } } return 0.5*energy; }
void CpuIntegrateLangevinStepKernel::execute(ContextImpl& context, const LangevinIntegrator& integrator) { double temperature = integrator.getTemperature(); double friction = integrator.getFriction(); double stepSize = integrator.getStepSize(); vector<RealVec>& posData = extractPositions(context); vector<RealVec>& velData = extractVelocities(context); vector<RealVec>& forceData = extractForces(context); if (dynamics == 0 || temperature != prevTemp || friction != prevFriction || stepSize != prevStepSize) { // Recreate the computation objects with the new parameters. if (dynamics) delete dynamics; RealOpenMM tau = (friction == 0.0 ? 0.0 : 1.0/friction); dynamics = new CpuLangevinDynamics(context.getSystem().getNumParticles(), stepSize, tau, temperature, data.threads, data.random); dynamics->setReferenceConstraintAlgorithm(&extractConstraints(context)); prevTemp = temperature; prevFriction = friction; prevStepSize = stepSize; } dynamics->update(context.getSystem(), posData, velData, forceData, masses, integrator.getConstraintTolerance()); ReferencePlatform::PlatformData* refData = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData()); refData->time += stepSize; refData->stepCount++; }
void CpuCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force) { if (force.getNumParticles() != numParticles) throw OpenMMException("updateParametersInContext: The number of particles has changed"); vector<int> nb14s; for (int i = 0; i < force.getNumExceptions(); i++) { int particle1, particle2; double chargeProd, sigma, epsilon; force.getExceptionParameters(i, particle1, particle2, chargeProd, sigma, epsilon); if (chargeProd != 0.0 || epsilon != 0.0) nb14s.push_back(i); } if (nb14s.size() != num14) throw OpenMMException("updateParametersInContext: The number of non-excluded exceptions has changed"); // Record the values. double sumSquaredCharges = 0.0; for (int i = 0; i < numParticles; ++i) { double charge, radius, depth; force.getParticleParameters(i, charge, radius, depth); data.posq[4*i+3] = (float) charge; particleParams[i] = make_pair((float) (0.5*radius), (float) (2.0*sqrt(depth))); sumSquaredCharges += charge*charge; } if (nonbondedMethod == Ewald || nonbondedMethod == PME) ewaldSelfEnergy = -ONE_4PI_EPS0*ewaldAlpha*sumSquaredCharges/sqrt(M_PI); else ewaldSelfEnergy = 0.0; for (int i = 0; i < num14; ++i) { int particle1, particle2; double charge, radius, depth; force.getExceptionParameters(nb14s[i], particle1, particle2, charge, radius, depth); bonded14IndexArray[i][0] = particle1; bonded14IndexArray[i][1] = particle2; bonded14ParamArray[i][0] = static_cast<RealOpenMM>(radius); bonded14ParamArray[i][1] = static_cast<RealOpenMM>(4.0*depth); bonded14ParamArray[i][2] = static_cast<RealOpenMM>(charge); } // Recompute the coefficient for the dispersion correction. NonbondedForce::NonbondedMethod method = force.getNonbondedMethod(); if (force.getUseDispersionCorrection() && (method == NonbondedForce::CutoffPeriodic || method == NonbondedForce::Ewald || method == NonbondedForce::PME)) dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(context.getSystem(), force); }
void ReferenceCalcMBPolElectrostaticsForceKernel::getSystemElectrostaticsMoments(ContextImpl& context, std::vector< double >& outputElectrostaticsMoments){ // retrieve masses const OpenMM::System& system = context.getSystem(); vector<RealOpenMM> masses; for (int i = 0; i < system.getNumParticles(); ++i) { masses.push_back( static_cast<RealOpenMM>(system.getParticleMass(i)) ); } MBPolReferenceElectrostaticsForce* mbpolReferenceElectrostaticsForce = setupMBPolReferenceElectrostaticsForce( context ); vector<RealVec>& posData = extractPositions(context); mbpolReferenceElectrostaticsForce->calculateMBPolSystemElectrostaticsMoments( masses, posData, charges, tholes, dampingFactors, polarity, axisTypes, multipoleAtomZs, multipoleAtomXs, multipoleAtomYs, multipoleAtomCovalentInfo, outputElectrostaticsMoments ); delete mbpolReferenceElectrostaticsForce; return; }
void ReferenceIntegrateDrudeSCFStepKernel::execute(ContextImpl& context, const DrudeSCFIntegrator& integrator) { vector<RealVec>& pos = extractPositions(context); vector<RealVec>& vel = extractVelocities(context); vector<RealVec>& force = extractForces(context); // Update the positions and velocities. int numParticles = particleInvMass.size(); vector<RealVec> xPrime(numParticles); RealOpenMM dt = integrator.getStepSize(); for (int i = 0; i < numParticles; i++) { if (particleInvMass[i] != 0.0) { vel[i] += force[i]*particleInvMass[i]*dt; xPrime[i] = pos[i]+vel[i]*dt; } } // Apply constraints. if (constraints != NULL) constraints->apply(numParticles, pos, xPrime, particleInvMass); // Record the constrained positions and velocities. RealOpenMM dtInv = 1.0/dt; for (int i = 0; i < numParticles; i++) { if (particleInvMass[i] != 0.0) { vel[i] = (xPrime[i]-pos[i])*dtInv; pos[i] = xPrime[i]; } } // Update the positions of virtual sites and Drude particles. ReferenceVirtualSites::computePositions(context.getSystem(), pos); minimize(context, integrator.getMinimizationErrorTolerance()); data.time += integrator.getStepSize(); data.stepCount++; }
void DrudeForceImpl::initialize(ContextImpl& context) { kernel = context.getPlatform().createKernel(CalcDrudeForceKernel::Name(), context); const System& system = context.getSystem(); // Check for errors in the specification of particles. set<int> usedParticles; for (int i = 0; i < owner.getNumParticles(); i++) { int particle, particle1, particle2, particle3, particle4; double charge, k, k2, k3; owner.getParticleParameters(i, particle, particle1, particle2, particle3, particle4, charge, k, k2, k3); if (particle < 0 || particle >= system.getNumParticles()) { stringstream msg; msg << "DrudeForce: Illegal particle index: "; msg << particle; throw OpenMMException(msg.str()); } if (particle1 < 0 || particle1 >= system.getNumParticles()) { stringstream msg; msg << "DrudeForce: Illegal particle index: "; msg << particle1; throw OpenMMException(msg.str()); } if (particle2 < -1 || particle2 >= system.getNumParticles()) { stringstream msg; msg << "DrudeForce: Illegal particle index: "; msg << particle2; throw OpenMMException(msg.str()); } if (particle3 < -1 || particle3 >= system.getNumParticles()) { stringstream msg; msg << "DrudeForce: Illegal particle index: "; msg << particle3; throw OpenMMException(msg.str()); } if (particle4 < -1 || particle4 >= system.getNumParticles()) { stringstream msg; msg << "DrudeForce: Illegal particle index: "; msg << particle4; throw OpenMMException(msg.str()); } if (usedParticles.find(particle) != usedParticles.end()) { stringstream msg; msg << "DrudeForce: Particle index is used by two different Drude particles: "; msg << particle; throw OpenMMException(msg.str()); } usedParticles.insert(particle); if (usedParticles.find(particle1) != usedParticles.end()) { stringstream msg; msg << "DrudeForce: Particle index is used by two different Drude particles: "; msg << particle1; throw OpenMMException(msg.str()); } usedParticles.insert(particle1); } // Check for errors in the specification of screened pairs. vector<set<int> > screenedPairs(owner.getNumParticles()); for (int i = 0; i < owner.getNumScreenedPairs(); i++) { int particle1, particle2; double thole; owner.getScreenedPairParameters(i, particle1, particle2, thole); if (particle1 < 0 || particle1 >= owner.getNumParticles()) { stringstream msg; msg << "DrudeForce: Illegal particle index for a screened pair: "; msg << particle1; throw OpenMMException(msg.str()); } if (particle2 < 0 || particle2 >= owner.getNumParticles()) { stringstream msg; msg << "DrudeForce: Illegal particle index for a screened pair: "; msg << particle2; throw OpenMMException(msg.str()); } if (screenedPairs[particle1].count(particle2) > 0 || screenedPairs[particle2].count(particle1) > 0) { stringstream msg; msg << "DrudeForce: Multiple screened pairs are specified for particles "; msg << particle1; msg << " and "; msg << particle2; throw OpenMMException(msg.str()); } screenedPairs[particle1].insert(particle2); screenedPairs[particle2].insert(particle1); } kernel.getAs<CalcDrudeForceKernel>().initialize(context.getSystem(), owner); }
void CustomHbondForceImpl::initialize(ContextImpl& context) { kernel = context.getPlatform().createKernel(CalcCustomHbondForceKernel::Name(), context); // Check for errors in the specification of parameters and exclusions. const System& system = context.getSystem(); vector<set<int> > exclusions(owner.getNumDonors()); vector<double> parameters; int numDonorParameters = owner.getNumPerDonorParameters(); for (int i = 0; i < owner.getNumDonors(); i++) { int d1, d2, d3; owner.getDonorParameters(i, d1, d2, d3, parameters); if (d1 < 0 || d1 >= system.getNumParticles()) { stringstream msg; msg << "CustomHbondForce: Illegal particle index for a donor: "; msg << d1; throw OpenMMException(msg.str()); } if (d2 < -1 || d2 >= system.getNumParticles()) { stringstream msg; msg << "CustomHbondForce: Illegal particle index for a donor: "; msg << d2; throw OpenMMException(msg.str()); } if (d3 < -1 || d3 >= system.getNumParticles()) { stringstream msg; msg << "CustomHbondForce: Illegal particle index for a donor: "; msg << d3; throw OpenMMException(msg.str()); } if (parameters.size() != numDonorParameters) { stringstream msg; msg << "CustomHbondForce: Wrong number of parameters for donor "; msg << i; throw OpenMMException(msg.str()); } } int numAcceptorParameters = owner.getNumPerAcceptorParameters(); for (int i = 0; i < owner.getNumAcceptors(); i++) { int a1, a2, a3; owner.getAcceptorParameters(i, a1, a2, a3, parameters); if (a1 < 0 || a1 >= system.getNumParticles()) { stringstream msg; msg << "CustomHbondForce: Illegal particle index for an acceptor: "; msg << a1; throw OpenMMException(msg.str()); } if (a2 < -1 || a2 >= system.getNumParticles()) { stringstream msg; msg << "CustomHbondForce: Illegal particle index for an acceptor: "; msg << a2; throw OpenMMException(msg.str()); } if (a3 < -1 || a3 >= system.getNumParticles()) { stringstream msg; msg << "CustomHbondForce: Illegal particle index for an acceptor: "; msg << a3; throw OpenMMException(msg.str()); } if (parameters.size() != numAcceptorParameters) { stringstream msg; msg << "CustomHbondForce: Wrong number of parameters for acceptor "; msg << i; throw OpenMMException(msg.str()); } } for (int i = 0; i < owner.getNumExclusions(); i++) { int donor, acceptor; owner.getExclusionParticles(i, donor, acceptor); if (donor < 0 || donor >= owner.getNumDonors()) { stringstream msg; msg << "CustomHbondForce: Illegal donor index for an exclusion: "; msg << donor; throw OpenMMException(msg.str()); } if (acceptor < 0 || acceptor >= owner.getNumAcceptors()) { stringstream msg; msg << "CustomHbondForce: Illegal acceptor index for an exclusion: "; msg << acceptor; throw OpenMMException(msg.str()); } if (exclusions[donor].count(acceptor) > 0) { stringstream msg; msg << "CustomHbondForce: Multiple exclusions are specified for donor "; msg << donor; msg << " and acceptor "; msg << acceptor; throw OpenMMException(msg.str()); } exclusions[donor].insert(acceptor); } if (owner.getNonbondedMethod() == CustomHbondForce::CutoffPeriodic) { Vec3 boxVectors[3]; system.getDefaultPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]); double cutoff = owner.getCutoffDistance(); if (cutoff > 0.5*boxVectors[0][0] || cutoff > 0.5*boxVectors[1][1] || cutoff > 0.5*boxVectors[2][2]) throw OpenMMException("CustomHbondForce: The cutoff distance cannot be greater than half the periodic box size."); } kernel.getAs<CalcCustomHbondForceKernel>().initialize(context.getSystem(), owner); }
void ReferencePlatform::contextCreated(ContextImpl& context, const map<string, string>& properties) const { context.setPlatformData(new PlatformData(context.getSystem())); }
void ReferenceCustomDynamics::update(ContextImpl& context, int numberOfAtoms, vector<RealVec>& atomCoordinates, vector<RealVec>& velocities, vector<RealVec>& forces, vector<RealOpenMM>& masses, map<string, RealOpenMM>& globals, vector<vector<RealVec> >& perDof, bool& forcesAreValid, RealOpenMM tolerance) { if (invalidatesForces.size() == 0) initialize(context, masses, globals); int numSteps = stepType.size(); globals.insert(context.getParameters().begin(), context.getParameters().end()); for (map<string, RealOpenMM>::const_iterator iter = globals.begin(); iter != globals.end(); ++iter) expressionSet.setVariable(expressionSet.getVariableIndex(iter->first), iter->second); oldPos = atomCoordinates; // Loop over steps and execute them. for (int step = 0; step < numSteps; ) { if ((needsForces[step] || needsEnergy[step]) && (!forcesAreValid || context.getLastForceGroups() != forceGroupFlags[step])) { // Recompute forces and/or energy. bool computeForce = needsForces[step] || computeBothForceAndEnergy[step]; bool computeEnergy = needsEnergy[step] || computeBothForceAndEnergy[step]; recordChangedParameters(context, globals); RealOpenMM e = context.calcForcesAndEnergy(computeForce, computeEnergy, forceGroupFlags[step]); if (computeEnergy) { energy = e; context.getEnergyParameterDerivatives(energyParamDerivs); } forcesAreValid = true; } // Execute the step. int nextStep = step+1; switch (stepType[step]) { case CustomIntegrator::ComputeGlobal: { uniform = SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber(); gaussian = SimTKOpenMMUtilities::getNormallyDistributedRandomNumber(); RealOpenMM result = stepExpressions[step][0].evaluate(); globals[stepVariable[step]] = result; expressionSet.setVariable(stepVariableIndex[step], result); break; } case CustomIntegrator::ComputePerDof: { vector<RealVec>* results = NULL; if (stepVariableIndex[step] == xIndex) results = &atomCoordinates; else if (stepVariableIndex[step] == vIndex) results = &velocities; else { for (int j = 0; j < integrator.getNumPerDofVariables(); j++) if (stepVariableIndex[step] == perDofVariableIndex[j]) results = &perDof[j]; } if (results == NULL) throw OpenMMException("Illegal per-DOF output variable: "+stepVariable[step]); computePerDof(numberOfAtoms, *results, atomCoordinates, velocities, forces, masses, perDof, stepExpressions[step][0]); break; } case CustomIntegrator::ComputeSum: { computePerDof(numberOfAtoms, sumBuffer, atomCoordinates, velocities, forces, masses, perDof, stepExpressions[step][0]); RealOpenMM sum = 0.0; for (int j = 0; j < numberOfAtoms; j++) if (masses[j] != 0.0) sum += sumBuffer[j][0]+sumBuffer[j][1]+sumBuffer[j][2]; globals[stepVariable[step]] = sum; expressionSet.setVariable(stepVariableIndex[step], sum); break; } case CustomIntegrator::ConstrainPositions: { getReferenceConstraintAlgorithm()->apply(oldPos, atomCoordinates, inverseMasses, tolerance); oldPos = atomCoordinates; break; } case CustomIntegrator::ConstrainVelocities: { getReferenceConstraintAlgorithm()->applyToVelocities(oldPos, velocities, inverseMasses, tolerance); break; } case CustomIntegrator::UpdateContextState: { recordChangedParameters(context, globals); context.updateContextState(); globals.insert(context.getParameters().begin(), context.getParameters().end()); for (map<string, RealOpenMM>::const_iterator iter = globals.begin(); iter != globals.end(); ++iter) expressionSet.setVariable(expressionSet.getVariableIndex(iter->first), iter->second); break; } case CustomIntegrator::IfBlockStart: { if (!evaluateCondition(step)) nextStep = blockEnd[step]+1; break; } case CustomIntegrator::WhileBlockStart: { if (!evaluateCondition(step)) nextStep = blockEnd[step]+1; break; } case CustomIntegrator::BlockEnd: { if (blockEnd[step] != -1) nextStep = blockEnd[step]; // Return to the start of a while block. break; } } if (invalidatesForces[step]) forcesAreValid = false; step = nextStep; } ReferenceVirtualSites::computePositions(context.getSystem(), atomCoordinates); incrementTimeStep(); recordChangedParameters(context, globals); }
void AmoebaMultipoleForceImpl::initialize(ContextImpl& context) { const System& system = context.getSystem(); if (owner.getNumMultipoles() != system.getNumParticles()) throw OpenMMException("AmoebaMultipoleForce must have exactly as many particles as the System it belongs to."); // check cutoff < 0.5*boxSize if (owner.getNonbondedMethod() == AmoebaMultipoleForce::PME) { Vec3 boxVectors[3]; system.getDefaultPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]); double cutoff = owner.getCutoffDistance(); if (cutoff > 0.5*boxVectors[0][0] || cutoff > 0.5*boxVectors[1][1] || cutoff > 0.5*boxVectors[2][2]) throw OpenMMException("AmoebaMultipoleForce: The cutoff distance cannot be greater than half the periodic box size."); } double quadrupoleValidationTolerance = 1.0e-05; for( int ii = 0; ii < system.getNumParticles(); ii++ ){ int axisType, multipoleAtomZ, multipoleAtomX, multipoleAtomY; double charge, thole, dampingFactor, polarity ; std::vector<double> molecularDipole; std::vector<double> molecularQuadrupole; owner.getMultipoleParameters( ii, charge, molecularDipole, molecularQuadrupole, axisType, multipoleAtomZ, multipoleAtomX, multipoleAtomY, thole, dampingFactor, polarity ); // check quadrupole is traceless and symmetric double trace = fabs( molecularQuadrupole[0] + molecularQuadrupole[4] + molecularQuadrupole[8] ); if( trace > quadrupoleValidationTolerance ){ std::stringstream buffer; buffer << "AmoebaMultipoleForce: qudarupole for particle=" << ii; buffer << " has nonzero trace: " << trace << "; AMOEBA plugin assumes traceless quadrupole."; throw OpenMMException(buffer.str()); } if( fabs( molecularQuadrupole[1] - molecularQuadrupole[3] ) > quadrupoleValidationTolerance ){ std::stringstream buffer; buffer << "AmoebaMultipoleForce: XY and YX components of quadrupole for particle=" << ii; buffer << " are not equal: [" << molecularQuadrupole[1] << " " << molecularQuadrupole[3] << "];"; buffer << " AMOEBA plugin assumes symmetric quadrupole tensor."; throw OpenMMException(buffer.str()); } if( fabs( molecularQuadrupole[2] - molecularQuadrupole[6] ) > quadrupoleValidationTolerance ){ std::stringstream buffer; buffer << "AmoebaMultipoleForce: XZ and ZX components of quadrupole for particle=" << ii; buffer << " are not equal: [" << molecularQuadrupole[2] << " " << molecularQuadrupole[6] << "];"; buffer << " AMOEBA plugin assumes symmetric quadrupole tensor."; throw OpenMMException(buffer.str()); } if( fabs( molecularQuadrupole[5] - molecularQuadrupole[7] ) > quadrupoleValidationTolerance ){ std::stringstream buffer; buffer << "AmoebaMultipoleForce: YZ and ZY components of quadrupole for particle=" << ii; buffer << " are not equal: [" << molecularQuadrupole[5] << " " << molecularQuadrupole[7] << "];"; buffer << " AMOEBA plugin assumes symmetric quadrupole tensor."; throw OpenMMException(buffer.str()); } // only 'Z-then-X', 'Bisector', Z-Bisect, ThreeFold currently handled if( axisType != AmoebaMultipoleForce::ZThenX && axisType != AmoebaMultipoleForce::Bisector && axisType != AmoebaMultipoleForce::ZBisect && axisType != AmoebaMultipoleForce::ThreeFold && axisType != AmoebaMultipoleForce::ZOnly && axisType != AmoebaMultipoleForce::NoAxisType ) { std::stringstream buffer; buffer << "AmoebaMultipoleForce: axis type=" << axisType; buffer << " not currently handled - only axisTypes[ "; buffer << AmoebaMultipoleForce::ZThenX << ", " << AmoebaMultipoleForce::Bisector << ", "; buffer << AmoebaMultipoleForce::ZBisect << ", " << AmoebaMultipoleForce::ThreeFold << ", "; buffer << AmoebaMultipoleForce::NoAxisType; buffer << "] (ZThenX, Bisector, Z-Bisect, ThreeFold, NoAxisType) currently handled ."; throw OpenMMException(buffer.str()); } } kernel = context.getPlatform().createKernel(CalcAmoebaMultipoleForceKernel::Name(), context); kernel.getAs<CalcAmoebaMultipoleForceKernel>().initialize(context.getSystem(), owner); }
void RBTorsionForceImpl::initialize(ContextImpl& context) { kernel = context.getPlatform().createKernel(CalcRBTorsionForceKernel::Name(), context); kernel.getAs<CalcRBTorsionForceKernel>().initialize(context.getSystem(), owner); }
void ReferenceIntegrateDrudeLangevinStepKernel::execute(ContextImpl& context, const DrudeLangevinIntegrator& integrator) { vector<RealVec>& pos = extractPositions(context); vector<RealVec>& vel = extractVelocities(context); vector<RealVec>& force = extractForces(context); // Update velocities of ordinary particles. const RealOpenMM vscale = exp(-integrator.getStepSize()*integrator.getFriction()); const RealOpenMM fscale = (1-vscale)/integrator.getFriction(); const RealOpenMM kT = BOLTZ*integrator.getTemperature(); const RealOpenMM noisescale = sqrt(2*kT*integrator.getFriction())*sqrt(0.5*(1-vscale*vscale)/integrator.getFriction()); for (int i = 0; i < (int) normalParticles.size(); i++) { int index = normalParticles[i]; RealOpenMM invMass = particleInvMass[index]; if (invMass != 0.0) { RealOpenMM sqrtInvMass = sqrt(invMass); for (int j = 0; j < 3; j++) vel[index][j] = vscale*vel[index][j] + fscale*invMass*force[index][j] + noisescale*sqrtInvMass*SimTKOpenMMUtilities::getNormallyDistributedRandomNumber(); } } // Update velocities of Drude particle pairs. const RealOpenMM vscaleDrude = exp(-integrator.getStepSize()*integrator.getDrudeFriction()); const RealOpenMM fscaleDrude = (1-vscaleDrude)/integrator.getDrudeFriction(); const RealOpenMM kTDrude = BOLTZ*integrator.getDrudeTemperature(); const RealOpenMM noisescaleDrude = sqrt(2*kTDrude*integrator.getDrudeFriction())*sqrt(0.5*(1-vscaleDrude*vscaleDrude)/integrator.getDrudeFriction()); for (int i = 0; i < (int) pairParticles.size(); i++) { int p1 = pairParticles[i].first; int p2 = pairParticles[i].second; RealOpenMM mass1fract = pairInvTotalMass[i]/particleInvMass[p1]; RealOpenMM mass2fract = pairInvTotalMass[i]/particleInvMass[p2]; RealOpenMM sqrtInvTotalMass = sqrt(pairInvTotalMass[i]); RealOpenMM sqrtInvReducedMass = sqrt(pairInvReducedMass[i]); RealVec cmVel = vel[p1]*mass1fract+vel[p2]*mass2fract; RealVec relVel = vel[p2]-vel[p1]; RealVec cmForce = force[p1]+force[p2]; RealVec relForce = force[p2]*mass1fract - force[p1]*mass2fract; for (int j = 0; j < 3; j++) { cmVel[j] = vscale*cmVel[j] + fscale*pairInvTotalMass[i]*cmForce[j] + noisescale*sqrtInvTotalMass*SimTKOpenMMUtilities::getNormallyDistributedRandomNumber(); relVel[j] = vscaleDrude*relVel[j] + fscaleDrude*pairInvReducedMass[i]*relForce[j] + noisescaleDrude*sqrtInvReducedMass*SimTKOpenMMUtilities::getNormallyDistributedRandomNumber(); } vel[p1] = cmVel-relVel*mass2fract; vel[p2] = cmVel+relVel*mass1fract; } // Update the particle positions. int numParticles = particleInvMass.size(); vector<RealVec> xPrime(numParticles); RealOpenMM dt = integrator.getStepSize(); for (int i = 0; i < numParticles; i++) if (particleInvMass[i] != 0.0) xPrime[i] = pos[i]+vel[i]*dt; // Apply constraints. extractConstraints(context).apply(pos, xPrime, particleInvMass, integrator.getConstraintTolerance()); // Record the constrained positions and velocities. RealOpenMM dtInv = 1.0/dt; for (int i = 0; i < numParticles; i++) { if (particleInvMass[i] != 0.0) { vel[i] = (xPrime[i]-pos[i])*dtInv; pos[i] = xPrime[i]; } } // Apply hard wall constraints. const RealOpenMM maxDrudeDistance = integrator.getMaxDrudeDistance(); if (maxDrudeDistance > 0) { const RealOpenMM hardwallscaleDrude = sqrt(kTDrude); for (int i = 0; i < (int) pairParticles.size(); i++) { int p1 = pairParticles[i].first; int p2 = pairParticles[i].second; RealVec delta = pos[p1]-pos[p2]; RealOpenMM r = sqrt(delta.dot(delta)); RealOpenMM rInv = 1/r; if (rInv*maxDrudeDistance < 1.0) { // The constraint has been violated, so make the inter-particle distance "bounce" // off the hard wall. if (rInv*maxDrudeDistance < 0.5) throw OpenMMException("Drude particle moved too far beyond hard wall constraint"); RealVec bondDir = delta*rInv; RealVec vel1 = vel[p1]; RealVec vel2 = vel[p2]; RealOpenMM mass1 = particleMass[p1]; RealOpenMM mass2 = particleMass[p2]; RealOpenMM deltaR = r-maxDrudeDistance; RealOpenMM deltaT = dt; RealOpenMM dotvr1 = vel1.dot(bondDir); RealVec vb1 = bondDir*dotvr1; RealVec vp1 = vel1-vb1; if (mass2 == 0) { // The parent particle is massless, so move only the Drude particle. if (dotvr1 != 0.0) deltaT = deltaR/abs(dotvr1); if (deltaT > dt) deltaT = dt; dotvr1 = -dotvr1*hardwallscaleDrude/(abs(dotvr1)*sqrt(mass1)); RealOpenMM dr = -deltaR + deltaT*dotvr1; pos[p1] += bondDir*dr; vel[p1] = vp1 + bondDir*dotvr1; } else { // Move both particles. RealOpenMM invTotalMass = pairInvTotalMass[i]; RealOpenMM dotvr2 = vel2.dot(bondDir); RealVec vb2 = bondDir*dotvr2; RealVec vp2 = vel2-vb2; RealOpenMM vbCMass = (mass1*dotvr1 + mass2*dotvr2)*invTotalMass; dotvr1 -= vbCMass; dotvr2 -= vbCMass; if (dotvr1 != dotvr2) deltaT = deltaR/abs(dotvr1-dotvr2); if (deltaT > dt) deltaT = dt; RealOpenMM vBond = hardwallscaleDrude/sqrt(mass1); dotvr1 = -dotvr1*vBond*mass2*invTotalMass/abs(dotvr1); dotvr2 = -dotvr2*vBond*mass1*invTotalMass/abs(dotvr2); RealOpenMM dr1 = -deltaR*mass2*invTotalMass + deltaT*dotvr1; RealOpenMM dr2 = deltaR*mass1*invTotalMass + deltaT*dotvr2; dotvr1 += vbCMass; dotvr2 += vbCMass; pos[p1] += bondDir*dr1; pos[p2] += bondDir*dr2; vel[p1] = vp1 + bondDir*dotvr1; vel[p2] = vp2 + bondDir*dotvr2; } } } } ReferenceVirtualSites::computePositions(context.getSystem(), pos); data.time += integrator.getStepSize(); data.stepCount++; }
void ReferenceCustomDynamics::update(ContextImpl& context, int numberOfAtoms, vector<RealVec>& atomCoordinates, vector<RealVec>& velocities, vector<RealVec>& forces, vector<RealOpenMM>& masses, map<string, RealOpenMM>& globals, vector<vector<RealVec> >& perDof, bool& forcesAreValid, RealOpenMM tolerance) { int numSteps = stepType.size(); globals.insert(context.getParameters().begin(), context.getParameters().end()); oldPos = atomCoordinates; if (invalidatesForces.size() == 0) { // Some initialization can't be done in the constructor, since we need a ContextImpl from which to get the list of // Context parameters. Instead, we do it the first time this method is called. vector<int> forceGroup; vector<vector<Lepton::ParsedExpression> > expressions; CustomIntegratorUtilities::analyzeComputations(context, integrator, expressions, comparisons, blockEnd, invalidatesForces, needsForces, needsEnergy, computeBothForceAndEnergy, forceGroup); stepExpressions.resize(expressions.size()); for (int i = 0; i < numSteps; i++) { for (int j = 0; j < (int) expressions[i].size(); j++) stepExpressions[i].push_back(expressions[i][j].createProgram()); if (stepType[i] == CustomIntegrator::BeginWhileBlock) blockEnd[blockEnd[i]] = i; // Record where to branch back to. } // Record the variable names and flags for the force and energy in each step. forceGroupFlags.resize(numSteps, -1); forceName.resize(numSteps, "f"); energyName.resize(numSteps, "energy"); vector<string> forceGroupName; vector<string> energyGroupName; for (int i = 0; i < 32; i++) { stringstream fname; fname << "f" << i; forceGroupName.push_back(fname.str()); stringstream ename; ename << "energy" << i; energyGroupName.push_back(ename.str()); } for (int i = 0; i < numSteps; i++) { if (needsForces[i] && forceGroup[i] > -1) forceName[i] = forceGroupName[forceGroup[i]]; if (needsEnergy[i] && forceGroup[i] > -1) energyName[i] = energyGroupName[forceGroup[i]]; if (forceGroup[i] > -1) forceGroupFlags[i] = 1<<forceGroup[i]; } // Build the list of inverse masses. inverseMasses.resize(numberOfAtoms); for (int i = 0; i < numberOfAtoms; i++) { if (masses[i] == 0.0) inverseMasses[i] = 0.0; else inverseMasses[i] = 1.0/masses[i]; } } // Loop over steps and execute them. for (int step = 0; step < numSteps; ) { if ((needsForces[step] || needsEnergy[step]) && (!forcesAreValid || context.getLastForceGroups() != forceGroupFlags[step])) { // Recompute forces and/or energy. bool computeForce = needsForces[step] || computeBothForceAndEnergy[step]; bool computeEnergy = needsEnergy[step] || computeBothForceAndEnergy[step]; recordChangedParameters(context, globals); RealOpenMM e = context.calcForcesAndEnergy(computeForce, computeEnergy, forceGroupFlags[step]); if (computeEnergy) energy = e; forcesAreValid = true; } globals[energyName[step]] = energy; // Execute the step. int nextStep = step+1; switch (stepType[step]) { case CustomIntegrator::ComputeGlobal: { map<string, RealOpenMM> variables = globals; variables["uniform"] = SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber(); variables["gaussian"] = SimTKOpenMMUtilities::getNormallyDistributedRandomNumber(); globals[stepVariable[step]] = stepExpressions[step][0].evaluate(variables); break; } case CustomIntegrator::ComputePerDof: { vector<RealVec>* results = NULL; if (stepVariable[step] == "x") results = &atomCoordinates; else if (stepVariable[step] == "v") results = &velocities; else { for (int j = 0; j < integrator.getNumPerDofVariables(); j++) if (stepVariable[step] == integrator.getPerDofVariableName(j)) results = &perDof[j]; } if (results == NULL) throw OpenMMException("Illegal per-DOF output variable: "+stepVariable[step]); computePerDof(numberOfAtoms, *results, atomCoordinates, velocities, forces, masses, globals, perDof, stepExpressions[step][0], forceName[step]); break; } case CustomIntegrator::ComputeSum: { computePerDof(numberOfAtoms, sumBuffer, atomCoordinates, velocities, forces, masses, globals, perDof, stepExpressions[step][0], forceName[step]); RealOpenMM sum = 0.0; for (int j = 0; j < numberOfAtoms; j++) if (masses[j] != 0.0) sum += sumBuffer[j][0]+sumBuffer[j][1]+sumBuffer[j][2]; globals[stepVariable[step]] = sum; break; } case CustomIntegrator::ConstrainPositions: { getReferenceConstraintAlgorithm()->apply(oldPos, atomCoordinates, inverseMasses, tolerance); oldPos = atomCoordinates; break; } case CustomIntegrator::ConstrainVelocities: { getReferenceConstraintAlgorithm()->applyToVelocities(oldPos, velocities, inverseMasses, tolerance); break; } case CustomIntegrator::UpdateContextState: { recordChangedParameters(context, globals); context.updateContextState(); globals.insert(context.getParameters().begin(), context.getParameters().end()); break; } case CustomIntegrator::BeginIfBlock: { if (!evaluateCondition(step, globals)) nextStep = blockEnd[step]+1; break; } case CustomIntegrator::BeginWhileBlock: { if (!evaluateCondition(step, globals)) nextStep = blockEnd[step]+1; break; } case CustomIntegrator::EndBlock: { if (blockEnd[step] != -1) nextStep = blockEnd[step]; // Return to the start of a while block. break; } } if (invalidatesForces[step]) forcesAreValid = false; step = nextStep; } ReferenceVirtualSites::computePositions(context.getSystem(), atomCoordinates); incrementTimeStep(); recordChangedParameters(context, globals); }
void ReferenceIntegrateDrudeLangevinStepKernel::execute(ContextImpl& context, const DrudeLangevinIntegrator& integrator) { vector<RealVec>& pos = extractPositions(context); vector<RealVec>& vel = extractVelocities(context); vector<RealVec>& force = extractForces(context); // Update velocities of ordinary particles. const RealOpenMM vscale = exp(-integrator.getStepSize()*integrator.getFriction()); const RealOpenMM fscale = (1-vscale)/integrator.getFriction(); const RealOpenMM kT = BOLTZ*integrator.getTemperature(); const RealOpenMM noisescale = sqrt(2*kT*integrator.getFriction())*sqrt(0.5*(1-vscale*vscale)/integrator.getFriction()); for (int i = 0; i < (int) normalParticles.size(); i++) { int index = normalParticles[i]; RealOpenMM invMass = particleInvMass[index]; if (invMass != 0.0) { RealOpenMM sqrtInvMass = sqrt(invMass); for (int j = 0; j < 3; j++) vel[index][j] = vscale*vel[index][j] + fscale*invMass*force[index][j] + noisescale*sqrtInvMass*SimTKOpenMMUtilities::getNormallyDistributedRandomNumber(); } } // Update velocities of Drude particle pairs. const RealOpenMM vscaleDrude = exp(-integrator.getStepSize()*integrator.getDrudeFriction()); const RealOpenMM fscaleDrude = (1-vscaleDrude)/integrator.getDrudeFriction(); const RealOpenMM kTDrude = BOLTZ*integrator.getDrudeTemperature(); const RealOpenMM noisescaleDrude = sqrt(2*kTDrude*integrator.getDrudeFriction())*sqrt(0.5*(1-vscaleDrude*vscaleDrude)/integrator.getDrudeFriction()); for (int i = 0; i < (int) pairParticles.size(); i++) { int p1 = pairParticles[i].first; int p2 = pairParticles[i].second; RealOpenMM mass1fract = pairInvTotalMass[i]/particleInvMass[p1]; RealOpenMM mass2fract = pairInvTotalMass[i]/particleInvMass[p2]; RealOpenMM sqrtInvTotalMass = sqrt(pairInvTotalMass[i]); RealOpenMM sqrtInvReducedMass = sqrt(pairInvReducedMass[i]); RealVec cmVel = vel[p1]*mass1fract+vel[p2]*mass2fract; RealVec relVel = vel[p2]-vel[p1]; RealVec cmForce = force[p1]+force[p2]; RealVec relForce = force[p2]*mass1fract - force[p1]*mass2fract; for (int j = 0; j < 3; j++) { cmVel[j] = vscale*cmVel[j] + fscale*pairInvTotalMass[i]*cmForce[j] + noisescale*sqrtInvTotalMass*SimTKOpenMMUtilities::getNormallyDistributedRandomNumber(); relVel[j] = vscaleDrude*relVel[j] + fscaleDrude*pairInvReducedMass[i]*relForce[j] + noisescaleDrude*sqrtInvReducedMass*SimTKOpenMMUtilities::getNormallyDistributedRandomNumber(); } vel[p1] = cmVel-relVel*mass2fract; vel[p2] = cmVel+relVel*mass1fract; } // Update the particle positions. int numParticles = particleInvMass.size(); vector<RealVec> xPrime(numParticles); RealOpenMM dt = integrator.getStepSize(); for (int i = 0; i < numParticles; i++) if (particleInvMass[i] != 0.0) xPrime[i] = pos[i]+vel[i]*dt; // Apply constraints. if (constraints != NULL) constraints->apply(numParticles, pos, xPrime, particleInvMass); // Record the constrained positions and velocities. RealOpenMM dtInv = 1.0/dt; for (int i = 0; i < numParticles; i++) { if (particleInvMass[i] != 0.0) { vel[i] = (xPrime[i]-pos[i])*dtInv; pos[i] = xPrime[i]; } } ReferenceVirtualSites::computePositions(context.getSystem(), pos); data.time += integrator.getStepSize(); data.stepCount++; }