ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/nonbonded/EAM.cpp
Revision: 1929
Committed: Mon Aug 19 13:12:00 2013 UTC (11 years, 11 months ago) by gezelter
File size: 13895 byte(s)
Log Message:
Backing out fluc-rho and putting back the Electrostatic fluctuating
charge with coulomb integrals for atoms within a region.

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

Properties

Name Value
svn:eol-style native