void* CustomNonbondedForceProxy::deserialize(const SerializationNode& node) const { if (node.getIntProperty("version") != 1) throw OpenMMException("Unsupported version number"); CustomNonbondedForce* force = NULL; try { CustomNonbondedForce* force = new CustomNonbondedForce(node.getStringProperty("energy")); force->setNonbondedMethod((CustomNonbondedForce::NonbondedMethod) node.getIntProperty("method")); force->setCutoffDistance(node.getDoubleProperty("cutoff")); const SerializationNode& perParticleParams = node.getChildNode("PerParticleParameters"); for (int i = 0; i < (int) perParticleParams.getChildren().size(); i++) { const SerializationNode& parameter = perParticleParams.getChildren()[i]; force->addPerParticleParameter(parameter.getStringProperty("name")); } const SerializationNode& globalParams = node.getChildNode("GlobalParameters"); for (int i = 0; i < (int) globalParams.getChildren().size(); i++) { const SerializationNode& parameter = globalParams.getChildren()[i]; force->addGlobalParameter(parameter.getStringProperty("name"), parameter.getDoubleProperty("default")); } const SerializationNode& particles = node.getChildNode("Particles"); vector<double> params(force->getNumPerParticleParameters()); for (int i = 0; i < (int) particles.getChildren().size(); i++) { const SerializationNode& particle = particles.getChildren()[i]; for (int j = 0; j < (int) params.size(); j++) { stringstream key; key << "param"; key << j+1; params[j] = particle.getDoubleProperty(key.str()); } force->addParticle(params); } const SerializationNode& exclusions = node.getChildNode("Exclusions"); for (int i = 0; i < (int) exclusions.getChildren().size(); i++) { const SerializationNode& exclusion = exclusions.getChildren()[i]; force->addExclusion(exclusion.getIntProperty("p1"), exclusion.getIntProperty("p2")); } const SerializationNode& functions = node.getChildNode("Functions"); for (int i = 0; i < (int) functions.getChildren().size(); i++) { const SerializationNode& function = functions.getChildren()[i]; const SerializationNode& valuesNode = function.getChildNode("Values"); vector<double> values; for (int j = 0; j < (int) valuesNode.getChildren().size(); j++) values.push_back(valuesNode.getChildren()[j].getDoubleProperty("v")); force->addFunction(function.getStringProperty("name"), values, function.getDoubleProperty("min"), function.getDoubleProperty("max")); } return force; } catch (...) { if (force != NULL) delete force; throw; } }
void testTabulatedFunction() { ReferencePlatform platform; System system; system.addParticle(1.0); system.addParticle(1.0); VerletIntegrator integrator(0.01); CustomNonbondedForce* forceField = new CustomNonbondedForce("fn(r)+1"); forceField->addParticle(vector<double>()); forceField->addParticle(vector<double>()); vector<double> table; for (int i = 0; i < 21; i++) table.push_back(std::sin(0.25*i)); forceField->addFunction("fn", table, 1.0, 6.0); system.addForce(forceField); Context context(system, integrator, platform); vector<Vec3> positions(2); positions[0] = Vec3(0, 0, 0); double tol = 0.01; for (int i = 1; i < 30; i++) { double x = (7.0/30.0)*i; positions[1] = Vec3(x, 0, 0); context.setPositions(positions); State state = context.getState(State::Forces | State::Energy); const vector<Vec3>& forces = state.getForces(); double force = (x < 1.0 || x > 6.0 ? 0.0 : -std::cos(x-1.0)); double energy = (x < 1.0 || x > 6.0 ? 0.0 : std::sin(x-1.0))+1.0; ASSERT_EQUAL_VEC(Vec3(-force, 0, 0), forces[0], 0.1); ASSERT_EQUAL_VEC(Vec3(force, 0, 0), forces[1], 0.1); ASSERT_EQUAL_TOL(energy, state.getPotentialEnergy(), 0.02); } for (int i = 1; i < 20; i++) { double x = 0.25*i+1.0; positions[1] = Vec3(x, 0, 0); context.setPositions(positions); State state = context.getState(State::Energy); double energy = (x < 1.0 || x > 6.0 ? 0.0 : std::sin(x-1.0))+1.0; ASSERT_EQUAL_TOL(energy, state.getPotentialEnergy(), 1e-4); } }