"platforms/vscode:/vscode.git/clone" did not exist on "2669ec5dee2838f9d988b68bd7c61957274384df"
TestReferenceCustomHbondForce.cpp 10.3 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-2012 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
32
 * 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.                                     *
 * -------------------------------------------------------------------------- */

/**
33
 * This tests the reference implementation of CustomHbondForce.
34
35
 */

36
#include "openmm/internal/AssertionUtilities.h"
37
38
39
40
41
42
43
44
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "openmm/CustomHbondForce.h"
#include "openmm/HarmonicAngleForce.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
45
#include "sfmt/SFMT.h"
46
47
48
49
50
51
#include <iostream>
#include <vector>

using namespace OpenMM;
using namespace std;

52
53
ReferencePlatform platform;

54
55
56
57
58
59
60
61
62
63
const double TOL = 1e-5;

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);
64
65
    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))");
66
67
68
69
70
71
72
73
74
75
76
77
78
    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;
79
    custom->addDonor(1, 0, -1, parameters);
80
81
82
    parameters.resize(2);
    parameters[0] = 2.1;
    parameters[1] = 2;
83
    custom->addAcceptor(2, 3, 4, parameters);
84
85
    custom->setCutoffDistance(10.0);
    customSystem.addForce(custom);
86
87
    ASSERT(!custom->usesPeriodicBoundaryConditions());
    ASSERT(!customSystem.usesPeriodicBoundaryConditions());
88
89
90
91
92
93
94
95

    // 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);
96
    standardSystem.addParticle(1.0);
97
98
99
100
101
102
103
104
    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();
105
    torsion->addTorsion(1, 2, 3, 4, 2, 2.1, 0.7);
106
107
108
109
    standardSystem.addForce(torsion);

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

110
111
112
    OpenMM_SFMT::SFMT sfmt;
    init_gen_rand(0, sfmt);

113
    vector<Vec3> positions(5);
114
115
116
117
    VerletIntegrator integrator1(0.01);
    VerletIntegrator integrator2(0.01);
    Context c1(customSystem, integrator1, platform);
    Context c2(standardSystem, integrator2, platform);
118
119
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < (int) positions.size(); j++)
120
            positions[j] = Vec3(2.0*genrand_real2(sfmt), 2.0*genrand_real2(sfmt), 2.0*genrand_real2(sfmt));
121
122
123
124
125
126
127
128
        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);
    }
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
    
    // 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);
151
152
153
154
155
156
157
158
}

void testExclusions() {
    System system;
    system.addParticle(1.0);
    system.addParticle(1.0);
    system.addParticle(1.0);
    VerletIntegrator integrator(0.01);
159
160
161
162
    CustomHbondForce* custom = new CustomHbondForce("(distance(d1,a1)-1)^2");
    custom->addDonor(0, 1, -1, vector<double>());
    custom->addDonor(1, 0, -1, vector<double>());
    custom->addAcceptor(2, 0, -1, vector<double>());
163
164
165
166
167
168
169
170
171
172
173
174
175
    custom->addExclusion(1, 0);
    system.addForce(custom);
    Context context(system, integrator, platform);
    vector<Vec3> positions(3);
    positions[0] = Vec3(0, 0, 0);
    positions[1] = Vec3(0, 2, 0);
    positions[2] = Vec3(2, 0, 0);
    context.setPositions(positions);
    State state = context.getState(State::Forces | State::Energy);
    const vector<Vec3>& forces = state.getForces();
    ASSERT_EQUAL_VEC(Vec3(2, 0, 0), forces[0], TOL);
    ASSERT_EQUAL_VEC(Vec3(0, 0, 0), forces[1], TOL);
    ASSERT_EQUAL_VEC(Vec3(-2, 0, 0), forces[2], TOL);
176
    ASSERT_EQUAL_TOL(1.0, state.getPotentialEnergy(), TOL);
177
178
179
180
181
182
183
184
}

void testCutoff() {
    System system;
    system.addParticle(1.0);
    system.addParticle(1.0);
    system.addParticle(1.0);
    VerletIntegrator integrator(0.01);
185
186
187
188
    CustomHbondForce* custom = new CustomHbondForce("(distance(d1,a1)-1)^2");
    custom->addDonor(0, 1, -1, vector<double>());
    custom->addDonor(1, 0, -1, vector<double>());
    custom->addAcceptor(2, 0, -1, vector<double>());
189
190
191
192
193
194
195
196
197
198
199
200
201
202
    custom->setNonbondedMethod(CustomHbondForce::CutoffNonPeriodic);
    custom->setCutoffDistance(2.5);
    system.addForce(custom);
    Context context(system, integrator, platform);
    vector<Vec3> positions(3);
    positions[0] = Vec3(0, 0, 0);
    positions[1] = Vec3(0, 3, 0);
    positions[2] = Vec3(2, 0, 0);
    context.setPositions(positions);
    State state = context.getState(State::Forces | State::Energy);
    const vector<Vec3>& forces = state.getForces();
    ASSERT_EQUAL_VEC(Vec3(2, 0, 0), forces[0], TOL);
    ASSERT_EQUAL_VEC(Vec3(0, 0, 0), forces[1], TOL);
    ASSERT_EQUAL_VEC(Vec3(-2, 0, 0), forces[2], TOL);
203
    ASSERT_EQUAL_TOL(1.0, state.getPotentialEnergy(), TOL);
204
205
}

206
207
208
209
210
211
212
213
214
215
216
217
218
void testCustomFunctions() {
    System system;
    system.addParticle(1.0);
    system.addParticle(1.0);
    system.addParticle(1.0);
    VerletIntegrator integrator(0.01);
    CustomHbondForce* custom = new CustomHbondForce("foo(distance(d1,a1))");
    custom->addDonor(1, 0, -1, vector<double>());
    custom->addDonor(2, 0, -1, vector<double>());
    custom->addAcceptor(0, 1, -1, vector<double>());
    vector<double> function(2);
    function[0] = 0;
    function[1] = 1;
219
    custom->addTabulatedFunction("foo", new Continuous1DFunction(function, 0, 10));
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
    system.addForce(custom);
    Context context(system, integrator, platform);
    vector<Vec3> positions(3);
    positions[0] = Vec3(0, 0, 0);
    positions[1] = Vec3(0, 2, 0);
    positions[2] = Vec3(2, 0, 0);
    context.setPositions(positions);
    State state = context.getState(State::Forces | State::Energy);
    const vector<Vec3>& forces = state.getForces();
    ASSERT_EQUAL_VEC(Vec3(0.1, 0.1, 0), forces[0], TOL);
    ASSERT_EQUAL_VEC(Vec3(0, -0.1, 0), forces[1], TOL);
    ASSERT_EQUAL_VEC(Vec3(-0.1, 0, 0), forces[2], TOL);
    ASSERT_EQUAL_TOL(0.1*2+0.1*2, state.getPotentialEnergy(), TOL);
}

235
236
237
238
239
int main() {
    try {
        testHbond();
        testExclusions();
        testCutoff();
240
        testCustomFunctions();
241
242
243
244
245
246
247
248
249
    }
    catch(const exception& e) {
        cout << "exception: " << e.what() << endl;
        return 1;
    }
    cout << "Done" << endl;
    return 0;
}