"platforms/opencl/tests/TestOpenCLRMSDForce.cpp" did not exist on "099b8e55d6548b4199d7ab82b08325317dfb7e5b"
ReferenceCMAPTorsionIxn.cpp 8.66 KB
Newer Older
1

2
/* Portions copyright (c) 2010-2016 Stanford University and Simbios.
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
 * Contributors: Peter Eastman
 *
 * 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.
 */

#include "ReferenceCMAPTorsionIxn.h"
#include "ReferenceForce.h"

using std::vector;
29
using namespace OpenMM;
30
31
32
33
34
35
36

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

   Constructor

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

peastman's avatar
peastman committed
37
ReferenceCMAPTorsionIxn::ReferenceCMAPTorsionIxn(const vector<vector<vector<double> > >& coeff,
38
        const vector<int>& torsionMaps, const vector<vector<int> >& torsionIndices) :
39
40
41
        coeff(coeff), torsionMaps(torsionMaps), torsionIndices(torsionIndices), usePeriodic(false) {
}

peastman's avatar
peastman committed
42
void ReferenceCMAPTorsionIxn::setPeriodic(OpenMM::Vec3* vectors) {
43
44
45
46
    usePeriodic = true;
    boxVectors[0] = vectors[0];
    boxVectors[1] = vectors[1];
    boxVectors[2] = vectors[2];
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
}

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

   Calculate torsion interaction

   @param atomIndices      bond indices
   @param atomCoordinates  atom coordinates
   @param parameters       parameters
   @param forces           force array (forces added)
   @param energyByBond     bond energy
   @param energy           atom energy

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

peastman's avatar
peastman committed
62
void ReferenceCMAPTorsionIxn::calculateIxn(vector<Vec3>& atomCoordinates, vector<Vec3>& forces, double* totalEnergy) const {
Christopher Bruns's avatar
Christopher Bruns committed
63
    for (unsigned int i = 0; i < torsionMaps.size(); i++)
64
65
66
67
68
69
70
71
72
73
74
75
76
77
        calculateOneIxn(i, atomCoordinates, forces, totalEnergy);
}

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

   Calculate the interaction due to a single torsion pair

   @param index            the index of the torsion
   @param atomCoordinates  atom coordinates
   @param forces           force array (forces added)
   @param totalEnergy      total energy

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

peastman's avatar
peastman committed
78
79
void ReferenceCMAPTorsionIxn::calculateOneIxn(int index, vector<Vec3>& atomCoordinates, vector<Vec3>& forces,
                     double* totalEnergy) const {
80
81
82
83
84
85
86
87
88
89
90
91
    int map = torsionMaps[index];
    int a1 = torsionIndices[index][0];
    int a2 = torsionIndices[index][1];
    int a3 = torsionIndices[index][2];
    int a4 = torsionIndices[index][3];
    int b1 = torsionIndices[index][4];
    int b2 = torsionIndices[index][5];
    int b3 = torsionIndices[index][6];
    int b4 = torsionIndices[index][7];

    // Compute deltas between the various atoms involved.

peastman's avatar
peastman committed
92
93
    double deltaA[3][ReferenceForce::LastDeltaRIndex];
    double deltaB[3][ReferenceForce::LastDeltaRIndex];
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
    if (usePeriodic) {
        ReferenceForce::getDeltaRPeriodic(atomCoordinates[a2], atomCoordinates[a1], boxVectors, deltaA[0]);
        ReferenceForce::getDeltaRPeriodic(atomCoordinates[a2], atomCoordinates[a3], boxVectors, deltaA[1]);
        ReferenceForce::getDeltaRPeriodic(atomCoordinates[a4], atomCoordinates[a3], boxVectors, deltaA[2]);
        ReferenceForce::getDeltaRPeriodic(atomCoordinates[b2], atomCoordinates[b1], boxVectors, deltaB[0]);
        ReferenceForce::getDeltaRPeriodic(atomCoordinates[b2], atomCoordinates[b3], boxVectors, deltaB[1]);
        ReferenceForce::getDeltaRPeriodic(atomCoordinates[b4], atomCoordinates[b3], boxVectors, deltaB[2]);
    }
    else {
        ReferenceForce::getDeltaR(atomCoordinates[a2], atomCoordinates[a1], deltaA[0]);
        ReferenceForce::getDeltaR(atomCoordinates[a2], atomCoordinates[a3], deltaA[1]);
        ReferenceForce::getDeltaR(atomCoordinates[a4], atomCoordinates[a3], deltaA[2]);
        ReferenceForce::getDeltaR(atomCoordinates[b2], atomCoordinates[b1], deltaB[0]);
        ReferenceForce::getDeltaR(atomCoordinates[b2], atomCoordinates[b3], deltaB[1]);
        ReferenceForce::getDeltaR(atomCoordinates[b4], atomCoordinates[b3], deltaB[2]);
    }
110
111
112

    // Visual Studio complains if crossProduct declared as 'crossProduct[2][3]'

peastman's avatar
peastman committed
113
114
    double crossProductMemory[12];
    double* cpA[2];
115
116
    cpA[0] = crossProductMemory;
    cpA[1] = crossProductMemory + 3;
peastman's avatar
peastman committed
117
    double* cpB[2];
118
119
120
121
122
    cpB[0] = crossProductMemory + 6;
    cpB[1] = crossProductMemory + 9;

   // Compute the dihedral angles.

peastman's avatar
peastman committed
123
124
125
    double dotDihedral;
    double signOfAngle;
    double angleA =  getDihedralAngleBetweenThreeVectors(deltaA[0], deltaA[1], deltaA[2],
126
         cpA, &dotDihedral, deltaA[0], &signOfAngle, 1);
peastman's avatar
peastman committed
127
    double angleB =  getDihedralAngleBetweenThreeVectors(deltaB[0], deltaB[1], deltaB[2],
128
129
130
131
132
133
         cpB, &dotDihedral, deltaB[0], &signOfAngle, 1);
    angleA = fmod(angleA+2.0*M_PI, 2.0*M_PI);
    angleB = fmod(angleB+2.0*M_PI, 2.0*M_PI);

    // Identify which patch this is in.

peastman's avatar
peastman committed
134
135
    int size = (int) sqrt(coeff[map].size());
    double delta = 2*M_PI/size;
136
137
    int s = (int) (angleA/delta);
    int t = (int) (angleB/delta);
peastman's avatar
peastman committed
138
139
140
    const vector<double>& c = coeff[map][s+size*t];
    double da = angleA/delta-s;
    double db = angleB/delta-t;
141
142
143

    // Evaluate the spline to determine the energy and gradients.

peastman's avatar
peastman committed
144
145
146
    double energy = 0;
    double dEdA = 0;
    double dEdB = 0;
147
148
149
150
151
152
153
154
155
156
157
158
    for (int i = 3; i >= 0; i--) {
        energy = da*energy + ((c[i*4+3]*db + c[i*4+2])*db + c[i*4+1])*db + c[i*4+0];
        dEdA = db*dEdA + (3.0*c[i+3*4]*da + 2.0*c[i+2*4])*da + c[i+1*4];
        dEdB = da*dEdB + (3.0*c[i*4+3]*db + 2.0*c[i*4+2])*db + c[i*4+1];
    }
    dEdA /= delta;
    dEdB /= delta;
    if (totalEnergy != NULL)
        *totalEnergy += energy;

    // Apply the force to the first torsion.

peastman's avatar
peastman committed
159
160
161
    double forceFactors[4];
    double normCross1 = DOT3(cpA[0], cpA[0]);
    double normBC = deltaA[1][ReferenceForce::RIndex];
162
    forceFactors[0] = (-dEdA*normBC)/normCross1;
peastman's avatar
peastman committed
163
    double normCross2 = DOT3(cpA[1], cpA[1]);
164
165
166
167
168
169
    forceFactors[3] = (dEdA*normBC)/normCross2;
    forceFactors[1] = DOT3(deltaA[0], deltaA[1]);
    forceFactors[1] /= deltaA[1][ReferenceForce::R2Index];
    forceFactors[2] = DOT3(deltaA[2], deltaA[1]);
    forceFactors[2] /= deltaA[1][ReferenceForce::R2Index];
    for (int i = 0; i < 3; i++) {
peastman's avatar
peastman committed
170
171
172
        double f0 = forceFactors[0]*cpA[0][i];
        double f3 = forceFactors[3]*cpA[1][i];
        double s = forceFactors[1]*f0 - forceFactors[2]*f3;
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
        forces[a1][i] += f0;
        forces[a2][i] -= f0-s;
        forces[a3][i] -= f3+s;
        forces[a4][i] += f3;
    }

    // Apply the force to the second torsion.

    normCross1 = DOT3(cpB[0], cpB[0]);
    normBC = deltaB[1][ReferenceForce::RIndex];
    forceFactors[0] = (-dEdB*normBC)/normCross1;
    normCross2 = DOT3(cpB[1], cpB[1]);
    forceFactors[3] = (dEdB*normBC)/normCross2;
    forceFactors[1] = DOT3(deltaB[0], deltaB[1]);
    forceFactors[1] /= deltaB[1][ReferenceForce::R2Index];
    forceFactors[2] = DOT3(deltaB[2], deltaB[1]);
    forceFactors[2] /= deltaB[1][ReferenceForce::R2Index];
    for (int i = 0; i < 3; i++) {
peastman's avatar
peastman committed
191
192
193
        double f0 = forceFactors[0]*cpB[0][i];
        double f3 = forceFactors[3]*cpB[1][i];
        double s = forceFactors[1]*f0 - forceFactors[2]*f3;
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
        forces[b1][i] += f0;
        forces[b2][i] -= f0-s;
        forces[b3][i] -= f3+s;
        forces[b4][i] += f3;
    }
}

// ---------------------------------------------------------------------------------------

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

   This is present only because we must define it to subclass ReferenceBondIxn.  It is never called.

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

peastman's avatar
peastman committed
209
210
void ReferenceCMAPTorsionIxn::calculateBondIxn(int* atomIndices, vector<Vec3>& atomCoordinates,
        double* parameters, vector<Vec3>& forces, double* totalEnergy, double* energyParamDerivs) {
211
}