void ReferenceCustomDynamics::computePerDof(int numberOfAtoms, vector<RealVec>& results, const vector<RealVec>& atomCoordinates, const vector<RealVec>& velocities, const vector<RealVec>& forces, const vector<RealOpenMM>& masses, const map<string, RealOpenMM>& globals, const vector<vector<RealVec> >& perDof, const Lepton::ExpressionProgram& expression, const std::string& forceName) { // Loop over all degrees of freedom. map<string, RealOpenMM> variables = globals; for (int i = 0; i < numberOfAtoms; i++) { if (masses[i] != 0.0) { variables["m"] = masses[i]; for (int j = 0; j < 3; j++) { // Compute the expression. variables["x"] = atomCoordinates[i][j]; variables["v"] = velocities[i][j]; variables[forceName] = forces[i][j]; variables["uniform"] = SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber(); variables["gaussian"] = SimTKOpenMMUtilities::getNormallyDistributedRandomNumber(); for (int k = 0; k < (int) perDof.size(); k++) variables[integrator.getPerDofVariableName(k)] = perDof[k][i][j]; results[i][j] = expression.evaluate(variables); } } } }
//------------------------------------------------------------------------------------------------- double BenchLepton::DoBenchmark(const std::string& sExpr, long iCount) { std::map<std::string,double> var_list; var_list["a" ] = 1.1; var_list["b" ] = 2.2; var_list["c" ] = 3.3; var_list["x" ] = 2.123456; var_list["y" ] = 3.123456; var_list["z" ] = 4.123456; var_list["w" ] = 5.123456; var_list["e" ] = 2.718281828459045235360; var_list["pi"] = 3.141592653589793238462; double& a = var_list["a"]; double& b = var_list["b"]; double& c = var_list["c"]; double& x = var_list["x"]; double& y = var_list["y"]; double& z = var_list["z"]; double& w = var_list["w"]; try { Lepton::ExpressionProgram program = Lepton::Parser::parse(sExpr).optimize().createProgram(); program.evaluate(var_list); } catch (std::exception& e) { StopTimerAndReport(e.what()); return std::numeric_limits<double>::quiet_NaN(); } Lepton::ExpressionProgram program = Lepton::Parser::parse(sExpr).optimize().createProgram(); // Perform basic tests for the variables used // in the expressions { bool test_result = true; auto tests_list = test_expressions(); try { for (auto test : tests_list) { Lepton::ExpressionProgram test_program = Lepton::Parser::parse(test.first).optimize().createProgram(); if (!is_equal(test.second,test_program.evaluate(var_list))) { StopTimerAndReport("Failed variable test"); return m_fTime1; } } } catch (std::exception& e) { StopTimerAndReport(e.what()); return std::numeric_limits<double>::quiet_NaN(); } } //Prime the I and D caches for the expression { double d0 = 0.0; double d1 = 0.0; for (std::size_t i = 0; i < priming_rounds; ++i) { if (i & 1) d0 += program.evaluate(var_list); else d1 += program.evaluate(var_list); } if ( (d0 == std::numeric_limits<double>::infinity()) && (d1 == std::numeric_limits<double>::infinity()) ) { printf("\n"); } } // Perform benchmark then return results double fRes = 0; double fSum = 0; fRes = program.evaluate(var_list); StartTimer(); for (int j = 0; j < iCount; ++j) { fSum += program.evaluate(var_list); std::swap(a,b); std::swap(x,y); } StopTimer(fRes, fSum, iCount); return m_fTime1; }
double CustomNonbondedForceImpl::integrateInteraction(const Lepton::ExpressionProgram& expression, const vector<double>& params1, const vector<double>& params2, const CustomNonbondedForce& force, const Context& context) { map<std::string, double> variables; for (int i = 0; i < force.getNumPerParticleParameters(); i++) { stringstream name1, name2; name1 << force.getPerParticleParameterName(i) << 1; name2 << force.getPerParticleParameterName(i) << 2; variables[name1.str()] = params1[i]; variables[name2.str()] = params2[i]; } for (int i = 0; i < force.getNumGlobalParameters(); i++) { const string& name = force.getGlobalParameterName(i); variables[name] = context.getParameter(name); } // To integrate from r_cutoff to infinity, make the change of variables x=r_cutoff/r and integrate from 0 to 1. // This introduces another r^2 into the integral, which along with the r^2 in the formula for the correction // means we multiply the function by r^4. Use the midpoint method. double cutoff = force.getCutoffDistance(); double sum = 0; int numPoints = 1; for (int iteration = 0; ; iteration++) { double oldSum = sum; double newSum = 0; for (int i = 0; i < numPoints; i++) { if (i%3 == 1) continue; double x = (i+0.5)/numPoints; double r = cutoff/x; variables["r"] = r; double r2 = r*r; newSum += expression.evaluate(variables)*r2*r2; } sum = newSum/numPoints + oldSum/3; if (iteration > 2 && (fabs((sum-oldSum)/sum) < 1e-5 || sum == 0)) break; if (iteration == 8) throw OpenMMException("CustomNonbondedForce: Long range correction did not converge. Does the energy go to 0 faster than 1/r^2?"); numPoints *= 3; } // If a switching function is used, integrate over the switching interval. double sum2 = 0; if (force.getUseSwitchingFunction()) { double rswitch = force.getSwitchingDistance(); sum2 = 0; numPoints = 1; for (int iteration = 0; ; iteration++) { double oldSum = sum2; double newSum = 0; for (int i = 0; i < numPoints; i++) { if (i%3 == 1) continue; double x = (i+0.5)/numPoints; double r = rswitch+x*(cutoff-rswitch); double switchValue = x*x*x*(10+x*(-15+x*6)); variables["r"] = r; newSum += switchValue*expression.evaluate(variables)*r*r; } sum2 = newSum/numPoints + oldSum/3; if (iteration > 2 && (fabs((sum2-oldSum)/sum2) < 1e-5 || sum2 == 0)) break; if (iteration == 8) throw OpenMMException("CustomNonbondedForce: Long range correction did not converge. Is the energy finite everywhere in the switching interval?"); numPoints *= 3; } sum2 *= cutoff-rswitch; } return sum/cutoff+sum2; }