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]); } }
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 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 MonteCarloBarostatImpl::updateContextState(ContextImpl& context) { if (++step < owner.getFrequency() || owner.getFrequency() == 0) return; step = 0; // Compute the current potential energy. double initialEnergy = context.getOwner().getState(State::Energy).getPotentialEnergy(); // Modify the periodic box size. Vec3 box[3]; context.getPeriodicBoxVectors(box[0], box[1], box[2]); double volume = box[0][0]*box[1][1]*box[2][2]; double deltaVolume = volumeScale*2*(genrand_real2(random)-0.5); double newVolume = volume+deltaVolume; double lengthScale = std::pow(newVolume/volume, 1.0/3.0); kernel.getAs<ApplyMonteCarloBarostatKernel>().scaleCoordinates(context, lengthScale, lengthScale, lengthScale); context.getOwner().setPeriodicBoxVectors(box[0]*lengthScale, box[1]*lengthScale, box[2]*lengthScale); // Compute the energy of the modified system. double finalEnergy = context.getOwner().getState(State::Energy).getPotentialEnergy(); double pressure = context.getParameter(MonteCarloBarostat::Pressure())*(AVOGADRO*1e-25); double kT = BOLTZ*context.getParameter(MonteCarloBarostat::Temperature()); double w = finalEnergy-initialEnergy + pressure*deltaVolume - context.getMolecules().size()*kT*std::log(newVolume/volume); if (w > 0 && genrand_real2(random) > std::exp(-w/kT)) { // Reject the step. kernel.getAs<ApplyMonteCarloBarostatKernel>().restoreCoordinates(context); context.getOwner().setPeriodicBoxVectors(box[0], box[1], box[2]); volume = newVolume; } else numAccepted++; numAttempted++; if (numAttempted >= 10) { if (numAccepted < 0.25*numAttempted) { volumeScale /= 1.1; numAttempted = 0; numAccepted = 0; } else if (numAccepted > 0.75*numAttempted) { volumeScale = std::min(volumeScale*1.1, volume*0.3); numAttempted = 0; numAccepted = 0; } } }
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 CpuCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force) { if (numParticles != force.getNumParticles()) throw OpenMMException("updateParametersInContext: The number of particles has changed"); // Record the values. int numParameters = force.getNumPerParticleParameters(); vector<double> params; for (int i = 0; i < numParticles; ++i) { vector<double> parameters; force.getParticleParameters(i, parameters); for (int j = 0; j < numParameters; j++) particleParamArray[i][j] = parameters[j]; } // If necessary, recompute the long range correction. if (forceCopy != NULL) { longRangeCoefficient = CustomNonbondedForceImpl::calcLongRangeCorrection(force, context.getOwner()); hasInitializedLongRangeCorrection = true; *forceCopy = force; } }
double CpuCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { vector<RealVec>& posData = extractPositions(context); vector<RealVec>& forceData = extractForces(context); RealVec& box = extractBoxSize(context); float floatBoxSize[3] = {(float) box[0], (float) box[1], (float) box[2]}; double energy = 0; bool periodic = (nonbondedMethod == CutoffPeriodic); if (nonbondedMethod != NoCutoff) { neighborList->computeNeighborList(numParticles, data.posq, exclusions, floatBoxSize, data.isPeriodic, nonbondedCutoff, data.threads); nonbonded->setUseCutoff(nonbondedCutoff, *neighborList); } if (periodic) { double minAllowedSize = 2*nonbondedCutoff; if (box[0] < minAllowedSize || box[1] < minAllowedSize || box[2] < minAllowedSize) throw OpenMMException("The periodic box size has decreased to less than twice the nonbonded cutoff."); nonbonded->setPeriodic(box); } bool globalParamsChanged = false; for (int i = 0; i < (int) globalParameterNames.size(); i++) { double value = context.getParameter(globalParameterNames[i]); if (globalParamValues[globalParameterNames[i]] != value) globalParamsChanged = true; globalParamValues[globalParameterNames[i]] = value; } if (useSwitchingFunction) nonbonded->setUseSwitchingFunction(switchingDistance); nonbonded->calculatePairIxn(numParticles, &data.posq[0], posData, particleParamArray, 0, globalParamValues, data.threadForce, includeForces, includeEnergy, energy); // Add in the long range correction. if (!hasInitializedLongRangeCorrection || (globalParamsChanged && forceCopy != NULL)) { longRangeCoefficient = CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner()); hasInitializedLongRangeCorrection = true; } energy += longRangeCoefficient/(box[0]*box[1]*box[2]); return energy; }
void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context) { if (++step < owner.getFrequency() || owner.getFrequency() == 0) return; if (!owner.getScaleX() && !owner.getScaleY() && !owner.getScaleZ()) return; step = 0; // Compute the current potential energy. double initialEnergy = context.getOwner().getState(State::Energy).getPotentialEnergy(); double pressure; // Choose which axis to modify at random. int axis; while (true) { double rnd = genrand_real2(random)*3.0; if (rnd < 1.0) { if (owner.getScaleX()) { axis = 0; pressure = context.getParameter(MonteCarloAnisotropicBarostat::PressureX())*(AVOGADRO*1e-25); break; } } else if (rnd < 2.0) { if (owner.getScaleY()) { axis = 1; pressure = context.getParameter(MonteCarloAnisotropicBarostat::PressureY())*(AVOGADRO*1e-25); break; } } else if (owner.getScaleZ()) { axis = 2; pressure = context.getParameter(MonteCarloAnisotropicBarostat::PressureZ())*(AVOGADRO*1e-25); break; } } // Modify the periodic box size. Vec3 box[3]; context.getPeriodicBoxVectors(box[0], box[1], box[2]); double volume = box[0][0]*box[1][1]*box[2][2]; double deltaVolume = volumeScale[axis]*2*(genrand_real2(random)-0.5); double newVolume = volume+deltaVolume; Vec3 lengthScale(1.0, 1.0, 1.0); lengthScale[axis] = newVolume/volume; kernel.getAs<ApplyMonteCarloBarostatKernel>().scaleCoordinates(context, lengthScale[0], lengthScale[1], lengthScale[2]); context.getOwner().setPeriodicBoxVectors(box[0]*lengthScale[0], box[1]*lengthScale[1], box[2]*lengthScale[2]); // Compute the energy of the modified system. double finalEnergy = context.getOwner().getState(State::Energy).getPotentialEnergy(); double kT = BOLTZ*owner.getTemperature(); double w = finalEnergy-initialEnergy + pressure*deltaVolume - context.getMolecules().size()*kT*std::log(newVolume/volume); if (w > 0 && genrand_real2(random) > std::exp(-w/kT)) { // Reject the step. kernel.getAs<ApplyMonteCarloBarostatKernel>().restoreCoordinates(context); context.getOwner().setPeriodicBoxVectors(box[0], box[1], box[2]); volume = newVolume; } else numAccepted[axis]++; numAttempted[axis]++; if (numAttempted[axis] >= 10) { if (numAccepted[axis] < 0.25*numAttempted[axis]) { volumeScale[axis] /= 1.1; numAttempted[axis] = 0; numAccepted[axis] = 0; } else if (numAccepted[axis] > 0.75*numAttempted[axis]) { volumeScale[axis] = std::min(volumeScale[axis]*1.1, volume*0.3); numAttempted[axis] = 0; numAccepted[axis] = 0; } } }