ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/nonbonded/LJ.cpp
Revision: 1473
Committed: Tue Jul 20 15:43:00 2010 UTC (14 years, 9 months ago) by gezelter
File size: 13197 byte(s)
Log Message:
fixing c/fortran bugs

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, 24107 (2008).
39 * [4] Vardeman & Gezelter, in progress (2009).
40 */
41
42 #include <stdio.h>
43 #include <string.h>
44
45 #include <cmath>
46 #include "nonbonded/LJ.hpp"
47 #include "utils/simError.h"
48
49
50 namespace OpenMD {
51
52 bool LJ::initialized_ = false;
53 bool LJ::shiftedPot_ = false;
54 bool LJ::shiftedFrc_ = false;
55 ForceField* LJ::forceField_ = NULL;
56 std::map<int, AtomType*> LJ::LJMap;
57 std::map<std::pair<AtomType*, AtomType*>, LJInteractionData> LJ::MixingMap;
58
59 LJ* LJ::_instance = NULL;
60
61 LJ* LJ::Instance() {
62 if (!_instance) {
63 _instance = new LJ();
64 }
65 return _instance;
66 }
67
68 LJParam LJ::getLJParam(AtomType* atomType) {
69
70 // Do sanity checking on the AtomType we were passed before
71 // building any data structures:
72 if (!atomType->isLennardJones()) {
73 sprintf( painCave.errMsg,
74 "LJ::getLJParam was passed an atomType (%s) that does not\n"
75 "\tappear to be a Lennard-Jones atom.\n",
76 atomType->getName().c_str());
77 painCave.severity = OPENMD_ERROR;
78 painCave.isFatal = 1;
79 simError();
80 }
81
82 GenericData* data = atomType->getPropertyByName("LennardJones");
83 if (data == NULL) {
84 sprintf( painCave.errMsg, "LJ::getLJParam could not find Lennard-Jones\n"
85 "\tparameters for atomType %s.\n", atomType->getName().c_str());
86 painCave.severity = OPENMD_ERROR;
87 painCave.isFatal = 1;
88 simError();
89 }
90
91 LJParamGenericData* ljData = dynamic_cast<LJParamGenericData*>(data);
92 if (ljData == NULL) {
93 sprintf( painCave.errMsg,
94 "LJ::getLJParam could not convert GenericData to LJParam for\n"
95 "\tatom type %s\n", atomType->getName().c_str());
96 painCave.severity = OPENMD_ERROR;
97 painCave.isFatal = 1;
98 simError();
99 }
100
101 return ljData->getData();
102 }
103
104 RealType LJ::getSigma(AtomType* atomType) {
105 LJParam ljParam = getLJParam(atomType);
106 return ljParam.sigma;
107 }
108
109 RealType LJ::getSigma(int atid) {
110 if (!initialized_) initialize();
111 std::map<int, AtomType*> :: const_iterator it;
112 it = LJMap.find(atid);
113 if (it == LJMap.end()) {
114 sprintf( painCave.errMsg,
115 "LJ::getSigma could not find atid %d in LJMap\n",
116 (atid));
117 painCave.severity = OPENMD_ERROR;
118 painCave.isFatal = 1;
119 simError();
120 }
121 AtomType* atype = it->second;
122
123 return getSigma(atype);
124 }
125
126 RealType LJ::getSigma(AtomType* atomType1, AtomType* atomType2) {
127 RealType sigma1 = getSigma(atomType1);
128 RealType sigma2 = getSigma(atomType2);
129
130 ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
131 std::string DistanceMix = fopts.getDistanceMixingRule();
132 toUpper(DistanceMix);
133
134 if (DistanceMix == "GEOMETRIC")
135 return sqrt(sigma1 * sigma2);
136 else
137 return 0.5 * (sigma1 + sigma2);
138 }
139
140 RealType LJ::getEpsilon(AtomType* atomType) {
141 LJParam ljParam = getLJParam(atomType);
142 return ljParam.epsilon;
143 }
144
145 RealType LJ::getEpsilon(int atid) {
146 if (!initialized_) initialize();
147 std::map<int, AtomType*> :: const_iterator it;
148 it = LJMap.find(atid);
149 if (it == LJMap.end()) {
150 sprintf( painCave.errMsg,
151 "LJ::getEpsilon could not find atid %d in LJMap\n",
152 (atid));
153 painCave.severity = OPENMD_ERROR;
154 painCave.isFatal = 1;
155 simError();
156 }
157 AtomType* atype = it->second;
158
159 return getEpsilon(atype);
160 }
161
162 RealType LJ::getEpsilon(AtomType* atomType1, AtomType* atomType2) {
163 RealType epsilon1 = getEpsilon(atomType1);
164 RealType epsilon2 = getEpsilon(atomType2);
165 return sqrt(epsilon1 * epsilon2);
166 }
167
168 void LJ::initialize() {
169 ForceField::AtomTypeContainer atomTypes = forceField_->getAtomTypes();
170 ForceField::AtomTypeContainer::MapTypeIterator i;
171 AtomType* at;
172
173 for (at = atomTypes.beginType(i); at != NULL;
174 at = atomTypes.nextType(i)) {
175
176 if (at->isLennardJones())
177 addType(at);
178 }
179
180 ForceField::NonBondedInteractionTypeContainer nbiTypes = forceField_->getNonBondedInteractionTypes();
181 ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
182 NonBondedInteractionType* nbt;
183
184 for (nbt = nbiTypes.beginType(j); nbt != NULL;
185 nbt = nbiTypes.nextType(j)) {
186
187 if (nbt->isLennardJones()) {
188
189 std::pair<AtomType*, AtomType*> atypes = nbt->getAtomTypes();
190
191 GenericData* data = nbt->getPropertyByName("LennardJones");
192 if (data == NULL) {
193 sprintf( painCave.errMsg, "LJ::rebuildMixingMap could not find\n"
194 "\tLennard-Jones parameters for %s - %s interaction.\n",
195 atypes.first->getName().c_str(),
196 atypes.second->getName().c_str());
197 painCave.severity = OPENMD_ERROR;
198 painCave.isFatal = 1;
199 simError();
200 }
201
202 LJParamGenericData* ljData = dynamic_cast<LJParamGenericData*>(data);
203 if (ljData == NULL) {
204 sprintf( painCave.errMsg,
205 "LJ::rebuildMixingMap could not convert GenericData to\n"
206 "\tLJParam for %s - %s interaction.\n",
207 atypes.first->getName().c_str(),
208 atypes.second->getName().c_str());
209 painCave.severity = OPENMD_ERROR;
210 painCave.isFatal = 1;
211 simError();
212 }
213
214 LJParam ljParam = ljData->getData();
215
216 RealType sigma = ljParam.sigma;
217 RealType epsilon = ljParam.epsilon;
218
219 addExplicitInteraction(atypes.first, atypes.second, sigma, epsilon);
220 }
221 }
222 initialized_ = true;
223 }
224
225
226
227 void LJ::addType(AtomType* atomType){
228 RealType sigma1 = getSigma(atomType);
229 RealType epsilon1 = getEpsilon(atomType);
230
231 // add it to the map:
232 AtomTypeProperties atp = atomType->getATP();
233
234 std::pair<std::map<int,AtomType*>::iterator,bool> ret;
235 ret = LJMap.insert( std::pair<int, AtomType*>(atp.ident, atomType) );
236 if (ret.second == false) {
237 sprintf( painCave.errMsg,
238 "LJ already had a previous entry with ident %d\n",
239 atp.ident);
240 painCave.severity = OPENMD_INFO;
241 painCave.isFatal = 0;
242 simError();
243 }
244
245 // Now, iterate over all known types and add to the mixing map:
246
247 std::map<int, AtomType*>::iterator it;
248 for( it = LJMap.begin(); it != LJMap.end(); ++it) {
249
250 AtomType* atype2 = (*it).second;
251
252 LJInteractionData mixer;
253 mixer.sigma = getSigma(atomType, atype2);
254 mixer.epsilon = getEpsilon(atomType, atype2);
255 mixer.sigmai = 1.0 / mixer.sigma;
256 mixer.explicitlySet = false;
257
258 std::pair<AtomType*, AtomType*> key1, key2;
259 key1 = std::make_pair(atomType, atype2);
260 key2 = std::make_pair(atype2, atomType);
261
262 MixingMap[key1] = mixer;
263 if (key2 != key1) {
264 MixingMap[key2] = mixer;
265 }
266 }
267 }
268
269 void LJ::addExplicitInteraction(AtomType* atype1, AtomType* atype2, RealType sigma, RealType epsilon){
270
271 // in case these weren't already in the map
272 addType(atype1);
273 addType(atype2);
274
275 LJInteractionData mixer;
276 mixer.sigma = sigma;
277 mixer.epsilon = epsilon;
278 mixer.sigmai = 1.0 / mixer.sigma;
279 mixer.explicitlySet = true;
280
281 std::pair<AtomType*, AtomType*> key1, key2;
282 key1 = std::make_pair(atype1, atype2);
283 key2 = std::make_pair(atype2, atype1);
284
285 MixingMap[key1] = mixer;
286 if (key2 != key1) {
287 MixingMap[key2] = mixer;
288 }
289 }
290
291 void LJ::calcForce(AtomType* at1, AtomType* at2, Vector3d d,
292 RealType rij, RealType r2, RealType rcut, RealType sw,
293 RealType vdwMult, RealType &vpair, RealType &pot,
294 Vector3d &f1) {
295
296 if (!initialized_) initialize();
297
298 RealType ros;
299 RealType rcos;
300 RealType myPot = 0.0;
301 RealType myPotC = 0.0;
302 RealType myDeriv = 0.0;
303 RealType myDerivC = 0.0;
304
305 std::pair<AtomType*, AtomType*> key = std::make_pair(at1, at2);
306 LJInteractionData mixer = MixingMap[key];
307
308 RealType sigmai = mixer.sigmai;
309 RealType epsilon = mixer.epsilon;
310
311
312 ros = rij * sigmai;
313
314 getLJfunc(ros, myPot, myDeriv);
315
316 if (shiftedPot_) {
317 rcos = rcut * sigmai;
318 getLJfunc(rcos, myPotC, myDerivC);
319 myDerivC = 0.0;
320 } else if (LJ::shiftedFrc_) {
321 rcos = rcut * sigmai;
322 getLJfunc(rcos, myPotC, myDerivC);
323 myPotC = myPotC + myDerivC * (rij - rcut) * sigmai;
324 } else {
325 myPotC = 0.0;
326 myDerivC = 0.0;
327 }
328
329 RealType pot_temp = vdwMult * epsilon * (myPot - myPotC);
330 vpair += pot_temp;
331
332 RealType dudr = sw * vdwMult * epsilon * (myDeriv - myDerivC)*sigmai;
333
334 pot += sw * pot_temp;
335 f1 = d * dudr / rij;
336
337 return;
338
339
340
341 }
342
343 void LJ::do_lj_pair(int *atid1, int *atid2, RealType *d, RealType *rij,
344 RealType *r2, RealType *rcut, RealType *sw,
345 RealType *vdwMult,
346 RealType *vpair, RealType *pot, RealType *f1) {
347
348 if (!initialized_) initialize();
349
350 AtomType* atype1 = LJMap[*atid1];
351 AtomType* atype2 = LJMap[*atid2];
352
353 Vector3d disp(d[0], d[1], d[2]);
354 Vector3d frc(f1[0], f1[1], f1[2]);
355
356 calcForce(atype1, atype2, disp, *rij, *r2, *rcut, *sw, *vdwMult, *vpair,
357 *pot, frc);
358
359 f1[0] = frc.x();
360 f1[1] = frc.y();
361 f1[2] = frc.z();
362
363 return;
364 }
365
366 void LJ::getLJfunc(RealType r, RealType &pot, RealType &deriv) {
367
368 RealType ri = 1.0 / r;
369 RealType ri2 = ri * ri;
370 RealType ri6 = ri2 * ri2 * ri2;
371 RealType ri7 = ri6 * ri;
372 RealType ri12 = ri6 * ri6;
373 RealType ri13 = ri12 * ri;
374
375 pot = 4.0 * (ri12 - ri6);
376 deriv = 24.0 * (ri7 - 2.0 * ri13);
377
378 return;
379 }
380
381
382 void LJ::setLJDefaultCutoff(RealType *thisRcut, int *sP, int *sF) {
383 shiftedPot_ = (bool)(*sP);
384 shiftedFrc_ = (bool)(*sF);
385 }
386 }
387
388 extern "C" {
389
390 #define fortranGetSigma FC_FUNC(getsigma, GETSIGMA)
391 #define fortranGetEpsilon FC_FUNC(getepsilon, GETEPSILON)
392 #define fortranSetLJCutoff FC_FUNC(setljdefaultcutoff, SETLJDEFAULTCUTOFF)
393 #define fortranDoLJPair FC_FUNC(do_lj_pair, DO_LJ_PAIR)
394
395 RealType fortranGetSigma(int* atid) {
396 return OpenMD::LJ::Instance()->getSigma(*atid);
397 }
398 RealType fortranGetEpsilon(int* atid) {
399 return OpenMD::LJ::Instance()->getEpsilon(*atid);
400 }
401 void fortranSetLJCutoff(RealType *rcut, int *shiftedPot, int *shiftedFrc) {
402 return OpenMD::LJ::Instance()->setLJDefaultCutoff(rcut, shiftedPot,
403 shiftedFrc);
404 }
405 void fortranDoLJPair(int *atid1, int *atid2, RealType *d, RealType *rij,
406 RealType *r2, RealType *rcut, RealType *sw,
407 RealType *vdwMult, RealType* vpair, RealType* pot,
408 RealType *f1){
409
410 return OpenMD::LJ::Instance()->do_lj_pair(atid1, atid2, d, rij, r2, rcut,
411 sw, vdwMult, vpair, pot, f1);
412 }
413 }

Properties

Name Value
svn:eol-style native