ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/nonbonded/LJ.cpp
(Generate patch)

Comparing:
branches/development/src/nonbonded/LJ.cpp (file contents), Revision 1472 by gezelter, Mon Jul 19 20:42:55 2010 UTC vs.
trunk/src/nonbonded/LJ.cpp (file contents), Revision 2069 by gezelter, Thu Mar 5 16:30:23 2015 UTC

# Line 35 | Line 35
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).                        
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>
# Line 45 | Line 46
46   #include <cmath>
47   #include "nonbonded/LJ.hpp"
48   #include "utils/simError.h"
49 + #include "types/LennardJonesAdapter.hpp"
50 + #include "types/LennardJonesInteractionType.hpp"
51  
49
52   namespace OpenMD {
53  
54 <  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;
54 >  LJ::LJ() : name_("LJ"), initialized_(false), forceField_(NULL) {}
55  
56 <  LJ* LJ::Instance() {
62 <    if (!_instance) {
63 <      _instance = new LJ();
64 <    }
65 <    return _instance;
66 <  }
56 >  RealType LJ::getSigma(AtomType* atomType1, AtomType* atomType2) {
57  
58 <  LJParam LJ::getLJParam(AtomType* atomType) {
58 >    LennardJonesAdapter lja1 = LennardJonesAdapter(atomType1);
59 >    LennardJonesAdapter lja2 = LennardJonesAdapter(atomType2);
60 >    RealType sigma1 = lja1.getSigma();
61 >    RealType sigma2 = lja2.getSigma();
62      
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    std::map<int, AtomType*> :: const_iterator it;
111    it = LJMap.find(atid);
112    if (it == LJMap.end()) {
113      sprintf( painCave.errMsg,
114               "LJ::getSigma could not find atid %d in LJMap\n",
115               (atid));
116      painCave.severity = OPENMD_ERROR;
117      painCave.isFatal = 1;
118      simError();          
119    }
120    AtomType* atype = it->second;
121
122    return getSigma(atype);    
123  }
124
125  RealType LJ::getSigma(AtomType* atomType1, AtomType* atomType2) {    
126    RealType sigma1 = getSigma(atomType1);
127    RealType sigma2 = getSigma(atomType2);
128    
63      ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
64 <    std::string DistanceMix = fopts.getDistanceMixingRule();
64 >    string DistanceMix = fopts.getDistanceMixingRule();
65      toUpper(DistanceMix);
66  
67      if (DistanceMix == "GEOMETRIC")
# Line 136 | Line 70 | namespace OpenMD {
70        return 0.5 * (sigma1 + sigma2);
71    }
72  
73 <  RealType LJ::getEpsilon(AtomType* atomType) {    
74 <    LJParam ljParam = getLJParam(atomType);
75 <    return ljParam.epsilon;
73 >  RealType LJ::getEpsilon(AtomType* atomType1, AtomType* atomType2) {  
74 >    LennardJonesAdapter lja1 = LennardJonesAdapter(atomType1);
75 >    LennardJonesAdapter lja2 = LennardJonesAdapter(atomType2);
76 >  
77 >    RealType epsilon1 = lja1.getEpsilon();
78 >    RealType epsilon2 = lja2.getEpsilon();
79 >    return sqrt(epsilon1 * epsilon2);
80    }
81  
82 <  RealType LJ::getEpsilon(int atid) {    
145 <    std::map<int, AtomType*> :: const_iterator it;
146 <    it = LJMap.find(atid);
147 <    if (it == LJMap.end()) {
148 <      sprintf( painCave.errMsg,
149 <               "LJ::getEpsilon could not find atid %d in LJMap\n",
150 <               (atid));
151 <      painCave.severity = OPENMD_ERROR;
152 <      painCave.isFatal = 1;
153 <      simError();          
154 <    }
155 <    AtomType* atype = it->second;
82 >  void LJ::initialize() {    
83  
84 <    return getEpsilon(atype);    
85 <  }
84 >    LJtypes.clear();
85 >    LJtids.clear();
86 >    MixingMap.clear();
87 >    nLJ_ = 0;
88  
89 <  RealType LJ::getEpsilon(AtomType* atomType1, AtomType* atomType2) {    
161 <    RealType epsilon1 = getEpsilon(atomType1);
162 <    RealType epsilon2 = getEpsilon(atomType2);
163 <    return sqrt(epsilon1 * epsilon2);
164 <  }
89 >    LJtids.resize( forceField_->getNAtomType(), -1);
90  
91 <  void LJ::initialize() {    
92 <    ForceField::AtomTypeContainer atomTypes = forceField_->getAtomTypes();
93 <    ForceField::AtomTypeContainer::MapTypeIterator i;
94 <    AtomType* at;
91 >    set<AtomType*>::iterator at;
92 >    for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
93 >      if ((*at)->isLennardJones()) nLJ_++;
94 >    }
95  
96 <    for (at = atomTypes.beginType(i); at != NULL;
97 <         at = atomTypes.nextType(i)) {
98 <      
99 <      if (at->isLennardJones())
175 <        addType(at);
96 >    MixingMap.resize(nLJ_);
97 >
98 >    for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
99 >      if ((*at)->isLennardJones()) addType(*at);      
100      }
101  
102 <    ForceField::NonBondedInteractionTypeContainer nbiTypes = forceField_->getNonBondedInteractionTypes();
102 >    ForceField::NonBondedInteractionTypeContainer* nbiTypes = forceField_->getNonBondedInteractionTypes();
103      ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
104      NonBondedInteractionType* nbt;
105 +    ForceField::NonBondedInteractionTypeContainer::KeyType keys;
106  
107 <    for (nbt = nbiTypes.beginType(j); nbt != NULL;
108 <         nbt = nbiTypes.nextType(j)) {
109 <      
107 >    for (nbt = nbiTypes->beginType(j); nbt != NULL;
108 >         nbt = nbiTypes->nextType(j)) {
109 >
110        if (nbt->isLennardJones()) {
111 <        
112 <        std::pair<AtomType*, AtomType*> atypes = nbt->getAtomTypes();
113 <        
114 <        GenericData* data = nbt->getPropertyByName("LennardJones");
115 <        if (data == NULL) {
116 <          sprintf( painCave.errMsg, "LJ::rebuildMixingMap could not find\n"
117 <               "\tLennard-Jones parameters for %s - %s interaction.\n",
193 <                   atypes.first->getName().c_str(),
194 <                   atypes.second->getName().c_str());
195 <          painCave.severity = OPENMD_ERROR;
196 <          painCave.isFatal = 1;
197 <          simError();
198 <        }
199 <    
200 <        LJParamGenericData* ljData = dynamic_cast<LJParamGenericData*>(data);
201 <        if (ljData == NULL) {
111 >        keys = nbiTypes->getKeys(j);
112 >        AtomType* at1 = forceField_->getAtomType(keys[0]);
113 >        AtomType* at2 = forceField_->getAtomType(keys[1]);
114 >
115 >        LennardJonesInteractionType* ljit = dynamic_cast<LennardJonesInteractionType*>(nbt);
116 >
117 >        if (ljit == NULL) {
118            sprintf( painCave.errMsg,
119 <                   "LJ::rebuildMixingMap could not convert GenericData to\n"
120 <                   "\tLJParam for %s - %s interaction.\n",
121 <                   atypes.first->getName().c_str(),
122 <                   atypes.second->getName().c_str());
119 >                   "LJ::initialize could not convert NonBondedInteractionType\n"
120 >                   "\tto LennardJonesInteractionType for %s - %s interaction.\n",
121 >                   at1->getName().c_str(),
122 >                   at2->getName().c_str());
123            painCave.severity = OPENMD_ERROR;
124            painCave.isFatal = 1;
125            simError();          
126          }
211        
212        LJParam ljParam = ljData->getData();
127  
128 <        RealType sigma = ljParam.sigma;
129 <        RealType epsilon = ljParam.epsilon;
130 <
217 <        addExplicitInteraction(atypes.first, atypes.second, sigma, epsilon);
128 >        RealType sigma = ljit->getSigma();
129 >        RealType epsilon = ljit->getEpsilon();
130 >        addExplicitInteraction(at1, at2, sigma, epsilon);
131        }
132      }  
133      initialized_ = true;
134    }
222      
135  
136  
137    void LJ::addType(AtomType* atomType){
138 <    RealType sigma1 = getSigma(atomType);
139 <    RealType epsilon1 = getEpsilon(atomType);
228 <
138 >    LennardJonesAdapter lja1 = LennardJonesAdapter(atomType);
139 >    
140      // add it to the map:
141 <    AtomTypeProperties atp = atomType->getATP();    
142 <    std::pair<std::map<int,AtomType*>::iterator,bool> ret;
143 <    ret = LJMap.insert( std::pair<int, AtomType*>(atp.ident, atomType) );
141 >    int atid = atomType->getIdent();
142 >    int ljtid = LJtypes.size();
143 >  
144 >    pair<set<int>::iterator,bool> ret;    
145 >    ret = LJtypes.insert( atid );
146      if (ret.second == false) {
147        sprintf( painCave.errMsg,
148                 "LJ already had a previous entry with ident %d\n",
149 <               atp.ident);
149 >               atid) ;
150        painCave.severity = OPENMD_INFO;
151        painCave.isFatal = 0;
152        simError();        
153      }
154 <    
154 >
155 >    LJtids[atid] = ljtid;
156 >    MixingMap[ljtid].resize( nLJ_ );
157 >
158      // Now, iterate over all known types and add to the mixing map:
159      
160 <    std::map<int, AtomType*>::iterator it;
161 <    for( it = LJMap.begin(); it != LJMap.end(); ++it) {
246 <      
247 <      AtomType* atype2 = (*it).second;
160 >    std::set<int>::iterator it;
161 >    for( it = LJtypes.begin(); it != LJtypes.end(); ++it) {
162  
163 +      int ljtid2 = LJtids[ (*it) ];
164 +      AtomType* atype2 = forceField_->getAtomType( (*it) );
165 +
166        LJInteractionData mixer;
167        mixer.sigma = getSigma(atomType, atype2);
168        mixer.epsilon = getEpsilon(atomType, atype2);
169        mixer.sigmai = 1.0 / mixer.sigma;
170        mixer.explicitlySet = false;
171 +      MixingMap[ljtid2].resize( nLJ_ );
172  
173 <      std::pair<AtomType*, AtomType*> key1, key2;
174 <      key1 = std::make_pair(atomType, atype2);
175 <      key2 = std::make_pair(atype2, atomType);
258 <      
259 <      MixingMap[key1] = mixer;
260 <      if (key2 != key1) {
261 <        MixingMap[key2] = mixer;
173 >      MixingMap[ljtid][ljtid2] = mixer;
174 >      if (ljtid2 != ljtid) {
175 >        MixingMap[ljtid2][ljtid] = mixer;
176        }
177      }      
178    }
179    
180    void LJ::addExplicitInteraction(AtomType* atype1, AtomType* atype2, RealType sigma, RealType epsilon){
181      
268    // in case these weren't already in the map
269    addType(atype1);
270    addType(atype2);
271
182      LJInteractionData mixer;
183      mixer.sigma = sigma;
184      mixer.epsilon = epsilon;
185      mixer.sigmai = 1.0 / mixer.sigma;
186      mixer.explicitlySet = true;
187  
188 <    std::pair<AtomType*, AtomType*> key1, key2;
189 <    key1 = std::make_pair(atype1, atype2);
190 <    key2 = std::make_pair(atype2, atype1);
188 >    int atid1 = atype1->getIdent();
189 >    int atid2 = atype2->getIdent();
190 >
191 >    int ljtid1, ljtid2;
192 >
193 >    pair<set<int>::iterator,bool> ret;    
194 >    ret = LJtypes.insert( atid1 );
195 >    if (ret.second == false) {
196 >      // already had this type in the LJMap, just get the ljtid:
197 >      ljtid1 = LJtids[ atid1 ];
198 >    } else {
199 >      // didn't already have it, so make a new one and assign it:
200 >      ljtid1 = nLJ_;
201 >      LJtids[atid1] = nLJ_;
202 >      nLJ_++;
203 >    }
204 >
205 >    ret = LJtypes.insert( atid2 );
206 >    if (ret.second == false) {
207 >      // already had this type in the LJMap, just get the ljtid:
208 >      ljtid2 = LJtids[ atid2 ];
209 >    } else {
210 >      // didn't already have it, so make a new one and assign it:
211 >      ljtid2 = nLJ_;
212 >      LJtids[atid2] = nLJ_;
213 >      nLJ_++;
214 >    }
215      
216 <    MixingMap[key1] = mixer;
217 <    if (key2 != key1) {
218 <      MixingMap[key2] = mixer;
216 >    MixingMap.resize(nLJ_);
217 >    MixingMap[ljtid1].resize(nLJ_);
218 >
219 >    MixingMap[ljtid1][ljtid2] = mixer;
220 >    if (ljtid2 != ljtid1) {
221 >      MixingMap[ljtid2].resize(nLJ_);
222 >      MixingMap[ljtid2][ljtid1] = mixer;
223      }    
224    }
225  
226 <  void LJ::calcForce(AtomType* at1, AtomType* at2, Vector3d d,
289 <                     RealType rij, RealType r2, RealType rcut, RealType sw,
290 <                     RealType vdwMult, RealType &vpair, RealType &pot,
291 <                     Vector3d &f1) {
292 <
226 >  void LJ::calcForce(InteractionData &idat) {
227      if (!initialized_) initialize();
228      
229 +    LJInteractionData &mixer = MixingMap[LJtids[idat.atid1]][LJtids[idat.atid2]];
230 +
231 +    RealType sigmai = mixer.sigmai;
232 +    RealType epsilon = mixer.epsilon;
233 +    
234      RealType ros;
235      RealType rcos;
236      RealType myPot = 0.0;
237      RealType myPotC = 0.0;
238      RealType myDeriv = 0.0;
239      RealType myDerivC = 0.0;
301
302    std::pair<AtomType*, AtomType*> key = std::make_pair(at1, at2);
303    LJInteractionData mixer = MixingMap[key];
304
305    RealType sigmai = mixer.sigmai;
306    RealType epsilon = mixer.epsilon;
240      
241 <    ros = rij * sigmai;
242 <
241 >    ros = *(idat.rij) * sigmai;    
242 >    
243      getLJfunc(ros, myPot, myDeriv);
244 <
245 <    if (shiftedPot_) {
246 <      rcos = rcut * sigmai;
244 >    
245 >    if (idat.shiftedPot) {
246 >      rcos = *(idat.rcut) * sigmai;
247        getLJfunc(rcos, myPotC, myDerivC);
248        myDerivC = 0.0;
249 <    } else if (LJ::shiftedFrc_) {
250 <      rcos = rcut * sigmai;
249 >    } else if (idat.shiftedForce) {
250 >      rcos = *(idat.rcut) * sigmai;
251        getLJfunc(rcos, myPotC, myDerivC);
252 <      myPotC = myPotC + myDerivC * (rij - rcut) * sigmai;
252 >      myPotC = myPotC + myDerivC * (*(idat.rij) - *(idat.rcut)) * sigmai;
253      } else {
254        myPotC = 0.0;
255 <      myDerivC = 0.0;
255 >      myDerivC = 0.0;        
256      }
324
325    RealType pot_temp = vdwMult * epsilon * (myPot - myPotC);
326    vpair += pot_temp;
327
328    RealType dudr = sw * vdwMult * epsilon * (myDeriv - myDerivC)*sigmai;
257      
258 <    pot += sw * pot_temp;
259 <    f1 = d * dudr / rij;
332 <
333 <    return;
334 <  }
335 <
336 <  void LJ::do_lj_pair(int *atid1, int *atid2, RealType *d, RealType *rij,
337 <                      RealType *r2, RealType *rcut, RealType *sw,
338 <                      RealType *vdwMult,
339 <                      RealType *vpair, RealType *pot, RealType *f1) {
340 <
341 <    if (!initialized_) initialize();
258 >    RealType pot_temp = *(idat.vdwMult) * epsilon * (myPot - myPotC);
259 >    *(idat.vpair) += pot_temp;
260      
261 <    AtomType* atype1 = LJMap[*atid1];
262 <    AtomType* atype2 = LJMap[*atid2];
261 >    RealType dudr = *(idat.sw) * *(idat.vdwMult) * epsilon * (myDeriv -
262 >                                                              myDerivC)*sigmai;      
263 >    (*(idat.pot))[VANDERWAALS_FAMILY] += *(idat.sw) * pot_temp;
264 >    *(idat.f1) += *(idat.d) * dudr / *(idat.rij);
265      
266 <    Vector3d disp(d[0], d[1], d[2]);
347 <    Vector3d frc(f1[0], f1[1], f1[2]);
348 <    
349 <    calcForce(atype1, atype2, disp, *rij, *r2, *rcut, *sw, *vdwMult, *vpair,
350 <              *pot, frc);
351 <      
352 <    f1[0] = frc.x();
353 <    f1[1] = frc.y();
354 <    f1[2] = frc.z();
355 <    
356 <    return;    
266 >    return;
267    }
268    
269    void LJ::getLJfunc(RealType r, RealType &pot, RealType &deriv) {
# Line 371 | Line 281 | namespace OpenMD {
281      return;
282    }
283    
284 <
285 <  void LJ::setLJDefaultCutoff(RealType *thisRcut, int *sP, int *sF) {
376 <    shiftedPot_ = (bool)(*sP);
377 <    shiftedFrc_ = (bool)(*sF);
378 <  }
379 < }
380 <
381 < extern "C" {
382 <  
383 < #define fortranGetSigma FC_FUNC(getsigma, GETSIGMA)
384 < #define fortranGetEpsilon FC_FUNC(getepsilon, GETEPSILON)
385 < #define fortranSetLJCutoff FC_FUNC(setljdefaultcutoff, SETLJDEFAULTCUTOFF)
386 < #define fortranDoLJPair FC_FUNC(do_lj_pair, DO_LJ_PAIR)
387 <  
388 <  RealType fortranGetSigma(int* atid) {
389 <    return OpenMD::LJ::Instance()->getSigma(*atid);
390 <  }
391 <  RealType fortranGetEpsilon(int* atid) {  
392 <    return OpenMD::LJ::Instance()->getEpsilon(*atid);
393 <  }
394 <  void fortranSetLJCutoff(RealType *rcut, int *shiftedPot, int *shiftedFrc) {
395 <    return OpenMD::LJ::Instance()->setLJDefaultCutoff(rcut, shiftedPot,
396 <                                                      shiftedFrc);
397 <  }
398 <  void fortranDoLJPair(int *atid1, int *atid2, RealType *d, RealType *rij,
399 <                       RealType *r2, RealType *rcut, RealType *sw,
400 <                       RealType *vdwMult, RealType* vpair, RealType* pot,
401 <                       RealType *f1){
284 >  RealType LJ::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
285 >    if (!initialized_) initialize();  
286      
287 <    return OpenMD::LJ::Instance()->do_lj_pair(atid1, atid2, d, rij, r2, rcut,
288 <                                              sw, vdwMult, vpair, pot, f1);
287 >    int atid1 = atypes.first->getIdent();
288 >    int atid2 = atypes.second->getIdent();
289 >    int ljtid1 = LJtids[atid1];
290 >    int ljtid2 = LJtids[atid2];
291 >    
292 >    if (ljtid1 == -1 || ljtid2 == -1) return 0.0;
293 >    else {      
294 >      LJInteractionData mixer = MixingMap[ljtid1][ljtid2];
295 >      return 2.5 * mixer.sigma;
296 >    }
297    }
298 +  
299   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines