Context.cpp 9.61 KB
Newer Older
1
2
3
4
5
6
7
8
/* -------------------------------------------------------------------------- *
 *                                   OpenMM                                   *
 * -------------------------------------------------------------------------- *
 * This is part of the OpenMM molecular simulation toolkit originating from   *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org.               *
 *                                                                            *
9
 * Portions copyright (c) 2008-2016 Stanford University and the Authors.      *
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 * Authors: Peter Eastman                                                     *
 * Contributors:                                                              *
 *                                                                            *
 * Permission is hereby granted, free of charge, to any person obtaining a    *
 * copy of this software and associated documentation files (the "Software"), *
 * to deal in the Software without restriction, including without limitation  *
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
 * and/or sell copies of the Software, and to permit persons to whom the      *
 * Software is furnished to do so, subject to the following conditions:       *
 *                                                                            *
 * The above copyright notice and this permission notice shall be included in *
 * all copies or substantial portions of the Software.                        *
 *                                                                            *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
 * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
 * -------------------------------------------------------------------------- */

32
33
#include "openmm/Context.h"
#include "openmm/internal/ContextImpl.h"
34
#include "openmm/OpenMMException.h"
35
#include "openmm/internal/ForceImpl.h"
36
#include <cmath>
37
38
#include <iostream>
#include <sstream>
39
40
41
42

using namespace OpenMM;
using namespace std;

43
44
45
46
47
48
Context::Context(const System& system, Integrator& integrator, ContextImpl& linked) : properties(linked.getOwner().properties) {
    // This is used by ContextImpl::createLinkedContext().
    impl = new ContextImpl(*this, system, integrator, &linked.getPlatform(), properties, &linked);
    impl->initialize();
}

49
Context::Context(const System& system, Integrator& integrator) : properties(map<string, string>()) {
50
    impl = new ContextImpl(*this, system, integrator, 0, properties);
51
    impl->initialize();
52
53
}

54
Context::Context(const System& system, Integrator& integrator, Platform& platform) : properties(map<string, string>()) {
55
    impl = new ContextImpl(*this, system, integrator, &platform, properties);
56
    impl->initialize();
57
58
}

59
Context::Context(const System& system, Integrator& integrator, Platform& platform, const map<string, string>& properties) : properties(properties) {
60
    impl = new ContextImpl(*this, system, integrator, &platform, properties);
61
    impl->initialize();
62
63
}

64
Context::~Context() {
Lee-Ping's avatar
Lee-Ping committed
65
    delete impl;
66
67
}

68
const System& Context::getSystem() const {
69
70
71
72
    return impl->getSystem();

}

73
const Integrator& Context::getIntegrator() const {
74
75
76
    return impl->getIntegrator();
}

77
Integrator& Context::getIntegrator() {
78
    return impl->getIntegrator();
79
80
}

81
const Platform& Context::getPlatform() const {
82
83
    return impl->getPlatform();
}
84

85
Platform& Context::getPlatform() {
86
    return impl->getPlatform();
87
88
}

89
State Context::getState(int types, bool enforcePeriodicBox, int groups) const {
90
    State::StateBuilder builder(impl->getTime());
91
92
    Vec3 periodicBoxSize[3];
    impl->getPeriodicBoxVectors(periodicBoxSize[0], periodicBoxSize[1], periodicBoxSize[2]);
93
    builder.setPeriodicBoxVectors(periodicBoxSize[0], periodicBoxSize[1], periodicBoxSize[2]);
94
95
    bool includeForces = types&State::Forces;
    bool includeEnergy = types&State::Energy;
96
    bool includeParameterDerivs = types&State::ParameterDerivatives;
97
    bool needForcesForEnergy = (includeEnergy && getIntegrator().kineticEnergyRequiresForce());
98
    if (includeForces || includeEnergy || includeParameterDerivs) {
99
        double energy = impl->calcForcesAndEnergy(includeForces || needForcesForEnergy || includeParameterDerivs, includeEnergy, groups);
100
        if (includeEnergy)
101
102
103
104
105
106
            builder.setEnergy(impl->calcKineticEnergy(), energy);
        if (includeForces) {
            vector<Vec3> forces;
            impl->getForces(forces);
            builder.setForces(forces);
        }
107
    }
108
    if (types&State::Parameters) {
109
        map<string, double> params;
peastman's avatar
peastman committed
110
111
        for (auto& param : impl->parameters)
            params[param.first] = param.second;
112
        builder.setParameters(params);
113
    }
114
115
116
117
118
    if (types&State::ParameterDerivatives) {
        map<string, double> derivs;
        impl->getEnergyParameterDerivatives(derivs);
        builder.setEnergyParameterDerivatives(derivs);
    }
119
    if (types&State::Positions) {
120
121
        vector<Vec3> positions;
        impl->getPositions(positions);
122
123
        if (enforcePeriodicBox) {
            const vector<vector<int> >& molecules = impl->getMolecules();
peastman's avatar
peastman committed
124
            for (auto& mol : molecules) {
125
126
127
                // Find the molecule center.

                Vec3 center;
peastman's avatar
peastman committed
128
129
130
                for (int j : mol)
                    center += positions[j];
                center *= 1.0/mol.size();
131
132

                // Find the displacement to move it into the first periodic box.
133
                Vec3 diff;
134
135
136
                diff += periodicBoxSize[2]*floor(center[2]/periodicBoxSize[2][2]);
                diff += periodicBoxSize[1]*floor((center[1]-diff[1])/periodicBoxSize[1][1]);
                diff += periodicBoxSize[0]*floor((center[0]-diff[0])/periodicBoxSize[0][0]);
137
138

                // Translate all the particles in the molecule.
peastman's avatar
peastman committed
139
140
                for (int j : mol)
                    positions[j] -= diff;
141
142
            }
        }
143
144
145
146
147
148
        builder.setPositions(positions);
    }
    if (types&State::Velocities) {
        vector<Vec3> velocities;
        impl->getVelocities(velocities);
        builder.setVelocities(velocities);
149
    }
150
    return builder.getState();
151
152
}

Peter Eastman's avatar
Peter Eastman committed
153
154
155
156
157
void Context::setState(const State& state) {
    setTime(state.getTime());
    Vec3 a, b, c;
    state.getPeriodicBoxVectors(a, b, c);
    setPeriodicBoxVectors(a, b, c);
peastman's avatar
peastman committed
158
    if ((state.getDataTypes()&State::Positions) != 0)
Peter Eastman's avatar
Peter Eastman committed
159
        setPositions(state.getPositions());
peastman's avatar
peastman committed
160
    if ((state.getDataTypes()&State::Velocities) != 0)
Peter Eastman's avatar
Peter Eastman committed
161
        setVelocities(state.getVelocities());
peastman's avatar
peastman committed
162
    if ((state.getDataTypes()&State::Parameters) != 0)
peastman's avatar
peastman committed
163
164
        for (auto& param : state.getParameters())
            setParameter(param.first, param.second);
Peter Eastman's avatar
Peter Eastman committed
165
166
}

167
void Context::setTime(double time) {
168
169
170
    impl->setTime(time);
}

171
void Context::setPositions(const vector<Vec3>& positions) {
Peter Eastman's avatar
Peter Eastman committed
172
    if ((int) positions.size() != impl->getSystem().getNumParticles())
173
        throw OpenMMException("Called setPositions() on a Context with the wrong number of positions");
174
    impl->setPositions(positions);
175
176
}

177
void Context::setVelocities(const vector<Vec3>& velocities) {
Peter Eastman's avatar
Peter Eastman committed
178
    if ((int) velocities.size() != impl->getSystem().getNumParticles())
179
        throw OpenMMException("Called setVelocities() on a Context with the wrong number of velocities");
180
    impl->setVelocities(velocities);
181
182
}

183
void Context::setVelocitiesToTemperature(double temperature, int randomSeed) {
184
    const Integrator& integrator = impl->getIntegrator();
185
    const System& system = impl->getSystem();
186
    setVelocities(integrator.getVelocitiesForTemperature(system, temperature, randomSeed));
187
188
189
    impl->applyVelocityConstraints(1e-5);
}

Peter Eastman's avatar
Peter Eastman committed
190
191
192
193
const map<string, double>& Context::getParameters() const {
    return impl->getParameters();
}

194
double Context::getParameter(const string& name) const {
195
196
197
    return impl->getParameter(name);
}

198
void Context::setParameter(const string& name, double value) {
199
200
201
    impl->setParameter(name, value);
}

202
203
void Context::setPeriodicBoxVectors(const Vec3& a, const Vec3& b, const Vec3& c) {
    impl->setPeriodicBoxVectors(a, b, c);
204
205
}

206
207
208
209
void Context::applyConstraints(double tol) {
    impl->applyConstraints(tol);
}

210
211
212
213
void Context::applyVelocityConstraints(double tol) {
    impl->applyVelocityConstraints(tol);
}

214
215
216
217
void Context::computeVirtualSites() {
    impl->computeVirtualSites();
}

218
void Context::reinitialize(bool preserveState) {
219
    const System& system = impl->getSystem();
220
221
    Integrator& integrator = impl->getIntegrator();
    Platform& platform = impl->getPlatform();
222
223
224
    stringstream checkpoint(ios_base::out | ios_base::in | ios_base::binary);
    if (preserveState)
        createCheckpoint(checkpoint);
225
    integrator.cleanup();
226
    delete impl;
227
    impl = new ContextImpl(*this, system, integrator, &platform, properties);
228
    impl->initialize();
229
230
    if (preserveState)
        loadCheckpoint(checkpoint);
231
}
Peter Eastman's avatar
Peter Eastman committed
232
233
234
235
236
237
238
239

void Context::createCheckpoint(ostream& stream) {
    impl->createCheckpoint(stream);
}

void Context::loadCheckpoint(istream& stream) {
    impl->loadCheckpoint(stream);
}
240
241
242
243

ContextImpl& Context::getImpl() {
    return *impl;
}
244

245
246
247
248
const ContextImpl& Context::getImpl() const {
    return *impl;
}

249
250
251
const vector<vector<int> >& Context::getMolecules() const {
    return impl->getMolecules();
}