"wrappers/python/vscode:/vscode.git/clone" did not exist on "a1c0f18347b2264cdcd627b1664061589cfdb513"
ReferenceObc.cpp 18 KB
Newer Older
1

2
/* Portions copyright (c) 2006-2009 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
 * Contributors: Pande Group
 *
 * 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 <string.h>
26
#include <stdlib.h>
27
#include <sstream>
Mark Friedrichs's avatar
Mark Friedrichs committed
28
29
#include <cmath>
#include <cstdio>
30

31
#include "ReferenceForce.h"
32
#include "ReferenceObc.h"
33

34
35
36
using namespace OpenMM;
using namespace std;

37
38
/**---------------------------------------------------------------------------------------

39
    ReferenceObc constructor
40

Mark Friedrichs's avatar
Mark Friedrichs committed
41
42
43
    obcParameters      obcParameters object
    
    --------------------------------------------------------------------------------------- */
44

45
ReferenceObc::ReferenceObc(ObcParameters* obcParameters) : _obcParameters(obcParameters), _includeAceApproximation(1) {
Mark Friedrichs's avatar
Mark Friedrichs committed
46
47
    _obcChain.resize(_obcParameters->getNumberOfAtoms());
}
48

Mark Friedrichs's avatar
Mark Friedrichs committed
49
/**---------------------------------------------------------------------------------------
50

51
    ReferenceObc destructor
52

Mark Friedrichs's avatar
Mark Friedrichs committed
53
    --------------------------------------------------------------------------------------- */
54

55
ReferenceObc::~ReferenceObc() {
56
57
58
59
}

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

Mark Friedrichs's avatar
Mark Friedrichs committed
60
    Get ObcParameters reference
61

Mark Friedrichs's avatar
Mark Friedrichs committed
62
    @return ObcParameters reference
63

Mark Friedrichs's avatar
Mark Friedrichs committed
64
    --------------------------------------------------------------------------------------- */
65

66
ObcParameters* ReferenceObc::getObcParameters() const {
Mark Friedrichs's avatar
Mark Friedrichs committed
67
    return _obcParameters;
68
69
70
71
}

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

Mark Friedrichs's avatar
Mark Friedrichs committed
72
    Set ObcParameters reference
73

Mark Friedrichs's avatar
Mark Friedrichs committed
74
    @param ObcParameters reference
75

Mark Friedrichs's avatar
Mark Friedrichs committed
76
    --------------------------------------------------------------------------------------- */
77

78
void ReferenceObc::setObcParameters( ObcParameters* obcParameters) {
Mark Friedrichs's avatar
Mark Friedrichs committed
79
    _obcParameters = obcParameters;
80
81
82
83
}

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

Mark Friedrichs's avatar
Mark Friedrichs committed
84
   Return flag signalling whether AceApproximation for nonpolar term is to be included
85

Mark Friedrichs's avatar
Mark Friedrichs committed
86
   @return flag
87
88
89

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

90
int ReferenceObc::includeAceApproximation() const {
Mark Friedrichs's avatar
Mark Friedrichs committed
91
    return _includeAceApproximation;
92
93
94
95
}

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

Mark Friedrichs's avatar
Mark Friedrichs committed
96
   Set flag indicating whether AceApproximation is to be included
97

Mark Friedrichs's avatar
Mark Friedrichs committed
98
   @param includeAceApproximation new includeAceApproximation value
99
100
101

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

102
void ReferenceObc::setIncludeAceApproximation(int includeAceApproximation) {
Mark Friedrichs's avatar
Mark Friedrichs committed
103
    _includeAceApproximation = includeAceApproximation;
104
105
106
107
}

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

Mark Friedrichs's avatar
Mark Friedrichs committed
108
    Return OBC chain derivative: size = _obcParameters->getNumberOfAtoms()
109

Mark Friedrichs's avatar
Mark Friedrichs committed
110
    @return array
111

Mark Friedrichs's avatar
Mark Friedrichs committed
112
    --------------------------------------------------------------------------------------- */
113

peastman's avatar
peastman committed
114
vector<double>& ReferenceObc::getObcChain() {
Mark Friedrichs's avatar
Mark Friedrichs committed
115
    return _obcChain;
116
117
118
119
}

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

Mark Friedrichs's avatar
Mark Friedrichs committed
120
    Get Born radii based on papers:
121

Mark Friedrichs's avatar
Mark Friedrichs committed
122
123
       J. Phys. Chem. 1996 100, 19824-19839 (HCT paper)
       Proteins: Structure, Function, and Bioinformatcis 55:383-394 (2004) (OBC paper)
124

Mark Friedrichs's avatar
Mark Friedrichs committed
125
126
    @param atomCoordinates     atomic coordinates
    @param bornRadii           output array of Born radii
127

Mark Friedrichs's avatar
Mark Friedrichs committed
128
    --------------------------------------------------------------------------------------- */
129

peastman's avatar
peastman committed
130
void ReferenceObc::computeBornRadii(const vector<Vec3>& atomCoordinates, vector<double>& bornRadii) {
131

peastman's avatar
peastman committed
132
    ObcParameters* obcParameters              = getObcParameters();
133

peastman's avatar
peastman committed
134
135
136
137
    int numberOfAtoms                         = obcParameters->getNumberOfAtoms();
    const vector<double>& atomicRadii         = obcParameters->getAtomicRadii();
    const vector<double>& scaledRadiusFactor  = obcParameters->getScaledRadiusFactors();
    vector<double>& obcChain                  = getObcChain();
138

peastman's avatar
peastman committed
139
140
141
142
    double dielectricOffset                 = obcParameters->getDielectricOffset();
    double alphaObc                         = obcParameters->getAlphaObc();
    double betaObc                          = obcParameters->getBetaObc();
    double gammaObc                         = obcParameters->getGammaObc();
143

Mark Friedrichs's avatar
Mark Friedrichs committed
144
    // ---------------------------------------------------------------------------------------
145

Mark Friedrichs's avatar
Mark Friedrichs committed
146
    // calculate Born radii
147

148
    for (int atomI = 0; atomI < numberOfAtoms; atomI++) {
Mark Friedrichs's avatar
Mark Friedrichs committed
149
      
peastman's avatar
peastman committed
150
151
       double radiusI         = atomicRadii[atomI];
       double offsetRadiusI   = radiusI - dielectricOffset;
152

peastman's avatar
peastman committed
153
154
       double radiusIInverse  = 1.0/offsetRadiusI;
       double sum             = 0.0;
155

Mark Friedrichs's avatar
Mark Friedrichs committed
156
       // HCT code
157

158
       for (int atomJ = 0; atomJ < numberOfAtoms; atomJ++) {
159

160
          if (atomJ != atomI) {
161

peastman's avatar
peastman committed
162
             double deltaR[ReferenceForce::LastDeltaRIndex];
Mark Friedrichs's avatar
Mark Friedrichs committed
163
             if (_obcParameters->getPeriodic())
164
                 ReferenceForce::getDeltaRPeriodic(atomCoordinates[atomI], atomCoordinates[atomJ], _obcParameters->getPeriodicBox(), deltaR);
Mark Friedrichs's avatar
Mark Friedrichs committed
165
             else
166
                 ReferenceForce::getDeltaR(atomCoordinates[atomI], atomCoordinates[atomJ], deltaR);
peastman's avatar
peastman committed
167
             double r               = deltaR[ReferenceForce::RIndex];
Mark Friedrichs's avatar
Mark Friedrichs committed
168
169
             if (_obcParameters->getUseCutoff() && r > _obcParameters->getCutoffDistance())
                 continue;
170

peastman's avatar
peastman committed
171
172
173
             double offsetRadiusJ   = atomicRadii[atomJ] - dielectricOffset; 
             double scaledRadiusJ   = offsetRadiusJ*scaledRadiusFactor[atomJ];
             double rScaledRadiusJ  = r + scaledRadiusJ;
174

175
             if (offsetRadiusI < rScaledRadiusJ) {
peastman's avatar
peastman committed
176
177
178
                double rInverse = 1.0/r;
                double l_ij     = offsetRadiusI > fabs(r - scaledRadiusJ) ? offsetRadiusI : fabs(r - scaledRadiusJ);
                       l_ij     = 1.0/l_ij;
179

peastman's avatar
peastman committed
180
                double u_ij     = 1.0/rScaledRadiusJ;
181

peastman's avatar
peastman committed
182
183
                double l_ij2    = l_ij*l_ij;
                double u_ij2    = u_ij*u_ij;
Mark Friedrichs's avatar
Mark Friedrichs committed
184
 
peastman's avatar
peastman committed
185
186
                double ratio    = log((u_ij/l_ij));
                double term     = l_ij - u_ij + 0.25*r*(u_ij2 - l_ij2)  + (0.5*rInverse*ratio) + (0.25*scaledRadiusJ*scaledRadiusJ*rInverse)*(l_ij2 - u_ij2);
187

Mark Friedrichs's avatar
Mark Friedrichs committed
188
189
190
                // this case (atom i completely inside atom j) is not considered in the original paper
                // Jay Ponder and the authors of Tinker recognized this and
                // worked out the details
191

192
                if (offsetRadiusI < (scaledRadiusJ - r)) {
peastman's avatar
peastman committed
193
                   term += 2.0*(radiusIInverse - l_ij);
Mark Friedrichs's avatar
Mark Friedrichs committed
194
195
                }
                sum += term;
196

Mark Friedrichs's avatar
Mark Friedrichs committed
197
198
199
200
201
202
             }
          }
       }
 
       // OBC-specific code (Eqs. 6-8 in paper)

peastman's avatar
peastman committed
203
204
205
206
       sum              *= 0.5*offsetRadiusI;
       double sum2       = sum*sum;
       double sum3       = sum*sum2;
       double tanhSum    = tanh(alphaObc*sum - betaObc*sum2 + gammaObc*sum3);
Mark Friedrichs's avatar
Mark Friedrichs committed
207
       
peastman's avatar
peastman committed
208
       bornRadii[atomI]      = 1.0/(1.0/offsetRadiusI - tanhSum/radiusI); 
Mark Friedrichs's avatar
Mark Friedrichs committed
209
 
peastman's avatar
peastman committed
210
211
       obcChain[atomI]       = offsetRadiusI*(alphaObc - 2.0*betaObc*sum + 3.0*gammaObc*sum2);
       obcChain[atomI]       = (1.0 - tanhSum*tanhSum)*obcChain[atomI]/radiusI;
212

Mark Friedrichs's avatar
Mark Friedrichs committed
213
214
    }
}
215

Mark Friedrichs's avatar
Mark Friedrichs committed
216
/**---------------------------------------------------------------------------------------
217

Mark Friedrichs's avatar
Mark Friedrichs committed
218
    Get nonpolar solvation force constribution via ACE approximation
219

Mark Friedrichs's avatar
Mark Friedrichs committed
220
221
222
223
    @param obcParameters parameters
    @param bornRadii                 Born radii
    @param energy                    energy (output): value is incremented from input value 
    @param forces                    forces: values are incremented from input values
224

Mark Friedrichs's avatar
Mark Friedrichs committed
225
    --------------------------------------------------------------------------------------- */
226

227
void ReferenceObc::computeAceNonPolarForce(const ObcParameters* obcParameters,
peastman's avatar
peastman committed
228
229
230
                                      const vector<double>& bornRadii,
                                      double* energy,
                                      vector<double>& forces) const {
231

Mark Friedrichs's avatar
Mark Friedrichs committed
232
    // compute the nonpolar solvation via ACE approximation
233

peastman's avatar
peastman committed
234
235
    const double probeRadius          = obcParameters->getProbeRadius();
    const double surfaceAreaFactor    = obcParameters->getPi4Asolv();
236

peastman's avatar
peastman committed
237
    const vector<double>& atomicRadii   = obcParameters->getAtomicRadii();
Mark Friedrichs's avatar
Mark Friedrichs committed
238
    int numberOfAtoms                     = obcParameters->getNumberOfAtoms();
239

Mark Friedrichs's avatar
Mark Friedrichs committed
240
    // the original ACE equation is based on Eq.2 of
241

Mark Friedrichs's avatar
Mark Friedrichs committed
242
243
244
245
    // M. Schaefer, C. Bartels and M. Karplus, "Solution Conformations
    // and Thermodynamics of Structured Peptides: Molecular Dynamics
    // Simulation with an Implicit Solvation Model", J. Mol. Biol.,
    // 284, 835-848 (1998)  (ACE Method)
246

Mark Friedrichs's avatar
Mark Friedrichs committed
247
248
    // The original equation includes the factor (atomicRadii[atomI]/bornRadii[atomI]) to the first power,
    // whereas here the ratio is raised to the sixth power: (atomicRadii[atomI]/bornRadii[atomI])**6
249

Mark Friedrichs's avatar
Mark Friedrichs committed
250
251
252
    // This modification was made by Jay Ponder who observed it gave better correlations w/
    // observed values. He did not think it was important enough to write up, so there is
    // no paper to cite.
253

254
    for (int atomI = 0; atomI < numberOfAtoms; atomI++) {
peastman's avatar
peastman committed
255
256
257
258
        if (bornRadii[atomI] > 0.0) {
            double r            = atomicRadii[atomI] + probeRadius;
            double ratio6       = pow(atomicRadii[atomI]/bornRadii[atomI], 6.0);
            double saTerm       = surfaceAreaFactor*r*r*ratio6;
Mark Friedrichs's avatar
Mark Friedrichs committed
259
            *energy                += saTerm;
peastman's avatar
peastman committed
260
            forces[atomI]          -= 6.0*saTerm/bornRadii[atomI]; 
Mark Friedrichs's avatar
Mark Friedrichs committed
261
262
        }
    }
263
264
265
266
}

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

Mark Friedrichs's avatar
Mark Friedrichs committed
267
    Get Obc Born energy and forces
268

Mark Friedrichs's avatar
Mark Friedrichs committed
269
270
271
    @param atomCoordinates     atomic coordinates
    @param partialCharges      partial charges
    @param forces              forces
272

Mark Friedrichs's avatar
Mark Friedrichs committed
273
    The array bornRadii is also updated and the obcEnergy
274

Mark Friedrichs's avatar
Mark Friedrichs committed
275
    --------------------------------------------------------------------------------------- */
276

peastman's avatar
peastman committed
277
278
double ReferenceObc::computeBornEnergyForces(const vector<Vec3>& atomCoordinates,
                                           const vector<double>& partialCharges, vector<Vec3>& inputForces) {
279

Mark Friedrichs's avatar
Mark Friedrichs committed
280
    // constants
281

282
    const int numberOfAtoms = _obcParameters->getNumberOfAtoms();
peastman's avatar
peastman committed
283
284
285
286
287
288
289
    const double dielectricOffset = _obcParameters->getDielectricOffset();
    const double cutoffDistance = _obcParameters->getCutoffDistance();
    const double soluteDielectric = _obcParameters->getSoluteDielectric();
    const double solventDielectric = _obcParameters->getSolventDielectric();
    double preFactor;
    if (soluteDielectric != 0.0 && solventDielectric != 0.0)
        preFactor = 2.0*_obcParameters->getElectricConstant()*((1.0/soluteDielectric) - (1.0/solventDielectric));
290
    else
peastman's avatar
peastman committed
291
        preFactor = 0.0;
292

Mark Friedrichs's avatar
Mark Friedrichs committed
293
    // ---------------------------------------------------------------------------------------
294

Mark Friedrichs's avatar
Mark Friedrichs committed
295
    // compute Born radii
296

peastman's avatar
peastman committed
297
    vector<double> bornRadii(numberOfAtoms);
298
    computeBornRadii(atomCoordinates, bornRadii);
299

Mark Friedrichs's avatar
Mark Friedrichs committed
300
    // set energy/forces to zero
301

peastman's avatar
peastman committed
302
303
    double obcEnergy = 0.0;
    vector<double> bornForces(numberOfAtoms, 0.0);
304

Mark Friedrichs's avatar
Mark Friedrichs committed
305
    // ---------------------------------------------------------------------------------------
306

Mark Friedrichs's avatar
Mark Friedrichs committed
307
308
    // compute the nonpolar solvation via ACE approximation
     
309
310
    if (includeAceApproximation()) {
       computeAceNonPolarForce(_obcParameters, bornRadii, &obcEnergy, bornForces);
Mark Friedrichs's avatar
Mark Friedrichs committed
311
    }
312
 
Mark Friedrichs's avatar
Mark Friedrichs committed
313
    // ---------------------------------------------------------------------------------------
314

Mark Friedrichs's avatar
Mark Friedrichs committed
315
    // first main loop
316

317
    for (int atomI = 0; atomI < numberOfAtoms; atomI++) {
318
 
peastman's avatar
peastman committed
319
       double partialChargeI = preFactor*partialCharges[atomI];
320
       for (int atomJ = atomI; atomJ < numberOfAtoms; atomJ++) {
321

peastman's avatar
peastman committed
322
          double deltaR[ReferenceForce::LastDeltaRIndex];
Mark Friedrichs's avatar
Mark Friedrichs committed
323
          if (_obcParameters->getPeriodic())
324
              ReferenceForce::getDeltaRPeriodic(atomCoordinates[atomI], atomCoordinates[atomJ], _obcParameters->getPeriodicBox(), deltaR);
Mark Friedrichs's avatar
Mark Friedrichs committed
325
          else
326
              ReferenceForce::getDeltaR(atomCoordinates[atomI], atomCoordinates[atomJ], deltaR);
327
          if (_obcParameters->getUseCutoff() && deltaR[ReferenceForce::RIndex] > cutoffDistance)
Mark Friedrichs's avatar
Mark Friedrichs committed
328
              continue;
329

peastman's avatar
peastman committed
330
331
332
333
          double r2                 = deltaR[ReferenceForce::R2Index];
          double deltaX             = deltaR[ReferenceForce::XIndex];
          double deltaY             = deltaR[ReferenceForce::YIndex];
          double deltaZ             = deltaR[ReferenceForce::ZIndex];
334

peastman's avatar
peastman committed
335
336
          double alpha2_ij          = bornRadii[atomI]*bornRadii[atomJ];
          double D_ij               = r2/(4.0*alpha2_ij);
337

peastman's avatar
peastman committed
338
339
340
          double expTerm            = exp(-D_ij);
          double denominator2       = r2 + alpha2_ij*expTerm; 
          double denominator        = sqrt(denominator2); 
Mark Friedrichs's avatar
Mark Friedrichs committed
341
          
peastman's avatar
peastman committed
342
343
          double Gpol               = (partialChargeI*partialCharges[atomJ])/denominator; 
          double dGpol_dr           = -Gpol*(1.0 - 0.25*expTerm)/denominator2;  
344

peastman's avatar
peastman committed
345
          double dGpol_dalpha2_ij   = -0.5*Gpol*expTerm*(1.0 + D_ij)/denominator2;
346
          
peastman's avatar
peastman committed
347
          double energy = Gpol;
348

349
          if (atomI != atomJ) {
350

351
352
353
              if (_obcParameters->getUseCutoff())
                  energy -= partialChargeI*partialCharges[atomJ]/cutoffDistance;
              
Mark Friedrichs's avatar
Mark Friedrichs committed
354
              bornForces[atomJ]        += dGpol_dalpha2_ij*bornRadii[atomI];
355

Mark Friedrichs's avatar
Mark Friedrichs committed
356
357
358
              deltaX                   *= dGpol_dr;
              deltaY                   *= dGpol_dr;
              deltaZ                   *= dGpol_dr;
359

Mark Friedrichs's avatar
Mark Friedrichs committed
360
361
362
              inputForces[atomI][0]    += deltaX;
              inputForces[atomI][1]    += deltaY;
              inputForces[atomI][2]    += deltaZ;
363

Mark Friedrichs's avatar
Mark Friedrichs committed
364
365
366
              inputForces[atomJ][0]    -= deltaX;
              inputForces[atomJ][1]    -= deltaY;
              inputForces[atomJ][2]    -= deltaZ;
367

Mark Friedrichs's avatar
Mark Friedrichs committed
368
          } else {
peastman's avatar
peastman committed
369
             energy *= 0.5;
Mark Friedrichs's avatar
Mark Friedrichs committed
370
          }
371

372
          obcEnergy         += energy;
Mark Friedrichs's avatar
Mark Friedrichs committed
373
          bornForces[atomI] += dGpol_dalpha2_ij*bornRadii[atomJ];
374

Mark Friedrichs's avatar
Mark Friedrichs committed
375
376
       }
    }
377

Mark Friedrichs's avatar
Mark Friedrichs committed
378
    // ---------------------------------------------------------------------------------------
379

Mark Friedrichs's avatar
Mark Friedrichs committed
380
    // second main loop
381

peastman's avatar
peastman committed
382
383
    const vector<double>& obcChain            = getObcChain();
    const vector<double>& atomicRadii         = _obcParameters->getAtomicRadii();
384

peastman's avatar
peastman committed
385
386
387
388
    const double alphaObc                   = _obcParameters->getAlphaObc();
    const double betaObc                    = _obcParameters->getBetaObc();
    const double gammaObc                   = _obcParameters->getGammaObc();
    const vector<double>& scaledRadiusFactor  = _obcParameters->getScaledRadiusFactors();
389
390
391

    // compute factor that depends only on the outer loop index

392
    for (int atomI = 0; atomI < numberOfAtoms; atomI++) {
Mark Friedrichs's avatar
Mark Friedrichs committed
393
394
       bornForces[atomI] *= bornRadii[atomI]*bornRadii[atomI]*obcChain[atomI];      
    }
395

396
    for (int atomI = 0; atomI < numberOfAtoms; atomI++) {
397
 
Mark Friedrichs's avatar
Mark Friedrichs committed
398
       // radius w/ dielectric offset applied
399

peastman's avatar
peastman committed
400
401
       double radiusI        = atomicRadii[atomI];
       double offsetRadiusI  = radiusI - dielectricOffset;
402

403
       for (int atomJ = 0; atomJ < numberOfAtoms; atomJ++) {
404

405
          if (atomJ != atomI) {
406

peastman's avatar
peastman committed
407
             double deltaR[ReferenceForce::LastDeltaRIndex];
Mark Friedrichs's avatar
Mark Friedrichs committed
408
             if (_obcParameters->getPeriodic())
409
                ReferenceForce::getDeltaRPeriodic(atomCoordinates[atomI], atomCoordinates[atomJ], _obcParameters->getPeriodicBox(), deltaR);
Mark Friedrichs's avatar
Mark Friedrichs committed
410
             else 
411
                ReferenceForce::getDeltaR(atomCoordinates[atomI], atomCoordinates[atomJ], deltaR);
412
             if (_obcParameters->getUseCutoff() && deltaR[ReferenceForce::RIndex] > cutoffDistance)
Mark Friedrichs's avatar
Mark Friedrichs committed
413
414
                    continue;
    
peastman's avatar
peastman committed
415
416
417
418
             double deltaX             = deltaR[ReferenceForce::XIndex];
             double deltaY             = deltaR[ReferenceForce::YIndex];
             double deltaZ             = deltaR[ReferenceForce::ZIndex];
             double r                  = deltaR[ReferenceForce::RIndex];
419
 
Mark Friedrichs's avatar
Mark Friedrichs committed
420
             // radius w/ dielectric offset applied
421

peastman's avatar
peastman committed
422
             double offsetRadiusJ      = atomicRadii[atomJ] - dielectricOffset;
423

peastman's avatar
peastman committed
424
425
426
             double scaledRadiusJ      = offsetRadiusJ*scaledRadiusFactor[atomJ];
             double scaledRadiusJ2     = scaledRadiusJ*scaledRadiusJ;
             double rScaledRadiusJ     = r + scaledRadiusJ;
427

Mark Friedrichs's avatar
Mark Friedrichs committed
428
429
             // dL/dr & dU/dr are zero (this can be shown analytically)
             // removed from calculation
430

431
             if (offsetRadiusI < rScaledRadiusJ) {
432

peastman's avatar
peastman committed
433
434
                double l_ij          = offsetRadiusI > fabs(r - scaledRadiusJ) ? offsetRadiusI : fabs(r - scaledRadiusJ);
                       l_ij          = 1.0/l_ij;
435

peastman's avatar
peastman committed
436
                double u_ij          = 1.0/rScaledRadiusJ;
437

peastman's avatar
peastman committed
438
                double l_ij2         = l_ij*l_ij;
439

peastman's avatar
peastman committed
440
                double u_ij2         = u_ij*u_ij;
441
 
peastman's avatar
peastman committed
442
443
                double rInverse      = 1.0/r;
                double r2Inverse     = rInverse*rInverse;
444

peastman's avatar
peastman committed
445
                double t3            = 0.125*(1.0 + scaledRadiusJ2*r2Inverse)*(l_ij2 - u_ij2) + 0.25*log(u_ij/l_ij)*r2Inverse;
446

peastman's avatar
peastman committed
447
                double de            = bornForces[atomI]*t3*rInverse;
448

Mark Friedrichs's avatar
Mark Friedrichs committed
449
450
451
452
453
454
455
                deltaX                  *= de;
                deltaY                  *= de;
                deltaZ                  *= de;
    
                inputForces[atomI][0]   -= deltaX;
                inputForces[atomI][1]   -= deltaY;
                inputForces[atomI][2]   -= deltaZ;
456
  
Mark Friedrichs's avatar
Mark Friedrichs committed
457
458
459
                inputForces[atomJ][0]   += deltaX;
                inputForces[atomJ][1]   += deltaY;
                inputForces[atomJ][2]   += deltaZ;
460
 
Mark Friedrichs's avatar
Mark Friedrichs committed
461
462
463
             }
          }
       }
464

Mark Friedrichs's avatar
Mark Friedrichs committed
465
    }
466

Mark Friedrichs's avatar
Mark Friedrichs committed
467
    return obcEnergy;
468
}