ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/nonbonded/EAM.cpp
Revision: 1478
Committed: Fri Jul 23 20:45:40 2010 UTC (14 years, 9 months ago) by gezelter
File size: 18547 byte(s)
Log Message:
busticated EAM

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     * [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/EAM.hpp"
47     #include "utils/simError.h"
48    
49    
50     namespace OpenMD {
51    
52     bool EAM::initialized_ = false;
53     ForceField* EAM::forceField_ = NULL;
54     std::map<int, AtomType*> EAM::EAMlist;
55     std::map<AtomType*, EAMAtomData> EAM::EAMMap;
56     std::map<std::pair<AtomType*, AtomType*>, EAMInteractionData> EAM::MixingMap;
57    
58     EAM* EAM::_instance = NULL;
59    
60     EAM* EAM::Instance() {
61     if (!_instance) {
62     _instance = new EAM();
63     }
64     return _instance;
65     }
66    
67     EAMParam EAM::getEAMParam(AtomType* atomType) {
68    
69     // Do sanity checking on the AtomType we were passed before
70     // building any data structures:
71     if (!atomType->isEAM()) {
72     sprintf( painCave.errMsg,
73     "EAM::getEAMParam was passed an atomType (%s) that does not\n"
74     "\tappear to be an embedded atom method (EAM) atom.\n",
75     atomType->getName().c_str());
76     painCave.severity = OPENMD_ERROR;
77     painCave.isFatal = 1;
78     simError();
79     }
80    
81     GenericData* data = atomType->getPropertyByName("EAM");
82     if (data == NULL) {
83     sprintf( painCave.errMsg, "EAM::getEAMParam could not find EAM\n"
84     "\tparameters for atomType %s.\n",
85     atomType->getName().c_str());
86     painCave.severity = OPENMD_ERROR;
87     painCave.isFatal = 1;
88     simError();
89     }
90    
91     EAMParamGenericData* eamData = dynamic_cast<EAMParamGenericData*>(data);
92     if (eamData == NULL) {
93     sprintf( painCave.errMsg,
94     "EAM::getEAMParam could not convert GenericData to EAMParam 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 eamData->getData();
102     }
103    
104     CubicSpline* EAM::getZ(AtomType* atomType) {
105     EAMParam eamParam = getEAMParam(atomType);
106     int nr = eamParam.nr;
107     RealType dr = eamParam.dr;
108     vector<RealType> rvals;
109    
110     for (int i = 0; i < nr; i++) rvals.push_back(i * dr);
111    
112     CubicSpline* cs = new CubicSpline();
113     cs->addPoints(rvals, eamParam.Z);
114     return cs;
115     }
116    
117     CubicSpline* EAM::getRho(AtomType* atomType) {
118     EAMParam eamParam = getEAMParam(atomType);
119     int nr = eamParam.nr;
120     RealType dr = eamParam.dr;
121     vector<RealType> rvals;
122    
123     for (int i = 0; i < nr; i++) rvals.push_back(i * dr);
124    
125     CubicSpline* cs = new CubicSpline();
126     cs->addPoints(rvals, eamParam.rho);
127     return cs;
128     }
129    
130     CubicSpline* EAM::getF(AtomType* atomType) {
131     EAMParam eamParam = getEAMParam(atomType);
132     int nrho = eamParam.nrho;
133     RealType drho = eamParam.drho;
134     vector<RealType> rhovals;
135     vector<RealType> scaledF;
136    
137     for (int i = 0; i < nrho; i++) {
138     rhovals.push_back(i * drho);
139     scaledF.push_back( eamParam.F[i] * 23.06054 );
140     }
141    
142     CubicSpline* cs = new CubicSpline();
143     cs->addPoints(rhovals, eamParam.F);
144     return cs;
145     }
146    
147     CubicSpline* EAM::getPhi(AtomType* atomType1, AtomType* atomType2) {
148     EAMParam eamParam1 = getEAMParam(atomType1);
149     EAMParam eamParam2 = getEAMParam(atomType2);
150     CubicSpline* z1 = getZ(atomType1);
151     CubicSpline* z2 = getZ(atomType2);
152    
153     // make the r grid:
154    
155     // set rcut to be the smaller of the two atomic rcuts
156    
157     RealType rcut = eamParam1.rcut < eamParam2.rcut ?
158     eamParam1.rcut : eamParam2.rcut;
159    
160     // use the smallest dr (finest grid) to build our grid:
161    
162     RealType dr = eamParam1.dr < eamParam2.dr ? eamParam1.dr : eamParam2.dr;
163     int nr = int(rcut/dr);
164     vector<RealType> rvals;
165     for (int i = 0; i < nr; i++) rvals.push_back(i*dr);
166    
167     // construct the pair potential:
168    
169     vector<RealType> phivals;
170     RealType phi;
171     RealType r;
172     RealType zi, zj;
173    
174     phivals.push_back(0.0);
175    
176     for (int i = 1; i < rvals.size(); i++ ) {
177     r = rvals[i];
178     zi = z1->getValueAt(r);
179     zj = z2->getValueAt(r);
180    
181     phi = 331.999296 * (zi * zj) / r;
182     phivals.push_back(phi);
183     }
184    
185     CubicSpline* cs = new CubicSpline();
186     cs->addPoints(rvals, phivals);
187     return cs;
188     }
189    
190     void EAM::initialize() {
191    
192     // set up the mixing method:
193     ForceFieldOptions ffo = forceField_->getForceFieldOptions();
194     string EAMMixMeth = toUpperCopy(ffo.getEAMMixingMethod());
195    
196     if (EAMMixMeth == "JOHNSON")
197     mixMeth_ = eamJohnson;
198     else if (EAMMixMeth == "DAW")
199     mixMeth_ = eamDaw;
200     else
201     mixMeth_ = eamUnknown;
202    
203     // find all of the EAM atom Types:
204     ForceField::AtomTypeContainer* atomTypes = forceField_->getAtomTypes();
205     ForceField::AtomTypeContainer::MapTypeIterator i;
206     AtomType* at;
207    
208     for (at = atomTypes->beginType(i); at != NULL;
209     at = atomTypes->nextType(i)) {
210    
211     if (at->isEAM())
212     addType(at);
213     }
214    
215     // find all of the explicit EAM interactions (setfl):
216     ForceField::NonBondedInteractionTypeContainer* nbiTypes = forceField_->getNonBondedInteractionTypes();
217     ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
218     NonBondedInteractionType* nbt;
219    
220     for (nbt = nbiTypes->beginType(j); nbt != NULL;
221     nbt = nbiTypes->nextType(j)) {
222    
223     if (nbt->isEAM()) {
224    
225     std::pair<AtomType*, AtomType*> atypes = nbt->getAtomTypes();
226    
227     GenericData* data = nbt->getPropertyByName("EAM");
228     if (data == NULL) {
229     sprintf( painCave.errMsg, "EAM::rebuildMixingMap could not find\n"
230     "\tEAM parameters for %s - %s interaction.\n",
231     atypes.first->getName().c_str(),
232     atypes.second->getName().c_str());
233     painCave.severity = OPENMD_ERROR;
234     painCave.isFatal = 1;
235     simError();
236     }
237    
238     EAMMixingData* eamData = dynamic_cast<EAMMixingData*>(data);
239     if (eamData == NULL) {
240     sprintf( painCave.errMsg,
241     "EAM::rebuildMixingMap could not convert GenericData to\n"
242     "\tEAMMixingData for %s - %s interaction.\n",
243     atypes.first->getName().c_str(),
244     atypes.second->getName().c_str());
245     painCave.severity = OPENMD_ERROR;
246     painCave.isFatal = 1;
247     simError();
248     }
249    
250     EAMMix eamParam = eamData->getData();
251    
252     vector<RealType> phiAB = eamParam.phiAB;
253     RealType dr = eamParam.dr;
254     int nr = eamParam.nr;
255    
256     addExplicitInteraction(atypes.first, atypes.second, dr, nr, phiAB);
257     }
258     }
259     initialized_ = true;
260     }
261    
262    
263    
264     void EAM::addType(AtomType* atomType){
265    
266     EAMAtomData eamAtomData;
267    
268     eamAtomData.rho = getRho(atomType);
269     eamAtomData.F = getF(atomType);
270     eamAtomData.Z = getZ(atomType);
271     eamAtomData.rcut = getRcut(atomType);
272    
273     // add it to the map:
274     AtomTypeProperties atp = atomType->getATP();
275    
276     std::pair<std::map<int,AtomType*>::iterator,bool> ret;
277     ret = EAMlist.insert( std::pair<int, AtomType*>(atp.ident, atomType) );
278     if (ret.second == false) {
279     sprintf( painCave.errMsg,
280     "EAM already had a previous entry with ident %d\n",
281     atp.ident);
282     painCave.severity = OPENMD_INFO;
283     painCave.isFatal = 0;
284     simError();
285     }
286    
287     EAMMap[atomType] = eamAtomData;
288    
289     // Now, iterate over all known types and add to the mixing map:
290    
291     std::map<int, AtomType*>::iterator it;
292     for( it = EAMMap.begin(); it != EAMMap.end(); ++it) {
293    
294     AtomType* atype2 = (*it).second;
295    
296     EAMInteractionData mixer;
297     mixer.phi = getPhi(atomType, atype2);
298     mixer.explicitlySet = false;
299    
300     std::pair<AtomType*, AtomType*> key1, key2;
301     key1 = std::make_pair(atomType, atype2);
302     key2 = std::make_pair(atype2, atomType);
303    
304     MixingMap[key1] = mixer;
305     if (key2 != key1) {
306     MixingMap[key2] = mixer;
307     }
308     }
309     return;
310     }
311    
312     void EAM::addExplicitInteraction(AtomType* atype1, AtomType* atype2,
313     RealType dr, int nr,
314     vector<RealType> phiVals) {
315    
316     // in case these weren't already in the map
317     addType(atype1);
318     addType(atype2);
319    
320     EAMInteractionData mixer;
321     CubicSpline* cs = new CubicSpline();
322     vector<RealType> rvals;
323    
324     for (int i = 0; i < nr; i++) rvals.push_back(i * dr);
325    
326     cs->addPoints(rVals, phiVals);
327     mixer.phi = cs;
328     mixer.explicitlySet = true;
329    
330     std::pair<AtomType*, AtomType*> key1, key2;
331     key1 = std::make_pair(atype1, atype2);
332     key2 = std::make_pair(atype2, atype1);
333    
334     MixingMap[key1] = mixer;
335     if (key2 != key1) {
336     MixingMap[key2] = mixer;
337     }
338     return;
339     }
340    
341     void EAM::calcDensity(AtomType* at1, AtomType* at2, Vector3d d,
342     RealType rij, RealType r2, RealType rho_i_at_j,
343     RealType rho_j_at_i) {
344    
345     if (!initialized_) initialize();
346    
347     EAMAtomData data1 = EAMMap[at1];
348     EAMAtomData data2 = EAMMap[at2];
349    
350     if (rij < data1.rcut) rho_i_at_j = data1.rho->getValueAt(rij);
351     if (rij < data2.rcut) rho_j_at_i = data2.rho->getValueAt(rij);
352     return;
353     }
354    
355     void EAM::calcFunctional(AtomType* at1, RealType rho, RealType frho,
356     RealType dfrhodrho) {
357    
358     if (!initialized_) initialize();
359    
360     EAMAtomData data1 = EAMMap[at1];
361    
362     pair<RealType, RealType> result = data1.F->getValueAndDerivativeAt(rho);
363    
364     frho = result.first;
365     dfrhodrho = result.second;
366     return;
367     }
368    
369    
370     void EAM::calcForce(AtomType* at1, AtomType* at2, Vector3d d,
371     RealType rij, RealType r2, RealType sw,
372     RealType &vpair, RealType &pot, Vector3d &f1,
373     RealType rho1, RealType rho2, RealType dfrho1,
374     RealType dfrho2, RealType fshift1, RealType fshift2) {
375    
376     if (!initialized_) initialize();
377    
378     pair<RealType, RealType> res;
379    
380     if (rij < eamRcut_) {
381    
382     EAMAtomData data1 = EAMMap[at1];
383     EAMAtomData data2 = EAMMap[at2];
384    
385     // get type-specific cutoff radii
386    
387     RealType rci = data1.rcut;
388     RealType rcj = data2.rcut;
389    
390     RealType rha, drha, rhb, drhb;
391     RealType pha, dpha, phb, dphb;
392     RealType phab, dvpdr;
393     RealType drhoidr, drhojdr, dudr;
394    
395     if (rij < rci) {
396     res = data1.rho->getValueAndDerivativeAt(rij);
397     rha = res.first;
398     drha = res.second;
399    
400     res = MixingMap[make_pair(at1, at1)].phi->getValueAndDerivativeAt(rij);
401     pha = res.first;
402     dpha = res.second;
403     }
404    
405     if (rij < rcj) {
406     res = data2.rho->getValueAndDerivativeAt(rij);
407     rhb = res.first;
408     drhb = res.second;
409    
410     res = MixingMap[make_pair(at2, at2)].phi->getValueAndDerivativeAt(rij);
411     phb = res.first;
412     dphb = res.second;
413     }
414    
415     phab = 0.0;
416     dvpdr = 0.0;
417    
418     switch(mixMeth_) {
419     case eamJohnson:
420    
421     if (rij < rci) {
422     phab = phab + 0.5 * (rhb / rha) * pha;
423     dvpdr = dvpdr + 0.5*((rhb/rha)*dpha +
424     pha*((drhb/rha) - (rhb*drha/rha/rha)));
425     }
426    
427     if (rij < rcj) {
428     phab = phab + 0.5 * (rha / rhb) * phb;
429     dvpdr = dvpdr + 0.5 * ((rha/rhb)*dphb +
430     phb*((drha/rhb) - (rha*drhb/rhb/rhb)));
431     }
432    
433     break;
434    
435     case eamDaw:
436    
437     res = MixingMap[make_pair(at1,at2)].phi->getValueAndDerivativeAt(rij);
438     phab = res.first;
439     dvpdr = res.second;
440    
441     break;
442     case eamUnknown:
443     default:
444    
445     sprintf(painCave.errMsg,
446     "EAM::calcForce hit a mixing method it doesn't know about!\n"
447     );
448     painCave.severity = OPENMD_ERROR;
449     painCave.isFatal = 1;
450     simError();
451    
452     }
453    
454     drhoidr = drha;
455     drhojdr = drhb;
456    
457     dudr = drhojdr*dfrhodrho_i + drhoidr*dfrhodrho_j + dvpdr;
458    
459     f1 = d * dudr / rij;
460    
461     // particle_pot is the difference between the full potential
462     // and the full potential without the presence of a particular
463     // particle (atom1).
464     //
465     // This reduces the density at other particle locations, so
466     // we need to recompute the density at atom2 assuming atom1
467     // didn't contribute. This then requires recomputing the
468     // density functional for atom2 as well.
469     //
470     // Most of the particle_pot heavy lifting comes from the
471     // pair interaction, and will be handled by vpair.
472    
473     fshift_i = data1.F->getValueAt( rho_i - rhb );
474     fshift_j = data1.F->getValueAt( rho_j - rha );
475    
476     pot += phab;
477    
478     vpair += phab;
479     }
480    
481     return;
482    
483     }
484    
485    
486     void EAM::calc_eam_prepair_rho(int *atid1, int *atid2, RealType *d,
487     RealType *rij, RealType *r2,
488     RealType* rho_i_at_j, RealType* rho_j_at_i){
489     if (!initialized_) initialize();
490    
491     AtomType* atype1 = EAMlist[*atid1];
492     AtomType* atype2 = EAMlist[*atid2];
493    
494     Vector3d disp(d[0], d[1], d[2]);
495    
496     calcDensity(atype1, atype2, disp, *rij, *r2, *rho_i_at_j, *rho_j_at_i);
497    
498     return;
499     }
500    
501     void EAM::calc_eam_preforce_Frho(int *atid1, RealType *rho, RealType *frho,
502     RealType *dfrhodrho) {
503    
504     if (!initialized_) initialize();
505    
506     AtomType* atype1 = EAMlist[*atid1];
507    
508     calcFunctional(atype1, *rho, *frho, *dfrhodrho);
509    
510     return;
511     }
512    
513     void EAM::do_eam_pair(int *atid1, int *atid2, RealType *d, RealType *rij,
514     RealType *r2, RealType *sw, RealType *vpair,
515     RealType *pot, RealType *f1, RealType *rho1,
516     RealType *rho2, RealType *dfrho1, RealType *dfrho2,
517     RealType *fshift1, RealType *fshift2) {
518    
519     if (!initialized_) initialize();
520    
521     AtomType* atype1 = EAMMap[*atid1];
522     AtomType* atype2 = EAMMap[*atid2];
523    
524     Vector3d disp(d[0], d[1], d[2]);
525     Vector3d frc(f1[0], f1[1], f1[2]);
526    
527     calcForce(atype1, atype2, disp, *rij, *r2, *sw, *vpair, *pot, frc,
528     *rho1, *rho2, *dfrho1, *dfrho2, *fshift1, *fshift2);
529    
530     f1[0] = frc.x();
531     f1[1] = frc.y();
532     f1[2] = frc.z();
533    
534     return;
535     }
536    
537     void EAM::setCutoffEAM(RealType *thisRcut) {
538     eamRcut_ = thisRcut;
539     }
540     }
541    
542     extern "C" {
543    
544     #define fortranCalcDensity FC_FUNC(calc_eam_prepair_rho, CALC_EAM_PREPAIR_RHO)
545     #define fortranCalcFunctional FC_FUNC(calc_eam_preforce_frho, CALC_EAM_PREFORCE_FRHO)
546     #define fortranCalcForce FC_FUNC(do_eam_pair, DO_EAM_PAIR)
547     #define fortranSetCutoffEAM FC_FUNC(setcutoffeam, SETCUTOFFEAM)
548    
549     RealType fortranCalcDensity(int *atid1, int *atid2, RealType *d,
550     RealType *rij, RealType *r2,
551     RealType *rho_i_at_j, RealType *rho_j_at_i) {
552    
553     return OpenMD::EAM::Instance()->calc_eam_prepair_rho(*atid1, *atid2, *d,
554     *rij, *r2,
555     *rho_i_at_j,
556     *rho_j_at_i);
557     }
558     RealType fortranCalcFunctional(int *atid1, RealType *rho, RealType *frho,
559     RealType *dfrhodrho) {
560    
561     return OpenMD::EAM::Instance()->calc_eam_preforce_Frho(*atid1,
562     *rho,
563     *frho,
564     *dfrhodrho);
565    
566     }
567     void fortranSetEAMCutoff(RealType *rcut) {
568     return OpenMD::EAM::Instance()->setCutoffEAM(rcut);
569     }
570     void fortranDoEAMPair(int *atid1, int *atid2, RealType *d, RealType *rij,
571     RealType *r2, RealType *sw, RealType *vpair,
572     RealType *pot, RealType *f1, RealType *rho1,
573     RealType *rho2, RealType *dfrho1, RealType *dfrho2,
574     RealType *fshift1, RealType *fshift2){
575    
576     return OpenMD::EAM::Instance()->do_eam_pair(*atid1, *atid2, *d, *rij,
577     *r2, *sw, *vpair,
578     *pot, *f1, *rho1,
579     *rho2, *dfrho1, *dfrho2,
580     *fshift1, *fshift2);
581     }
582     }

Properties

Name Value
svn:eol-style native