ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/nonbonded/EAM.cpp
Revision: 1480
Committed: Mon Jul 26 19:50:53 2010 UTC (14 years, 9 months ago) by gezelter
File size: 18792 byte(s)
Log Message:
no longer segfaults

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

Properties

Name Value
svn:eol-style native