ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/nonbonded/EAM.cpp
Revision: 1895
Committed: Mon Jul 1 21:09:37 2013 UTC (12 years ago) by gezelter
File size: 13349 byte(s)
Log Message:
Speed!

File Contents

# User Rev Content
1 gezelter 1478 /*
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 gezelter 1879 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
39 gezelter 1665 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40     * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 gezelter 1478 */
42    
43     #include <stdio.h>
44     #include <string.h>
45    
46     #include <cmath>
47     #include "nonbonded/EAM.hpp"
48     #include "utils/simError.h"
49 gezelter 1479 #include "types/NonBondedInteractionType.hpp"
50 gezelter 1478
51    
52     namespace OpenMD {
53    
54 gezelter 1502 EAM::EAM() : name_("EAM"), initialized_(false), forceField_(NULL),
55 gezelter 1586 mixMeth_(eamJohnson), eamRcut_(0.0), haveCutoffRadius_(false) {}
56 gezelter 1478
57 gezelter 1710 CubicSpline* EAM::getPhi(AtomType* atomType1, AtomType* atomType2) {
58     EAMAdapter ea1 = EAMAdapter(atomType1);
59     EAMAdapter ea2 = EAMAdapter(atomType2);
60     CubicSpline* z1 = ea1.getZ();
61     CubicSpline* z2 = ea2.getZ();
62 gezelter 1478
63     // make the r grid:
64    
65    
66 gezelter 1481 // we need phi out to the largest value we'll encounter in the radial space;
67    
68     RealType rmax = 0.0;
69 gezelter 1710 rmax = max(rmax, ea1.getRcut());
70     rmax = max(rmax, ea1.getNr() * ea1.getDr());
71 gezelter 1478
72 gezelter 1710 rmax = max(rmax, ea2.getRcut());
73     rmax = max(rmax, ea2.getNr() * ea2.getDr());
74 gezelter 1481
75 gezelter 1478 // use the smallest dr (finest grid) to build our grid:
76    
77 gezelter 1710 RealType dr = min(ea1.getDr(), ea2.getDr());
78 gezelter 1481
79     int nr = int(rmax/dr + 0.5);
80    
81 gezelter 1478 vector<RealType> rvals;
82 gezelter 1481 for (int i = 0; i < nr; i++) rvals.push_back(RealType(i*dr));
83 gezelter 1478
84     // construct the pair potential:
85    
86     vector<RealType> phivals;
87     RealType phi;
88     RealType r;
89     RealType zi, zj;
90    
91     phivals.push_back(0.0);
92    
93 gezelter 1767 for (unsigned int i = 1; i < rvals.size(); i++ ) {
94 gezelter 1478 r = rvals[i];
95    
96 gezelter 1502 // only use z(r) if we're inside this atom's cutoff radius,
97     // otherwise, we'll use zero for the charge. This effectively
98     // means that our phi grid goes out beyond the cutoff of the
99     // pair potential
100 gezelter 1481
101 gezelter 1710 zi = r <= ea1.getRcut() ? z1->getValueAt(r) : 0.0;
102     zj = r <= ea2.getRcut() ? z2->getValueAt(r) : 0.0;
103 gezelter 1481
104 gezelter 1478 phi = 331.999296 * (zi * zj) / r;
105 gezelter 1481
106 gezelter 1478 phivals.push_back(phi);
107     }
108    
109     CubicSpline* cs = new CubicSpline();
110     cs->addPoints(rvals, phivals);
111     return cs;
112     }
113    
114 gezelter 1586 void EAM::setCutoffRadius( RealType rCut ) {
115     eamRcut_ = rCut;
116     haveCutoffRadius_ = true;
117     }
118    
119 gezelter 1478 void EAM::initialize() {
120     // set up the mixing method:
121 gezelter 1479 ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
122 gezelter 1481 string EAMMixMeth = fopts.getEAMMixingMethod();
123 gezelter 1480 toUpper(EAMMixMeth);
124    
125 gezelter 1478 if (EAMMixMeth == "JOHNSON")
126     mixMeth_ = eamJohnson;
127     else if (EAMMixMeth == "DAW")
128     mixMeth_ = eamDaw;
129     else
130     mixMeth_ = eamUnknown;
131    
132     // find all of the EAM atom Types:
133 gezelter 1895 EAMtypes.clear();
134     EAMtids.clear();
135     EAMdata.clear();
136     MixingMap.clear();
137     nEAM_ = 0;
138    
139     EAMtids.resize( forceField_->getNAtomType(), -1);
140 gezelter 1478
141 gezelter 1895 set<AtomType*>::iterator at;
142     for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
143     if ((*at)->isEAM()) nEAM_++;
144 gezelter 1478 }
145 gezelter 1895 EAMdata.resize(nEAM_);
146     MixingMap.resize(nEAM_);
147    
148     for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
149     if ((*at)->isEAM()) addType(*at);
150     }
151 gezelter 1478
152     // find all of the explicit EAM interactions (setfl):
153     ForceField::NonBondedInteractionTypeContainer* nbiTypes = forceField_->getNonBondedInteractionTypes();
154     ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
155     NonBondedInteractionType* nbt;
156    
157     for (nbt = nbiTypes->beginType(j); nbt != NULL;
158     nbt = nbiTypes->nextType(j)) {
159    
160     if (nbt->isEAM()) {
161    
162 gezelter 1481 pair<AtomType*, AtomType*> atypes = nbt->getAtomTypes();
163 gezelter 1478
164     GenericData* data = nbt->getPropertyByName("EAM");
165     if (data == NULL) {
166     sprintf( painCave.errMsg, "EAM::rebuildMixingMap could not find\n"
167     "\tEAM parameters for %s - %s interaction.\n",
168     atypes.first->getName().c_str(),
169     atypes.second->getName().c_str());
170     painCave.severity = OPENMD_ERROR;
171     painCave.isFatal = 1;
172     simError();
173     }
174    
175     EAMMixingData* eamData = dynamic_cast<EAMMixingData*>(data);
176     if (eamData == NULL) {
177     sprintf( painCave.errMsg,
178     "EAM::rebuildMixingMap could not convert GenericData to\n"
179     "\tEAMMixingData for %s - %s interaction.\n",
180     atypes.first->getName().c_str(),
181     atypes.second->getName().c_str());
182     painCave.severity = OPENMD_ERROR;
183     painCave.isFatal = 1;
184     simError();
185     }
186    
187 gezelter 1479 EAMMixingParam eamParam = eamData->getData();
188 gezelter 1478
189 gezelter 1479 vector<RealType> phiAB = eamParam.phi;
190 gezelter 1478 RealType dr = eamParam.dr;
191     int nr = eamParam.nr;
192    
193     addExplicitInteraction(atypes.first, atypes.second, dr, nr, phiAB);
194     }
195     }
196     initialized_ = true;
197     }
198    
199    
200    
201     void EAM::addType(AtomType* atomType){
202    
203 gezelter 1710 EAMAdapter ea = EAMAdapter(atomType);
204 gezelter 1478 EAMAtomData eamAtomData;
205    
206 gezelter 1710 eamAtomData.rho = ea.getRho();
207     eamAtomData.F = ea.getF();
208     eamAtomData.Z = ea.getZ();
209     eamAtomData.rcut = ea.getRcut();
210    
211 gezelter 1478 // add it to the map:
212 gezelter 1895 int atid = atomType->getIdent();
213     int eamtid = EAMtypes.size();
214 gezelter 1478
215 gezelter 1895 pair<set<int>::iterator,bool> ret;
216     ret = EAMtypes.insert( atid );
217 gezelter 1478 if (ret.second == false) {
218     sprintf( painCave.errMsg,
219     "EAM already had a previous entry with ident %d\n",
220 gezelter 1895 atid);
221 gezelter 1478 painCave.severity = OPENMD_INFO;
222     painCave.isFatal = 0;
223     simError();
224     }
225    
226 gezelter 1895 EAMtids[atid] = eamtid;
227     EAMdata[eamtid] = eamAtomData;
228     MixingMap[eamtid].resize(nEAM_);
229 gezelter 1478
230     // Now, iterate over all known types and add to the mixing map:
231    
232 gezelter 1895 std::set<int>::iterator it;
233     for( it = EAMtypes.begin(); it != EAMtypes.end(); ++it) {
234 gezelter 1478
235 gezelter 1895 int eamtid2 = EAMtids[ (*it) ];
236     AtomType* atype2 = forceField_->getAtomType( (*it) );
237 gezelter 1478
238     EAMInteractionData mixer;
239     mixer.phi = getPhi(atomType, atype2);
240     mixer.explicitlySet = false;
241    
242 gezelter 1895 MixingMap[eamtid2].resize( nEAM_ );
243 gezelter 1478
244 gezelter 1895 MixingMap[eamtid][eamtid2] = mixer;
245     if (eamtid2 != eamtid) {
246     MixingMap[eamtid2][eamtid] = mixer;
247 gezelter 1478 }
248     }
249     return;
250     }
251    
252     void EAM::addExplicitInteraction(AtomType* atype1, AtomType* atype2,
253     RealType dr, int nr,
254     vector<RealType> phiVals) {
255    
256     // in case these weren't already in the map
257     addType(atype1);
258     addType(atype2);
259    
260     EAMInteractionData mixer;
261     CubicSpline* cs = new CubicSpline();
262 gezelter 1479 vector<RealType> rVals;
263 gezelter 1478
264 gezelter 1479 for (int i = 0; i < nr; i++) rVals.push_back(i * dr);
265 gezelter 1478
266     cs->addPoints(rVals, phiVals);
267     mixer.phi = cs;
268     mixer.explicitlySet = true;
269    
270 gezelter 1895 int eamtid1 = EAMtids[ atype1->getIdent() ];
271     int eamtid2 = EAMtids[ atype2->getIdent() ];
272 gezelter 1478
273 gezelter 1895 MixingMap[eamtid1][eamtid2] = mixer;
274     if (eamtid2 != eamtid1) {
275     MixingMap[eamtid2][eamtid1] = mixer;
276 gezelter 1478 }
277     return;
278     }
279    
280 gezelter 1545 void EAM::calcDensity(InteractionData &idat) {
281 gezelter 1479
282 gezelter 1478 if (!initialized_) initialize();
283 gezelter 1479
284 gezelter 1895 EAMAtomData &data1 = EAMdata[EAMtids[idat.atid1]];
285     EAMAtomData &data2 = EAMdata[EAMtids[idat.atid2]];
286    
287 gezelter 1586 if (haveCutoffRadius_)
288     if ( *(idat.rij) > eamRcut_) return;
289    
290 gezelter 1629 if ( *(idat.rij) < data1.rcut)
291 gezelter 1575 *(idat.rho1) += data1.rho->getValueAt( *(idat.rij));
292 gezelter 1629
293 gezelter 1586
294 gezelter 1629 if ( *(idat.rij) < data2.rcut)
295     *(idat.rho2) += data2.rho->getValueAt( *(idat.rij));
296    
297     return;
298 gezelter 1478 }
299 gezelter 1586
300 gezelter 1545 void EAM::calcFunctional(SelfData &sdat) {
301 gezelter 1586
302 gezelter 1478 if (!initialized_) initialize();
303    
304 gezelter 1895 EAMAtomData &data1 = EAMdata[ EAMtids[sdat.atid] ];
305 gezelter 1478
306 gezelter 1895 data1.F->getValueAndDerivativeAt( *(sdat.rho), *(sdat.frho), *(sdat.dfrhodrho) );
307 gezelter 1478
308 gezelter 1895 (*(sdat.pot))[METALLIC_FAMILY] += *(sdat.frho);
309 gezelter 1711 if (sdat.doParticlePot) {
310 gezelter 1895 *(sdat.particlePot) += *(sdat.frho);
311 gezelter 1711 }
312 gezelter 1575
313 gezelter 1478 return;
314     }
315    
316    
317 gezelter 1536 void EAM::calcForce(InteractionData &idat) {
318 gezelter 1478
319     if (!initialized_) initialize();
320 gezelter 1481
321 gezelter 1586 if (haveCutoffRadius_)
322     if ( *(idat.rij) > eamRcut_) return;
323    
324 gezelter 1895
325     int eamtid1 = EAMtids[idat.atid1];
326     int eamtid2 = EAMtids[idat.atid2];
327 gezelter 1478
328 gezelter 1895 EAMAtomData &data1 = EAMdata[eamtid1];
329     EAMAtomData &data2 = EAMdata[eamtid2];
330 gezelter 1586
331     // get type-specific cutoff radii
332    
333     RealType rci = data1.rcut;
334     RealType rcj = data2.rcut;
335    
336     RealType rha(0.0), drha(0.0), rhb(0.0), drhb(0.0);
337     RealType pha(0.0), dpha(0.0), phb(0.0), dphb(0.0);
338     RealType phab(0.0), dvpdr(0.0);
339     RealType drhoidr, drhojdr, dudr;
340    
341     if ( *(idat.rij) < rci) {
342 gezelter 1895 data1.rho->getValueAndDerivativeAt( *(idat.rij), rha, drha);
343     CubicSpline* phi = MixingMap[eamtid1][eamtid1].phi;
344     phi->getValueAndDerivativeAt( *(idat.rij), pha, dpha);
345 gezelter 1586 }
346    
347     if ( *(idat.rij) < rcj) {
348 gezelter 1895 data2.rho->getValueAndDerivativeAt( *(idat.rij), rhb, drhb );
349     CubicSpline* phi = MixingMap[eamtid2][eamtid2].phi;
350     phi->getValueAndDerivativeAt( *(idat.rij), phb, dphb);
351 gezelter 1586 }
352 gezelter 1478
353 gezelter 1586 switch(mixMeth_) {
354     case eamJohnson:
355 gezelter 1478
356 gezelter 1554 if ( *(idat.rij) < rci) {
357 gezelter 1586 phab = phab + 0.5 * (rhb / rha) * pha;
358     dvpdr = dvpdr + 0.5*((rhb/rha)*dpha +
359     pha*((drhb/rha) - (rhb*drha/rha/rha)));
360 gezelter 1478 }
361 gezelter 1586
362    
363    
364 gezelter 1554 if ( *(idat.rij) < rcj) {
365 gezelter 1586 phab = phab + 0.5 * (rha / rhb) * phb;
366     dvpdr = dvpdr + 0.5 * ((rha/rhb)*dphb +
367     phb*((drha/rhb) - (rha*drhb/rhb/rhb)));
368 gezelter 1478 }
369    
370 gezelter 1586 break;
371    
372     case eamDaw:
373 gezelter 1895 MixingMap[eamtid1][eamtid2].phi->getValueAndDerivativeAt( *(idat.rij), phab, dvpdr);
374 gezelter 1586
375     break;
376     case eamUnknown:
377     default:
378    
379     sprintf(painCave.errMsg,
380     "EAM::calcForce hit a mixing method it doesn't know about!\n"
381     );
382     painCave.severity = OPENMD_ERROR;
383     painCave.isFatal = 1;
384     simError();
385    
386     }
387    
388     drhoidr = drha;
389     drhojdr = drhb;
390    
391     dudr = drhojdr* *(idat.dfrho1) + drhoidr* *(idat.dfrho2) + dvpdr;
392    
393     *(idat.f1) += *(idat.d) * dudr / *(idat.rij);
394 gezelter 1478
395 gezelter 1711 if (idat.doParticlePot) {
396     // particlePot is the difference between the full potential and
397     // the full potential without the presence of a particular
398     // particle (atom1).
399     //
400     // This reduces the density at other particle locations, so we
401     // need to recompute the density at atom2 assuming atom1 didn't
402     // contribute. This then requires recomputing the density
403     // functional for atom2 as well.
404    
405     *(idat.particlePot1) += data2.F->getValueAt( *(idat.rho2) - rha )
406     - *(idat.frho2);
407    
408     *(idat.particlePot2) += data1.F->getValueAt( *(idat.rho1) - rhb)
409     - *(idat.frho1);
410     }
411 gezelter 1586
412     (*(idat.pot))[METALLIC_FAMILY] += phab;
413    
414     *(idat.vpair) += phab;
415    
416 gezelter 1478 return;
417    
418     }
419 gezelter 1505
420 gezelter 1545 RealType EAM::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
421 gezelter 1505 if (!initialized_) initialize();
422    
423     RealType cut = 0.0;
424    
425 gezelter 1895 int atid1 = atypes.first->getIdent();
426     int atid2 = atypes.second->getIdent();
427     int eamtid1 = EAMtids[atid1];
428     int eamtid2 = EAMtids[atid2];
429    
430     if (eamtid1 != -1) {
431     EAMAtomData data1 = EAMdata[eamtid1];
432 gezelter 1505 cut = data1.rcut;
433     }
434    
435 gezelter 1895 if (eamtid2 != -1) {
436     EAMAtomData data2 = EAMdata[eamtid2];
437 gezelter 1505 if (data2.rcut > cut)
438     cut = data2.rcut;
439     }
440 gezelter 1895
441 gezelter 1505 return cut;
442     }
443 gezelter 1478 }
444    

Properties

Name Value
svn:eol-style native