TestReferenceAmoebaInPlaneAngleForce.cpp 16.2 KB
Newer Older
Mark Friedrichs's avatar
Mark Friedrichs committed
1
2
3
4
5
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
/* -------------------------------------------------------------------------- *
 *                                   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.               *
 *                                                                            *
 * Portions copyright (c) 2008 Stanford University and the Authors.           *
 * 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 ReferenceAmoebaInPlaneAngleForce.
Mark Friedrichs's avatar
Mark Friedrichs committed
34
35
 */

36
#include "openmm/internal/AssertionUtilities.h"
Mark Friedrichs's avatar
Mark Friedrichs committed
37
38
//#include "AmoebaTinkerParameterFile.h"
#include "openmm/Context.h"
39
#include "OpenMMAmoeba.h"
Mark Friedrichs's avatar
Mark Friedrichs committed
40
41
42
43
44
45
46
#include "openmm/System.h"
#include "openmm/LangevinIntegrator.h"
#include <iostream>
#include <vector>

using namespace OpenMM;

47
48
extern "C" OPENMM_EXPORT void registerAmoebaReferenceKernelFactories();

Mark Friedrichs's avatar
Mark Friedrichs committed
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
const double TOL = 1e-5;
#define PI_M               3.141592653589
#define RADIAN            57.29577951308

/* ---------------------------------------------------------------------------------------

   Compute cross product of two 3-vectors and place in 3rd vector

   vectorZ = vectorX x vectorY

   @param vectorX             x-vector
   @param vectorY             y-vector
   @param vectorZ             z-vector

   @return vector is vectorZ

   --------------------------------------------------------------------------------------- */
     
67
static void crossProductVector3(double* vectorX, double* vectorY, double* vectorZ) {
Mark Friedrichs's avatar
Mark Friedrichs committed
68
69
70
71
72
73
74
75

    vectorZ[0]  = vectorX[1]*vectorY[2] - vectorX[2]*vectorY[1];
    vectorZ[1]  = vectorX[2]*vectorY[0] - vectorX[0]*vectorY[2];
    vectorZ[2]  = vectorX[0]*vectorY[1] - vectorX[1]*vectorY[0];

    return;
}

76
static double dotVector3(double* vectorX, double* vectorY) {
Mark Friedrichs's avatar
Mark Friedrichs committed
77
78
79
    return vectorX[0]*vectorY[0] + vectorX[1]*vectorY[1] + vectorX[2]*vectorY[2];
}

80
81
82
static void getPrefactorsGivenInPlaneAngleCosine(double cosine, double idealInPlaneAngle, double quadraticK, double cubicK,
                                                 double quarticK, double penticK, double sexticK,
                                                 double* dEdR, double* energyTerm, FILE* log) {
Mark Friedrichs's avatar
Mark Friedrichs committed
83
84

    double angle;
85
    if (cosine >= 1.0) {
Mark Friedrichs's avatar
Mark Friedrichs committed
86
        angle = 0.0f;
Jason Swails's avatar
More  
Jason Swails committed
87
    }
88
    else if (cosine <= -1.0) {
Mark Friedrichs's avatar
Mark Friedrichs committed
89
        angle = RADIAN*PI_M;
Jason Swails's avatar
More  
Jason Swails committed
90
91
    }
    else {
Mark Friedrichs's avatar
Mark Friedrichs committed
92
93
        angle = RADIAN*acos(cosine);
    }
Mark Friedrichs's avatar
Mark Friedrichs committed
94
#ifdef AMOEBA_DEBUG
95
96
97
    if (log) {
        (void) fprintf(log, "getPrefactorsGivenInPlaneAngleCosine: cosine=%10.3e angle=%10.3e ideal=%10.3e\n", cosine, angle, idealInPlaneAngle); 
        (void) fflush(log);
Mark Friedrichs's avatar
Mark Friedrichs committed
98
    }
Mark Friedrichs's avatar
Mark Friedrichs committed
99
#endif
Mark Friedrichs's avatar
Mark Friedrichs committed
100
101
102
103
104
105
106
107

    double deltaIdeal         = angle - idealInPlaneAngle;
    double deltaIdeal2        = deltaIdeal*deltaIdeal;
    double deltaIdeal3        = deltaIdeal*deltaIdeal2;
    double deltaIdeal4        = deltaIdeal2*deltaIdeal2;
 
    // deltaIdeal = r - r_0
 
108
    *dEdR        = (2.0                        +
Mark Friedrichs's avatar
Mark Friedrichs committed
109
110
111
                     3.0*cubicK*  deltaIdeal    +
                     4.0*quarticK*deltaIdeal2   +
                     5.0*penticK* deltaIdeal3   +
112
                     6.0*sexticK* deltaIdeal4    );
Mark Friedrichs's avatar
Mark Friedrichs committed
113
114
115
116
117
118
119
120
121
122
123
124
125
 
    *dEdR       *= RADIAN*quadraticK*deltaIdeal;
 

    *energyTerm  = 1.0f + cubicK* deltaIdeal    +
                          quarticK*deltaIdeal2   +
                          penticK* deltaIdeal3   +
                          sexticK* deltaIdeal4;
    *energyTerm *= quadraticK*deltaIdeal2;

    return;
}

126
static void computeAmoebaInPlaneAngleForce(int bondIndex,  std::vector<Vec3>& positions, AmoebaInPlaneAngleForce& AmoebaInPlaneAngleForce,
127
                                                   std::vector<Vec3>& forces, double* energy, FILE* log) {
Mark Friedrichs's avatar
Mark Friedrichs committed
128
129
130
131

    int particle1, particle2, particle3, particle4;
    double idealInPlaneAngle;
    double quadraticK;
132
    AmoebaInPlaneAngleForce.getAngleParameters(bondIndex, particle1, particle2, particle3, particle4, idealInPlaneAngle, quadraticK);
Mark Friedrichs's avatar
Mark Friedrichs committed
133

134
135
136
137
    double cubicK         = AmoebaInPlaneAngleForce.getAmoebaGlobalInPlaneAngleCubic();
    double quarticK       = AmoebaInPlaneAngleForce.getAmoebaGlobalInPlaneAngleQuartic();
    double penticK        = AmoebaInPlaneAngleForce.getAmoebaGlobalInPlaneAnglePentic();
    double sexticK        = AmoebaInPlaneAngleForce.getAmoebaGlobalInPlaneAngleSextic();
Mark Friedrichs's avatar
Mark Friedrichs committed
138
#ifdef AMOEBA_DEBUG
139
140
141
142
    if (log) {
        (void) fprintf(log, "computeAmoebaInPlaneAngleForce: bond %d [%d %d %d %d] ang=%10.3f k=%10.3f [%10.3e %10.3e %10.3e %10.3e]\n", 
                             bondIndex, particle1, particle2, particle3, particle4, idealInPlaneAngle, quadraticK, cubicK, quarticK, penticK, sexticK);
        (void) fflush(log);
Mark Friedrichs's avatar
Mark Friedrichs committed
143
    }
Mark Friedrichs's avatar
Mark Friedrichs committed
144
#endif
Mark Friedrichs's avatar
Mark Friedrichs committed
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

    // T   = AD x CD
    // P   = B + T*delta
    // AP  = A - P
    // CP  = A - P
    // M   = CP x AP

    enum { AD, BD, CD, T, AP, P, CP, M, APxM, CPxM, ADxBD, BDxCD, TxCD, ADxT, dBxAD, CDxdB, LastDeltaAtomIndex };
 
    // AD   0
    // BD   1
    // CD   2 
    //  T   3
    // AP   4
    //  P   5
    // CP   6
    // M    7
    // APxM, CPxM, ADxBD, BDxCD, TxCD, ADxT, dBxAD, CDxdB, LastDeltaAtomIndex

    double deltaR[LastDeltaAtomIndex][3];
165
    for (int ii = 0; ii < 3; ii++) {
Mark Friedrichs's avatar
Mark Friedrichs committed
166
167
168
169
        deltaR[AD][ii] = positions[particle1][ii] - positions[particle4][ii];
        deltaR[BD][ii] = positions[particle2][ii] - positions[particle4][ii];
        deltaR[CD][ii] = positions[particle3][ii] - positions[particle4][ii];
    }
170
    crossProductVector3(deltaR[AD], deltaR[CD], deltaR[T]);
Mark Friedrichs's avatar
Mark Friedrichs committed
171
 
172
173
    double rT2     = dotVector3(deltaR[T], deltaR[T]);
    double delta   = dotVector3(deltaR[T], deltaR[BD]);
Mark Friedrichs's avatar
Mark Friedrichs committed
174
175
         delta    *= -1.0/rT2;
 
176
    for (int ii = 0; ii < 3; ii++) {
Mark Friedrichs's avatar
Mark Friedrichs committed
177
178
179
       deltaR[P][ii]  = positions[particle2][ii] + deltaR[T][ii]*delta;
       deltaR[AP][ii] = positions[particle1][ii] - deltaR[P][ii];
       deltaR[CP][ii] = positions[particle3][ii] - deltaR[P][ii];
Jason Swails's avatar
More  
Jason Swails committed
180
    }
Mark Friedrichs's avatar
Mark Friedrichs committed
181
 
182
183
184
    double rAp2 = dotVector3(deltaR[AP],  deltaR[AP]);
    double rCp2 = dotVector3(deltaR[CP],  deltaR[CP]);
    if (rAp2 <= 0.0 && rCp2 <= 0.0) {
Mark Friedrichs's avatar
Mark Friedrichs committed
185
#ifdef AMOEBA_DEBUG
186
187
188
        if (log) {
            (void) fprintf(log, "computeAmoebaInPlaneAngleForce:  rAp2 or rCp2 <= 0.0\n");
            (void) fflush(log);
Mark Friedrichs's avatar
Mark Friedrichs committed
189
        }
Mark Friedrichs's avatar
Mark Friedrichs committed
190
#endif
Mark Friedrichs's avatar
Mark Friedrichs committed
191
192
193
        return;
    }

194
    crossProductVector3(deltaR[CP], deltaR[AP], deltaR[M]);
Mark Friedrichs's avatar
Mark Friedrichs committed
195
 
196
197
198
    double rm = dotVector3(deltaR[M], deltaR[M]);
         rm   = sqrt(rm);
    if (rm < 0.000001) {
Mark Friedrichs's avatar
Mark Friedrichs committed
199
200
201
       rm = 0.000001;
    }
 
202
203
    double dot     = dotVector3(deltaR[AP], deltaR[CP]);
    double cosine  = dot/sqrt(rAp2*rCp2);
Mark Friedrichs's avatar
Mark Friedrichs committed
204
205
206
 
    double dEdR;
    double energyTerm;
207
208
    getPrefactorsGivenInPlaneAngleCosine(cosine, idealInPlaneAngle, quadraticK, cubicK,
                                         quarticK, penticK, sexticK, &dEdR,  &energyTerm, log);
Mark Friedrichs's avatar
Mark Friedrichs committed
209
210
211
212
 
    double termA   = -dEdR/(rAp2*rm);
    double termC   =  dEdR/(rCp2*rm);
 
213
214
    crossProductVector3(deltaR[AP], deltaR[M], deltaR[APxM]);
    crossProductVector3(deltaR[CP], deltaR[M], deltaR[CPxM]);
Mark Friedrichs's avatar
Mark Friedrichs committed
215
216
217
218
219
220
 
    // forces will be gathered here
 
    enum { dA, dB, dC, dD, LastDIndex };
    double forceTerm[LastDIndex][3];
 
221
    for (int ii = 0; ii < 3; ii++) {
Mark Friedrichs's avatar
Mark Friedrichs committed
222
223
       forceTerm[dA][ii] = deltaR[APxM][ii]*termA;
       forceTerm[dC][ii] = deltaR[CPxM][ii]*termC;
224
       forceTerm[dB][ii] = -1.0*(forceTerm[dA][ii] + forceTerm[dC][ii]);
Mark Friedrichs's avatar
Mark Friedrichs committed
225
226
    }
 
227
    double pTrT2  = dotVector3(forceTerm[dB], deltaR[T]);
Mark Friedrichs's avatar
Mark Friedrichs committed
228
229
         pTrT2   /= rT2;
 
230
231
    crossProductVector3(deltaR[CD], forceTerm[dB], deltaR[CDxdB]);
    crossProductVector3(forceTerm[dB], deltaR[AD], deltaR[dBxAD]);
Mark Friedrichs's avatar
Mark Friedrichs committed
232
 
233
    if (fabs(pTrT2) > 1.0e-08) {
Mark Friedrichs's avatar
Mark Friedrichs committed
234
235
       double delta2 = delta*2.0;
 
236
237
238
239
240
       crossProductVector3(deltaR[BD], deltaR[CD], deltaR[BDxCD]);
       crossProductVector3(deltaR[T],  deltaR[CD], deltaR[TxCD] );
       crossProductVector3(deltaR[AD], deltaR[BD], deltaR[ADxBD]);
       crossProductVector3(deltaR[AD], deltaR[T],  deltaR[ADxT] );
       for (int ii = 0; ii < 3; ii++) {
Mark Friedrichs's avatar
Mark Friedrichs committed
241
242
243
244
245
246
247
 
          double term           = deltaR[BDxCD][ii] + delta2*deltaR[TxCD][ii];
          forceTerm[dA][ii]  += delta*deltaR[CDxdB][ii] + term*pTrT2;
 
               term           = deltaR[ADxBD][ii] + delta2*deltaR[ADxT][ii];
          forceTerm[dC][ii]  += delta*deltaR[dBxAD][ii] + term*pTrT2;
 
248
          forceTerm[dD][ii]  = -(forceTerm[dA][ii] + forceTerm[dB][ii] + forceTerm[dC][ii]);
Mark Friedrichs's avatar
Mark Friedrichs committed
249
       }
Jason Swails's avatar
More  
Jason Swails committed
250
251
    }
    else {
252
       for (int ii = 0; ii < 3; ii++) {
Mark Friedrichs's avatar
Mark Friedrichs committed
253
254
255
256
 
          forceTerm[dA][ii] += delta*deltaR[CDxdB][ii];
          forceTerm[dC][ii] += delta*deltaR[dBxAD][ii];
 
257
          forceTerm[dD][ii]  = -(forceTerm[dA][ii] + forceTerm[dB][ii] + forceTerm[dC][ii]);
Mark Friedrichs's avatar
Mark Friedrichs committed
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
       }
    }
 
    // accumulate forces and energy
 
    *energy                    += energyTerm;
 
    forces[particle1][0]       -= forceTerm[0][0];
    forces[particle1][1]       -= forceTerm[0][1];
    forces[particle1][2]       -= forceTerm[0][2];

    forces[particle2][0]       -= forceTerm[1][0];
    forces[particle2][1]       -= forceTerm[1][1];
    forces[particle2][2]       -= forceTerm[1][2];

    forces[particle3][0]       -= forceTerm[2][0];
    forces[particle3][1]       -= forceTerm[2][1];
    forces[particle3][2]       -= forceTerm[2][2];

    forces[particle4][0]       -= forceTerm[3][0];
    forces[particle4][1]       -= forceTerm[3][1];
    forces[particle4][2]       -= forceTerm[3][2];

}

283
284
static void computeAmoebaInPlaneAngleForces(Context& context, AmoebaInPlaneAngleForce& AmoebaInPlaneAngleForce,
                                                     std::vector<Vec3>& expectedForces, double* expectedEnergy, FILE* log) {
Mark Friedrichs's avatar
Mark Friedrichs committed
285
286
287
288
289

    // get positions and zero forces

    State state                 = context.getState(State::Positions);
    std::vector<Vec3> positions = state.getPositions();
290
    expectedForces.resize(positions.size());
Mark Friedrichs's avatar
Mark Friedrichs committed
291
    
292
    for (unsigned int ii = 0; ii < expectedForces.size(); ii++) {
Mark Friedrichs's avatar
Mark Friedrichs committed
293
294
295
296
297
298
        expectedForces[ii][0] = expectedForces[ii][1] = expectedForces[ii][2] = 0.0;
    }

    // calculates forces/energy

    *expectedEnergy = 0.0;
299
300
    for (int ii = 0; ii < AmoebaInPlaneAngleForce.getNumAngles(); ii++) {
        computeAmoebaInPlaneAngleForce(ii, positions, AmoebaInPlaneAngleForce, expectedForces, expectedEnergy, log);
Mark Friedrichs's avatar
Mark Friedrichs committed
301
    }
Mark Friedrichs's avatar
Mark Friedrichs committed
302
#ifdef AMOEBA_DEBUG
303
304
305
306
    if (log) {
        (void) fprintf(log, "computeAmoebaInPlaneAngleForces: expected energy=%14.7e\n", *expectedEnergy);
        for (unsigned int ii = 0; ii < positions.size(); ii++) {
            (void) fprintf(log, "%6u [%14.7e %14.7e %14.7e]\n", ii, expectedForces[ii][0], expectedForces[ii][1], expectedForces[ii][2]);
Mark Friedrichs's avatar
Mark Friedrichs committed
307
        }
308
        (void) fflush(log);
Mark Friedrichs's avatar
Mark Friedrichs committed
309
    }
Mark Friedrichs's avatar
Mark Friedrichs committed
310
#endif
Mark Friedrichs's avatar
Mark Friedrichs committed
311
312
313
314
    return;

}

315
316
void compareWithExpectedForceAndEnergy(Context& context, AmoebaInPlaneAngleForce& AmoebaInPlaneAngleForce,
                                       double tolerance, const std::string& idString, FILE* log) {
Mark Friedrichs's avatar
Mark Friedrichs committed
317
318
319

    std::vector<Vec3> expectedForces;
    double expectedEnergy;
320
    computeAmoebaInPlaneAngleForces(context, AmoebaInPlaneAngleForce, expectedForces, &expectedEnergy, log);
Mark Friedrichs's avatar
Mark Friedrichs committed
321
322
323
   
    State state                      = context.getState(State::Forces | State::Energy);
    const std::vector<Vec3> forces   = state.getForces();
Mark Friedrichs's avatar
Mark Friedrichs committed
324
#ifdef AMOEBA_DEBUG
325
326
327
328
329
    if (log) {
        (void) fprintf(log, "computeAmoebaInPlaneAngleForces: expected energy=%14.7e %14.7e\n", expectedEnergy, state.getPotentialEnergy());
        for (unsigned int ii = 0; ii < forces.size(); ii++) {
            (void) fprintf(log, "%6u [%14.7e %14.7e %14.7e]   [%14.7e %14.7e %14.7e]\n", ii,
                            expectedForces[ii][0], expectedForces[ii][1], expectedForces[ii][2], forces[ii][0], forces[ii][1], forces[ii][2]);
Mark Friedrichs's avatar
Mark Friedrichs committed
330
        }
331
        (void) fflush(log);
Mark Friedrichs's avatar
Mark Friedrichs committed
332
    }
Mark Friedrichs's avatar
Mark Friedrichs committed
333
#endif
Mark Friedrichs's avatar
Mark Friedrichs committed
334

335
336
    for (unsigned int ii = 0; ii < forces.size(); ii++) {
        ASSERT_EQUAL_VEC(expectedForces[ii], forces[ii], tolerance);
Mark Friedrichs's avatar
Mark Friedrichs committed
337
    }
338
    ASSERT_EQUAL_TOL(expectedEnergy, state.getPotentialEnergy(), tolerance);
Mark Friedrichs's avatar
Mark Friedrichs committed
339
340
}

341
void testOneAngle(FILE* log) {
Mark Friedrichs's avatar
Mark Friedrichs committed
342
343
344

    System system;
    int numberOfParticles = 4;
345
    for (int ii = 0; ii < numberOfParticles; ii++) {
Mark Friedrichs's avatar
Mark Friedrichs committed
346
347
348
349
350
        system.addParticle(1.0);
    }

    LangevinIntegrator integrator(0.0, 0.1, 0.01);

351
    AmoebaInPlaneAngleForce* amoebaInPlaneAngleForce = new AmoebaInPlaneAngleForce();
Mark Friedrichs's avatar
Mark Friedrichs committed
352
353
354
355
356
357
358

    double angle      = 65.0;
    double quadraticK = 1.0;
    double cubicK     = 0.0e-01;
    double quarticK   = 0.0e-02;
    double penticK    = 0.0e-03;
    double sexticK    = 0.0e-04;
359
    amoebaInPlaneAngleForce->addAngle(0, 1, 2, 3, angle, quadraticK);
Mark Friedrichs's avatar
Mark Friedrichs committed
360

361
362
363
364
    amoebaInPlaneAngleForce->setAmoebaGlobalInPlaneAngleCubic(cubicK);
    amoebaInPlaneAngleForce->setAmoebaGlobalInPlaneAngleQuartic(quarticK);
    amoebaInPlaneAngleForce->setAmoebaGlobalInPlaneAnglePentic(penticK);
    amoebaInPlaneAngleForce->setAmoebaGlobalInPlaneAngleSextic(sexticK);
Mark Friedrichs's avatar
Mark Friedrichs committed
365

366
    system.addForce(amoebaInPlaneAngleForce);
367
368
    ASSERT(!amoebaInPlaneAngleForce->usesPeriodicBoundaryConditions());
    ASSERT(!system.usesPeriodicBoundaryConditions());
369
    Context context(system, integrator, Platform::getPlatformByName("Reference"));
Mark Friedrichs's avatar
Mark Friedrichs committed
370
371
372
373
374
375
376
377
378

    std::vector<Vec3> positions(numberOfParticles);

    positions[0] = Vec3(0, 1, 0);
    positions[1] = Vec3(0, 0, 0);
    positions[2] = Vec3(0, 0, 1);
    positions[3] = Vec3(1, 1, 1);

    context.setPositions(positions);
379
    compareWithExpectedForceAndEnergy(context, *amoebaInPlaneAngleForce, TOL, "testOneInPlaneAngle", log);
380
381
382
383
384
385
386
    
    // Try changing the angle parameters and make sure it's still correct.
    
    amoebaInPlaneAngleForce->setAngleParameters(0, 0, 1, 2, 3, 1.1*angle, 1.4*quadraticK);
    bool exceptionThrown = false;
    try {
        // This should throw an exception.
387
        compareWithExpectedForceAndEnergy(context, *amoebaInPlaneAngleForce, TOL, "testOneInPlaneAngle", log);
388
389
390
391
392
393
    }
    catch (std::exception ex) {
        exceptionThrown = true;
    }
    ASSERT(exceptionThrown);
    amoebaInPlaneAngleForce->updateParametersInContext(context);
394
    compareWithExpectedForceAndEnergy(context, *amoebaInPlaneAngleForce, TOL, "testOneInPlaneAngle", log);
Mark Friedrichs's avatar
Mark Friedrichs committed
395
396
}

397
int main(int numberOfArguments, char* argv[]) {
Mark Friedrichs's avatar
Mark Friedrichs committed
398
399

    try {
400
        std::cout << "TestReferenceAmoebaInPlaneAngleForce running test..." << std::endl;
401
        registerAmoebaReferenceKernelFactories();
Mark Friedrichs's avatar
Mark Friedrichs committed
402
403
        FILE* log = NULL;
        //FILE* log = stderr;
404
        //FILE* log = fopen("AmoebaInPlaneAngleForce.log", "w");;
Mark Friedrichs's avatar
Mark Friedrichs committed
405

406
        testOneAngle(NULL);
Mark Friedrichs's avatar
Mark Friedrichs committed
407
#ifdef AMOEBA_DEBUG
408
409
        if (log && log != stderr)
            (void) fclose(log);
Mark Friedrichs's avatar
Mark Friedrichs committed
410
#endif
Mark Friedrichs's avatar
Mark Friedrichs committed
411
412
413
414
415
416
417

    }
    catch(const std::exception& e) {
        std::cout << "exception: " << e.what() << std::endl;
        std::cout << "FAIL - ERROR.  Test failed." << std::endl;
        return 1;
    }
418
419
    //std::cout << "PASS - Test succeeded." << std::endl;
    std::cout << "Done" << std::endl;
Mark Friedrichs's avatar
Mark Friedrichs committed
420
421
    return 0;
}