ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/nonbonded/Electrostatic.cpp
Revision: 1925
Committed: Wed Aug 7 15:24:16 2013 UTC (11 years, 9 months ago) by gezelter
File size: 54231 byte(s)
Log Message:
More ewald fixes, reporting reciprocal potential in stats.

File Contents

# User Rev Content
1 gezelter 1502 /*
2     * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3     *
4     * The University of Notre Dame grants you ("Licensee") a
5     * non-exclusive, royalty free, license to use, modify and
6     * redistribute this software in source and binary code form, provided
7     * that the following conditions are met:
8     *
9     * 1. Redistributions of source code must retain the above copyright
10     * notice, this list of conditions and the following disclaimer.
11     *
12     * 2. Redistributions in binary form must reproduce the above copyright
13     * notice, this list of conditions and the following disclaimer in the
14     * documentation and/or other materials provided with the
15     * distribution.
16     *
17     * This software is provided "AS IS," without a warranty of any
18     * kind. All express or implied conditions, representations and
19     * warranties, including any implied warranty of merchantability,
20     * fitness for a particular purpose or non-infringement, are hereby
21     * excluded. The University of Notre Dame and its licensors shall not
22     * be liable for any damages suffered by licensee as a result of
23     * using, modifying or distributing the software or its
24     * derivatives. In no event will the University of Notre Dame or its
25     * licensors be liable for any lost revenue, profit or data, or for
26     * direct, indirect, special, consequential, incidental or punitive
27     * damages, however caused and regardless of the theory of liability,
28     * arising out of the use of or inability to use software, even if the
29     * University of Notre Dame has been advised of the possibility of
30     * such damages.
31     *
32     * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33     * research, please cite the appropriate papers when you publish your
34     * work. Good starting points are:
35     *
36     * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37 gezelter 1587 * [2] Fennell & Gezelter, J. Chem. Phys. 124 234104 (2006).
38 gezelter 1879 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
39 gezelter 1665 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40     * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 gezelter 1502 */
42    
43     #include <stdio.h>
44     #include <string.h>
45    
46     #include <cmath>
47 gezelter 1915 #include <numeric>
48 gezelter 1502 #include "nonbonded/Electrostatic.hpp"
49     #include "utils/simError.h"
50     #include "types/NonBondedInteractionType.hpp"
51 gezelter 1710 #include "types/FixedChargeAdapter.hpp"
52 gezelter 1720 #include "types/FluctuatingChargeAdapter.hpp"
53 gezelter 1710 #include "types/MultipoleAdapter.hpp"
54 gezelter 1535 #include "io/Globals.hpp"
55 gezelter 1718 #include "nonbonded/SlaterIntegrals.hpp"
56     #include "utils/PhysicalConstants.hpp"
57 gezelter 1767 #include "math/erfc.hpp"
58 gezelter 1879 #include "math/SquareMatrix.hpp"
59 gezelter 1915 #include "primitives/Molecule.hpp"
60 gezelter 1925 #ifdef IS_MPI
61     #include <mpi.h>
62     #endif
63 gezelter 1502
64     namespace OpenMD {
65    
66     Electrostatic::Electrostatic(): name_("Electrostatic"), initialized_(false),
67 gezelter 1587 forceField_(NULL), info_(NULL),
68     haveCutoffRadius_(false),
69     haveDampingAlpha_(false),
70     haveDielectric_(false),
71 gezelter 1879 haveElectroSplines_(false)
72 gezelter 1587 {}
73 gezelter 1502
74     void Electrostatic::initialize() {
75 gezelter 1587
76 gezelter 1584 Globals* simParams_ = info_->getSimParams();
77 gezelter 1535
78 gezelter 1528 summationMap_["HARD"] = esm_HARD;
79 gezelter 1616 summationMap_["NONE"] = esm_HARD;
80 gezelter 1528 summationMap_["SWITCHING_FUNCTION"] = esm_SWITCHING_FUNCTION;
81     summationMap_["SHIFTED_POTENTIAL"] = esm_SHIFTED_POTENTIAL;
82     summationMap_["SHIFTED_FORCE"] = esm_SHIFTED_FORCE;
83 gezelter 1879 summationMap_["TAYLOR_SHIFTED"] = esm_TAYLOR_SHIFTED;
84 gezelter 1528 summationMap_["REACTION_FIELD"] = esm_REACTION_FIELD;
85     summationMap_["EWALD_FULL"] = esm_EWALD_FULL;
86     summationMap_["EWALD_PME"] = esm_EWALD_PME;
87     summationMap_["EWALD_SPME"] = esm_EWALD_SPME;
88     screeningMap_["DAMPED"] = DAMPED;
89     screeningMap_["UNDAMPED"] = UNDAMPED;
90    
91 gezelter 1502 // these prefactors convert the multipole interactions into kcal / mol
92     // all were computed assuming distances are measured in angstroms
93     // Charge-Charge, assuming charges are measured in electrons
94     pre11_ = 332.0637778;
95     // Charge-Dipole, assuming charges are measured in electrons, and
96     // dipoles are measured in debyes
97     pre12_ = 69.13373;
98 gezelter 1879 // Dipole-Dipole, assuming dipoles are measured in Debye
99 gezelter 1502 pre22_ = 14.39325;
100     // Charge-Quadrupole, assuming charges are measured in electrons, and
101     // quadrupoles are measured in 10^-26 esu cm^2
102 gezelter 1879 // This unit is also known affectionately as an esu centibarn.
103 gezelter 1502 pre14_ = 69.13373;
104 gezelter 1879 // Dipole-Quadrupole, assuming dipoles are measured in debyes and
105     // quadrupoles in esu centibarns:
106     pre24_ = 14.39325;
107     // Quadrupole-Quadrupole, assuming esu centibarns:
108     pre44_ = 14.39325;
109    
110 gezelter 1502 // conversions for the simulation box dipole moment
111     chargeToC_ = 1.60217733e-19;
112     angstromToM_ = 1.0e-10;
113     debyeToCm_ = 3.33564095198e-30;
114    
115 gezelter 1879 // Default number of points for electrostatic splines
116 gezelter 1502 np_ = 100;
117    
118     // variables to handle different summation methods for long-range
119     // electrostatics:
120 gezelter 1528 summationMethod_ = esm_HARD;
121 gezelter 1502 screeningMethod_ = UNDAMPED;
122     dielectric_ = 1.0;
123    
124 gezelter 1528 // check the summation method:
125     if (simParams_->haveElectrostaticSummationMethod()) {
126     string myMethod = simParams_->getElectrostaticSummationMethod();
127     toUpper(myMethod);
128     map<string, ElectrostaticSummationMethod>::iterator i;
129     i = summationMap_.find(myMethod);
130     if ( i != summationMap_.end() ) {
131     summationMethod_ = (*i).second;
132     } else {
133     // throw error
134     sprintf( painCave.errMsg,
135 gezelter 1536 "Electrostatic::initialize: Unknown electrostaticSummationMethod.\n"
136 gezelter 1528 "\t(Input file specified %s .)\n"
137 gezelter 1616 "\telectrostaticSummationMethod must be one of: \"hard\",\n"
138 gezelter 1879 "\t\"shifted_potential\", \"shifted_force\",\n"
139     "\t\"taylor_shifted\", or \"reaction_field\".\n",
140     myMethod.c_str() );
141 gezelter 1528 painCave.isFatal = 1;
142     simError();
143     }
144     } else {
145     // set ElectrostaticSummationMethod to the cutoffMethod:
146     if (simParams_->haveCutoffMethod()){
147     string myMethod = simParams_->getCutoffMethod();
148     toUpper(myMethod);
149     map<string, ElectrostaticSummationMethod>::iterator i;
150     i = summationMap_.find(myMethod);
151     if ( i != summationMap_.end() ) {
152     summationMethod_ = (*i).second;
153     }
154     }
155     }
156    
157     if (summationMethod_ == esm_REACTION_FIELD) {
158     if (!simParams_->haveDielectric()) {
159     // throw warning
160     sprintf( painCave.errMsg,
161     "SimInfo warning: dielectric was not specified in the input file\n\tfor the reaction field correction method.\n"
162     "\tA default value of %f will be used for the dielectric.\n", dielectric_);
163     painCave.isFatal = 0;
164     painCave.severity = OPENMD_INFO;
165     simError();
166     } else {
167     dielectric_ = simParams_->getDielectric();
168     }
169     haveDielectric_ = true;
170     }
171    
172     if (simParams_->haveElectrostaticScreeningMethod()) {
173     string myScreen = simParams_->getElectrostaticScreeningMethod();
174     toUpper(myScreen);
175     map<string, ElectrostaticScreeningMethod>::iterator i;
176     i = screeningMap_.find(myScreen);
177     if ( i != screeningMap_.end()) {
178     screeningMethod_ = (*i).second;
179     } else {
180     sprintf( painCave.errMsg,
181     "SimInfo error: Unknown electrostaticScreeningMethod.\n"
182     "\t(Input file specified %s .)\n"
183     "\telectrostaticScreeningMethod must be one of: \"undamped\"\n"
184     "or \"damped\".\n", myScreen.c_str() );
185     painCave.isFatal = 1;
186     simError();
187     }
188     }
189    
190     // check to make sure a cutoff value has been set:
191     if (!haveCutoffRadius_) {
192     sprintf( painCave.errMsg, "Electrostatic::initialize has no Default "
193     "Cutoff value!\n");
194     painCave.severity = OPENMD_ERROR;
195     painCave.isFatal = 1;
196     simError();
197     }
198    
199 gezelter 1915 if (screeningMethod_ == DAMPED || summationMethod_ == esm_EWALD_FULL) {
200 gezelter 1528 if (!simParams_->haveDampingAlpha()) {
201     // first set a cutoff dependent alpha value
202     // we assume alpha depends linearly with rcut from 0 to 20.5 ang
203     dampingAlpha_ = 0.425 - cutoffRadius_* 0.02;
204 gezelter 1915 if (dampingAlpha_ < 0.0) dampingAlpha_ = 0.0;
205 gezelter 1528 // throw warning
206     sprintf( painCave.errMsg,
207 gezelter 1750 "Electrostatic::initialize: dampingAlpha was not specified in the\n"
208     "\tinput file. A default value of %f (1/ang) will be used for the\n"
209     "\tcutoff of %f (ang).\n",
210 gezelter 1528 dampingAlpha_, cutoffRadius_);
211     painCave.severity = OPENMD_INFO;
212     painCave.isFatal = 0;
213     simError();
214     } else {
215     dampingAlpha_ = simParams_->getDampingAlpha();
216     }
217     haveDampingAlpha_ = true;
218     }
219    
220 gezelter 1915
221 gezelter 1895 Etypes.clear();
222     Etids.clear();
223     FQtypes.clear();
224     FQtids.clear();
225     ElectrostaticMap.clear();
226     Jij.clear();
227     nElectro_ = 0;
228     nFlucq_ = 0;
229    
230     Etids.resize( forceField_->getNAtomType(), -1);
231     FQtids.resize( forceField_->getNAtomType(), -1);
232    
233     set<AtomType*>::iterator at;
234     for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
235     if ((*at)->isElectrostatic()) nElectro_++;
236     if ((*at)->isFluctuatingCharge()) nFlucq_++;
237     }
238 gezelter 1528
239 gezelter 1895 Jij.resize(nFlucq_);
240    
241     for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
242     if ((*at)->isElectrostatic()) addType(*at);
243 gezelter 1879 }
244    
245     if (summationMethod_ == esm_REACTION_FIELD) {
246     preRF_ = (dielectric_ - 1.0) /
247     ((2.0 * dielectric_ + 1.0) * pow(cutoffRadius_,3) );
248 gezelter 1502 }
249    
250 gezelter 1879 RealType b0c, b1c, b2c, b3c, b4c, b5c;
251     RealType db0c_1, db0c_2, db0c_3, db0c_4, db0c_5;
252     RealType a2, expTerm, invArootPi;
253    
254     RealType r = cutoffRadius_;
255     RealType r2 = r * r;
256     RealType ric = 1.0 / r;
257     RealType ric2 = ric * ric;
258 gezelter 1502
259 gezelter 1879 if (screeningMethod_ == DAMPED) {
260     a2 = dampingAlpha_ * dampingAlpha_;
261     invArootPi = 1.0 / (dampingAlpha_ * sqrt(M_PI));
262     expTerm = exp(-a2 * r2);
263     // values of Smith's B_l functions at the cutoff radius:
264     b0c = erfc(dampingAlpha_ * r) / r;
265     b1c = ( b0c + 2.0*a2 * expTerm * invArootPi) / r2;
266     b2c = (3.0 * b1c + pow(2.0*a2, 2) * expTerm * invArootPi) / r2;
267     b3c = (5.0 * b2c + pow(2.0*a2, 3) * expTerm * invArootPi) / r2;
268     b4c = (7.0 * b3c + pow(2.0*a2, 4) * expTerm * invArootPi) / r2;
269     b5c = (9.0 * b4c + pow(2.0*a2, 5) * expTerm * invArootPi) / r2;
270 gezelter 1900 // Half the Smith self piece:
271     selfMult1_ = - a2 * invArootPi;
272     selfMult2_ = - 2.0 * a2 * a2 * invArootPi / 3.0;
273     selfMult4_ = - 4.0 * a2 * a2 * a2 * invArootPi / 5.0;
274 gezelter 1502 } else {
275 gezelter 1879 a2 = 0.0;
276     b0c = 1.0 / r;
277     b1c = ( b0c) / r2;
278     b2c = (3.0 * b1c) / r2;
279     b3c = (5.0 * b2c) / r2;
280     b4c = (7.0 * b3c) / r2;
281     b5c = (9.0 * b4c) / r2;
282 gezelter 1900 selfMult1_ = 0.0;
283     selfMult2_ = 0.0;
284     selfMult4_ = 0.0;
285 gezelter 1502 }
286 gezelter 1879
287     // higher derivatives of B_0 at the cutoff radius:
288     db0c_1 = -r * b1c;
289     db0c_2 = -b1c + r2 * b2c;
290     db0c_3 = 3.0*r*b2c - r2*r*b3c;
291     db0c_4 = 3.0*b2c - 6.0*r2*b3c + r2*r2*b4c;
292 gezelter 1900 db0c_5 = -15.0*r*b3c + 10.0*r2*r*b4c - r2*r2*r*b5c;
293 gezelter 1879
294 gezelter 1922 if (summationMethod_ != esm_EWALD_FULL) {
295 gezelter 1915 selfMult1_ -= b0c;
296     selfMult2_ += (db0c_2 + 2.0*db0c_1*ric) / 3.0;
297     selfMult4_ -= (db0c_4 + 4.0*db0c_3*ric) / 15.0;
298     }
299    
300 gezelter 1879 // working variables for the splines:
301     RealType ri, ri2;
302     RealType b0, b1, b2, b3, b4, b5;
303     RealType db0_1, db0_2, db0_3, db0_4, db0_5;
304     RealType f, fc, f0;
305     RealType g, gc, g0, g1, g2, g3, g4;
306     RealType h, hc, h1, h2, h3, h4;
307     RealType s, sc, s2, s3, s4;
308     RealType t, tc, t3, t4;
309     RealType u, uc, u4;
310    
311     // working variables for Taylor expansion:
312     RealType rmRc, rmRc2, rmRc3, rmRc4;
313    
314     // Approximate using splines using a maximum of 0.1 Angstroms
315     // between points.
316     int nptest = int((cutoffRadius_ + 2.0) / 0.1);
317     np_ = (np_ > nptest) ? np_ : nptest;
318    
319 gezelter 1613 // Add a 2 angstrom safety window to deal with cutoffGroups that
320     // have charged atoms longer than the cutoffRadius away from each
321 gezelter 1879 // other. Splining is almost certainly the best choice here.
322     // Direct calls to erfc would be preferrable if it is a very fast
323     // implementation.
324 gezelter 1613
325 gezelter 1879 RealType dx = (cutoffRadius_ + 2.0) / RealType(np_);
326    
327     // Storage vectors for the computed functions
328     vector<RealType> rv;
329     vector<RealType> v01v;
330     vector<RealType> v11v;
331     vector<RealType> v21v, v22v;
332     vector<RealType> v31v, v32v;
333     vector<RealType> v41v, v42v, v43v;
334    
335     for (int i = 1; i < np_ + 1; i++) {
336     r = RealType(i) * dx;
337     rv.push_back(r);
338    
339     ri = 1.0 / r;
340     ri2 = ri * ri;
341    
342     r2 = r * r;
343     expTerm = exp(-a2 * r2);
344    
345     // Taylor expansion factors (no need for factorials this way):
346     rmRc = r - cutoffRadius_;
347     rmRc2 = rmRc * rmRc / 2.0;
348     rmRc3 = rmRc2 * rmRc / 3.0;
349     rmRc4 = rmRc3 * rmRc / 4.0;
350    
351     // values of Smith's B_l functions at r:
352     if (screeningMethod_ == DAMPED) {
353     b0 = erfc(dampingAlpha_ * r) * ri;
354     b1 = ( b0 + 2.0*a2 * expTerm * invArootPi) * ri2;
355     b2 = (3.0 * b1 + pow(2.0*a2, 2) * expTerm * invArootPi) * ri2;
356     b3 = (5.0 * b2 + pow(2.0*a2, 3) * expTerm * invArootPi) * ri2;
357     b4 = (7.0 * b3 + pow(2.0*a2, 4) * expTerm * invArootPi) * ri2;
358     b5 = (9.0 * b4 + pow(2.0*a2, 5) * expTerm * invArootPi) * ri2;
359     } else {
360     b0 = ri;
361     b1 = ( b0) * ri2;
362     b2 = (3.0 * b1) * ri2;
363     b3 = (5.0 * b2) * ri2;
364     b4 = (7.0 * b3) * ri2;
365     b5 = (9.0 * b4) * ri2;
366     }
367    
368     // higher derivatives of B_0 at r:
369     db0_1 = -r * b1;
370     db0_2 = -b1 + r2 * b2;
371     db0_3 = 3.0*r*b2 - r2*r*b3;
372     db0_4 = 3.0*b2 - 6.0*r2*b3 + r2*r2*b4;
373     db0_5 = -15.0*r*b3 + 10.0*r2*r*b4 - r2*r2*r*b5;
374    
375     f = b0;
376     fc = b0c;
377     f0 = f - fc - rmRc*db0c_1;
378    
379     g = db0_1;
380     gc = db0c_1;
381     g0 = g - gc;
382     g1 = g0 - rmRc *db0c_2;
383     g2 = g1 - rmRc2*db0c_3;
384     g3 = g2 - rmRc3*db0c_4;
385     g4 = g3 - rmRc4*db0c_5;
386    
387     h = db0_2;
388     hc = db0c_2;
389     h1 = h - hc;
390     h2 = h1 - rmRc *db0c_3;
391     h3 = h2 - rmRc2*db0c_4;
392     h4 = h3 - rmRc3*db0c_5;
393    
394     s = db0_3;
395     sc = db0c_3;
396     s2 = s - sc;
397     s3 = s2 - rmRc *db0c_4;
398     s4 = s3 - rmRc2*db0c_5;
399    
400     t = db0_4;
401     tc = db0c_4;
402     t3 = t - tc;
403     t4 = t3 - rmRc *db0c_5;
404    
405     u = db0_5;
406     uc = db0c_5;
407     u4 = u - uc;
408    
409     // in what follows below, the various v functions are used for
410     // potentials and torques, while the w functions show up in the
411     // forces.
412    
413     switch (summationMethod_) {
414     case esm_SHIFTED_FORCE:
415    
416     v01 = f - fc - rmRc*gc;
417     v11 = g - gc - rmRc*hc;
418     v21 = g*ri - gc*ric - rmRc*(hc - gc*ric)*ric;
419     v22 = h - g*ri - (hc - gc*ric) - rmRc*(sc - (hc - gc*ric)*ric);
420 gezelter 1894 v31 = (h-g*ri)*ri - (hc-gc*ric)*ric - rmRc*(sc-2.0*(hc-gc*ric)*ric)*ric;
421 gezelter 1879 v32 = (s - 3.0*(h-g*ri)*ri) - (sc - 3.0*(hc-gc*ric)*ric)
422     - rmRc*(tc - 3.0*(sc-2.0*(hc-gc*ric)*ric)*ric);
423     v41 = (h - g*ri)*ri2 - (hc - gc*ric)*ric2
424     - rmRc*(sc - 3.0*(hc-gc*ric)*ric)*ric2;
425     v42 = (s-3.0*(h-g*ri)*ri)*ri - (sc-3.0*(hc-gc*ric)*ric)*ric
426     - rmRc*(tc - (4.0*sc - 9.0*(hc - gc*ric)*ric)*ric)*ric;
427    
428     v43 = (t - 3.0*(2.0*s - 5.0*(h - g*ri)*ri)*ri)
429     - (tc - 3.0*(2.0*sc - 5.0*(hc - gc*ric)*ric)*ric)
430     - rmRc*(uc-3.0*(2.0*tc - (7.0*sc - 15.0*(hc - gc*ric)*ric)*ric)*ric);
431    
432     dv01 = g - gc;
433     dv11 = h - hc;
434     dv21 = (h - g*ri)*ri - (hc - gc*ric)*ric;
435     dv22 = (s - (h - g*ri)*ri) - (sc - (hc - gc*ric)*ric);
436     dv31 = (s - 2.0*(h-g*ri)*ri)*ri - (sc - 2.0*(hc-gc*ric)*ric)*ric;
437     dv32 = (t - 3.0*(s-2.0*(h-g*ri)*ri)*ri)
438     - (tc - 3.0*(sc-2.0*(hc-gc*ric)*ric)*ric);
439     dv41 = (s - 3.0*(h - g*ri)*ri)*ri2 - (sc - 3.0*(hc - gc*ric)*ric)*ric2;
440     dv42 = (t - (4.0*s - 9.0*(h-g*ri)*ri)*ri)*ri
441     - (tc - (4.0*sc - 9.0*(hc-gc*ric)*ric)*ric)*ric;
442     dv43 = (u - 3.0*(2.0*t - (7.0*s - 15.0*(h - g*ri)*ri)*ri)*ri)
443     - (uc - 3.0*(2.0*tc - (7.0*sc - 15.0*(hc - gc*ric)*ric)*ric)*ric);
444    
445     break;
446    
447     case esm_TAYLOR_SHIFTED:
448    
449     v01 = f0;
450     v11 = g1;
451     v21 = g2 * ri;
452     v22 = h2 - v21;
453     v31 = (h3 - g3 * ri) * ri;
454     v32 = s3 - 3.0*v31;
455     v41 = (h4 - g4 * ri) * ri2;
456     v42 = s4 * ri - 3.0*v41;
457     v43 = t4 - 6.0*v42 - 3.0*v41;
458    
459     dv01 = g0;
460     dv11 = h1;
461     dv21 = (h2 - g2*ri)*ri;
462     dv22 = (s2 - (h2 - g2*ri)*ri);
463     dv31 = (s3 - 2.0*(h3-g3*ri)*ri)*ri;
464     dv32 = (t3 - 3.0*(s3-2.0*(h3-g3*ri)*ri)*ri);
465     dv41 = (s4 - 3.0*(h4 - g4*ri)*ri)*ri2;
466     dv42 = (t4 - (4.0*s4 - 9.0*(h4-g4*ri)*ri)*ri)*ri;
467     dv43 = (u4 - 3.0*(2.0*t4 - (7.0*s4 - 15.0*(h4 - g4*ri)*ri)*ri)*ri);
468    
469     break;
470    
471     case esm_SHIFTED_POTENTIAL:
472    
473     v01 = f - fc;
474     v11 = g - gc;
475     v21 = g*ri - gc*ric;
476     v22 = h - g*ri - (hc - gc*ric);
477 gezelter 1894 v31 = (h-g*ri)*ri - (hc-gc*ric)*ric;
478 gezelter 1879 v32 = (s - 3.0*(h-g*ri)*ri) - (sc - 3.0*(hc-gc*ric)*ric);
479     v41 = (h - g*ri)*ri2 - (hc - gc*ric)*ric2;
480     v42 = (s-3.0*(h-g*ri)*ri)*ri - (sc-3.0*(hc-gc*ric)*ric)*ric;
481     v43 = (t - 3.0*(2.0*s - 5.0*(h - g*ri)*ri)*ri)
482     - (tc - 3.0*(2.0*sc - 5.0*(hc - gc*ric)*ric)*ric);
483    
484     dv01 = g;
485     dv11 = h;
486     dv21 = (h - g*ri)*ri;
487     dv22 = (s - (h - g*ri)*ri);
488     dv31 = (s - 2.0*(h-g*ri)*ri)*ri;
489     dv32 = (t - 3.0*(s-2.0*(h-g*ri)*ri)*ri);
490     dv41 = (s - 3.0*(h - g*ri)*ri)*ri2;
491     dv42 = (t - (4.0*s - 9.0*(h-g*ri)*ri)*ri)*ri;
492     dv43 = (u - 3.0*(2.0*t - (7.0*s - 15.0*(h - g*ri)*ri)*ri)*ri);
493    
494     break;
495    
496     case esm_SWITCHING_FUNCTION:
497     case esm_HARD:
498 gezelter 1915 case esm_EWALD_FULL:
499 gezelter 1879
500     v01 = f;
501     v11 = g;
502     v21 = g*ri;
503     v22 = h - g*ri;
504     v31 = (h-g*ri)*ri;
505     v32 = (s - 3.0*(h-g*ri)*ri);
506     v41 = (h - g*ri)*ri2;
507     v42 = (s-3.0*(h-g*ri)*ri)*ri;
508     v43 = (t - 3.0*(2.0*s - 5.0*(h - g*ri)*ri)*ri);
509    
510     dv01 = g;
511     dv11 = h;
512     dv21 = (h - g*ri)*ri;
513     dv22 = (s - (h - g*ri)*ri);
514     dv31 = (s - 2.0*(h-g*ri)*ri)*ri;
515     dv32 = (t - 3.0*(s-2.0*(h-g*ri)*ri)*ri);
516     dv41 = (s - 3.0*(h - g*ri)*ri)*ri2;
517     dv42 = (t - (4.0*s - 9.0*(h-g*ri)*ri)*ri)*ri;
518     dv43 = (u - 3.0*(2.0*t - (7.0*s - 15.0*(h - g*ri)*ri)*ri)*ri);
519    
520     break;
521    
522     case esm_REACTION_FIELD:
523    
524     // following DL_POLY's lead for shifting the image charge potential:
525     f = b0 + preRF_ * r2;
526     fc = b0c + preRF_ * cutoffRadius_ * cutoffRadius_;
527    
528     g = db0_1 + preRF_ * 2.0 * r;
529     gc = db0c_1 + preRF_ * 2.0 * cutoffRadius_;
530    
531     h = db0_2 + preRF_ * 2.0;
532     hc = db0c_2 + preRF_ * 2.0;
533    
534     v01 = f - fc;
535     v11 = g - gc;
536     v21 = g*ri - gc*ric;
537     v22 = h - g*ri - (hc - gc*ric);
538 gezelter 1894 v31 = (h-g*ri)*ri - (hc-gc*ric)*ric;
539 gezelter 1879 v32 = (s - 3.0*(h-g*ri)*ri) - (sc - 3.0*(hc-gc*ric)*ric);
540     v41 = (h - g*ri)*ri2 - (hc - gc*ric)*ric2;
541     v42 = (s-3.0*(h-g*ri)*ri)*ri - (sc-3.0*(hc-gc*ric)*ric)*ric;
542     v43 = (t - 3.0*(2.0*s - 5.0*(h - g*ri)*ri)*ri)
543     - (tc - 3.0*(2.0*sc - 5.0*(hc - gc*ric)*ric)*ric);
544    
545     dv01 = g;
546     dv11 = h;
547     dv21 = (h - g*ri)*ri;
548     dv22 = (s - (h - g*ri)*ri);
549     dv31 = (s - 2.0*(h-g*ri)*ri)*ri;
550     dv32 = (t - 3.0*(s-2.0*(h-g*ri)*ri)*ri);
551     dv41 = (s - 3.0*(h - g*ri)*ri)*ri2;
552     dv42 = (t - (4.0*s - 9.0*(h-g*ri)*ri)*ri)*ri;
553     dv43 = (u - 3.0*(2.0*t - (7.0*s - 15.0*(h - g*ri)*ri)*ri)*ri);
554    
555     break;
556    
557     case esm_EWALD_PME:
558     case esm_EWALD_SPME:
559     default :
560     map<string, ElectrostaticSummationMethod>::iterator i;
561     std::string meth;
562     for (i = summationMap_.begin(); i != summationMap_.end(); ++i) {
563     if ((*i).second == summationMethod_) meth = (*i).first;
564     }
565     sprintf( painCave.errMsg,
566     "Electrostatic::initialize: electrostaticSummationMethod %s \n"
567     "\thas not been implemented yet. Please select one of:\n"
568     "\t\"hard\", \"shifted_potential\", or \"shifted_force\"\n",
569     meth.c_str() );
570     painCave.isFatal = 1;
571     simError();
572     break;
573     }
574    
575     // Add these computed values to the storage vectors for spline creation:
576     v01v.push_back(v01);
577     v11v.push_back(v11);
578     v21v.push_back(v21);
579     v22v.push_back(v22);
580     v31v.push_back(v31);
581     v32v.push_back(v32);
582     v41v.push_back(v41);
583     v42v.push_back(v42);
584     v43v.push_back(v43);
585 gezelter 1502 }
586    
587 gezelter 1879 // construct the spline structures and fill them with the values we've
588     // computed:
589    
590     v01s = new CubicSpline();
591     v01s->addPoints(rv, v01v);
592     v11s = new CubicSpline();
593     v11s->addPoints(rv, v11v);
594     v21s = new CubicSpline();
595     v21s->addPoints(rv, v21v);
596     v22s = new CubicSpline();
597     v22s->addPoints(rv, v22v);
598     v31s = new CubicSpline();
599     v31s->addPoints(rv, v31v);
600     v32s = new CubicSpline();
601     v32s->addPoints(rv, v32v);
602     v41s = new CubicSpline();
603     v41s->addPoints(rv, v41v);
604     v42s = new CubicSpline();
605     v42s->addPoints(rv, v42v);
606     v43s = new CubicSpline();
607     v43s->addPoints(rv, v43v);
608    
609     haveElectroSplines_ = true;
610    
611 gezelter 1502 initialized_ = true;
612     }
613    
614     void Electrostatic::addType(AtomType* atomType){
615 gezelter 1895
616 gezelter 1502 ElectrostaticAtomData electrostaticAtomData;
617     electrostaticAtomData.is_Charge = false;
618     electrostaticAtomData.is_Dipole = false;
619     electrostaticAtomData.is_Quadrupole = false;
620 gezelter 1723 electrostaticAtomData.is_Fluctuating = false;
621 gezelter 1502
622 gezelter 1710 FixedChargeAdapter fca = FixedChargeAdapter(atomType);
623 gezelter 1502
624 gezelter 1710 if (fca.isFixedCharge()) {
625 gezelter 1502 electrostaticAtomData.is_Charge = true;
626 gezelter 1720 electrostaticAtomData.fixedCharge = fca.getCharge();
627 gezelter 1502 }
628    
629 gezelter 1710 MultipoleAdapter ma = MultipoleAdapter(atomType);
630     if (ma.isMultipole()) {
631     if (ma.isDipole()) {
632 gezelter 1502 electrostaticAtomData.is_Dipole = true;
633 gezelter 1879 electrostaticAtomData.dipole = ma.getDipole();
634 gezelter 1502 }
635 gezelter 1710 if (ma.isQuadrupole()) {
636 gezelter 1502 electrostaticAtomData.is_Quadrupole = true;
637 gezelter 1879 electrostaticAtomData.quadrupole = ma.getQuadrupole();
638 gezelter 1502 }
639     }
640    
641 gezelter 1718 FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(atomType);
642 gezelter 1502
643 gezelter 1718 if (fqa.isFluctuatingCharge()) {
644 gezelter 1720 electrostaticAtomData.is_Fluctuating = true;
645     electrostaticAtomData.electronegativity = fqa.getElectronegativity();
646     electrostaticAtomData.hardness = fqa.getHardness();
647     electrostaticAtomData.slaterN = fqa.getSlaterN();
648     electrostaticAtomData.slaterZeta = fqa.getSlaterZeta();
649 gezelter 1718 }
650    
651 gezelter 1895 int atid = atomType->getIdent();
652     int etid = Etypes.size();
653     int fqtid = FQtypes.size();
654    
655     pair<set<int>::iterator,bool> ret;
656     ret = Etypes.insert( atid );
657 gezelter 1502 if (ret.second == false) {
658     sprintf( painCave.errMsg,
659     "Electrostatic already had a previous entry with ident %d\n",
660 gezelter 1895 atid);
661 gezelter 1502 painCave.severity = OPENMD_INFO;
662     painCave.isFatal = 0;
663     simError();
664     }
665    
666 gezelter 1895 Etids[ atid ] = etid;
667     ElectrostaticMap.push_back(electrostaticAtomData);
668 gezelter 1718
669 gezelter 1895 if (electrostaticAtomData.is_Fluctuating) {
670     ret = FQtypes.insert( atid );
671     if (ret.second == false) {
672     sprintf( painCave.errMsg,
673     "Electrostatic already had a previous fluctuating charge entry with ident %d\n",
674     atid );
675     painCave.severity = OPENMD_INFO;
676     painCave.isFatal = 0;
677     simError();
678     }
679     FQtids[atid] = fqtid;
680     Jij[fqtid].resize(nFlucq_);
681    
682 gezelter 1921 // Now, iterate over all known fluctuating and add to the
683     // coulomb integral map:
684 gezelter 1895
685     std::set<int>::iterator it;
686     for( it = FQtypes.begin(); it != FQtypes.end(); ++it) {
687     int etid2 = Etids[ (*it) ];
688     int fqtid2 = FQtids[ (*it) ];
689     ElectrostaticAtomData eaData2 = ElectrostaticMap[ etid2 ];
690 gezelter 1718 RealType a = electrostaticAtomData.slaterZeta;
691 gezelter 1720 RealType b = eaData2.slaterZeta;
692 gezelter 1718 int m = electrostaticAtomData.slaterN;
693 gezelter 1720 int n = eaData2.slaterN;
694 gezelter 1895
695 gezelter 1718 // Create the spline of the coulombic integral for s-type
696     // Slater orbitals. Add a 2 angstrom safety window to deal
697     // with cutoffGroups that have charged atoms longer than the
698     // cutoffRadius away from each other.
699 gezelter 1895
700 gezelter 1720 RealType rval;
701 gezelter 1718 RealType dr = (cutoffRadius_ + 2.0) / RealType(np_ - 1);
702     vector<RealType> rvals;
703 gezelter 1879 vector<RealType> Jvals;
704     // don't start at i = 0, as rval = 0 is undefined for the
705     // slater overlap integrals.
706 gezelter 1761 for (int i = 1; i < np_+1; i++) {
707 gezelter 1718 rval = RealType(i) * dr;
708     rvals.push_back(rval);
709 gezelter 1879 Jvals.push_back(sSTOCoulInt( a, b, m, n, rval *
710     PhysicalConstants::angstromToBohr ) *
711     PhysicalConstants::hartreeToKcal );
712 gezelter 1718 }
713    
714 gezelter 1879 CubicSpline* J = new CubicSpline();
715     J->addPoints(rvals, Jvals);
716 gezelter 1895 Jij[fqtid][fqtid2] = J;
717     Jij[fqtid2].resize( nFlucq_ );
718     Jij[fqtid2][fqtid] = J;
719     }
720     }
721 gezelter 1502 return;
722     }
723    
724 gezelter 1584 void Electrostatic::setCutoffRadius( RealType rCut ) {
725     cutoffRadius_ = rCut;
726 gezelter 1528 haveCutoffRadius_ = true;
727 gezelter 1502 }
728 gezelter 1584
729 gezelter 1502 void Electrostatic::setElectrostaticSummationMethod( ElectrostaticSummationMethod esm ) {
730     summationMethod_ = esm;
731     }
732     void Electrostatic::setElectrostaticScreeningMethod( ElectrostaticScreeningMethod sm ) {
733     screeningMethod_ = sm;
734     }
735     void Electrostatic::setDampingAlpha( RealType alpha ) {
736     dampingAlpha_ = alpha;
737     haveDampingAlpha_ = true;
738     }
739     void Electrostatic::setReactionFieldDielectric( RealType dielectric ){
740     dielectric_ = dielectric;
741     haveDielectric_ = true;
742     }
743    
744 gezelter 1536 void Electrostatic::calcForce(InteractionData &idat) {
745 gezelter 1502
746 gezelter 1893 if (!initialized_) initialize();
747    
748 gezelter 1895 data1 = ElectrostaticMap[Etids[idat.atid1]];
749     data2 = ElectrostaticMap[Etids[idat.atid2]];
750 gezelter 1502
751 gezelter 1893 U = 0.0; // Potential
752     F.zero(); // Force
753     Ta.zero(); // Torque on site a
754     Tb.zero(); // Torque on site b
755     Ea.zero(); // Electric field at site a
756     Eb.zero(); // Electric field at site b
757     dUdCa = 0.0; // fluctuating charge force at site a
758     dUdCb = 0.0; // fluctuating charge force at site a
759 gezelter 1879
760     // Indirect interactions mediated by the reaction field.
761 gezelter 1893 indirect_Pot = 0.0; // Potential
762     indirect_F.zero(); // Force
763     indirect_Ta.zero(); // Torque on site a
764     indirect_Tb.zero(); // Torque on site b
765 gezelter 1587
766 gezelter 1879 // Excluded potential that is still computed for fluctuating charges
767 gezelter 1893 excluded_Pot= 0.0;
768 gezelter 1879
769    
770 gezelter 1502 // some variables we'll need independent of electrostatic type:
771    
772 gezelter 1879 ri = 1.0 / *(idat.rij);
773 gezelter 1893 rhat = *(idat.d) * ri;
774 gezelter 1879
775 gezelter 1502 // logicals
776    
777 gezelter 1893 a_is_Charge = data1.is_Charge;
778     a_is_Dipole = data1.is_Dipole;
779     a_is_Quadrupole = data1.is_Quadrupole;
780     a_is_Fluctuating = data1.is_Fluctuating;
781 gezelter 1502
782 gezelter 1893 b_is_Charge = data2.is_Charge;
783     b_is_Dipole = data2.is_Dipole;
784     b_is_Quadrupole = data2.is_Quadrupole;
785     b_is_Fluctuating = data2.is_Fluctuating;
786 gezelter 1879
787     // Obtain all of the required radial function values from the
788     // spline structures:
789 gezelter 1502
790 gezelter 1879 // needed for fields (and forces):
791     if (a_is_Charge || b_is_Charge) {
792     v01s->getValueAndDerivativeAt( *(idat.rij), v01, dv01);
793     }
794     if (a_is_Dipole || b_is_Dipole) {
795     v11s->getValueAndDerivativeAt( *(idat.rij), v11, dv11);
796     v11or = ri * v11;
797     }
798     if (a_is_Quadrupole || b_is_Quadrupole || (a_is_Dipole && b_is_Dipole)) {
799     v21s->getValueAndDerivativeAt( *(idat.rij), v21, dv21);
800     v22s->getValueAndDerivativeAt( *(idat.rij), v22, dv22);
801     v22or = ri * v22;
802     }
803 gezelter 1721
804 gezelter 1879 // needed for potentials (and forces and torques):
805     if ((a_is_Dipole && b_is_Quadrupole) ||
806     (b_is_Dipole && a_is_Quadrupole)) {
807     v31s->getValueAndDerivativeAt( *(idat.rij), v31, dv31);
808     v32s->getValueAndDerivativeAt( *(idat.rij), v32, dv32);
809     v31or = v31 * ri;
810     v32or = v32 * ri;
811     }
812     if (a_is_Quadrupole && b_is_Quadrupole) {
813     v41s->getValueAndDerivativeAt( *(idat.rij), v41, dv41);
814     v42s->getValueAndDerivativeAt( *(idat.rij), v42, dv42);
815     v43s->getValueAndDerivativeAt( *(idat.rij), v43, dv43);
816     v42or = v42 * ri;
817     v43or = v43 * ri;
818     }
819    
820     // calculate the single-site contributions (fields, etc).
821    
822     if (a_is_Charge) {
823     C_a = data1.fixedCharge;
824    
825     if (a_is_Fluctuating) {
826     C_a += *(idat.flucQ1);
827 gezelter 1721 }
828    
829 gezelter 1587 if (idat.excluded) {
830 gezelter 1879 *(idat.skippedCharge2) += C_a;
831     } else {
832     // only do the field if we're not excluded:
833     Eb -= C_a * pre11_ * dv01 * rhat;
834 gezelter 1587 }
835     }
836 gezelter 1879
837     if (a_is_Dipole) {
838     D_a = *(idat.dipole1);
839     rdDa = dot(rhat, D_a);
840     rxDa = cross(rhat, D_a);
841     if (!idat.excluded)
842     Eb -= pre12_ * ((dv11-v11or) * rdDa * rhat + v11or * D_a);
843 gezelter 1502 }
844    
845 gezelter 1879 if (a_is_Quadrupole) {
846     Q_a = *(idat.quadrupole1);
847     trQa = Q_a.trace();
848     Qar = Q_a * rhat;
849     rQa = rhat * Q_a;
850     rdQar = dot(rhat, Qar);
851     rxQar = cross(rhat, Qar);
852     if (!idat.excluded)
853     Eb -= pre14_ * (trQa * rhat * dv21 + 2.0 * Qar * v22or
854     + rdQar * rhat * (dv22 - 2.0*v22or));
855     }
856    
857     if (b_is_Charge) {
858     C_b = data2.fixedCharge;
859 gezelter 1502
860 gezelter 1879 if (b_is_Fluctuating)
861     C_b += *(idat.flucQ2);
862    
863 gezelter 1587 if (idat.excluded) {
864 gezelter 1879 *(idat.skippedCharge1) += C_b;
865     } else {
866     // only do the field if we're not excluded:
867     Ea += C_b * pre11_ * dv01 * rhat;
868 gezelter 1587 }
869     }
870 gezelter 1502
871 gezelter 1879 if (b_is_Dipole) {
872     D_b = *(idat.dipole2);
873     rdDb = dot(rhat, D_b);
874     rxDb = cross(rhat, D_b);
875     if (!idat.excluded)
876     Ea += pre12_ * ((dv11-v11or) * rdDb * rhat + v11or * D_b);
877 gezelter 1502 }
878    
879 gezelter 1879 if (b_is_Quadrupole) {
880     Q_b = *(idat.quadrupole2);
881     trQb = Q_b.trace();
882     Qbr = Q_b * rhat;
883     rQb = rhat * Q_b;
884     rdQbr = dot(rhat, Qbr);
885     rxQbr = cross(rhat, Qbr);
886     if (!idat.excluded)
887     Ea += pre14_ * (trQb * rhat * dv21 + 2.0 * Qbr * v22or
888     + rdQbr * rhat * (dv22 - 2.0*v22or));
889 gezelter 1721 }
890 gezelter 1502
891 gezelter 1879 if ((a_is_Fluctuating || b_is_Fluctuating) && idat.excluded) {
892 gezelter 1895 J = Jij[FQtids[idat.atid1]][FQtids[idat.atid2]];
893 gezelter 1879 }
894    
895     if (a_is_Charge) {
896 gezelter 1502
897 gezelter 1879 if (b_is_Charge) {
898     pref = pre11_ * *(idat.electroMult);
899     U += C_a * C_b * pref * v01;
900     F += C_a * C_b * pref * dv01 * rhat;
901    
902     // If this is an excluded pair, there are still indirect
903     // interactions via the reaction field we must worry about:
904 gezelter 1616
905 gezelter 1879 if (summationMethod_ == esm_REACTION_FIELD && idat.excluded) {
906     rfContrib = preRF_ * pref * C_a * C_b * *(idat.r2);
907     indirect_Pot += rfContrib;
908     indirect_F += rfContrib * 2.0 * ri * rhat;
909 gezelter 1502 }
910    
911 gezelter 1879 // Fluctuating charge forces are handled via Coulomb integrals
912     // for excluded pairs (i.e. those connected via bonds) and
913     // with the standard charge-charge interaction otherwise.
914 gezelter 1502
915 gezelter 1879 if (idat.excluded) {
916     if (a_is_Fluctuating || b_is_Fluctuating) {
917     coulInt = J->getValueAt( *(idat.rij) );
918     if (a_is_Fluctuating) dUdCa += coulInt * C_b;
919     if (b_is_Fluctuating) dUdCb += coulInt * C_a;
920     excluded_Pot += C_a * C_b * coulInt;
921     }
922 gezelter 1502 } else {
923 gezelter 1879 if (a_is_Fluctuating) dUdCa += C_b * pref * v01;
924     if (a_is_Fluctuating) dUdCb += C_a * pref * v01;
925 gezelter 1721 }
926 gezelter 1502 }
927    
928 gezelter 1879 if (b_is_Dipole) {
929     pref = pre12_ * *(idat.electroMult);
930     U += C_a * pref * v11 * rdDb;
931     F += C_a * pref * ((dv11 - v11or) * rdDb * rhat + v11or * D_b);
932     Tb += C_a * pref * v11 * rxDb;
933 gezelter 1502
934 gezelter 1879 if (a_is_Fluctuating) dUdCa += pref * v11 * rdDb;
935 gezelter 1502
936 gezelter 1879 // Even if we excluded this pair from direct interactions, we
937     // still have the reaction-field-mediated charge-dipole
938     // interaction:
939 gezelter 1502
940 gezelter 1879 if (summationMethod_ == esm_REACTION_FIELD && idat.excluded) {
941     rfContrib = C_a * pref * preRF_ * 2.0 * *(idat.rij);
942     indirect_Pot += rfContrib * rdDb;
943     indirect_F += rfContrib * D_b / (*idat.rij);
944     indirect_Tb += C_a * pref * preRF_ * rxDb;
945 gezelter 1502 }
946     }
947    
948 gezelter 1879 if (b_is_Quadrupole) {
949     pref = pre14_ * *(idat.electroMult);
950     U += C_a * pref * (v21 * trQb + v22 * rdQbr);
951     F += C_a * pref * (trQb * dv21 * rhat + 2.0 * Qbr * v22or);
952     F += C_a * pref * rdQbr * rhat * (dv22 - 2.0*v22or);
953     Tb += C_a * pref * 2.0 * rxQbr * v22;
954 gezelter 1502
955 gezelter 1879 if (a_is_Fluctuating) dUdCa += pref * (v21 * trQb + v22 * rdQbr);
956 gezelter 1502 }
957     }
958    
959 gezelter 1879 if (a_is_Dipole) {
960 gezelter 1502
961 gezelter 1879 if (b_is_Charge) {
962     pref = pre12_ * *(idat.electroMult);
963 gezelter 1502
964 gezelter 1879 U -= C_b * pref * v11 * rdDa;
965     F -= C_b * pref * ((dv11-v11or) * rdDa * rhat + v11or * D_a);
966     Ta -= C_b * pref * v11 * rxDa;
967 gezelter 1502
968 gezelter 1879 if (b_is_Fluctuating) dUdCb -= pref * v11 * rdDa;
969 gezelter 1587
970 gezelter 1879 // Even if we excluded this pair from direct interactions,
971     // we still have the reaction-field-mediated charge-dipole
972     // interaction:
973     if (summationMethod_ == esm_REACTION_FIELD && idat.excluded) {
974     rfContrib = C_b * pref * preRF_ * 2.0 * *(idat.rij);
975     indirect_Pot -= rfContrib * rdDa;
976     indirect_F -= rfContrib * D_a / (*idat.rij);
977     indirect_Ta -= C_b * pref * preRF_ * rxDa;
978     }
979     }
980 gezelter 1587
981 gezelter 1879 if (b_is_Dipole) {
982     pref = pre22_ * *(idat.electroMult);
983     DadDb = dot(D_a, D_b);
984     DaxDb = cross(D_a, D_b);
985 gezelter 1502
986 gezelter 1879 U -= pref * (DadDb * v21 + rdDa * rdDb * v22);
987     F -= pref * (dv21 * DadDb * rhat + v22or * (rdDb * D_a + rdDa * D_b));
988     F -= pref * (rdDa * rdDb) * (dv22 - 2.0*v22or) * rhat;
989     Ta += pref * ( v21 * DaxDb - v22 * rdDb * rxDa);
990     Tb += pref * (-v21 * DaxDb - v22 * rdDa * rxDb);
991 gezelter 1723
992 gezelter 1879 // Even if we excluded this pair from direct interactions, we
993     // still have the reaction-field-mediated dipole-dipole
994     // interaction:
995     if (summationMethod_ == esm_REACTION_FIELD && idat.excluded) {
996     rfContrib = -pref * preRF_ * 2.0;
997     indirect_Pot += rfContrib * DadDb;
998     indirect_Ta += rfContrib * DaxDb;
999     indirect_Tb -= rfContrib * DaxDb;
1000 gezelter 1723 }
1001 gezelter 1502 }
1002    
1003 gezelter 1879 if (b_is_Quadrupole) {
1004     pref = pre24_ * *(idat.electroMult);
1005     DadQb = D_a * Q_b;
1006     DadQbr = dot(D_a, Qbr);
1007     DaxQbr = cross(D_a, Qbr);
1008 gezelter 1502
1009 gezelter 1879 U -= pref * ((trQb*rdDa + 2.0*DadQbr)*v31 + rdDa*rdQbr*v32);
1010     F -= pref * (trQb*D_a + 2.0*DadQb) * v31or;
1011     F -= pref * (trQb*rdDa + 2.0*DadQbr) * (dv31-v31or) * rhat;
1012     F -= pref * (D_a*rdQbr + 2.0*rdDa*rQb) * v32or;
1013     F -= pref * (rdDa * rdQbr * rhat * (dv32-3.0*v32or));
1014     Ta += pref * ((-trQb*rxDa + 2.0 * DaxQbr)*v31 - rxDa*rdQbr*v32);
1015     Tb += pref * ((2.0*cross(DadQb, rhat) - 2.0*DaxQbr)*v31
1016     - 2.0*rdDa*rxQbr*v32);
1017     }
1018     }
1019 gezelter 1502
1020 gezelter 1879 if (a_is_Quadrupole) {
1021     if (b_is_Charge) {
1022     pref = pre14_ * *(idat.electroMult);
1023     U += C_b * pref * (v21 * trQa + v22 * rdQar);
1024     F += C_b * pref * (trQa * rhat * dv21 + 2.0 * Qar * v22or);
1025     F += C_b * pref * rdQar * rhat * (dv22 - 2.0*v22or);
1026     Ta += C_b * pref * 2.0 * rxQar * v22;
1027 gezelter 1502
1028 gezelter 1879 if (b_is_Fluctuating) dUdCb += pref * (v21 * trQa + v22 * rdQar);
1029     }
1030     if (b_is_Dipole) {
1031     pref = pre24_ * *(idat.electroMult);
1032     DbdQa = D_b * Q_a;
1033     DbdQar = dot(D_b, Qar);
1034     DbxQar = cross(D_b, Qar);
1035 gezelter 1502
1036 gezelter 1879 U += pref * ((trQa*rdDb + 2.0*DbdQar)*v31 + rdDb*rdQar*v32);
1037     F += pref * (trQa*D_b + 2.0*DbdQa) * v31or;
1038     F += pref * (trQa*rdDb + 2.0*DbdQar) * (dv31-v31or) * rhat;
1039     F += pref * (D_b*rdQar + 2.0*rdDb*rQa) * v32or;
1040     F += pref * (rdDb * rdQar * rhat * (dv32-3.0*v32or));
1041     Ta += pref * ((-2.0*cross(DbdQa, rhat) + 2.0*DbxQar)*v31
1042     + 2.0*rdDb*rxQar*v32);
1043     Tb += pref * ((trQa*rxDb - 2.0 * DbxQar)*v31 + rxDb*rdQar*v32);
1044 gezelter 1502 }
1045 gezelter 1879 if (b_is_Quadrupole) {
1046     pref = pre44_ * *(idat.electroMult); // yes
1047     QaQb = Q_a * Q_b;
1048     trQaQb = QaQb.trace();
1049     rQaQb = rhat * QaQb;
1050     QaQbr = QaQb * rhat;
1051     QaxQb = cross(Q_a, Q_b);
1052     rQaQbr = dot(rQa, Qbr);
1053     rQaxQbr = cross(rQa, Qbr);
1054    
1055     U += pref * (trQa * trQb + 2.0 * trQaQb) * v41;
1056     U += pref * (trQa * rdQbr + trQb * rdQar + 4.0 * rQaQbr) * v42;
1057     U += pref * (rdQar * rdQbr) * v43;
1058 gezelter 1502
1059 gezelter 1879 F += pref * rhat * (trQa * trQb + 2.0 * trQaQb)*dv41;
1060     F += pref*rhat*(trQa*rdQbr + trQb*rdQar + 4.0*rQaQbr)*(dv42-2.0*v42or);
1061     F += pref * rhat * (rdQar * rdQbr)*(dv43 - 4.0*v43or);
1062 gezelter 1502
1063 gezelter 1879 F += pref * 2.0 * (trQb*rQa + trQa*rQb) * v42or;
1064     F += pref * 4.0 * (rQaQb + QaQbr) * v42or;
1065     F += pref * 2.0 * (rQa*rdQbr + rdQar*rQb) * v43or;
1066 gezelter 1502
1067 gezelter 1879 Ta += pref * (- 4.0 * QaxQb * v41);
1068     Ta += pref * (- 2.0 * trQb * cross(rQa, rhat)
1069     + 4.0 * cross(rhat, QaQbr)
1070     - 4.0 * rQaxQbr) * v42;
1071     Ta += pref * 2.0 * cross(rhat,Qar) * rdQbr * v43;
1072 gezelter 1502
1073    
1074 gezelter 1879 Tb += pref * (+ 4.0 * QaxQb * v41);
1075     Tb += pref * (- 2.0 * trQa * cross(rQb, rhat)
1076     - 4.0 * cross(rQaQb, rhat)
1077     + 4.0 * rQaxQbr) * v42;
1078     // Possible replacement for line 2 above:
1079     // + 4.0 * cross(rhat, QbQar)
1080 gezelter 1502
1081 gezelter 1879 Tb += pref * 2.0 * cross(rhat,Qbr) * rdQar * v43;
1082 gezelter 1502
1083     }
1084     }
1085    
1086 gezelter 1879 if (idat.doElectricField) {
1087     *(idat.eField1) += Ea * *(idat.electroMult);
1088     *(idat.eField2) += Eb * *(idat.electroMult);
1089     }
1090 gezelter 1502
1091 gezelter 1879 if (a_is_Fluctuating) *(idat.dVdFQ1) += dUdCa * *(idat.sw);
1092     if (b_is_Fluctuating) *(idat.dVdFQ2) += dUdCb * *(idat.sw);
1093    
1094 gezelter 1587 if (!idat.excluded) {
1095    
1096 gezelter 1879 *(idat.vpair) += U;
1097     (*(idat.pot))[ELECTROSTATIC_FAMILY] += U * *(idat.sw);
1098     *(idat.f1) += F * *(idat.sw);
1099 gezelter 1587
1100 gezelter 1879 if (a_is_Dipole || a_is_Quadrupole)
1101     *(idat.t1) += Ta * *(idat.sw);
1102 gezelter 1587
1103 gezelter 1879 if (b_is_Dipole || b_is_Quadrupole)
1104     *(idat.t2) += Tb * *(idat.sw);
1105    
1106 gezelter 1587 } else {
1107    
1108     // only accumulate the forces and torques resulting from the
1109     // indirect reaction field terms.
1110 gezelter 1616
1111 gezelter 1879 *(idat.vpair) += indirect_Pot;
1112     (*(idat.excludedPot))[ELECTROSTATIC_FAMILY] += excluded_Pot;
1113     (*(idat.pot))[ELECTROSTATIC_FAMILY] += *(idat.sw) * indirect_Pot;
1114     *(idat.f1) += *(idat.sw) * indirect_F;
1115 gezelter 1761
1116 gezelter 1879 if (a_is_Dipole || a_is_Quadrupole)
1117     *(idat.t1) += *(idat.sw) * indirect_Ta;
1118    
1119     if (b_is_Dipole || b_is_Quadrupole)
1120     *(idat.t2) += *(idat.sw) * indirect_Tb;
1121 gezelter 1502 }
1122     return;
1123 gezelter 1879 }
1124 gezelter 1502
1125 gezelter 1545 void Electrostatic::calcSelfCorrection(SelfData &sdat) {
1126 gezelter 1879
1127 gezelter 1502 if (!initialized_) initialize();
1128 gezelter 1586
1129 gezelter 1895 ElectrostaticAtomData data = ElectrostaticMap[Etids[sdat.atid]];
1130 gezelter 1879
1131 gezelter 1502 // logicals
1132     bool i_is_Charge = data.is_Charge;
1133     bool i_is_Dipole = data.is_Dipole;
1134 gezelter 1900 bool i_is_Quadrupole = data.is_Quadrupole;
1135 jmichalk 1734 bool i_is_Fluctuating = data.is_Fluctuating;
1136 gezelter 1879 RealType C_a = data.fixedCharge;
1137 gezelter 1900 RealType self(0.0), preVal, DdD, trQ, trQQ;
1138    
1139     if (i_is_Dipole) {
1140     DdD = data.dipole.lengthSquare();
1141     }
1142    
1143 jmichalk 1734 if (i_is_Fluctuating) {
1144 gezelter 1879 C_a += *(sdat.flucQ);
1145 jmichalk 1734 // dVdFQ is really a force, so this is negative the derivative
1146     *(sdat.dVdFQ) -= *(sdat.flucQ) * data.hardness + data.electronegativity;
1147 gezelter 1761 (*(sdat.excludedPot))[ELECTROSTATIC_FAMILY] += (*sdat.flucQ) *
1148     (*(sdat.flucQ) * data.hardness * 0.5 + data.electronegativity);
1149 jmichalk 1734 }
1150 gezelter 1502
1151 gezelter 1879 switch (summationMethod_) {
1152     case esm_REACTION_FIELD:
1153    
1154     if (i_is_Charge) {
1155     // Self potential [see Wang and Hermans, "Reaction Field
1156     // Molecular Dynamics Simulation with Friedman’s Image Charge
1157     // Method," J. Phys. Chem. 99, 12001-12007 (1995).]
1158     preVal = pre11_ * preRF_ * C_a * C_a;
1159     (*(sdat.pot))[ELECTROSTATIC_FAMILY] -= 0.5 * preVal / cutoffRadius_;
1160     }
1161    
1162 gezelter 1502 if (i_is_Dipole) {
1163 gezelter 1900 (*(sdat.pot))[ELECTROSTATIC_FAMILY] -= pre22_ * preRF_ * DdD;
1164 gezelter 1502 }
1165 gezelter 1879
1166     break;
1167    
1168     case esm_SHIFTED_FORCE:
1169     case esm_SHIFTED_POTENTIAL:
1170 gezelter 1907 case esm_TAYLOR_SHIFTED:
1171 gezelter 1921 case esm_EWALD_FULL:
1172 gezelter 1900 if (i_is_Charge)
1173     self += selfMult1_ * pre11_ * C_a * (C_a + *(sdat.skippedCharge));
1174     if (i_is_Dipole)
1175     self += selfMult2_ * pre22_ * DdD;
1176     if (i_is_Quadrupole) {
1177     trQ = data.quadrupole.trace();
1178     trQQ = (data.quadrupole * data.quadrupole).trace();
1179     self += selfMult4_ * pre44_ * (2.0*trQQ + trQ*trQ);
1180     if (i_is_Charge)
1181     self -= selfMult2_ * pre14_ * 2.0 * C_a * trQ;
1182 gezelter 1502 }
1183 gezelter 1900 (*(sdat.pot))[ELECTROSTATIC_FAMILY] += self;
1184 gezelter 1879 break;
1185     default:
1186     break;
1187 gezelter 1502 }
1188     }
1189 gezelter 1879
1190 gezelter 1545 RealType Electrostatic::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
1191 gezelter 1505 // This seems to work moderately well as a default. There's no
1192     // inherent scale for 1/r interactions that we can standardize.
1193     // 12 angstroms seems to be a reasonably good guess for most
1194     // cases.
1195     return 12.0;
1196     }
1197 gezelter 1915
1198    
1199 gezelter 1925 void Electrostatic::ReciprocalSpaceSum(RealType& pot) {
1200 gezelter 1915
1201     RealType kPot = 0.0;
1202     RealType kVir = 0.0;
1203    
1204     const RealType mPoleConverter = 0.20819434; // converts from the
1205     // internal units of
1206     // Debye (for dipoles)
1207     // or Debye-angstroms
1208     // (for quadrupoles) to
1209     // electron angstroms or
1210     // electron-angstroms^2
1211    
1212     const RealType eConverter = 332.0637778; // convert the
1213     // Charge-Charge
1214     // electrostatic
1215     // interactions into kcal /
1216     // mol assuming distances
1217     // are measured in
1218     // angstroms.
1219    
1220     Mat3x3d hmat = info_->getSnapshotManager()->getCurrentSnapshot()->getHmat();
1221     Vector3d box = hmat.diagonals();
1222     RealType boxMax = box.max();
1223    
1224 gezelter 1921 //int kMax = int(2.0 * M_PI / (pow(dampingAlpha_,2)*cutoffRadius_ * boxMax) );
1225 gezelter 1922 int kMax = 7;
1226 gezelter 1915 int kSqMax = kMax*kMax + 2;
1227    
1228     int kLimit = kMax+1;
1229     int kLim2 = 2*kMax+1;
1230     int kSqLim = kSqMax;
1231    
1232     vector<RealType> AK(kSqLim+1, 0.0);
1233     RealType xcl = 2.0 * M_PI / box.x();
1234     RealType ycl = 2.0 * M_PI / box.y();
1235     RealType zcl = 2.0 * M_PI / box.z();
1236     RealType rcl = 2.0 * M_PI / boxMax;
1237     RealType rvol = 2.0 * M_PI /(box.x() * box.y() * box.z());
1238    
1239     if(dampingAlpha_ < 1.0e-12) return;
1240    
1241     RealType ralph = -0.25/pow(dampingAlpha_,2);
1242    
1243     // Calculate and store exponential factors
1244    
1245 gezelter 1925 vector<vector<RealType> > elc;
1246     vector<vector<RealType> > emc;
1247     vector<vector<RealType> > enc;
1248     vector<vector<RealType> > els;
1249     vector<vector<RealType> > ems;
1250     vector<vector<RealType> > ens;
1251    
1252 gezelter 1915
1253     int nMax = info_->getNAtoms();
1254    
1255 gezelter 1925 elc.resize(kLimit+1);
1256     emc.resize(kLimit+1);
1257     enc.resize(kLimit+1);
1258     els.resize(kLimit+1);
1259     ems.resize(kLimit+1);
1260     ens.resize(kLimit+1);
1261    
1262 gezelter 1915 for (int j = 0; j < kLimit+1; j++) {
1263 gezelter 1925 elc[j].resize(nMax);
1264     emc[j].resize(nMax);
1265     enc[j].resize(nMax);
1266     els[j].resize(nMax);
1267     ems[j].resize(nMax);
1268     ens[j].resize(nMax);
1269 gezelter 1915 }
1270    
1271     Vector3d t( 2.0 * M_PI );
1272     t.Vdiv(t, box);
1273 gezelter 1922
1274 gezelter 1915
1275     SimInfo::MoleculeIterator mi;
1276     Molecule::AtomIterator ai;
1277     int i;
1278     Vector3d r;
1279     Vector3d tt;
1280    
1281     for (Molecule* mol = info_->beginMolecule(mi); mol != NULL;
1282     mol = info_->nextMolecule(mi)) {
1283     for(Atom* atom = mol->beginAtom(ai); atom != NULL;
1284     atom = mol->nextAtom(ai)) {
1285    
1286     i = atom->getLocalIndex();
1287     r = atom->getPos();
1288     info_->getSnapshotManager()->getCurrentSnapshot()->wrapVector(r);
1289    
1290     tt.Vmul(t, r);
1291 gezelter 1921
1292 gezelter 1925 elc[1][i] = 1.0;
1293     emc[1][i] = 1.0;
1294     enc[1][i] = 1.0;
1295     els[1][i] = 0.0;
1296     ems[1][i] = 0.0;
1297     ens[1][i] = 0.0;
1298 gezelter 1922
1299 gezelter 1925 elc[2][i] = cos(tt.x());
1300     emc[2][i] = cos(tt.y());
1301     enc[2][i] = cos(tt.z());
1302     els[2][i] = sin(tt.x());
1303     ems[2][i] = sin(tt.y());
1304     ens[2][i] = sin(tt.z());
1305 gezelter 1915
1306     for(int l = 3; l <= kLimit; l++) {
1307 gezelter 1925 elc[l][i]=elc[l-1][i]*elc[2][i]-els[l-1][i]*els[2][i];
1308     emc[l][i]=emc[l-1][i]*emc[2][i]-ems[l-1][i]*ems[2][i];
1309     enc[l][i]=enc[l-1][i]*enc[2][i]-ens[l-1][i]*ens[2][i];
1310     els[l][i]=els[l-1][i]*elc[2][i]+elc[l-1][i]*els[2][i];
1311     ems[l][i]=ems[l-1][i]*emc[2][i]+emc[l-1][i]*ems[2][i];
1312     ens[l][i]=ens[l-1][i]*enc[2][i]+enc[l-1][i]*ens[2][i];
1313 gezelter 1915 }
1314     }
1315     }
1316    
1317     // Calculate and store AK coefficients:
1318    
1319     RealType eksq = 1.0;
1320     RealType expf = 0.0;
1321     if (ralph < 0.0) expf = exp(ralph*rcl*rcl);
1322     for (i = 1; i <= kSqLim; i++) {
1323     RealType rksq = float(i)*rcl*rcl;
1324     eksq = expf*eksq;
1325     AK[i] = eConverter * eksq/rksq;
1326     }
1327    
1328     /*
1329     * Loop over all k vectors k = 2 pi (ll/Lx, mm/Ly, nn/Lz)
1330     * the values of ll, mm and nn are selected so that the symmetry of
1331     * reciprocal lattice is taken into account i.e. the following
1332     * rules apply.
1333     *
1334     * ll ranges over the values 0 to kMax only.
1335     *
1336     * mm ranges over 0 to kMax when ll=0 and over
1337     * -kMax to kMax otherwise.
1338     * nn ranges over 1 to kMax when ll=mm=0 and over
1339     * -kMax to kMax otherwise.
1340     *
1341     * Hence the result of the summation must be doubled at the end.
1342     */
1343    
1344     std::vector<RealType> clm(nMax, 0.0);
1345     std::vector<RealType> slm(nMax, 0.0);
1346     std::vector<RealType> ckr(nMax, 0.0);
1347     std::vector<RealType> skr(nMax, 0.0);
1348     std::vector<RealType> ckc(nMax, 0.0);
1349     std::vector<RealType> cks(nMax, 0.0);
1350     std::vector<RealType> dkc(nMax, 0.0);
1351     std::vector<RealType> dks(nMax, 0.0);
1352     std::vector<RealType> qkc(nMax, 0.0);
1353     std::vector<RealType> qks(nMax, 0.0);
1354     std::vector<Vector3d> dxk(nMax, V3Zero);
1355     std::vector<Vector3d> qxk(nMax, V3Zero);
1356 gezelter 1925 RealType rl, rm, rn;
1357     Vector3d kVec;
1358     Vector3d Qk;
1359     Mat3x3d k2;
1360     RealType ckcs, ckss, dkcs, dkss, qkcs, qkss;
1361     int atid;
1362     ElectrostaticAtomData data;
1363     RealType C, dk, qk;
1364     Vector3d D;
1365     Mat3x3d Q;
1366    
1367 gezelter 1915 int mMin = kLimit;
1368     int nMin = kLimit + 1;
1369     for (int l = 1; l <= kLimit; l++) {
1370 gezelter 1922 int ll = l - 1;
1371 gezelter 1925 rl = xcl * float(ll);
1372 gezelter 1915 for (int mmm = mMin; mmm <= kLim2; mmm++) {
1373     int mm = mmm - kLimit;
1374     int m = abs(mm) + 1;
1375 gezelter 1925 rm = ycl * float(mm);
1376 gezelter 1915 // Set temporary products of exponential terms
1377     for (Molecule* mol = info_->beginMolecule(mi); mol != NULL;
1378     mol = info_->nextMolecule(mi)) {
1379     for(Atom* atom = mol->beginAtom(ai); atom != NULL;
1380     atom = mol->nextAtom(ai)) {
1381    
1382     i = atom->getLocalIndex();
1383     if(mm < 0) {
1384 gezelter 1925 clm[i]=elc[l][i]*emc[m][i]+els[l][i]*ems[m][i];
1385     slm[i]=els[l][i]*emc[m][i]-ems[m][i]*elc[l][i];
1386 gezelter 1915 } else {
1387 gezelter 1925 clm[i]=elc[l][i]*emc[m][i]-els[l][i]*ems[m][i];
1388     slm[i]=els[l][i]*emc[m][i]+ems[m][i]*elc[l][i];
1389 gezelter 1915 }
1390     }
1391     }
1392     for (int nnn = nMin; nnn <= kLim2; nnn++) {
1393     int nn = nnn - kLimit;
1394     int n = abs(nn) + 1;
1395 gezelter 1925 rn = zcl * float(nn);
1396 gezelter 1915 // Test on magnitude of k vector:
1397     int kk=ll*ll + mm*mm + nn*nn;
1398     if(kk <= kSqLim) {
1399 gezelter 1925 kVec = Vector3d(rl, rm, rn);
1400     k2 = outProduct(kVec, kVec);
1401 gezelter 1915 // Calculate exp(ikr) terms
1402     for (Molecule* mol = info_->beginMolecule(mi); mol != NULL;
1403     mol = info_->nextMolecule(mi)) {
1404     for(Atom* atom = mol->beginAtom(ai); atom != NULL;
1405     atom = mol->nextAtom(ai)) {
1406     i = atom->getLocalIndex();
1407    
1408     if (nn < 0) {
1409 gezelter 1925 ckr[i]=clm[i]*enc[n][i]+slm[i]*ens[n][i];
1410     skr[i]=slm[i]*enc[n][i]-clm[i]*ens[n][i];
1411    
1412 gezelter 1915 } else {
1413 gezelter 1925 ckr[i]=clm[i]*enc[n][i]-slm[i]*ens[n][i];
1414     skr[i]=slm[i]*enc[n][i]+clm[i]*ens[n][i];
1415 gezelter 1915 }
1416     }
1417     }
1418    
1419     // Calculate scalar and vector products for each site:
1420    
1421     for (Molecule* mol = info_->beginMolecule(mi); mol != NULL;
1422     mol = info_->nextMolecule(mi)) {
1423     for(Atom* atom = mol->beginAtom(ai); atom != NULL;
1424     atom = mol->nextAtom(ai)) {
1425 gezelter 1921 i = atom->getLocalIndex();
1426 gezelter 1915 int atid = atom->getAtomType()->getIdent();
1427 gezelter 1925 data = ElectrostaticMap[Etids[atid]];
1428 gezelter 1915
1429     if (data.is_Charge) {
1430 gezelter 1925 C = data.fixedCharge;
1431 gezelter 1915 if (atom->isFluctuatingCharge()) C += atom->getFlucQPos();
1432     ckc[i] = C * ckr[i];
1433 gezelter 1921 cks[i] = C * skr[i];
1434 gezelter 1915 }
1435    
1436     if (data.is_Dipole) {
1437 gezelter 1925 D = atom->getDipole() * mPoleConverter;
1438     dk = dot(D, kVec);
1439 gezelter 1924 dxk[i] = cross(D, kVec);
1440 gezelter 1915 dkc[i] = dk * ckr[i];
1441     dks[i] = dk * skr[i];
1442     }
1443     if (data.is_Quadrupole) {
1444 gezelter 1925 Q = atom->getQuadrupole();
1445 gezelter 1915 Q *= mPoleConverter;
1446 gezelter 1925 Qk = Q * kVec;
1447     qk = dot(kVec, Qk);
1448     qxk[i] = cross(kVec, Qk);
1449 gezelter 1915 qkc[i] = qk * ckr[i];
1450     qks[i] = qk * skr[i];
1451     }
1452     }
1453     }
1454 gezelter 1921
1455 gezelter 1915 // calculate vector sums
1456    
1457 gezelter 1925 ckcs = std::accumulate(ckc.begin(),ckc.end(),0.0);
1458     ckss = std::accumulate(cks.begin(),cks.end(),0.0);
1459     dkcs = std::accumulate(dkc.begin(),dkc.end(),0.0);
1460     dkss = std::accumulate(dks.begin(),dks.end(),0.0);
1461     qkcs = std::accumulate(qkc.begin(),qkc.end(),0.0);
1462     qkss = std::accumulate(qks.begin(),qks.end(),0.0);
1463 gezelter 1915
1464     #ifdef IS_MPI
1465     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &ckcs, 1, MPI::REALTYPE,
1466     MPI::SUM);
1467     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &ckss, 1, MPI::REALTYPE,
1468     MPI::SUM);
1469     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &dkcs, 1, MPI::REALTYPE,
1470     MPI::SUM);
1471     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &dkss, 1, MPI::REALTYPE,
1472     MPI::SUM);
1473     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &qkcs, 1, MPI::REALTYPE,
1474     MPI::SUM);
1475     MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &qkss, 1, MPI::REALTYPE,
1476     MPI::SUM);
1477     #endif
1478    
1479 gezelter 1923 // Accumulate potential energy and virial contribution:
1480 gezelter 1921
1481 gezelter 1925 kPot += 2.0 * rvol * AK[kk]*((ckss+dkcs-qkss)*(ckss+dkcs-qkss)
1482     + (ckcs-dkss-qkcs)*(ckcs-dkss-qkcs));
1483 gezelter 1921
1484 gezelter 1925 kVir += 2.0 * rvol * AK[kk]*(ckcs*ckcs+ckss*ckss
1485     +4.0*(ckss*dkcs-ckcs*dkss)
1486     +3.0*(dkcs*dkcs+dkss*dkss)
1487     -6.0*(ckss*qkss+ckcs*qkcs)
1488     +8.0*(dkss*qkcs-dkcs*qkss)
1489     +5.0*(qkss*qkss+qkcs*qkcs));
1490 gezelter 1915
1491     // Calculate force and torque for each site:
1492    
1493     for (Molecule* mol = info_->beginMolecule(mi); mol != NULL;
1494     mol = info_->nextMolecule(mi)) {
1495     for(Atom* atom = mol->beginAtom(ai); atom != NULL;
1496     atom = mol->nextAtom(ai)) {
1497    
1498     i = atom->getLocalIndex();
1499 gezelter 1925 atid = atom->getAtomType()->getIdent();
1500     data = ElectrostaticMap[Etids[atid]];
1501    
1502 gezelter 1915 RealType qfrc = AK[kk]*((cks[i]+dkc[i]-qks[i])*(ckcs-dkss-qkcs)
1503 gezelter 1922 - (ckc[i]-dks[i]-qkc[i])*(ckss+dkcs-qkss));
1504 gezelter 1915 RealType qtrq1 = AK[kk]*(skr[i]*(ckcs-dkss-qkcs)
1505     -ckr[i]*(ckss+dkcs-qkss));
1506 gezelter 1925 RealType qtrq2 = 2.0*AK[kk]*(ckr[i]*(ckcs-dkss-qkcs)
1507     +skr[i]*(ckss+dkcs-qkss));
1508 gezelter 1923
1509 gezelter 1915 atom->addFrc( 4.0 * rvol * qfrc * kVec );
1510    
1511     if (data.is_Dipole) {
1512     atom->addTrq( 4.0 * rvol * qtrq1 * dxk[i] );
1513     }
1514     if (data.is_Quadrupole) {
1515     atom->addTrq( 4.0 * rvol * qtrq2 * qxk[i] );
1516     }
1517     }
1518     }
1519     }
1520     }
1521 gezelter 1922 nMin = 1;
1522 gezelter 1915 }
1523 gezelter 1922 mMin = 1;
1524 gezelter 1915 }
1525 gezelter 1925 pot += kPot;
1526 gezelter 1915 }
1527 gezelter 1502 }

Properties

Name Value
svn:eol-style native