void testHarmonicBonds() {
    const int numParticles = 10;
    System system;
    HarmonicBondForce* bonds = new HarmonicBondForce();
    system.addForce(bonds);

    // Create a chain of particles connected by harmonic bonds.

    vector<Vec3> positions(numParticles);
    for (int i = 0; i < numParticles; i++) {
        system.addParticle(1.0);
        positions[i] = Vec3(i, 0, 0);
        if (i > 0)
            bonds->addBond(i-1, i, 1+0.1*i, 1);
    }

    // Minimize it and check that all bonds are at their equilibrium distances.

    VerletIntegrator integrator(0.01);
    Context context(system, integrator, platform);
    context.setPositions(positions);
    LocalEnergyMinimizer::minimize(context, 1e-5);
    State state = context.getState(State::Positions);
    for (int i = 1; i < numParticles; i++) {
        Vec3 delta = state.getPositions()[i]-state.getPositions()[i-1];
        ASSERT_EQUAL_TOL(1+0.1*i, sqrt(delta.dot(delta)), 1e-4);
    }
}
void testSingleBond() {
    System system;
    system.addParticle(2.0);
    system.addParticle(2.0);
    VariableVerletIntegrator integrator(1e-6);
    HarmonicBondForce* forceField = new HarmonicBondForce();
    forceField->addBond(0, 1, 1.5, 1);
    system.addForce(forceField);
    Context context(system, integrator, platform);
    vector<Vec3> positions(2);
    positions[0] = Vec3(-1, 0, 0);
    positions[1] = Vec3(1, 0, 0);
    context.setPositions(positions);

    // This is simply a harmonic oscillator, so compare it to the analytical solution.

    const double freq = 1.0;;
    State state = context.getState(State::Energy);
    const double initialEnergy = state.getKineticEnergy()+state.getPotentialEnergy();
    for (int i = 0; i < 1000; ++i) {
        state = context.getState(State::Positions | State::Velocities | State::Energy);
        double time = state.getTime();
        double expectedDist = 1.5+0.5*std::cos(freq*time);
        ASSERT_EQUAL_VEC(Vec3(-0.5*expectedDist, 0, 0), state.getPositions()[0], 0.02);
        ASSERT_EQUAL_VEC(Vec3(0.5*expectedDist, 0, 0), state.getPositions()[1], 0.02);
        double expectedSpeed = -0.5*freq*std::sin(freq*time);
        ASSERT_EQUAL_VEC(Vec3(-0.5*expectedSpeed, 0, 0), state.getVelocities()[0], 0.02);
        ASSERT_EQUAL_VEC(Vec3(0.5*expectedSpeed, 0, 0), state.getVelocities()[1], 0.02);
        double energy = state.getKineticEnergy()+state.getPotentialEnergy();
        ASSERT_EQUAL_TOL(initialEnergy, energy, 0.05);
        integrator.step(1);
    }
}
void testParallelComputation() {
    System system;
    const int numParticles = 200;
    for (int i = 0; i < numParticles; i++)
        system.addParticle(1.0);
    HarmonicBondForce* force = new HarmonicBondForce();
    for (int i = 1; i < numParticles; i++)
        force->addBond(i-1, i, 1.1, i);
    system.addForce(force);
    vector<Vec3> positions(numParticles);
    for (int i = 0; i < numParticles; i++)
        positions[i] = Vec3(i, 0, 0);
    VerletIntegrator integrator1(0.01);
    Context context1(system, integrator1, platform);
    context1.setPositions(positions);
    State state1 = context1.getState(State::Forces | State::Energy);
    VerletIntegrator integrator2(0.01);
    string deviceIndex = platform.getPropertyValue(context1, CudaPlatform::CudaDeviceIndex());
    map<string, string> props;
    props[CudaPlatform::CudaDeviceIndex()] = deviceIndex+","+deviceIndex;
    Context context2(system, integrator2, platform, props);
    context2.setPositions(positions);
    State state2 = context2.getState(State::Forces | State::Energy);
    ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5);
    for (int i = 0; i < numParticles; i++)
        ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
}
void testTemperature() {
    const int numParticles = 8;
    const int numBonds = numParticles-1;
    const double temp = 10.0;
    System system;
    BrownianIntegrator integrator(temp, 2.0, 0.01);
    HarmonicBondForce* forceField = new HarmonicBondForce();
    for (int i = 0; i < numParticles; ++i)
        system.addParticle(2.0);
    for (int i = 0; i < numBonds; ++i)
        forceField->addBond(i, i+1, 1.0, 5.0);
    system.addForce(forceField);
    Context context(system, integrator, platform);
    vector<Vec3> positions(numParticles);
    for (int i = 0; i < numParticles; ++i)
        positions[i] = Vec3(i, 0, 0);
    context.setPositions(positions);

    // Let it equilibrate.

    integrator.step(10000);

    // Now run it for a while and see if the temperature is correct.

    double pe = 0.0;
    const int steps = 50000;
    for (int i = 0; i < steps; ++i) {
        State state = context.getState(State::Energy);
        pe += state.getPotentialEnergy();
        integrator.step(1);
    }
    pe /= steps;
    double expected = 0.5*numBonds*BOLTZ*temp;
    ASSERT_USUALLY_EQUAL_TOL(expected, pe, 0.1*expected);
}
void testSingleBond() {
    System system;
    system.addParticle(2.0);
    system.addParticle(2.0);
    double dt = 0.01;
    BrownianIntegrator integrator(0, 0.1, dt);
    HarmonicBondForce* forceField = new HarmonicBondForce();
    forceField->addBond(0, 1, 1.5, 1);
    system.addForce(forceField);
    Context context(system, integrator, platform);
    vector<Vec3> positions(2);
    positions[0] = Vec3(-1, 0, 0);
    positions[1] = Vec3(1, 0, 0);
    context.setPositions(positions);

    // This is simply an overdamped harmonic oscillator, so compare it to the analytical solution.

    double rate = 2*1.0/(0.1*2.0);
    for (int i = 0; i < 1000; ++i) {
        State state = context.getState(State::Positions | State::Velocities);
        double time = state.getTime();
        double expectedDist = 1.5+0.5*std::exp(-rate*time);
        ASSERT_EQUAL_VEC(Vec3(-0.5*expectedDist, 0, 0), state.getPositions()[0], 0.02);
        ASSERT_EQUAL_VEC(Vec3(0.5*expectedDist, 0, 0), state.getPositions()[1], 0.02);
        if (i > 0) {
            double expectedSpeed = -0.5*rate*std::exp(-rate*(time-0.5*dt));
            ASSERT_EQUAL_VEC(Vec3(-0.5*expectedSpeed, 0, 0), state.getVelocities()[0], 0.11);
            ASSERT_EQUAL_VEC(Vec3(0.5*expectedSpeed, 0, 0), state.getVelocities()[1], 0.11);
        }
        integrator.step(1);
    }
}
Example #6
0
void ValidateOpenMM::writeHarmonicBondForce( FILE* filePtr, const HarmonicBondForce& harmonicBondForce ) const {

    (void) fprintf( filePtr, "HarmonicBondForce %d\n", harmonicBondForce.getNumBonds() );
    for(int ii = 0; ii < harmonicBondForce.getNumBonds(); ii++ ){
       int particle1, particle2;
       double length, k;
       harmonicBondForce.getBondParameters( ii, particle1, particle2, length, k );
       (void) fprintf( filePtr, "%8d %8d %8d %14.7e %14.7e\n", ii, particle1, particle2, length, k);
    }
}
/**
 * Test a multiple time step r-RESPA integrator.
 */
void testRespa() {
    const int numParticles = 8;
    System system;
    system.setDefaultPeriodicBoxVectors(Vec3(4, 0, 0), Vec3(0, 4, 0), Vec3(0, 0, 4));
    CustomIntegrator integrator(0.002);
    integrator.addComputePerDof("v", "v+0.5*dt*f1/m");
    for (int i = 0; i < 2; i++) {
        integrator.addComputePerDof("v", "v+0.5*(dt/2)*f0/m");
        integrator.addComputePerDof("x", "x+(dt/2)*v");
        integrator.addComputePerDof("v", "v+0.5*(dt/2)*f0/m");
    }
    integrator.addComputePerDof("v", "v+0.5*dt*f1/m");
    HarmonicBondForce* bonds = new HarmonicBondForce();
    for (int i = 0; i < numParticles-2; i++)
        bonds->addBond(i, i+1, 1.0, 0.5);
    system.addForce(bonds);
    NonbondedForce* nb = new NonbondedForce();
    nb->setCutoffDistance(2.0);
    nb->setNonbondedMethod(NonbondedForce::Ewald);
    for (int i = 0; i < numParticles; ++i) {
        system.addParticle(i%2 == 0 ? 5.0 : 10.0);
        nb->addParticle((i%2 == 0 ? 0.2 : -0.2), 0.5, 5.0);
    }
    nb->setForceGroup(1);
    nb->setReciprocalSpaceForceGroup(0);
    system.addForce(nb);
    Context context(system, integrator, platform);
    vector<Vec3> positions(numParticles);
    vector<Vec3> velocities(numParticles);
    OpenMM_SFMT::SFMT sfmt;
    init_gen_rand(0, sfmt);
    for (int i = 0; i < numParticles; ++i) {
        positions[i] = Vec3(i/2, (i+1)/2, 0);
        velocities[i] = Vec3(genrand_real2(sfmt)-0.5, genrand_real2(sfmt)-0.5, genrand_real2(sfmt)-0.5);
    }
    context.setPositions(positions);
    context.setVelocities(velocities);
    
    // Simulate it and monitor energy conservations.
    
    double initialEnergy = 0.0;
    for (int i = 0; i < 1000; ++i) {
        State state = context.getState(State::Energy);
        double energy = state.getKineticEnergy()+state.getPotentialEnergy();
        if (i == 1)
            initialEnergy = energy;
        else if (i > 1)
            ASSERT_EQUAL_TOL(initialEnergy, energy, 0.05);
        integrator.step(2);
    }
}
/**
 * Test a Monte Carlo integrator that uses global variables and depends on energy.
 */
void testMonteCarlo() {
    System system;
    system.addParticle(1.0);
    system.addParticle(1.0);
    CustomIntegrator integrator(0.1);
    const double kT = BOLTZ*300.0;
    integrator.addGlobalVariable("kT", kT);
    integrator.addGlobalVariable("oldE", 0);
    integrator.addGlobalVariable("accept", 0);
    integrator.addPerDofVariable("oldx", 0);
    integrator.addComputeGlobal("oldE", "energy");
    integrator.addComputePerDof("oldx", "x");
    integrator.addComputePerDof("x", "x+dt*gaussian");
    integrator.addComputeGlobal("accept", "step(exp((oldE-energy)/kT)-uniform)");
    integrator.addComputePerDof("x", "accept*x + (1-accept)*oldx");
    HarmonicBondForce* forceField = new HarmonicBondForce();
    forceField->addBond(0, 1, 2.0, 10.0);
    system.addForce(forceField);
    Context context(system, integrator, platform);
    vector<Vec3> positions(2);
    positions[0] = Vec3(-1, 0, 0);
    positions[1] = Vec3(1, 0, 0);
    context.setPositions(positions);
    
    // Compute the histogram of distances and see if it satisfies a Boltzmann distribution.
    
    const int numBins = 100;
    const double maxDist = 4.0;
    const int numIterations = 5000;
    vector<int> counts(numBins, 0);
    for (int i = 0; i < numIterations; ++i) {
        integrator.step(10);
        State state = context.getState(State::Positions);
        Vec3 delta = state.getPositions()[0]-state.getPositions()[1];
        double dist = sqrt(delta.dot(delta));
        if (dist < maxDist)
            counts[(int) (numBins*dist/maxDist)]++;
    }
    vector<double> expected(numBins, 0);
    double sum = 0;
    for (int i = 0; i < numBins; i++) {
        double dist = (i+0.5)*maxDist/numBins;
        expected[i] = dist*dist*exp(-5.0*(dist-2)*(dist-2)/kT);
        sum += expected[i];
    }
    for (int i = 0; i < numBins; i++)
        ASSERT_USUALLY_EQUAL_TOL((double) counts[i]/numIterations, expected[i]/sum, 0.01);
}
void testMotionRemoval() {
    const int numParticles = 8;
    const double temp = 100.0;
    const double collisionFreq = 10.0;
    ReferencePlatform platform;
    System system;
    VerletIntegrator integrator(0.01);
    HarmonicBondForce* bonds = new HarmonicBondForce();
    bonds->addBond(2, 3, 2.0, 0.5);
    system.addForce(bonds);
    NonbondedForce* nonbonded = new NonbondedForce();
    for (int i = 0; i < numParticles; ++i) {
        system.addParticle(i+1);
        nonbonded->addParticle((i%2 == 0 ? 1.0 : -1.0), 1.0, 5.0);
    }
    system.addForce(nonbonded);
    CMMotionRemover* remover = new CMMotionRemover();
    system.addForce(remover);
    Context context(system, integrator, platform);
    vector<Vec3> positions(numParticles);
    vector<Vec3> velocities(numParticles);
    OpenMM_SFMT::SFMT sfmt;
    init_gen_rand(0, sfmt);

    for (int i = 0; i < numParticles; ++i) {
        positions[i] = Vec3((i%2 == 0 ? 2 : -2), (i%4 < 2 ? 2 : -2), (i < 4 ? 2 : -2));
        velocities[i] = Vec3(genrand_real2(sfmt)-0.5, genrand_real2(sfmt)-0.5, genrand_real2(sfmt)-0.5);
    }
    context.setPositions(positions);
    context.setVelocities(velocities);
    
    // Now run it for a while and see if the center of mass remains fixed.
    
    Vec3 cmPos = calcCM(context.getState(State::Positions).getPositions(), system);
    for (int i = 0; i < 1000; ++i) {
        integrator.step(1);
        State state = context.getState(State::Positions | State::Velocities);
        Vec3 pos = calcCM(state.getPositions(), system);
        ASSERT_EQUAL_VEC(cmPos, pos, 1e-2);
        Vec3 vel = calcCM(state.getVelocities(), system);
        ASSERT_EQUAL_VEC(Vec3(0, 0, 0), vel, 1e-2);
    }
}
Example #10
0
void testWithoutThermostat() {
    const int numParticles = 20;
    const int numCopies = 10;
    const double temperature = 300.0;
    const double mass = 2.0;
    
    // Create a chain of particles.
    
    System system;
    HarmonicBondForce* bonds = new HarmonicBondForce();
    system.addForce(bonds);
    for (int i = 0; i < numParticles; i++) {
        system.addParticle(mass);
        if (i > 0)
            bonds->addBond(i-1, i, 1.0, 1000.0);
    }
    RPMDIntegrator integ(numCopies, temperature, 1.0, 0.001);
    integ.setApplyThermostat(false);
    Platform& platform = Platform::getPlatformByName("Reference");
    Context context(system, integ, platform);
    OpenMM_SFMT::SFMT sfmt;
    init_gen_rand(0, sfmt);
    vector<vector<Vec3> > positions(numCopies);
    for (int i = 0; i < numCopies; i++) {
        positions[i].resize(numParticles);
        for (int j = 0; j < numParticles; j++)
            positions[i][j] = Vec3(0.95*j, 0.01*genrand_real2(sfmt), 0.01*genrand_real2(sfmt));
        integ.setPositions(i, positions[i]);
    }
    
    // Simulate it and see if the energy remains constant.
    
    double initialEnergy;
    int numSteps = 100;
    for (int i = 0; i < numSteps; i++) {
        integ.step(1);
        double energy = integ.getTotalEnergy();
        if (i == 0)
            initialEnergy = energy;
        else
            ASSERT_EQUAL_TOL(initialEnergy, energy, 1e-4);
    }
}
void testBonds() {
    ReferencePlatform platform;
    System system;
    system.addParticle(1.0);
    system.addParticle(1.0);
    system.addParticle(1.0);
    VerletIntegrator integrator(0.01);
    HarmonicBondForce* forceField = new HarmonicBondForce();
    forceField->addBond(0, 1, 1.5, 0.8);
    forceField->addBond(1, 2, 1.2, 0.7);
    system.addForce(forceField);
    Context context(system, integrator, platform);
    vector<Vec3> positions(3);
    positions[0] = Vec3(0, 2, 0);
    positions[1] = Vec3(0, 0, 0);
    positions[2] = Vec3(1, 0, 0);
    context.setPositions(positions);
    State state = context.getState(State::Forces | State::Energy);
    {
        const vector<Vec3>& forces = state.getForces();
        ASSERT_EQUAL_VEC(Vec3(0, -0.8*0.5, 0), forces[0], TOL);
        ASSERT_EQUAL_VEC(Vec3(0.7*0.2, 0, 0), forces[2], TOL);
        ASSERT_EQUAL_VEC(Vec3(-forces[0][0]-forces[2][0], -forces[0][1]-forces[2][1], -forces[0][2]-forces[2][2]), forces[1], TOL);
        ASSERT_EQUAL_TOL(0.5*0.8*0.5*0.5 + 0.5*0.7*0.2*0.2, state.getPotentialEnergy(), TOL);
    }
    
    // Try changing the bond parameters and make sure it's still correct.
    
    forceField->setBondParameters(0, 0, 1, 1.6, 0.9);
    forceField->setBondParameters(1, 1, 2, 1.3, 0.8);
    forceField->updateParametersInContext(context);
    state = context.getState(State::Forces | State::Energy);
    {
        const vector<Vec3>& forces = state.getForces();
        ASSERT_EQUAL_VEC(Vec3(0, -0.9*0.4, 0), forces[0], TOL);
        ASSERT_EQUAL_VEC(Vec3(0.8*0.3, 0, 0), forces[2], TOL);
        ASSERT_EQUAL_VEC(Vec3(-forces[0][0]-forces[2][0], -forces[0][1]-forces[2][1], -forces[0][2]-forces[2][2]), forces[1], TOL);
        ASSERT_EQUAL_TOL(0.5*0.9*0.4*0.4 + 0.5*0.8*0.3*0.3, state.getPotentialEnergy(), TOL);
    }
}
/**
 * Test a simple leapfrog integrator on a single bond.
 */
void testSingleBond() {
    System system;
    system.addParticle(2.0);
    system.addParticle(2.0);
    const double dt = 0.01;
    CustomIntegrator integrator(dt);
    integrator.addComputePerDof("v", "v+dt*f/m");
    integrator.addComputePerDof("x", "x+dt*v");
    integrator.setKineticEnergyExpression("m*v1*v1/2; v1=v+0.5*dt*f/m");
    HarmonicBondForce* forceField = new HarmonicBondForce();
    forceField->addBond(0, 1, 1.5, 1);
    system.addForce(forceField);
    Context context(system, integrator, platform);
    vector<Vec3> positions(2);
    positions[0] = Vec3(-1, 0, 0);
    positions[1] = Vec3(1, 0, 0);
    context.setPositions(positions);
    vector<Vec3> velocities(2);
    velocities[0] = Vec3(-0.5*dt*0.5*0.5, 0, 0);
    velocities[1] = Vec3(0.5*dt*0.5*0.5, 0, 0);
    context.setVelocities(velocities);
    
    // This is simply a harmonic oscillator, so compare it to the analytical solution.
    
    const double freq = 1.0;;
    for (int i = 0; i < 1000; ++i) {
        State state = context.getState(State::Positions | State::Velocities | State::Energy);
        double time = state.getTime();
        double expectedDist = 1.5+0.5*std::cos(freq*time);
        ASSERT_EQUAL_VEC(Vec3(-0.5*expectedDist, 0, 0), state.getPositions()[0], 1e-4);
        ASSERT_EQUAL_VEC(Vec3(0.5*expectedDist, 0, 0), state.getPositions()[1], 1e-4);
        double expectedSpeed = -0.5*freq*std::sin(freq*(time-dt/2));
        ASSERT_EQUAL_VEC(Vec3(-0.5*expectedSpeed, 0, 0), state.getVelocities()[0], 1e-4);
        ASSERT_EQUAL_VEC(Vec3(0.5*expectedSpeed, 0, 0), state.getVelocities()[1], 1e-4);
        double energy = state.getKineticEnergy()+state.getPotentialEnergy();
        ASSERT_EQUAL_TOL(0.5*0.5*0.5, energy, 1e-4);
        integrator.step(1);
    }
}
void testBond() {
    // Create a system using a CustomCompoundBondForce.

    System customSystem;
    customSystem.addParticle(1.0);
    customSystem.addParticle(1.0);
    customSystem.addParticle(1.0);
    customSystem.addParticle(1.0);
    CustomCompoundBondForce* custom = new CustomCompoundBondForce(4, "0.5*kb*((distance(p1,p2)-b0)^2+(distance(p2,p3)-b0)^2)+0.5*ka*(angle(p2,p3,p4)-a0)^2+kt*(1+cos(dihedral(p1,p2,p3,p4)-t0))");
    custom->addPerBondParameter("kb");
    custom->addPerBondParameter("ka");
    custom->addPerBondParameter("kt");
    custom->addPerBondParameter("b0");
    custom->addPerBondParameter("a0");
    custom->addPerBondParameter("t0");
    vector<int> particles(4);
    particles[0] = 0;
    particles[1] = 1;
    particles[2] = 3;
    particles[3] = 2;
    vector<double> parameters(6);
    parameters[0] = 1.5;
    parameters[1] = 0.8;
    parameters[2] = 0.6;
    parameters[3] = 1.1;
    parameters[4] = 2.9;
    parameters[5] = 1.3;
    custom->addBond(particles, parameters);
    customSystem.addForce(custom);

    // Create an identical system using standard forces.

    System standardSystem;
    standardSystem.addParticle(1.0);
    standardSystem.addParticle(1.0);
    standardSystem.addParticle(1.0);
    standardSystem.addParticle(1.0);
    HarmonicBondForce* bonds = new HarmonicBondForce();
    bonds->addBond(0, 1, 1.1, 1.5);
    bonds->addBond(1, 3, 1.1, 1.5);
    standardSystem.addForce(bonds);
    HarmonicAngleForce* angles = new HarmonicAngleForce();
    angles->addAngle(1, 3, 2, 2.9, 0.8);
    standardSystem.addForce(angles);
    PeriodicTorsionForce* torsions = new PeriodicTorsionForce();
    torsions->addTorsion(0, 1, 3, 2, 1, 1.3, 0.6);
    standardSystem.addForce(torsions);

    // Set the atoms in various positions, and verify that both systems give identical forces and energy.

    OpenMM_SFMT::SFMT sfmt;
    init_gen_rand(0, sfmt);
    VerletIntegrator integrator1(0.01);
    VerletIntegrator integrator2(0.01);
    Context c1(customSystem, integrator1, platform);
    Context c2(standardSystem, integrator2, platform);
    vector<Vec3> positions(4);
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < (int) positions.size(); j++)
            positions[j] = Vec3(5.0*genrand_real2(sfmt), 5.0*genrand_real2(sfmt), 5.0*genrand_real2(sfmt));
        c1.setPositions(positions);
        c2.setPositions(positions);
        State s1 = c1.getState(State::Forces | State::Energy);
        State s2 = c2.getState(State::Forces | State::Energy);
        for (int i = 0; i < customSystem.getNumParticles(); i++)
            ASSERT_EQUAL_VEC(s1.getForces()[i], s2.getForces()[i], TOL);
        ASSERT_EQUAL_TOL(s1.getPotentialEnergy(), s2.getPotentialEnergy(), TOL);
    }
    
    // Try changing the bond parameters and make sure it's still correct.
    
    parameters[0] = 1.6;
    parameters[3] = 1.3;
    custom->setBondParameters(0, particles, parameters);
    custom->updateParametersInContext(c1);
    bonds->setBondParameters(0, 0, 1, 1.3, 1.6);
    bonds->setBondParameters(1, 1, 3, 1.3, 1.6);
    bonds->updateParametersInContext(c2);
    {
        State s1 = c1.getState(State::Forces | State::Energy);
        State s2 = c2.getState(State::Forces | State::Energy);
        const vector<Vec3>& forces = s1.getForces();
        for (int i = 0; i < customSystem.getNumParticles(); i++)
            ASSERT_EQUAL_VEC(s1.getForces()[i], s2.getForces()[i], TOL);
        ASSERT_EQUAL_TOL(s1.getPotentialEnergy(), s2.getPotentialEnergy(), TOL);
    }
}
Example #14
0
void testWithBarostat() {
    const int gridSize = 3;
    const int numMolecules = gridSize*gridSize*gridSize;
    const int numParticles = numMolecules*2;
    const int numCopies = 5;
    const double spacing = 2.0;
    const double cutoff = 3.0;
    const double boxSize = spacing*(gridSize+1);
    const double temperature = 300.0;
    System system;
    system.setDefaultPeriodicBoxVectors(Vec3(boxSize, 0, 0), Vec3(0, boxSize, 0), Vec3(0, 0, boxSize));
    HarmonicBondForce* bonds = new HarmonicBondForce();
    system.addForce(bonds);
    NonbondedForce* nonbonded = new NonbondedForce();
    nonbonded->setCutoffDistance(cutoff);
    nonbonded->setNonbondedMethod(NonbondedForce::PME);
    nonbonded->setForceGroup(1);
    nonbonded->setReciprocalSpaceForceGroup(2);
    system.addForce(nonbonded);
    system.addForce(new MonteCarloBarostat(0.5, temperature));

    // Create a cloud of molecules.

    OpenMM_SFMT::SFMT sfmt;
    init_gen_rand(0, sfmt);
    vector<Vec3> positions(numParticles);
    for (int i = 0; i < numMolecules; i++) {
        system.addParticle(1.0);
        system.addParticle(1.0);
        nonbonded->addParticle(-0.2, 0.2, 0.2);
        nonbonded->addParticle(0.2, 0.2, 0.2);
        nonbonded->addException(2*i, 2*i+1, 0, 1, 0);
        bonds->addBond(2*i, 2*i+1, 1.0, 10000.0);
    }
    RPMDIntegrator integ(numCopies, temperature, 50.0, 0.001);
    Platform& platform = Platform::getPlatformByName("Reference");
    Context context(system, integ, platform);
    for (int copy = 0; copy < numCopies; copy++) {
        for (int i = 0; i < gridSize; i++)
            for (int j = 0; j < gridSize; j++)
                for (int k = 0; k < gridSize; k++) {
                    Vec3 pos = Vec3(spacing*(i+0.02*genrand_real2(sfmt)), spacing*(j+0.02*genrand_real2(sfmt)), spacing*(k+0.02*genrand_real2(sfmt)));
                    int index = k+gridSize*(j+gridSize*i);
                    positions[2*index] = pos;
                    positions[2*index+1] = Vec3(pos[0]+1.0, pos[1], pos[2]);
                }
        integ.setPositions(copy, positions);
    }

    // Check the temperature.
    
    const int numSteps = 500;
    integ.step(100);
    vector<double> ke(numCopies, 0.0);
    for (int i = 0; i < numSteps; i++) {
        integ.step(1);
        vector<State> state(numCopies);
        for (int j = 0; j < numCopies; j++)
            state[j] = integ.getState(j, State::Velocities, true);
        for (int j = 0; j < numParticles; j++) {
            for (int k = 0; k < numCopies; k++) {
                Vec3 v = state[k].getVelocities()[j];
                ke[k] += 0.5*system.getParticleMass(j)*v.dot(v);
            }
        }
    }
    double meanKE = 0.0;
    for (int i = 0; i < numCopies; i++)
        meanKE += ke[i];
    meanKE /= numSteps*numCopies;
    double expectedKE = 0.5*numCopies*numParticles*3*BOLTZ*temperature;
    ASSERT_USUALLY_EQUAL_TOL(expectedKE, meanKE, 1e-2);
}
void testLargeSystem() {
    const int numMolecules = 600;
    const int numParticles = numMolecules*2;
    const double cutoff = 2.0;
    const double boxSize = 20.0;
    const double tol = 2e-3;
    ReferencePlatform reference;
    System system;
    for (int i = 0; i < numParticles; i++)
        system.addParticle(1.0);
    NonbondedForce* nonbonded = new NonbondedForce();
    HarmonicBondForce* bonds = new HarmonicBondForce();
    vector<Vec3> positions(numParticles);
    vector<Vec3> velocities(numParticles);
    OpenMM_SFMT::SFMT sfmt;
    init_gen_rand(0, sfmt);

    for (int i = 0; i < numMolecules; i++) {
        if (i < numMolecules/2) {
            nonbonded->addParticle(-1.0, 0.2, 0.1);
            nonbonded->addParticle(1.0, 0.1, 0.1);
        }
        else {
            nonbonded->addParticle(-1.0, 0.2, 0.2);
            nonbonded->addParticle(1.0, 0.1, 0.2);
        }
        positions[2*i] = Vec3(boxSize*genrand_real2(sfmt), boxSize*genrand_real2(sfmt), boxSize*genrand_real2(sfmt));
        positions[2*i+1] = Vec3(positions[2*i][0]+1.0, positions[2*i][1], positions[2*i][2]);
        velocities[2*i] = Vec3(genrand_real2(sfmt), genrand_real2(sfmt), genrand_real2(sfmt));
        velocities[2*i+1] = Vec3(genrand_real2(sfmt), genrand_real2(sfmt), genrand_real2(sfmt));
        bonds->addBond(2*i, 2*i+1, 1.0, 0.1);
        nonbonded->addException(2*i, 2*i+1, 0.0, 0.15, 0.0);
    }

    // Try with cutoffs but not periodic boundary conditions, and make sure the cl and Reference
    // platforms agree.

    nonbonded->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic);
    nonbonded->setCutoffDistance(cutoff);
    system.addForce(nonbonded);
    system.addForce(bonds);
    VerletIntegrator integrator1(0.01);
    VerletIntegrator integrator2(0.01);
    Context cuContext(system, integrator1, platform);
    Context referenceContext(system, integrator2, reference);
    cuContext.setPositions(positions);
    cuContext.setVelocities(velocities);
    referenceContext.setPositions(positions);
    referenceContext.setVelocities(velocities);
    State cuState = cuContext.getState(State::Positions | State::Velocities | State::Forces | State::Energy);
    State referenceState = referenceContext.getState(State::Positions | State::Velocities | State::Forces | State::Energy);
    for (int i = 0; i < numParticles; i++) {
        ASSERT_EQUAL_VEC(cuState.getPositions()[i], referenceState.getPositions()[i], tol);
        ASSERT_EQUAL_VEC(cuState.getVelocities()[i], referenceState.getVelocities()[i], tol);
        ASSERT_EQUAL_VEC(cuState.getForces()[i], referenceState.getForces()[i], tol);
    }
    ASSERT_EQUAL_TOL(cuState.getPotentialEnergy(), referenceState.getPotentialEnergy(), tol);

    // Now do the same thing with periodic boundary conditions.

    nonbonded->setNonbondedMethod(NonbondedForce::CutoffPeriodic);
    system.setDefaultPeriodicBoxVectors(Vec3(boxSize, 0, 0), Vec3(0, boxSize, 0), Vec3(0, 0, boxSize));
    cuContext.reinitialize();
    referenceContext.reinitialize();
    cuContext.setPositions(positions);
    cuContext.setVelocities(velocities);
    referenceContext.setPositions(positions);
    referenceContext.setVelocities(velocities);
    cuState = cuContext.getState(State::Positions | State::Velocities | State::Forces | State::Energy);
    referenceState = referenceContext.getState(State::Positions | State::Velocities | State::Forces | State::Energy);
    for (int i = 0; i < numParticles; i++) {
        double dx = cuState.getPositions()[i][0]-referenceState.getPositions()[i][0];
        double dy = cuState.getPositions()[i][1]-referenceState.getPositions()[i][1];
        double dz = cuState.getPositions()[i][2]-referenceState.getPositions()[i][2];
        ASSERT_EQUAL_TOL(fmod(cuState.getPositions()[i][0]-referenceState.getPositions()[i][0], boxSize), 0, tol);
        ASSERT_EQUAL_TOL(fmod(cuState.getPositions()[i][1]-referenceState.getPositions()[i][1], boxSize), 0, tol);
        ASSERT_EQUAL_TOL(fmod(cuState.getPositions()[i][2]-referenceState.getPositions()[i][2], boxSize), 0, tol);
        ASSERT_EQUAL_VEC(cuState.getVelocities()[i], referenceState.getVelocities()[i], tol);
        ASSERT_EQUAL_VEC(cuState.getForces()[i], referenceState.getForces()[i], tol);
    }
    ASSERT_EQUAL_TOL(cuState.getPotentialEnergy(), referenceState.getPotentialEnergy(), tol);
}
void testHbond() {
    // Create a system using a CustomHbondForce.

    System customSystem;
    customSystem.addParticle(1.0);
    customSystem.addParticle(1.0);
    customSystem.addParticle(1.0);
    customSystem.addParticle(1.0);
    customSystem.addParticle(1.0);
    CustomHbondForce* custom = new CustomHbondForce("0.5*kr*(distance(d1,a1)-r0)^2 + 0.5*ktheta*(angle(a1,d1,d2)-theta0)^2 + 0.5*kpsi*(angle(d1,a1,a2)-psi0)^2 + kchi*(1+cos(n*dihedral(a3,a2,a1,d1)-chi0))");
    custom->addPerDonorParameter("r0");
    custom->addPerDonorParameter("theta0");
    custom->addPerDonorParameter("psi0");
    custom->addPerAcceptorParameter("chi0");
    custom->addPerAcceptorParameter("n");
    custom->addGlobalParameter("kr", 0.4);
    custom->addGlobalParameter("ktheta", 0.5);
    custom->addGlobalParameter("kpsi", 0.6);
    custom->addGlobalParameter("kchi", 0.7);
    vector<double> parameters(3);
    parameters[0] = 1.5;
    parameters[1] = 1.7;
    parameters[2] = 1.9;
    custom->addDonor(1, 0, -1, parameters);
    parameters.resize(2);
    parameters[0] = 2.1;
    parameters[1] = 2;
    custom->addAcceptor(2, 3, 4, parameters);
    custom->setCutoffDistance(10.0);
    customSystem.addForce(custom);

    // Create an identical system using HarmonicBondForce, HarmonicAngleForce, and PeriodicTorsionForce.

    System standardSystem;
    standardSystem.addParticle(1.0);
    standardSystem.addParticle(1.0);
    standardSystem.addParticle(1.0);
    standardSystem.addParticle(1.0);
    standardSystem.addParticle(1.0);
    HarmonicBondForce* bond = new HarmonicBondForce();
    bond->addBond(1, 2, 1.5, 0.4);
    standardSystem.addForce(bond);
    HarmonicAngleForce* angle = new HarmonicAngleForce();
    angle->addAngle(0, 1, 2, 1.7, 0.5);
    angle->addAngle(1, 2, 3, 1.9, 0.6);
    standardSystem.addForce(angle);
    PeriodicTorsionForce* torsion = new PeriodicTorsionForce();
    torsion->addTorsion(1, 2, 3, 4, 2, 2.1, 0.7);
    standardSystem.addForce(torsion);

    // Set the atoms in various positions, and verify that both systems give identical forces and energy.

    OpenMM_SFMT::SFMT sfmt;
    init_gen_rand(0, sfmt);

    vector<Vec3> positions(5);
    VerletIntegrator integrator1(0.01);
    VerletIntegrator integrator2(0.01);
    Context c1(customSystem, integrator1, platform);
    Context c2(standardSystem, integrator2, platform);
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < (int) positions.size(); j++)
            positions[j] = Vec3(2.0*genrand_real2(sfmt), 2.0*genrand_real2(sfmt), 2.0*genrand_real2(sfmt));
        c1.setPositions(positions);
        c2.setPositions(positions);
        State s1 = c1.getState(State::Forces | State::Energy);
        State s2 = c2.getState(State::Forces | State::Energy);
        for (int i = 0; i < customSystem.getNumParticles(); i++)
            ASSERT_EQUAL_VEC(s2.getForces()[i], s1.getForces()[i], TOL);
        ASSERT_EQUAL_TOL(s2.getPotentialEnergy(), s1.getPotentialEnergy(), TOL);
    }
    
    // Try changing the parameters and make sure it's still correct.
    
    parameters.resize(3);
    parameters[0] = 1.4;
    parameters[1] = 1.7;
    parameters[2] = 1.9;
    custom->setDonorParameters(0, 1, 0, -1, parameters);
    parameters.resize(2);
    parameters[0] = 2.2;
    parameters[1] = 2;
    custom->setAcceptorParameters(0, 2, 3, 4, parameters);
    bond->setBondParameters(0, 1, 2, 1.4, 0.4);
    torsion->setTorsionParameters(0, 1, 2, 3, 4, 2, 2.2, 0.7);
    custom->updateParametersInContext(c1);
    bond->updateParametersInContext(c2);
    torsion->updateParametersInContext(c2);
    State s1 = c1.getState(State::Forces | State::Energy);
    State s2 = c2.getState(State::Forces | State::Energy);
    for (int i = 0; i < customSystem.getNumParticles(); i++)
        ASSERT_EQUAL_VEC(s2.getForces()[i], s1.getForces()[i], TOL);
    ASSERT_EQUAL_TOL(s2.getPotentialEnergy(), s1.getPotentialEnergy(), TOL);
}
/**
 * Test evaluating force groups separately.
 */
void testForceGroups() {
    System system;
    system.addParticle(2.0);
    system.addParticle(2.0);
    CustomIntegrator integrator(0.01);
    integrator.addPerDofVariable("outf", 0);
    integrator.addPerDofVariable("outf1", 0);
    integrator.addPerDofVariable("outf2", 0);
    integrator.addGlobalVariable("oute", 0);
    integrator.addGlobalVariable("oute1", 0);
    integrator.addGlobalVariable("oute2", 0);
    integrator.addComputePerDof("outf", "f");
    integrator.addComputePerDof("outf1", "f1");
    integrator.addComputePerDof("outf2", "f2");
    integrator.addComputeGlobal("oute", "energy");
    integrator.addComputeGlobal("oute1", "energy1");
    integrator.addComputeGlobal("oute2", "energy2");
    HarmonicBondForce* bonds = new HarmonicBondForce();
    bonds->addBond(0, 1, 1.5, 1.1);
    bonds->setForceGroup(1);
    system.addForce(bonds);
    NonbondedForce* nb = new NonbondedForce();
    nb->addParticle(0.2, 1, 0);
    nb->addParticle(0.2, 1, 0);
    nb->setForceGroup(2);
    system.addForce(nb);
    Context context(system, integrator, platform);
    vector<Vec3> positions(2);
    positions[0] = Vec3(-1, 0, 0);
    positions[1] = Vec3(1, 0, 0);
    context.setPositions(positions);
    
    // See if the various forces are computed correctly.
    
    integrator.step(1);
    vector<Vec3> f, f1, f2;
    double e1 = 0.5*1.1*0.5*0.5;
    double e2 = 138.935456*0.2*0.2/2.0;
    integrator.getPerDofVariable(0, f);
    integrator.getPerDofVariable(1, f1);
    integrator.getPerDofVariable(2, f2);
    ASSERT_EQUAL_VEC(Vec3(1.1*0.5, 0, 0), f1[0], 1e-5);
    ASSERT_EQUAL_VEC(Vec3(-1.1*0.5, 0, 0), f1[1], 1e-5);
    ASSERT_EQUAL_VEC(Vec3(-138.935456*0.2*0.2/4.0, 0, 0), f2[0], 1e-5);
    ASSERT_EQUAL_VEC(Vec3(138.935456*0.2*0.2/4.0, 0, 0), f2[1], 1e-5);
    ASSERT_EQUAL_VEC(f1[0]+f2[0], f[0], 1e-5);
    ASSERT_EQUAL_VEC(f1[1]+f2[1], f[1], 1e-5);
    ASSERT_EQUAL_TOL(e1, integrator.getGlobalVariable(1), 1e-5);
    ASSERT_EQUAL_TOL(e2, integrator.getGlobalVariable(2), 1e-5);
    ASSERT_EQUAL_TOL(e1+e2, integrator.getGlobalVariable(0), 1e-5);
    
    // Make sure they also match the values returned by the Context.
    
    State s = context.getState(State::Forces | State::Energy, false);
    State s1 = context.getState(State::Forces | State::Energy, false, 2);
    State s2 = context.getState(State::Forces | State::Energy, false, 4);
    vector<Vec3> c, c1, c2;
    c = context.getState(State::Forces, false).getForces();
    c1 = context.getState(State::Forces, false, 2).getForces();
    c2 = context.getState(State::Forces, false, 4).getForces();
    ASSERT_EQUAL_VEC(f[0], c[0], 1e-5);
    ASSERT_EQUAL_VEC(f[1], c[1], 1e-5);
    ASSERT_EQUAL_VEC(f1[0], c1[0], 1e-5);
    ASSERT_EQUAL_VEC(f1[1], c1[1], 1e-5);
    ASSERT_EQUAL_VEC(f2[0], c2[0], 1e-5);
    ASSERT_EQUAL_VEC(f2[1], c2[1], 1e-5);
    ASSERT_EQUAL_TOL(s.getPotentialEnergy(), integrator.getGlobalVariable(0), 1e-5);
    ASSERT_EQUAL_TOL(s1.getPotentialEnergy(), integrator.getGlobalVariable(1), 1e-5);
    ASSERT_EQUAL_TOL(s2.getPotentialEnergy(), integrator.getGlobalVariable(2), 1e-5);
}
Example #18
0
void testWithoutThermostat() {
    const int numParticles = 20;
    const int numCopies = 10;
    const double temperature = 300.0;
    const double mass = 2.0;
    
    // Create a chain of particles.
    
    System system;
    HarmonicBondForce* bonds = new HarmonicBondForce();
    system.addForce(bonds);
    for (int i = 0; i < numParticles; i++) {
        system.addParticle(mass);
        if (i > 0)
            bonds->addBond(i-1, i, 1.0, 1000.0);
    }
    RPMDIntegrator integ(numCopies, temperature, 1.0, 0.001);
    integ.setApplyThermostat(false);
    Platform& platform = Platform::getPlatformByName("CUDA");
    Context context(system, integ, platform);
    OpenMM_SFMT::SFMT sfmt;
    init_gen_rand(0, sfmt);
    vector<vector<Vec3> > positions(numCopies);
    for (int i = 0; i < numCopies; i++) {
        positions[i].resize(numParticles);
        for (int j = 0; j < numParticles; j++)
            positions[i][j] = Vec3(0.95*j, 0.01*genrand_real2(sfmt), 0.01*genrand_real2(sfmt));
        integ.setPositions(i, positions[i]);
    }
    
    // Simulate it and see if the energy remains constant.
    
    double initialEnergy;
    int numSteps = 100;
    const double hbar = 1.054571628e-34*AVOGADRO/(1000*1e-12);
    const double wn = numCopies*BOLTZ*temperature/hbar;
    const double springConstant = mass*wn*wn;
    for (int i = 0; i < numSteps; i++) {
        integ.step(1);
        
        // Sum the energies of all the copies.
        
        double energy = 0.0;
        for (int j = 0; j < numCopies; j++) {
            State state = integ.getState(j, State::Positions | State::Energy);
            positions[j] = state.getPositions();
            energy += state.getPotentialEnergy()+state.getKineticEnergy();
        }
        
        // Add the energy from the springs connecting copies.
        
        for (int j = 0; j < numCopies; j++) {
            int previous = (j == 0 ? numCopies-1 : j-1);
            for (int k = 0; k < numParticles; k++) {
                Vec3 delta = positions[j][k]-positions[previous][k];
                energy += 0.5*springConstant*delta.dot(delta);
            }
        }
        if (i == 0)
            initialEnergy = energy;
        else
            ASSERT_EQUAL_TOL(initialEnergy, energy, 1e-4);
    }
}
Example #19
0
void testEnergyEthane(int applyBornRadiiScaling) {

    ReferencePlatform platform;
    const int numParticles = 8;
    System system;
    LangevinIntegrator integrator(0, 0.1, 0.01);

    // harmonic bond

    double C_HBondDistance   = 0.1097;
    double C_CBondDistance   = 0.1504;
    HarmonicBondForce* bonds = new HarmonicBondForce();
    bonds->addBond(0, 1, C_HBondDistance, 0.0);
    bonds->addBond(2, 1, C_HBondDistance, 0.0);
    bonds->addBond(3, 1, C_HBondDistance, 0.0);

    bonds->addBond(1, 4, C_CBondDistance, 0.0);

    bonds->addBond(5, 4, C_HBondDistance, 0.0);
    bonds->addBond(6, 4, C_HBondDistance, 0.0);
    bonds->addBond(7, 4, C_HBondDistance, 0.0);

    system.addForce(bonds);

    double C_radius, C_gamma, C_charge, H_radius, H_gamma, H_charge;

    int AM1_BCC = 1;
    H_charge    = -0.053;
    C_charge    = -3.0*H_charge;
    if (AM1_BCC) {
       C_radius =  0.180;
       C_gamma  = -0.2863;
       H_radius =  0.125;
       H_gamma  =  0.2437;
    }
    else {
       C_radius =  0.215;
       C_gamma  = -1.1087;
       H_radius =  0.150;
       H_gamma  =  0.1237;
    }

    NonbondedForce* nonbonded = new NonbondedForce();
    nonbonded->setNonbondedMethod(NonbondedForce::NoCutoff);

    GBVIForce* forceField = new GBVIForce();
    if (applyBornRadiiScaling) {
        forceField->setBornRadiusScalingMethod(GBVIForce::QuinticSpline);
    }
    else {
        forceField->setBornRadiusScalingMethod(GBVIForce::NoScaling);
    }
    for (int i = 0; i < numParticles; i++) {
       system.addParticle(1.0);
       forceField->addParticle(H_charge, H_radius, H_gamma);
       nonbonded->addParticle( H_charge, H_radius, 0.0);
    }
 
    forceField->setParticleParameters(1, C_charge, C_radius, C_gamma);
    forceField->setParticleParameters(4, C_charge, C_radius, C_gamma);
 
    nonbonded->setParticleParameters( 1, C_charge, C_radius, 0.0);
    nonbonded->setParticleParameters( 4, C_charge, C_radius, 0.0);
 
    forceField->addBond(0, 1, C_HBondDistance);
    forceField->addBond(2, 1, C_HBondDistance);
    forceField->addBond(3, 1, C_HBondDistance);
    forceField->addBond(1, 4, C_CBondDistance);
    forceField->addBond(5, 4, C_HBondDistance);
    forceField->addBond(6, 4, C_HBondDistance);
    forceField->addBond(7, 4, C_HBondDistance);
    
    std::vector<pair<int, int> > bondExceptions;
    std::vector<double> bondDistances;
    
    bondExceptions.push_back(pair<int, int>(0, 1)); 
    bondDistances.push_back(C_HBondDistance);
    
    bondExceptions.push_back(pair<int, int>(2, 1)); 
    bondDistances.push_back(C_HBondDistance);
    
    bondExceptions.push_back(pair<int, int>(3, 1)); 
    bondDistances.push_back(C_HBondDistance);
    
    bondExceptions.push_back(pair<int, int>(1, 4)); 
    bondDistances.push_back(C_CBondDistance);
    
    bondExceptions.push_back(pair<int, int>(5, 4)); 
    bondDistances.push_back(C_HBondDistance);
    
    bondExceptions.push_back(pair<int, int>(6, 4)); 
    bondDistances.push_back(C_HBondDistance);
 
    bondExceptions.push_back(pair<int, int>(7, 4));
    bondDistances.push_back(C_HBondDistance);
 
    nonbonded->createExceptionsFromBonds(bondExceptions, 0.0, 0.0);
 
    system.addForce(forceField);
    system.addForce(nonbonded);

    Context context(system, integrator, platform);
    
    vector<Vec3> positions(numParticles);
    positions[0] = Vec3(0.5480,    1.7661,    0.0000);
    positions[1] = Vec3(0.7286,    0.8978,    0.6468);
    positions[2] = Vec3(0.4974,    0.0000,    0.0588);
    positions[3] = Vec3(0.0000,    0.9459,    1.4666);
    positions[4] = Vec3(2.1421,    0.8746,    1.1615);
    positions[5] = Vec3(2.3239,    0.0050,    1.8065);
    positions[6] = Vec3(2.8705,    0.8295,    0.3416);
    positions[7] = Vec3(2.3722,    1.7711,    1.7518);
    context.setPositions(positions);

    State state = context.getState(State::Forces | State::Energy);
    
    // Take a small step in the direction of the energy gradient.
    
    double norm        = 0.0;
    double forceSum[3] = { 0.0, 0.0, 0.0 };
    for (int i = 0; i < numParticles; ++i) {
        Vec3 f  = state.getForces()[i];
        norm        += f[0]*f[0] + f[1]*f[1] + f[2]*f[2];
        forceSum[0] += f[0];
        forceSum[1] += f[1];
        forceSum[2] += f[2];
    }
    norm               = std::sqrt(norm);

    const double delta = 1e-4;
    double step = delta/norm;
    for (int i = 0; i < numParticles; ++i) {
        Vec3 p = positions[i];
        Vec3 f = state.getForces()[i];
        positions[i] = Vec3(p[0]-f[0]*step, p[1]-f[1]*step, p[2]-f[2]*step);
    }
    context.setPositions(positions);
    
    State state2 = context.getState(State::Energy);

    // See whether the potential energy changed by the expected amount.
    
    ASSERT_EQUAL_TOL(norm, (state2.getPotentialEnergy()-state.getPotentialEnergy())/delta, 0.01)
}