ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/nonbonded/EAM.cpp
Revision: 1479
Committed: Mon Jul 26 19:00:48 2010 UTC (14 years, 9 months ago) by gezelter
File size: 18772 byte(s)
Log Message:
Added EAM.  Still segfaults but compiles.

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     string EAMMixMeth = toUpperCopy(fopts.getEAMMixingMethod());
204 gezelter 1478
205     if (EAMMixMeth == "JOHNSON")
206     mixMeth_ = eamJohnson;
207     else if (EAMMixMeth == "DAW")
208     mixMeth_ = eamDaw;
209     else
210     mixMeth_ = eamUnknown;
211    
212     // find all of the EAM atom Types:
213     ForceField::AtomTypeContainer* atomTypes = forceField_->getAtomTypes();
214     ForceField::AtomTypeContainer::MapTypeIterator i;
215     AtomType* at;
216    
217     for (at = atomTypes->beginType(i); at != NULL;
218     at = atomTypes->nextType(i)) {
219    
220     if (at->isEAM())
221     addType(at);
222     }
223    
224     // find all of the explicit EAM interactions (setfl):
225     ForceField::NonBondedInteractionTypeContainer* nbiTypes = forceField_->getNonBondedInteractionTypes();
226     ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
227     NonBondedInteractionType* nbt;
228    
229     for (nbt = nbiTypes->beginType(j); nbt != NULL;
230     nbt = nbiTypes->nextType(j)) {
231    
232     if (nbt->isEAM()) {
233    
234     std::pair<AtomType*, AtomType*> atypes = nbt->getAtomTypes();
235    
236     GenericData* data = nbt->getPropertyByName("EAM");
237     if (data == NULL) {
238     sprintf( painCave.errMsg, "EAM::rebuildMixingMap could not find\n"
239     "\tEAM parameters for %s - %s interaction.\n",
240     atypes.first->getName().c_str(),
241     atypes.second->getName().c_str());
242     painCave.severity = OPENMD_ERROR;
243     painCave.isFatal = 1;
244     simError();
245     }
246    
247     EAMMixingData* eamData = dynamic_cast<EAMMixingData*>(data);
248     if (eamData == NULL) {
249     sprintf( painCave.errMsg,
250     "EAM::rebuildMixingMap could not convert GenericData to\n"
251     "\tEAMMixingData for %s - %s interaction.\n",
252     atypes.first->getName().c_str(),
253     atypes.second->getName().c_str());
254     painCave.severity = OPENMD_ERROR;
255     painCave.isFatal = 1;
256     simError();
257     }
258    
259 gezelter 1479 EAMMixingParam eamParam = eamData->getData();
260 gezelter 1478
261 gezelter 1479 vector<RealType> phiAB = eamParam.phi;
262 gezelter 1478 RealType dr = eamParam.dr;
263     int nr = eamParam.nr;
264    
265     addExplicitInteraction(atypes.first, atypes.second, dr, nr, phiAB);
266     }
267     }
268     initialized_ = true;
269     }
270    
271    
272    
273     void EAM::addType(AtomType* atomType){
274    
275     EAMAtomData eamAtomData;
276 gezelter 1479
277 gezelter 1478 eamAtomData.rho = getRho(atomType);
278     eamAtomData.F = getF(atomType);
279     eamAtomData.Z = getZ(atomType);
280     eamAtomData.rcut = getRcut(atomType);
281    
282     // add it to the map:
283     AtomTypeProperties atp = atomType->getATP();
284    
285     std::pair<std::map<int,AtomType*>::iterator,bool> ret;
286     ret = EAMlist.insert( std::pair<int, AtomType*>(atp.ident, atomType) );
287     if (ret.second == false) {
288     sprintf( painCave.errMsg,
289     "EAM already had a previous entry with ident %d\n",
290     atp.ident);
291     painCave.severity = OPENMD_INFO;
292     painCave.isFatal = 0;
293     simError();
294     }
295    
296     EAMMap[atomType] = eamAtomData;
297    
298     // Now, iterate over all known types and add to the mixing map:
299    
300 gezelter 1479 std::map<AtomType*, EAMAtomData>::iterator it;
301 gezelter 1478 for( it = EAMMap.begin(); it != EAMMap.end(); ++it) {
302    
303 gezelter 1479 AtomType* atype2 = (*it).first;
304 gezelter 1478
305     EAMInteractionData mixer;
306     mixer.phi = getPhi(atomType, atype2);
307     mixer.explicitlySet = false;
308    
309     std::pair<AtomType*, AtomType*> key1, key2;
310     key1 = std::make_pair(atomType, atype2);
311     key2 = std::make_pair(atype2, atomType);
312    
313     MixingMap[key1] = mixer;
314     if (key2 != key1) {
315     MixingMap[key2] = mixer;
316     }
317     }
318     return;
319     }
320    
321     void EAM::addExplicitInteraction(AtomType* atype1, AtomType* atype2,
322     RealType dr, int nr,
323     vector<RealType> phiVals) {
324    
325     // in case these weren't already in the map
326     addType(atype1);
327     addType(atype2);
328    
329     EAMInteractionData mixer;
330     CubicSpline* cs = new CubicSpline();
331 gezelter 1479 vector<RealType> rVals;
332 gezelter 1478
333 gezelter 1479 for (int i = 0; i < nr; i++) rVals.push_back(i * dr);
334 gezelter 1478
335     cs->addPoints(rVals, phiVals);
336     mixer.phi = cs;
337     mixer.explicitlySet = true;
338    
339     std::pair<AtomType*, AtomType*> key1, key2;
340     key1 = std::make_pair(atype1, atype2);
341     key2 = std::make_pair(atype2, atype1);
342    
343     MixingMap[key1] = mixer;
344     if (key2 != key1) {
345     MixingMap[key2] = mixer;
346     }
347     return;
348     }
349    
350 gezelter 1479 void EAM::calcDensity(AtomType* at1, AtomType* at2, const RealType rij,
351     RealType &rho_i_at_j, RealType &rho_j_at_i) {
352    
353 gezelter 1478 if (!initialized_) initialize();
354 gezelter 1479
355 gezelter 1478 EAMAtomData data1 = EAMMap[at1];
356     EAMAtomData data2 = EAMMap[at2];
357    
358     if (rij < data1.rcut) rho_i_at_j = data1.rho->getValueAt(rij);
359     if (rij < data2.rcut) rho_j_at_i = data2.rho->getValueAt(rij);
360     return;
361     }
362    
363 gezelter 1479 void EAM::calcFunctional(AtomType* at1, RealType rho, RealType &frho,
364     RealType &dfrhodrho) {
365 gezelter 1478
366     if (!initialized_) initialize();
367    
368     EAMAtomData data1 = EAMMap[at1];
369    
370     pair<RealType, RealType> result = data1.F->getValueAndDerivativeAt(rho);
371    
372     frho = result.first;
373     dfrhodrho = result.second;
374     return;
375     }
376    
377    
378     void EAM::calcForce(AtomType* at1, AtomType* at2, Vector3d d,
379     RealType rij, RealType r2, RealType sw,
380     RealType &vpair, RealType &pot, Vector3d &f1,
381 gezelter 1479 RealType rho_i, RealType rho_j,
382     RealType dfrhodrho_i, RealType dfrhodrho_j,
383     RealType &fshift_i, RealType &fshift_j) {
384 gezelter 1478
385     if (!initialized_) initialize();
386    
387     pair<RealType, RealType> res;
388    
389     if (rij < eamRcut_) {
390    
391     EAMAtomData data1 = EAMMap[at1];
392     EAMAtomData data2 = EAMMap[at2];
393    
394     // get type-specific cutoff radii
395    
396     RealType rci = data1.rcut;
397     RealType rcj = data2.rcut;
398    
399     RealType rha, drha, rhb, drhb;
400     RealType pha, dpha, phb, dphb;
401     RealType phab, dvpdr;
402     RealType drhoidr, drhojdr, dudr;
403    
404     if (rij < rci) {
405     res = data1.rho->getValueAndDerivativeAt(rij);
406     rha = res.first;
407     drha = res.second;
408    
409     res = MixingMap[make_pair(at1, at1)].phi->getValueAndDerivativeAt(rij);
410     pha = res.first;
411     dpha = res.second;
412     }
413    
414     if (rij < rcj) {
415     res = data2.rho->getValueAndDerivativeAt(rij);
416     rhb = res.first;
417     drhb = res.second;
418    
419     res = MixingMap[make_pair(at2, at2)].phi->getValueAndDerivativeAt(rij);
420     phb = res.first;
421     dphb = res.second;
422     }
423    
424     phab = 0.0;
425     dvpdr = 0.0;
426    
427     switch(mixMeth_) {
428     case eamJohnson:
429    
430     if (rij < rci) {
431     phab = phab + 0.5 * (rhb / rha) * pha;
432     dvpdr = dvpdr + 0.5*((rhb/rha)*dpha +
433     pha*((drhb/rha) - (rhb*drha/rha/rha)));
434     }
435    
436     if (rij < rcj) {
437     phab = phab + 0.5 * (rha / rhb) * phb;
438     dvpdr = dvpdr + 0.5 * ((rha/rhb)*dphb +
439     phb*((drha/rhb) - (rha*drhb/rhb/rhb)));
440     }
441    
442     break;
443    
444     case eamDaw:
445    
446     res = MixingMap[make_pair(at1,at2)].phi->getValueAndDerivativeAt(rij);
447     phab = res.first;
448     dvpdr = res.second;
449    
450     break;
451     case eamUnknown:
452     default:
453    
454     sprintf(painCave.errMsg,
455     "EAM::calcForce hit a mixing method it doesn't know about!\n"
456     );
457     painCave.severity = OPENMD_ERROR;
458     painCave.isFatal = 1;
459     simError();
460    
461     }
462    
463     drhoidr = drha;
464     drhojdr = drhb;
465    
466     dudr = drhojdr*dfrhodrho_i + drhoidr*dfrhodrho_j + dvpdr;
467    
468     f1 = d * dudr / rij;
469    
470     // particle_pot is the difference between the full potential
471     // and the full potential without the presence of a particular
472     // particle (atom1).
473     //
474     // This reduces the density at other particle locations, so
475     // we need to recompute the density at atom2 assuming atom1
476     // didn't contribute. This then requires recomputing the
477     // density functional for atom2 as well.
478     //
479     // Most of the particle_pot heavy lifting comes from the
480     // pair interaction, and will be handled by vpair.
481    
482     fshift_i = data1.F->getValueAt( rho_i - rhb );
483     fshift_j = data1.F->getValueAt( rho_j - rha );
484    
485     pot += phab;
486    
487     vpair += phab;
488     }
489    
490     return;
491    
492     }
493    
494    
495 gezelter 1479 void EAM::calc_eam_prepair_rho(int *atid1, int *atid2, RealType *rij,
496 gezelter 1478 RealType* rho_i_at_j, RealType* rho_j_at_i){
497 gezelter 1479
498 gezelter 1478 if (!initialized_) initialize();
499 gezelter 1479
500 gezelter 1478 AtomType* atype1 = EAMlist[*atid1];
501     AtomType* atype2 = EAMlist[*atid2];
502    
503 gezelter 1479 calcDensity(atype1, atype2, *rij, *rho_i_at_j, *rho_j_at_i);
504 gezelter 1478
505     return;
506     }
507    
508     void EAM::calc_eam_preforce_Frho(int *atid1, RealType *rho, RealType *frho,
509     RealType *dfrhodrho) {
510    
511     if (!initialized_) initialize();
512    
513     AtomType* atype1 = EAMlist[*atid1];
514    
515     calcFunctional(atype1, *rho, *frho, *dfrhodrho);
516    
517     return;
518     }
519 gezelter 1479 RealType EAM::getEAMcut(int *atid1) {
520 gezelter 1478
521 gezelter 1479 if (!initialized_) initialize();
522    
523     AtomType* atype1 = EAMlist[*atid1];
524    
525     return getRcut(atype1);
526     }
527    
528 gezelter 1478 void EAM::do_eam_pair(int *atid1, int *atid2, RealType *d, RealType *rij,
529     RealType *r2, RealType *sw, RealType *vpair,
530     RealType *pot, RealType *f1, RealType *rho1,
531     RealType *rho2, RealType *dfrho1, RealType *dfrho2,
532     RealType *fshift1, RealType *fshift2) {
533    
534     if (!initialized_) initialize();
535    
536 gezelter 1479 AtomType* atype1 = EAMlist[*atid1];
537     AtomType* atype2 = EAMlist[*atid2];
538 gezelter 1478
539     Vector3d disp(d[0], d[1], d[2]);
540     Vector3d frc(f1[0], f1[1], f1[2]);
541    
542     calcForce(atype1, atype2, disp, *rij, *r2, *sw, *vpair, *pot, frc,
543     *rho1, *rho2, *dfrho1, *dfrho2, *fshift1, *fshift2);
544    
545     f1[0] = frc.x();
546     f1[1] = frc.y();
547     f1[2] = frc.z();
548    
549     return;
550     }
551    
552     void EAM::setCutoffEAM(RealType *thisRcut) {
553 gezelter 1479 eamRcut_ = *thisRcut;
554 gezelter 1478 }
555     }
556    
557     extern "C" {
558    
559     #define fortranCalcDensity FC_FUNC(calc_eam_prepair_rho, CALC_EAM_PREPAIR_RHO)
560     #define fortranCalcFunctional FC_FUNC(calc_eam_preforce_frho, CALC_EAM_PREFORCE_FRHO)
561     #define fortranCalcForce FC_FUNC(do_eam_pair, DO_EAM_PAIR)
562     #define fortranSetCutoffEAM FC_FUNC(setcutoffeam, SETCUTOFFEAM)
563 gezelter 1479 #define fortranGetEAMcut FC_FUNC(geteamcut, GETEAMCUT)
564    
565 gezelter 1478
566 gezelter 1479 void fortranCalcDensity(int *atid1, int *atid2, RealType *rij,
567     RealType *rho_i_at_j, RealType *rho_j_at_i) {
568    
569     return OpenMD::EAM::Instance()->calc_eam_prepair_rho(atid1, atid2, rij,
570     rho_i_at_j,
571     rho_j_at_i);
572 gezelter 1478 }
573 gezelter 1479 void fortranCalcFunctional(int *atid1, RealType *rho, RealType *frho,
574     RealType *dfrhodrho) {
575    
576     return OpenMD::EAM::Instance()->calc_eam_preforce_Frho(atid1, rho, frho,
577     dfrhodrho);
578    
579 gezelter 1478 }
580 gezelter 1479 void fortranSetCutoffEAM(RealType *rcut) {
581 gezelter 1478 return OpenMD::EAM::Instance()->setCutoffEAM(rcut);
582     }
583 gezelter 1479 void fortranCalcForce(int *atid1, int *atid2, RealType *d, RealType *rij,
584 gezelter 1478 RealType *r2, RealType *sw, RealType *vpair,
585     RealType *pot, RealType *f1, RealType *rho1,
586     RealType *rho2, RealType *dfrho1, RealType *dfrho2,
587     RealType *fshift1, RealType *fshift2){
588    
589 gezelter 1479 return OpenMD::EAM::Instance()->do_eam_pair(atid1, atid2, d, rij,
590     r2, sw, vpair,
591     pot, f1, rho1,
592     rho2, dfrho1, dfrho2,
593     fshift1, fshift2);
594 gezelter 1478 }
595 gezelter 1479 RealType fortranGetEAMcut(int* atid) {
596     return OpenMD::EAM::Instance()->getEAMcut(atid);
597     }
598    
599 gezelter 1478 }

Properties

Name Value
svn:eol-style native