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

# User Rev Content
1 gezelter 1471 /*
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 gezelter 1473 if (!initialized_) initialize();
111 gezelter 1471 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 gezelter 1473 if (!initialized_) initialize();
147 gezelter 1471 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 gezelter 1473
234     std::pair<std::map<int,AtomType*>::iterator,bool> ret;
235 gezelter 1471 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 gezelter 1472 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 gezelter 1471
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 gezelter 1473
312 gezelter 1471 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 gezelter 1473
339    
340    
341 gezelter 1471 }
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 gezelter 1472
359     f1[0] = frc.x();
360     f1[1] = frc.y();
361     f1[2] = frc.z();
362 gezelter 1473
363 gezelter 1471 return;
364     }
365    
366 gezelter 1472 void LJ::getLJfunc(RealType r, RealType &pot, RealType &deriv) {
367    
368 gezelter 1471 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 gezelter 1472
375 gezelter 1471 pot = 4.0 * (ri12 - ri6);
376     deriv = 24.0 * (ri7 - 2.0 * ri13);
377 gezelter 1472
378 gezelter 1471 return;
379     }
380 gezelter 1472
381 gezelter 1471
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