ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/nonbonded/GB.cpp
Revision: 1875
Committed: Fri May 17 14:41:42 2013 UTC (12 years, 2 months ago) by gezelter
File size: 15575 byte(s)
Log Message:
Fixed a bunch of stylistic and performance issues discovered via cppcheck.

File Contents

# Content
1 /*
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 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
39 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 */
42
43 #include <stdio.h>
44 #include <string.h>
45
46 #include <cmath>
47 #include "nonbonded/GB.hpp"
48 #include "utils/simError.h"
49 #include "types/LennardJonesAdapter.hpp"
50 #include "types/GayBerneAdapter.hpp"
51
52 using namespace std;
53 namespace OpenMD {
54
55 /* GB is the Gay-Berne interaction for ellipsoidal particles. The original
56 * paper (for identical uniaxial particles) is:
57 * J. G. Gay and B. J. Berne, J. Chem. Phys., 74, 3316-3319 (1981).
58 * A more-general GB potential for dissimilar uniaxial particles:
59 * D. J. Cleaver, C. M. Care, M. P. Allen and M. P. Neal, Phys. Rev. E,
60 * 54, 559-567 (1996).
61 * Further parameterizations can be found in:
62 * A. P. J. Emerson, G. R. Luckhurst and S. G. Whatling, Mol. Phys.,
63 * 82, 113-124 (1994).
64 * And a nice force expression:
65 * G. R. Luckhurst and R. A. Stephens, Liq. Cryst. 8, 451-464 (1990).
66 * Even clearer force and torque expressions:
67 * P. A. Golubkov and P. Y. Ren, J. Chem. Phys., 125, 64103 (2006).
68 * New expressions for cross interactions of strength parameters:
69 * J. Wu, X. Zhen, H. Shen, G. Li, and P. Ren, J. Chem. Phys.,
70 * 135, 155104 (2011).
71 *
72 * In this version of the GB interaction, each uniaxial ellipsoidal type
73 * is described using a set of 6 parameters:
74 * d: range parameter for side-by-side (S) and cross (X) configurations
75 * l: range parameter for end-to-end (E) configuration
76 * epsilon_X: well-depth parameter for cross (X) configuration
77 * epsilon_S: well-depth parameter for side-by-side (S) configuration
78 * epsilon_E: well depth parameter for end-to-end (E) configuration
79 * dw: "softness" of the potential
80 *
81 * Additionally, there are two "universal" paramters to govern the overall
82 * importance of the purely orientational (nu) and the mixed
83 * orientational / translational (mu) parts of strength of the interactions.
84 * These parameters have default or "canonical" values, but may be changed
85 * as a force field option:
86 * nu_: purely orientational part : defaults to 1
87 * mu_: mixed orientational / translational part : defaults to 2
88 */
89
90
91 GB::GB() : name_("GB"), initialized_(false), mu_(2.0), nu_(1.0), forceField_(NULL) {}
92
93 void GB::initialize() {
94
95 ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
96 mu_ = fopts.getGayBerneMu();
97 nu_ = fopts.getGayBerneNu();
98 ForceField::AtomTypeContainer* atomTypes = forceField_->getAtomTypes();
99 ForceField::AtomTypeContainer::MapTypeIterator i;
100 AtomType* at;
101
102 // GB handles all of the GB-GB interactions as well as GB-LJ cross
103 // interactions:
104
105 for (at = atomTypes->beginType(i); at != NULL;
106 at = atomTypes->nextType(i)) {
107
108 LennardJonesAdapter lja = LennardJonesAdapter(at);
109 GayBerneAdapter gba = GayBerneAdapter(at);
110
111 if (gba.isGayBerne() || lja.isLennardJones())
112 addType(at);
113 }
114
115 initialized_ = true;
116 }
117
118 void GB::addType(AtomType* atomType){
119 // add it to the map:
120
121 pair<map<int,AtomType*>::iterator,bool> ret;
122 ret = GBMap.insert( pair<int, AtomType*>(atomType->getIdent(), atomType) );
123 if (ret.second == false) {
124 sprintf( painCave.errMsg,
125 "GB already had a previous entry with ident %d\n",
126 atomType->getIdent() );
127 painCave.severity = OPENMD_INFO;
128 painCave.isFatal = 0;
129 simError();
130 }
131
132 RealType d1, l1, eX1, eS1, eE1, dw1;
133
134 LennardJonesAdapter lja1 = LennardJonesAdapter(atomType);
135 GayBerneAdapter gba1 = GayBerneAdapter(atomType);
136 if (gba1.isGayBerne()) {
137 d1 = gba1.getD();
138 l1 = gba1.getL();
139 eX1 = gba1.getEpsX();
140 eS1 = gba1.getEpsS();
141 eE1 = gba1.getEpsE();
142 dw1 = gba1.getDw();
143 } else if (lja1.isLennardJones()) {
144 d1 = lja1.getSigma() / sqrt(2.0);
145 l1 = d1;
146 eX1 = lja1.getEpsilon();
147 eS1 = eX1;
148 eE1 = eX1;
149 dw1 = 1.0;
150 } else {
151 sprintf( painCave.errMsg,
152 "GB::addType was passed an atomType (%s) that does not\n"
153 "\tappear to be a Gay-Berne or Lennard-Jones atom.\n",
154 atomType->getName().c_str());
155 painCave.severity = OPENMD_ERROR;
156 painCave.isFatal = 1;
157 simError();
158 }
159
160
161 // Now, iterate over all known types and add to the mixing map:
162
163 map<int, AtomType*>::iterator it;
164 for( it = GBMap.begin(); it != GBMap.end(); ++it) {
165
166 AtomType* atype2 = (*it).second;
167 LennardJonesAdapter lja2 = LennardJonesAdapter(atype2);
168 GayBerneAdapter gba2 = GayBerneAdapter(atype2);
169 RealType d2, l2, eX2, eS2, eE2, dw2;
170
171 if (gba2.isGayBerne()) {
172 d2 = gba2.getD();
173 l2 = gba2.getL();
174 eX2 = gba2.getEpsX();
175 eS2 = gba2.getEpsS();
176 eE2 = gba2.getEpsE();
177 dw2 = gba2.getDw();
178 } else if (lja2.isLennardJones()) {
179 d2 = lja2.getSigma() / sqrt(2.0);
180 l2 = d2;
181 eX2 = lja2.getEpsilon();
182 eS2 = eX2;
183 eE2 = eX2;
184 dw2 = 1.0;
185 } else {
186 sprintf( painCave.errMsg,
187 "GB::addType found an atomType (%s) that does not\n"
188 "\tappear to be a Gay-Berne or Lennard-Jones atom.\n",
189 atype2->getName().c_str());
190 painCave.severity = OPENMD_ERROR;
191 painCave.isFatal = 1;
192 simError();
193 }
194
195
196 GBInteractionData mixer1, mixer2;
197
198 // Cleaver paper uses sqrt of squares to get sigma0 for
199 // mixed interactions.
200
201 mixer1.sigma0 = sqrt(d1*d1 + d2*d2);
202 mixer1.xa2 = (l1*l1 - d1*d1)/(l1*l1 + d2*d2);
203 mixer1.xai2 = (l2*l2 - d2*d2)/(l2*l2 + d1*d1);
204 mixer1.x2 = (l1*l1 - d1*d1) * (l2*l2 - d2*d2) /
205 ((l2*l2 + d1*d1) * (l1*l1 + d2*d2));
206
207 mixer2.sigma0 = mixer1.sigma0;
208 // xa2 and xai2 for j-i pairs are reversed from the same i-j pairing.
209 // Swapping the particles reverses the anisotropy parameters:
210 mixer2.xa2 = mixer1.xai2;
211 mixer2.xai2 = mixer1.xa2;
212 mixer2.x2 = mixer1.x2;
213
214 // assumed LB mixing rules for now:
215
216 mixer1.dw = 0.5 * (dw1 + dw2);
217 mixer1.eps0 = sqrt(eX1 * eX2);
218
219 mixer2.dw = mixer1.dw;
220 mixer2.eps0 = mixer1.eps0;
221
222 RealType mi = RealType(1.0)/mu_;
223
224 mixer1.xpap2 = (pow(eS1, mi) - pow(eE1, mi)) / (pow(eS1, mi) + pow(eE2, mi));
225 mixer1.xpapi2 = (pow(eS2, mi) - pow(eE2, mi)) / (pow(eS2, mi) + pow(eE1, mi));
226 mixer1.xp2 = (pow(eS1, mi) - pow(eE1, mi)) * (pow(eS2, mi) - pow(eE2, mi)) /
227 (pow(eS2, mi) + pow(eE1, mi)) / (pow(eS1, mi) + pow(eE2, mi)) ;
228
229 // xpap2 and xpapi2 for j-i pairs are reversed from the same i-j pairing.
230 // Swapping the particles reverses the anisotropy parameters:
231 mixer2.xpap2 = mixer1.xpapi2;
232 mixer2.xpapi2 = mixer1.xpap2;
233 mixer2.xp2 = mixer1.xp2;
234
235 // only add this pairing if at least one of the atoms is a Gay-Berne atom
236
237 if (gba1.isGayBerne() || gba2.isGayBerne()) {
238
239 pair<AtomType*, AtomType*> key1, key2;
240 key1 = make_pair(atomType, atype2);
241 key2 = make_pair(atype2, atomType);
242
243 MixingMap[key1] = mixer1;
244 if (key2 != key1) {
245 MixingMap[key2] = mixer2;
246 }
247 }
248 }
249 }
250
251 void GB::calcForce(InteractionData &idat) {
252
253 if (!initialized_) initialize();
254
255 GBInteractionData mixer = MixingMap[idat.atypes];
256
257 RealType sigma0 = mixer.sigma0;
258 RealType dw = mixer.dw;
259 RealType eps0 = mixer.eps0;
260 RealType x2 = mixer.x2;
261 RealType xa2 = mixer.xa2;
262 RealType xai2 = mixer.xai2;
263 RealType xp2 = mixer.xp2;
264 RealType xpap2 = mixer.xpap2;
265 RealType xpapi2 = mixer.xpapi2;
266
267 // cerr << "atypes = " << idat.atypes.first->getName() << " " << idat.atypes.second->getName() << "\n";
268 // cerr << "sigma0 = " <<mixer.sigma0 <<"\n";
269 // cerr << "dw = " <<mixer.dw <<"\n";
270 // cerr << "eps0 = " <<mixer.eps0 <<"\n";
271 // cerr << "x2 = " <<mixer.x2 <<"\n";
272 // cerr << "xa2 = " <<mixer.xa2 <<"\n";
273 // cerr << "xai2 = " <<mixer.xai2 <<"\n";
274 // cerr << "xp2 = " <<mixer.xp2 <<"\n";
275 // cerr << "xpap2 = " <<mixer.xpap2 <<"\n";
276 // cerr << "xpapi2 = " <<mixer.xpapi2 <<"\n";
277
278 Vector3d ul1 = idat.A1->getRow(2);
279 Vector3d ul2 = idat.A2->getRow(2);
280
281 // cerr << "ul1 = " <<ul1<<"\n";
282 // cerr << "ul2 = " <<ul2<<"\n";
283
284 RealType a, b, g;
285
286 // This is not good. We should store this in the mixing map, and not
287 // query atom types in calc force.
288 bool i_is_LJ = idat.atypes.first->isLennardJones();
289 bool j_is_LJ = idat.atypes.second->isLennardJones();
290
291 if (i_is_LJ) {
292 a = 0.0;
293 ul1 = V3Zero;
294 } else {
295 a = dot(*(idat.d), ul1);
296 }
297
298 if (j_is_LJ) {
299 b = 0.0;
300 ul2 = V3Zero;
301 } else {
302 b = dot(*(idat.d), ul2);
303 }
304
305 if (i_is_LJ || j_is_LJ)
306 g = 0.0;
307 else
308 g = dot(ul1, ul2);
309
310 RealType au = a / *(idat.rij);
311 RealType bu = b / *(idat.rij);
312
313 RealType au2 = au * au;
314 RealType bu2 = bu * bu;
315 RealType g2 = g * g;
316
317 RealType H = (xa2 * au2 + xai2 * bu2 - 2.0*x2*au*bu*g) / (1.0 - x2*g2);
318 RealType Hp = (xpap2*au2 + xpapi2*bu2 - 2.0*xp2*au*bu*g) / (1.0 - xp2*g2);
319
320 // cerr << "au2 = " << au2 << "\n";
321 // cerr << "bu2 = " << bu2 << "\n";
322 // cerr << "g2 = " << g2 << "\n";
323 // cerr << "H = " << H << "\n";
324 // cerr << "Hp = " << Hp << "\n";
325
326 RealType sigma = sigma0 / sqrt(1.0 - H);
327 RealType e1 = 1.0 / sqrt(1.0 - x2*g2);
328 RealType e2 = 1.0 - Hp;
329 RealType eps = eps0 * pow(e1,nu_) * pow(e2,mu_);
330 RealType BigR = dw*sigma0 / (*(idat.rij) - sigma + dw*sigma0);
331
332 RealType R3 = BigR*BigR*BigR;
333 RealType R6 = R3*R3;
334 RealType R7 = R6 * BigR;
335 RealType R12 = R6*R6;
336 RealType R13 = R6*R7;
337
338 RealType U = *(idat.vdwMult) * 4.0 * eps * (R12 - R6);
339
340 RealType s3 = sigma*sigma*sigma;
341 RealType s03 = sigma0*sigma0*sigma0;
342
343 // cerr << "vdwMult = " << *(idat.vdwMult) << "\n";
344 // cerr << "eps = " << eps <<"\n";
345 // cerr << "mu = " << mu_ << "\n";
346 // cerr << "R12 = " << R12 << "\n";
347 // cerr << "R6 = " << R6 << "\n";
348 // cerr << "R13 = " << R13 << "\n";
349 // cerr << "R7 = " << R7 << "\n";
350 // cerr << "e2 = " << e2 << "\n";
351 // cerr << "rij = " << *(idat.rij) << "\n";
352 // cerr << "s3 = " << s3 << "\n";
353 // cerr << "s03 = " << s03 << "\n";
354 // cerr << "dw = " << dw << "\n";
355
356 RealType pref1 = - *(idat.vdwMult) * 8.0 * eps * mu_ * (R12 - R6) /
357 (e2 * *(idat.rij));
358
359 RealType pref2 = *(idat.vdwMult) * 8.0 * eps * s3 * (6.0*R13 - 3.0*R7) /
360 (dw* *(idat.rij) * s03);
361
362 RealType dUdr = - (pref1 * Hp + pref2 * (sigma0 * sigma0 *
363 *(idat.rij) / s3 + H));
364
365 RealType dUda = pref1 * (xpap2*au - xp2*bu*g) / (1.0 - xp2 * g2)
366 + pref2 * (xa2 * au - x2 *bu*g) / (1.0 - x2 * g2);
367
368 RealType dUdb = pref1 * (xpapi2*bu - xp2*au*g) / (1.0 - xp2 * g2)
369 + pref2 * (xai2 * bu - x2 *au*g) / (1.0 - x2 * g2);
370
371 RealType dUdg = 4.0 * eps * nu_ * (R12 - R6) * x2 * g / (1.0 - x2*g2)
372 + 8.0 * eps * mu_ * (R12 - R6) * (xp2*au*bu - Hp*xp2*g) /
373 (1.0 - xp2 * g2) / e2 + 8.0 * eps * s3 * (3.0 * R7 - 6.0 * R13) *
374 (x2 * au * bu - H * x2 * g) / (1.0 - x2 * g2) / (dw * s03);
375
376 // cerr << "pref = " << pref1 << " " << pref2 << "\n";
377 // cerr << "dU = " << dUdr << " " << dUda <<" " << dUdb << " " << dUdg << "\n";
378
379 Vector3d rhat = *(idat.d) / *(idat.rij);
380 Vector3d rxu1 = cross(*(idat.d), ul1);
381 Vector3d rxu2 = cross(*(idat.d), ul2);
382 Vector3d uxu = cross(ul1, ul2);
383
384 (*(idat.pot))[VANDERWAALS_FAMILY] += U * *(idat.sw);
385 *(idat.f1) += (dUdr * rhat + dUda * ul1 + dUdb * ul2) * *(idat.sw);
386 *(idat.t1) += (dUda * rxu1 - dUdg * uxu) * *(idat.sw);
387 *(idat.t2) += (dUdb * rxu2 + dUdg * uxu) * *(idat.sw);
388 *(idat.vpair) += U;
389
390 // cerr << "f1 term = " << (dUdr * rhat + dUda * ul1 + dUdb * ul2) * *(idat.sw) << "\n";
391 // cerr << "t1 term = " << (dUda * rxu1 - dUdg * uxu) * *(idat.sw) << "\n";
392 // cerr << "t2 term = " << (dUdb * rxu2 + dUdg * uxu) * *(idat.sw) << "\n";
393 // cerr << "vp term = " << U << "\n";
394
395 return;
396
397 }
398
399 RealType GB::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
400 if (!initialized_) initialize();
401
402 RealType cut = 0.0;
403
404 LennardJonesAdapter lja1 = LennardJonesAdapter(atypes.first);
405 GayBerneAdapter gba1 = GayBerneAdapter(atypes.first);
406 LennardJonesAdapter lja2 = LennardJonesAdapter(atypes.second);
407 GayBerneAdapter gba2 = GayBerneAdapter(atypes.second);
408
409 if (gba1.isGayBerne()) {
410 RealType d1 = gba1.getD();
411 RealType l1 = gba1.getL();
412 // sigma is actually sqrt(2)*l for prolate ellipsoids
413 cut = max(cut, RealType(2.5) * sqrt(RealType(2.0)) * max(d1, l1));
414 } else if (lja1.isLennardJones()) {
415 cut = max(cut, RealType(2.5) * lja1.getSigma());
416 }
417
418 if (gba2.isGayBerne()) {
419 RealType d2 = gba2.getD();
420 RealType l2 = gba2.getL();
421 cut = max(cut, RealType(2.5) * sqrt(RealType(2.0)) * max(d2, l2));
422 } else if (lja2.isLennardJones()) {
423 cut = max(cut, RealType(2.5) * lja2.getSigma());
424 }
425
426 return cut;
427 }
428 }
429

Properties

Name Value
svn:eol-style native