ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/nonbonded/LJ.cpp
Revision: 1683
Committed: Wed Feb 29 20:33:01 2012 UTC (13 years, 2 months ago) by jmichalk
File size: 10201 byte(s)
Log Message:
LJ.cpp has been updated to more correctly deal with nonbonded interactions
(i.e. explicit interactions where the species are not necessarily defined
to be lennardJones type atoms)

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] 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/LJ.hpp"
48 #include "utils/simError.h"
49 #include "types/LennardJonesInteractionType.hpp"
50
51 namespace OpenMD {
52
53 LJ::LJ() : name_("LJ"), initialized_(false), forceField_(NULL) {}
54
55 LJParam LJ::getLJParam(AtomType* atomType) {
56
57 // Do sanity checking on the AtomType we were passed before
58 // building any data structures:
59 if (!atomType->isLennardJones()) {
60 sprintf( painCave.errMsg,
61 "LJ::getLJParam was passed an atomType (%s) that does not\n"
62 "\tappear to be a Lennard-Jones atom.\n",
63 atomType->getName().c_str());
64 painCave.severity = OPENMD_ERROR;
65 painCave.isFatal = 1;
66 simError();
67 }
68
69 GenericData* data = atomType->getPropertyByName("LennardJones");
70 if (data == NULL) {
71 sprintf( painCave.errMsg, "LJ::getLJParam could not find Lennard-Jones\n"
72 "\tparameters for atomType %s.\n", atomType->getName().c_str());
73 painCave.severity = OPENMD_ERROR;
74 painCave.isFatal = 1;
75 simError();
76 }
77
78 LJParamGenericData* ljData = dynamic_cast<LJParamGenericData*>(data);
79 if (ljData == NULL) {
80 sprintf( painCave.errMsg,
81 "LJ::getLJParam could not convert GenericData to LJParam for\n"
82 "\tatom type %s\n", atomType->getName().c_str());
83 painCave.severity = OPENMD_ERROR;
84 painCave.isFatal = 1;
85 simError();
86 }
87
88 return ljData->getData();
89 }
90
91 RealType LJ::getSigma(AtomType* atomType) {
92 LJParam ljParam = getLJParam(atomType);
93 return ljParam.sigma;
94 }
95
96 RealType LJ::getSigma(AtomType* atomType1, AtomType* atomType2) {
97 RealType sigma1 = getSigma(atomType1);
98 RealType sigma2 = getSigma(atomType2);
99
100 ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
101 string DistanceMix = fopts.getDistanceMixingRule();
102 toUpper(DistanceMix);
103
104 if (DistanceMix == "GEOMETRIC")
105 return sqrt(sigma1 * sigma2);
106 else
107 return 0.5 * (sigma1 + sigma2);
108 }
109
110 RealType LJ::getEpsilon(AtomType* atomType) {
111 LJParam ljParam = getLJParam(atomType);
112 return ljParam.epsilon;
113 }
114
115 RealType LJ::getEpsilon(AtomType* atomType1, AtomType* atomType2) {
116 RealType epsilon1 = getEpsilon(atomType1);
117 RealType epsilon2 = getEpsilon(atomType2);
118 return sqrt(epsilon1 * epsilon2);
119 }
120
121 void LJ::initialize() {
122 ForceField::AtomTypeContainer* atomTypes = forceField_->getAtomTypes();
123 ForceField::AtomTypeContainer::MapTypeIterator i;
124 AtomType* at;
125
126 for (at = atomTypes->beginType(i); at != NULL;
127 at = atomTypes->nextType(i)) {
128 if (at->isLennardJones()){
129 addType(at);
130 }
131 }
132 ForceField::NonBondedInteractionTypeContainer* nbiTypes = forceField_->getNonBondedInteractionTypes();
133 ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
134 NonBondedInteractionType* nbt;
135 ForceField::NonBondedInteractionTypeContainer::KeyType keys;
136
137
138 for (nbt = nbiTypes->beginType(j); nbt != NULL;
139 nbt = nbiTypes->nextType(j)) {
140
141 if (nbt->isLennardJones()) {
142 keys = nbiTypes->getKeys(j);
143 AtomType* at1 = forceField_->getAtomType(keys[0]);
144 AtomType* at2 = forceField_->getAtomType(keys[1]);
145
146 LennardJonesInteractionType* ljit = dynamic_cast<LennardJonesInteractionType*>(nbt);
147
148 if (ljit == NULL) {
149 sprintf( painCave.errMsg,
150 "LJ::initialize could not convert NonBondedInteractionType\n"
151 "\tto LennardJonesInteractionType for %s - %s interaction.\n",
152 at1->getName().c_str(),
153 at2->getName().c_str());
154 painCave.severity = OPENMD_ERROR;
155 painCave.isFatal = 1;
156 simError();
157 }
158
159 RealType sigma = ljit->getSigma();
160 RealType epsilon = ljit->getEpsilon();
161 addExplicitInteraction(at1, at2, sigma, epsilon);
162 }
163 }
164 initialized_ = true;
165 }
166
167
168
169 void LJ::addType(AtomType* atomType){
170 RealType sigma1 = getSigma(atomType);
171 RealType epsilon1 = getEpsilon(atomType);
172
173 // add it to the map:
174 AtomTypeProperties atp = atomType->getATP();
175
176 pair<map<int,AtomType*>::iterator,bool> ret;
177 ret = LJMap.insert( pair<int, AtomType*>(atp.ident, atomType) );
178 if (ret.second == false) {
179 sprintf( painCave.errMsg,
180 "LJ already had a previous entry with ident %d\n",
181 atp.ident);
182 painCave.severity = OPENMD_INFO;
183 painCave.isFatal = 0;
184 simError();
185 }
186
187 // Now, iterate over all known types and add to the mixing map:
188
189 std::map<int, AtomType*>::iterator it;
190 for( it = LJMap.begin(); it != LJMap.end(); ++it) {
191
192 AtomType* atype2 = (*it).second;
193
194 LJInteractionData mixer;
195 mixer.sigma = getSigma(atomType, atype2);
196 mixer.epsilon = getEpsilon(atomType, atype2);
197 mixer.sigmai = 1.0 / mixer.sigma;
198 mixer.explicitlySet = false;
199
200 std::pair<AtomType*, AtomType*> key1, key2;
201 key1 = std::make_pair(atomType, atype2);
202 key2 = std::make_pair(atype2, atomType);
203
204 MixingMap[key1] = mixer;
205 if (key2 != key1) {
206 MixingMap[key2] = mixer;
207 }
208 }
209 }
210
211 void LJ::addExplicitInteraction(AtomType* atype1, AtomType* atype2, RealType sigma, RealType epsilon){
212
213 LJInteractionData mixer;
214 mixer.sigma = sigma;
215 mixer.epsilon = epsilon;
216 mixer.sigmai = 1.0 / mixer.sigma;
217 mixer.explicitlySet = true;
218
219 std::pair<AtomType*, AtomType*> key1, key2;
220 key1 = std::make_pair(atype1, atype2);
221 key2 = std::make_pair(atype2, atype1);
222
223 MixingMap[key1] = mixer;
224 if (key2 != key1) {
225 MixingMap[key2] = mixer;
226 }
227 }
228
229 void LJ::calcForce(InteractionData &idat) {
230 if (!initialized_) initialize();
231 map<pair<AtomType*, AtomType*>, LJInteractionData>::iterator it;
232 it = MixingMap.find( idat.atypes );
233
234 if (it != MixingMap.end()) {
235
236 LJInteractionData mixer = (*it).second;
237
238 RealType sigmai = mixer.sigmai;
239 RealType epsilon = mixer.epsilon;
240
241 RealType ros;
242 RealType rcos;
243 RealType myPot = 0.0;
244 RealType myPotC = 0.0;
245 RealType myDeriv = 0.0;
246 RealType myDerivC = 0.0;
247
248 ros = *(idat.rij) * sigmai;
249
250 getLJfunc(ros, myPot, myDeriv);
251
252 if (idat.shiftedPot) {
253 rcos = *(idat.rcut) * sigmai;
254 getLJfunc(rcos, myPotC, myDerivC);
255 myDerivC = 0.0;
256 } else if (idat.shiftedForce) {
257 rcos = *(idat.rcut) * sigmai;
258 getLJfunc(rcos, myPotC, myDerivC);
259 myPotC = myPotC + myDerivC * (*(idat.rij) - *(idat.rcut)) * sigmai;
260 } else {
261 myPotC = 0.0;
262 myDerivC = 0.0;
263 }
264
265 RealType pot_temp = *(idat.vdwMult) * epsilon * (myPot - myPotC);
266 *(idat.vpair) += pot_temp;
267
268 RealType dudr = *(idat.sw) * *(idat.vdwMult) * epsilon * (myDeriv -
269 myDerivC)*sigmai;
270
271 (*(idat.pot))[VANDERWAALS_FAMILY] += *(idat.sw) * pot_temp;
272 *(idat.f1) += *(idat.d) * dudr / *(idat.rij);
273 }
274 return;
275 }
276
277 void LJ::getLJfunc(RealType r, RealType &pot, RealType &deriv) {
278
279 RealType ri = 1.0 / r;
280 RealType ri2 = ri * ri;
281 RealType ri6 = ri2 * ri2 * ri2;
282 RealType ri7 = ri6 * ri;
283 RealType ri12 = ri6 * ri6;
284 RealType ri13 = ri12 * ri;
285
286 pot = 4.0 * (ri12 - ri6);
287 deriv = 24.0 * (ri7 - 2.0 * ri13);
288
289 return;
290 }
291
292 RealType LJ::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
293 if (!initialized_) initialize();
294 map<pair<AtomType*, AtomType*>, LJInteractionData>::iterator it;
295 it = MixingMap.find(atypes);
296 if (it == MixingMap.end())
297 return 0.0;
298 else {
299 LJInteractionData mixer = (*it).second;
300 return 2.5 * mixer.sigma;
301 }
302 }
303
304 }

Properties

Name Value
svn:eol-style native