HelloWorld.cpp 4.27 KB
Newer Older
1
2
3
4
#include "OpenMM.h"

#include <iostream>
#include <string>
5
#include <limits>
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

using namespace OpenMM;

Vec3 operator*(const Vec3& v, double r) {
    return Vec3(v[0]*r, v[1]*r, v[2]*r);
}

Vec3 operator*(double r, const Vec3& v) {
    return Vec3(r*v[0], r*v[1], r*v[2]);
}

// This is not part of OpenMM; just a struct we can use to collect
// atom parameters for this example. Normally atom parameters would
// come from the force field's parameterization file.
// We're going to use data in Angstrom and Kilocalorie units and
// show how to safely convert to OpenMM's internal unit system
// which uses nanometers and kilojoules.
struct AtomInfo {
    char*  symbol;
    double mass, charge, vdwRadiusAng, vdwEnergyKcal;
    Vec3   startPosAng;
};

static AtomInfo atoms[] = {
    {"Na+", 22.99,  1, 1.8680, 0.00277, Vec3(-3,0,0)},
    {"Cl-", 35.45, -1, 2.4700, 0.1000,  Vec3( 3,0,0)},
    {""} // end of list
};

static const double Temperature         = 100;     // Kelvins
static const double Friction            = 1./91.;  // picoseconds between collisions
37
static const double StepSizeFs          = 2;     // femtoseconds
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
static const double ReportIntervalFs    = 1000;
static const double SimulationTimePs    = 1000;  // total simulation time (ps)

static const double SigmaPerVdwRadius = 2*std::pow(2., -1./6.);

static void showState(const OpenMMContext&);

int main() {
try {
    // Load all available OpenMM plugins from their default location.
    Platform::loadPluginsFromDirectory(Platform::getDefaultPluginsDirectory());

    // Create a System and a NonbondedForce object within the System. 
    System system;
    NonbondedForce* nonbond = new NonbondedForce();
    system.addForce(nonbond);

    int numAtoms = 0;
    for (; *atoms[numAtoms].symbol; ++numAtoms) {
        const AtomInfo& atom = atoms[numAtoms];
        system.addParticle(atom.mass);
        nonbond->addParticle(atom.charge,
                             atom.vdwRadiusAng  * NmPerAngstrom * SigmaPerVdwRadius,
                             atom.vdwEnergyKcal * KJPerKcal);
    }

    // Create an integrator object for advancing time.
    //LangevinIntegrator integrator(Temperature, Friction, StepSizeFs * PsPerFs);
    VerletIntegrator integrator(StepSizeFs * PsPerFs);

    // Create an OpenMM Context for execution; let it choose best platform.
    OpenMMContext context(system, integrator);

    std::cout << "Will use OpenMM platform " << context.getPlatform().getName() << std::endl;
72
    std::cout << "eps(float)=" << std::numeric_limits<float>::epsilon() << std::endl;
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

    // Fill in a vector of starting positions, one per atom.
    std::vector<Vec3> positions(numAtoms);
    for (int i=0; i < numAtoms; ++i)
        positions[i] = atoms[i].startPosAng * NmPerAngstrom;

    // Set the starting positions in the OpenMM context. Velocities will be zero.
    context.setPositions(positions);

    // Output the initial state.
    showState(context);

    const int NumSilentSteps = (int)(ReportIntervalFs / StepSizeFs + 0.5);
    do {
        integrator.step(NumSilentSteps);
        showState(context);
89
    } while (context.getTime() < SimulationTimePs);
90
91
92
93
94
95
96
97
98
99
100
101

    } catch(const std::exception& e) {
        std::cout << "EXCEPTION: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

static void
showState(const OpenMMContext& context) {
    // Caution: at the moment asking for energy requires use of slow reference calculation.
102
103
    const State                 state       = context.getState(  State::Positions | State::Velocities 
                                                               | State::Forces    | State::Energy);
104
105
    const double                energy      = state.getPotentialEnergy() + state.getKineticEnergy();
    const std::vector<Vec3>&    positions   = state.getPositions();
106
    const std::vector<Vec3>&    forces      = state.getForces();
107
108

    std::cout << "t=" << state.getTime() << " E=" << energy << std::endl;
109
110
111
112
113
114
    const double dt = StepSizeFs*PsPerFs;
    for (unsigned i=0; i < positions.size(); ++i) {
        const Vec3 dq = dt*dt/(2*atoms[i].mass) * forces[i];
        std::cout << i << " " << positions[i] * AngstromsPerNm << std::endl;
        std::cout << "f=" << forces[i] << " dq=" << dq << std::endl;
    }
115
}