45#include "nonbonded/EAM.hpp"
51#include "types/EAMInteractionType.hpp"
52#include "types/FluctuatingChargeAdapter.hpp"
53#include "utils/simError.h"
58 initialized_(false), haveCutoffRadius_(false), forceField_(NULL),
59 electrostatic_(NULL), eamRcut_(0.0), mixMeth_(eamJohnson), name_(
"EAM") {
67 RealType EAM::fastPower(RealType x,
int y) {
70 temp = fastPower(x, y / 2);
75 return x * temp * temp;
77 return (temp * temp) / x;
110 RealType EAM::PhiCoreCore(RealType r, RealType re, RealType A, RealType alpha,
112 if (mixMeth_ == eamDream2) {
115 return (A * exp(-alpha * (r / re - 1.0)) +
116 a * fastPower(sigma / (r + 1e-5), 30));
119 else if ((mixMeth_ == eamDream1) || (mixMeth_ == eamJohnson)) {
120 return (A * exp(-alpha * (r / re - 1.0))) /
121 (1.0 + fastPower(r / re - kappa, 20));
128 RealType EAM::PhiCoreValence(RealType r, RealType re, RealType B,
129 RealType beta, RealType lambda) {
130 if (mixMeth_ == eamDream2) {
131 return -(B * exp(-beta * (r / re - 1.0)));
134 else if ((mixMeth_ == eamDream1) || (mixMeth_ == eamJohnson)) {
135 return -(B * exp(-beta * (r / re - 1.0))) /
136 (1.0 + fastPower(r / re - lambda, 20));
143 RealType EAM::Phi(RealType r, RealType re, RealType A, RealType B,
144 RealType alpha, RealType beta, RealType kappa,
146 return PhiCoreCore(r, re, A, alpha, kappa) +
147 PhiCoreValence(r, re, B, beta, lambda);
150 RealType EAM::Rho(RealType r, RealType re, RealType fe, RealType beta,
152 if (mixMeth_ == eamDream2) {
153 return (fe * exp(-beta * (r / re - 1.0)));
156 else if ((mixMeth_ == eamDream1) || (mixMeth_ == eamJohnson)) {
157 return (fe * exp(-beta * (r / re - 1.0))) /
158 (1.0 + fastPower(r / re - lambda, 20));
165 RealType EAM::gFunc(RealType q, RealType nV, RealType nM) {
166 if (q >= nV) {
return 0.0; }
167 if (q <= -nM) {
return (nM + nV) / nV; }
169 return ((q - nV) * (q - nV) * (nM + q + nV)) / (nV * nV * (nM + nV));
172 RealType EAM::gPrime(RealType q, RealType nV, RealType nM) {
173 if (q >= nV) {
return 0.0; }
174 if (q <= -nM) {
return 0.0; }
176 return ((q - nV) * (2 * nM + 3 * q + nV)) / (nV * nV * (nM + nV));
179 RealType EAM::Zhou2001Functional(RealType rho, RealType rhoe,
180 std::vector<RealType> Fn,
181 std::vector<RealType> F, RealType Fe,
183 RealType rhon = 0.85 * rhoe;
184 RealType rho0 = 1.15 * rhoe;
185 RealType functional(0.0);
188 t = rho / rhon - 1.0;
189 functional = Fn.at(0) + t * (Fn.at(1) + t * (Fn.at(2) + t * Fn.at(3)));
190 }
else if (rho >= rhon && rho < rho0) {
191 t = rho / rhoe - 1.0;
192 functional = F.at(0) + t * (F.at(1) + t * (F.at(2) + t * F.at(3)));
193 }
else if (rho >= rho0) {
195 functional = Fe * (1.0 - log(pow(t, eta))) * pow(t, eta);
200 RealType EAM::Zhou2004Functional(RealType rho, RealType rhoe, RealType rhos,
201 std::vector<RealType> Fn,
202 std::vector<RealType> F, RealType Fe,
203 RealType eta, RealType rhol, RealType rhoh) {
204 RealType rhon = rhol * rhoe;
205 RealType rho0 = rhoh * rhoe;
206 RealType functional(0.0);
209 t = rho / rhon - 1.0;
210 functional = Fn.at(0) + t * (Fn.at(1) + t * (Fn.at(2) + t * Fn.at(3)));
211 }
else if (rhon <= rho && rho < rho0) {
212 t = rho / rhoe - 1.0;
213 functional = F.at(0) + t * (F.at(1) + t * (F.at(2) + t * F.at(3)));
214 }
else if (rho0 <= rho) {
216 functional = Fe * (1.0 - log(pow(t, eta))) * pow(t, eta);
221 RealType EAM::Zhou2005Functional(RealType rho, RealType rhoe, RealType rhos,
222 std::vector<RealType> Fn,
223 std::vector<RealType> F, RealType F3plus,
224 RealType F3minus, RealType Fe,
226 RealType rhon = 0.85 * rhoe;
227 RealType rho0 = 1.15 * rhoe;
228 RealType functional(0.0);
231 t = rho / rhon - 1.0;
232 functional = Fn.at(0) + t * (Fn.at(1) + t * (Fn.at(2) + t * Fn.at(3)));
233 }
else if (rho >= rhon && rho < rhoe) {
234 t = rho / rhoe - 1.0;
235 functional = F.at(0) + t * (F.at(1) + t * (F.at(2) + t * F3minus));
236 }
else if (rho >= rhoe && rho < rho0) {
237 t = rho / rhoe - 1.0;
238 functional = F.at(0) + t * (F.at(1) + t * (F.at(2) + t * F3plus));
239 }
else if (rho >= rho0) {
241 functional = Fe * (1.0 - log(pow(t, eta))) * pow(t, eta);
246 RealType EAM::Zhou2005OxygenFunctional(
247 RealType rho, std::vector<RealType> OrhoLimits,
248 std::vector<RealType> OrhoE, std::vector<std::vector<RealType>> OF) {
249 RealType functional(0.0);
252 if (rho < OrhoLimits[1]) {
253 t = rho / OrhoE[0] - 1.0;
254 functional = OF[0][0] + t * (OF[0][1] + t * (OF[0][2] + t * OF[0][3]));
255 }
else if (rho >= OrhoLimits[1] && rho < OrhoLimits[2]) {
256 t = rho / OrhoE[1] - 1.0;
257 functional = OF[1][0] + t * (OF[1][1] + t * OF[1][2]);
258 }
else if (rho >= OrhoLimits[2] && rho < OrhoLimits[3]) {
259 t = rho / OrhoE[2] - 1.0;
260 functional = OF[2][0] + t * (OF[2][1] + t * OF[2][2]);
261 }
else if (rho >= OrhoLimits[3] && rho < OrhoLimits[4]) {
262 t = rho / OrhoE[3] - 1.0;
263 functional = OF[3][0] + t * (OF[3][1] + t * OF[3][2]);
264 }
else if (rho >= OrhoLimits[4]) {
265 t = rho / OrhoE[4] - 1.0;
266 functional = OF[4][0] + t * (OF[4][1] + t * OF[4][2]);
271 RealType EAM::RoseFunctional(RealType rho, RealType rhoe, RealType F0) {
272 RealType t = rho / rhoe;
273 RealType functional(0.0);
274 if (t > 0.0) { functional = -F0 * log(t) * t; }
282 CubicSplinePtr cs {std::make_shared<CubicSpline>()};
284 RealType rha(0.0), rhb(0.0), pha(0.0), phb(0.0), phab(0.0);
285 vector<RealType> rvals;
286 vector<RealType> phivals;
287 RealType rmax(0.0), dr, r;
290 if (ea1.getEAMType() == eamFuncfl && ea2.getEAMType() == eamFuncfl) {
291 CubicSplinePtr z1 = ea1.getZSpline();
292 CubicSplinePtr z2 = ea2.getZSpline();
293 CubicSplinePtr rho1 = ea1.getRhoSpline();
294 CubicSplinePtr rho2 = ea2.getRhoSpline();
301 rmax = max(rmax, ea1.getRcut());
302 rmax = max(rmax, ea1.getNr() * ea1.getDr());
304 rmax = max(rmax, ea2.getRcut());
305 rmax = max(rmax, ea2.getNr() * ea2.getDr());
309 dr = min(ea1.getDr(), ea2.getDr());
310 nr = int(rmax / dr + 0.5);
312 for (
int i = 0; i < nr; i++)
313 rvals.push_back(RealType(i * dr));
319 phivals.push_back(0.0);
321 for (
unsigned int i = 1; i < rvals.size(); i++) {
329 rha = r <= ea1.getRcut() ? rho1->getValueAt(r) : 0.0;
330 rhb = r <= ea2.getRcut() ? rho2->getValueAt(r) : 0.0;
332 za = r <= ea1.getRcut() ? z1->getValueAt(r) : 0.0;
333 zb = r <= ea2.getRcut() ? z2->getValueAt(r) : 0.0;
341 pha = pre11_ * (za * za) / r;
342 phab = phab + 0.5 * (rhb / rha) * pha;
345 phb = pre11_ * (zb * zb) / r;
346 phab = phab + 0.5 * (rha / rhb) * phb;
352 if (r <= ea1.getRcut() && r <= ea2.getRcut()) {
353 phab = pre11_ * (za * zb) / r;
362 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
363 "EAM::getPhi hit a mixing method it doesn't know about!\n");
364 painCave.severity = OPENMD_ERROR;
365 painCave.isFatal = 1;
368 phivals.push_back(phab);
370 cs->addPoints(rvals, phivals);
372 EAMAtomData& data1 = EAMdata[EAMtids[atomType1->getIdent()]];
373 EAMAtomData& data2 = EAMdata[EAMtids[atomType2->getIdent()]];
375 RealType re1, A1, B1, alpha1, beta1, kappa1, lambda1;
376 RealType re2, A2, B2, alpha2, beta2, kappa2, lambda2;
381 alpha1 = ea1.getAlpha();
382 beta1 = ea1.getBeta();
383 kappa1 = ea1.getKappa();
384 lambda1 = ea1.getLambda();
389 alpha2 = ea2.getAlpha();
390 beta2 = ea2.getBeta();
391 kappa2 = ea2.getKappa();
392 lambda2 = ea2.getLambda();
395 rmax = max(rmax, data1.rcut);
396 rmax = max(rmax, data2.rcut);
397 rmax = max(rmax, eamRcut_);
401 RealType dr = min(data1.rho->getSpacing(), data2.rho->getSpacing());
403 int nr = int(rmax / dr + 1);
405 for (
int i = 0; i < nr; i++)
406 rvals.push_back(RealType(i * dr));
408 vector<RealType> phivals;
411 for (
unsigned int i = 0; i < rvals.size(); i++) {
421 if (r < data1.rcut) {
422 rha = data1.rho->getValueAt(r);
425 pha = Phi(r, re1, A1, B1, alpha1, beta1, kappa1, lambda1);
427 if (r < data2.rcut) {
428 rhb = data2.rho->getValueAt(r);
430 phb = Phi(r, re2, A2, B2, alpha2, beta2, kappa2, lambda2);
433 if (r < data1.rcut) phab = phab + 0.5 * (rhb / rha) * pha;
434 if (r < data2.rcut) phab = phab + 0.5 * (rha / rhb) * phb;
436 phivals.push_back(phab);
438 cs->addPoints(rvals, phivals);
444 void EAM::setCutoffRadius(RealType rCut) {
446 haveCutoffRadius_ =
true;
449 void EAM::initialize() {
452 string EAMMixMeth = fopts.getEAMMixingMethod();
454 if (EAMMixMeth ==
"JOHNSON")
455 mixMeth_ = eamJohnson;
456 else if (EAMMixMeth ==
"DREAM1")
457 mixMeth_ = eamDream1;
458 else if (EAMMixMeth ==
"DREAM2")
459 mixMeth_ = eamDream2;
460 else if (EAMMixMeth ==
"DAW")
463 mixMeth_ = eamUnknownMix;
472 EAMtids.resize(forceField_->getNAtomType(), -1);
474 AtomTypeSet::iterator at;
475 for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
476 if ((*at)->isEAM()) nEAM_++;
478 EAMdata.resize(nEAM_);
479 MixingMap.resize(nEAM_);
481 for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
482 if ((*at)->isEAM()) addType(*at);
487 forceField_->getNonBondedInteractionTypes();
488 ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
489 ForceField::NonBondedInteractionTypeContainer::KeyType keys;
492 for (nbt = nbiTypes->beginType(j); nbt != NULL;
493 nbt = nbiTypes->nextType(j)) {
494 if (nbt->isEAMTable() || nbt->isEAMZhou() || nbt->isEAMOxides()) {
495 keys = nbiTypes->getKeys(j);
498 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
499 "EAM::initialize could not find AtomType %s\n"
500 "\tfor %s - %s explicit interaction.\n",
501 keys[0].c_str(), keys[0].c_str(), keys[1].c_str());
502 painCave.severity = OPENMD_ERROR;
503 painCave.isFatal = 1;
509 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
510 "EAM::initialize could not find AtomType %s\n"
511 "\tfor %s - %s explicit interaction.\n",
512 keys[1].c_str(), keys[0].c_str(), keys[1].c_str());
513 painCave.severity = OPENMD_ERROR;
514 painCave.isFatal = 1;
522 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
523 "EAM::initialize could not convert NonBondedInteractionType\n"
524 "\tto EAMInteractionType for %s - %s interaction.\n",
525 at1->getName().c_str(), at2->getName().c_str());
526 painCave.severity = OPENMD_ERROR;
527 painCave.isFatal = 1;
530 if (nbt->isEAMTable()) {
531 vector<RealType> phiAB = eamit->getPhi();
532 RealType dr = eamit->getDr();
533 int nr = eamit->getNr();
535 addExplicitInteraction(at1, at2, dr, nr, phiAB);
537 }
else if (nbt->isEAMZhou()) {
538 RealType re = eamit->getRe();
539 RealType alpha = eamit->getAlpha();
540 RealType beta = eamit->getBeta();
541 RealType A = eamit->getA();
542 RealType B = eamit->getB();
543 RealType kappa = eamit->getKappa();
544 RealType lambda = eamit->getLambda();
546 addExplicitInteraction(at1, at2, re, alpha, beta, A, B, kappa,
549 }
else if (nbt->isEAMOxides()) {
550 RealType re = eamit->getRe();
551 RealType alpha = eamit->getAlpha();
552 RealType A = eamit->getA();
553 RealType Ci = eamit->getCi();
554 RealType Cj = eamit->getCj();
555 addExplicitInteraction(at1, at2, re, alpha, A, Ci, Cj);
562 void EAM::addType(
AtomType* atomType) {
565 EAMType et = ea.getEAMType();
569 eamAtomData.rho = ea.getRhoSpline();
570 eamAtomData.F = ea.getFSpline();
571 eamAtomData.Z = ea.getZSpline();
572 eamAtomData.rcut = ea.getRcut();
579 RealType re = ea.getRe();
580 RealType fe = ea.get_fe();
581 RealType rhoe = ea.getRhoe();
582 RealType A = ea.getA();
583 RealType B = ea.getB();
584 RealType alpha = ea.getAlpha();
585 RealType beta = ea.getBeta();
586 RealType kappa = ea.getKappa();
587 RealType lambda = ea.getLambda();
588 std::vector<RealType> Fn = ea.getFn();
589 std::vector<RealType> F = ea.getF();
590 RealType Fe = ea.getFe();
591 RealType eta = ea.getEta();
592 RealType F0 = ea.getF0();
598 eamAtomData.rcut = std::min(12.0, std::max(9.0, 4.0 * re));
600 RealType dr = eamAtomData.rcut / (RealType)(Nr - 1);
605 max(900.0, max(2.0 * rhoe, Rho(0.0, re, fe, beta, lambda)));
606 RealType drho = rhomax / (RealType)(Nrho - 1);
608 RealType phiCC, phiCV;
610 std::vector<RealType> rvals;
611 std::vector<RealType> zvals;
612 std::vector<RealType> ccvals;
613 std::vector<RealType> cvvals;
615 std::vector<RealType> rhovals;
616 std::vector<RealType> funcvals;
618 for (
int i = 0; i < Nr; i++) {
619 r = RealType(i) * dr;
621 rhovals.push_back(Rho(r, re, fe, beta, lambda));
622 phiCC = PhiCoreCore(r, re, A, alpha, kappa);
623 phiCV = PhiCoreValence(r, re, B, beta, lambda);
624 ccvals.push_back(phiCC);
625 cvvals.push_back(phiCV);
627 eamAtomData.rho = std::make_shared<CubicSpline>();
628 eamAtomData.rho->addPoints(rvals, rhovals);
629 eamAtomData.phiCC = std::make_shared<CubicSpline>();
630 eamAtomData.phiCC->addPoints(rvals, ccvals);
631 eamAtomData.phiCV = std::make_shared<CubicSpline>();
632 eamAtomData.phiCV->addPoints(rvals, cvvals);
635 if (et == eamZhou2001) {
636 for (
int i = 0; i < Nrho; i++) {
637 rho = RealType(i) * drho;
638 rhovals.push_back(rho);
639 funcvals.push_back(Zhou2001Functional(rho, rhoe, Fn, F, Fe, eta));
641 }
else if (et == eamZhou2004) {
642 RealType rhos = ea.getRhos();
643 RealType rhol = ea.getRhol();
644 RealType rhoh = ea.getRhoh();
645 for (
int i = 0; i < Nrho; i++) {
646 rho = RealType(i) * drho;
647 rhovals.push_back(rho);
649 Zhou2004Functional(rho, rhoe, rhos, Fn, F, Fe, eta, rhol, rhoh));
651 }
else if (et == eamZhou2005) {
652 RealType rhos = ea.getRhos();
653 RealType F3plus = ea.getF3plus();
654 RealType F3minus = ea.getF3minus();
655 for (
int i = 0; i < Nrho; i++) {
656 rho = RealType(i) * drho;
657 rhovals.push_back(rho);
658 funcvals.push_back(Zhou2005Functional(rho, rhoe, rhos, Fn, F, F3plus,
661 }
else if (et == eamZhouRose) {
662 for (
int i = 0; i < Nrho; i++) {
663 rho = RealType(i) * drho;
664 rhovals.push_back(rho);
665 funcvals.push_back(RoseFunctional(rho, rhoe, F0));
669 eamAtomData.F = std::make_shared<CubicSpline>();
670 eamAtomData.F->addPoints(rhovals, funcvals);
673 case eamOxygenFuncfl: {
674 RealType re = ea.getRe();
675 RealType fe = ea.get_fe();
677 RealType A = ea.getA();
678 RealType B = ea.getB();
679 RealType alpha = ea.getAlpha();
680 RealType beta = ea.getBeta();
681 RealType kappa = ea.getKappa();
682 RealType lambda = ea.getLambda();
689 eamAtomData.rcut = std::min(12.0, std::max(9.0, 4.0 * re));
691 RealType dr = eamAtomData.rcut / (RealType)(Nr - 1);
693 RealType phiCC, phiCV;
695 std::vector<RealType> rvals;
696 std::vector<RealType> zvals;
697 std::vector<RealType> ccvals;
698 std::vector<RealType> cvvals;
700 std::vector<RealType> rhovals;
702 for (
int i = 0; i < Nr; i++) {
703 r = RealType(i) * dr;
705 rhovals.push_back(Rho(r, re, fe, beta, lambda));
706 phiCC = PhiCoreCore(r, re, A, alpha, kappa);
707 phiCV = PhiCoreValence(r, re, B, beta, lambda);
708 ccvals.push_back(phiCC);
709 cvvals.push_back(phiCV);
711 eamAtomData.rho = std::make_shared<CubicSpline>();
712 eamAtomData.rho->addPoints(rvals, rhovals);
713 eamAtomData.phiCC = std::make_shared<CubicSpline>();
714 eamAtomData.phiCC->addPoints(rvals, ccvals);
715 eamAtomData.phiCV = std::make_shared<CubicSpline>();
716 eamAtomData.phiCV->addPoints(rvals, cvvals);
718 eamAtomData.F = ea.getFSpline();
721 case eamZhou2005Oxygen: {
722 RealType re = ea.getRe();
723 RealType fe = ea.get_fe();
724 RealType A = ea.getA();
725 RealType B = ea.getB();
726 RealType alpha = ea.getAlpha();
727 RealType beta = ea.getBeta();
728 RealType kappa = ea.getKappa();
729 RealType lambda = ea.getLambda();
730 RealType gamma = ea.getGamma();
731 RealType nu = ea.getNu();
732 std::vector<RealType> OrhoLimits = ea.getOrhoLimits();
733 std::vector<RealType> OrhoE = ea.getOrhoE();
734 std::vector<std::vector<RealType>> OF = ea.getOF();
740 eamAtomData.rcut = std::min(12.0, std::max(9.0, 4.0 * re));
742 RealType dr = eamAtomData.rcut / (RealType)(Nr - 1);
747 RealType rhomax = max(800.0, Rho(0.0, re, fe, gamma, nu));
748 RealType drho = rhomax / (RealType)(Nrho - 1);
749 RealType rho, phiCC, phiCV;
751 std::vector<RealType> rvals;
752 std::vector<RealType> zvals;
753 std::vector<RealType> ccvals;
754 std::vector<RealType> cvvals;
756 std::vector<RealType> rhovals;
757 std::vector<RealType> funcvals;
759 for (
int i = 0; i < Nr; i++) {
760 r = RealType(i) * dr;
762 rhovals.push_back(Rho(r, re, fe, gamma, nu));
763 phiCC = PhiCoreCore(r, re, A, alpha, kappa);
764 phiCV = PhiCoreValence(r, re, B, beta, lambda);
765 ccvals.push_back(phiCC);
766 cvvals.push_back(phiCV);
768 eamAtomData.rho = std::make_shared<CubicSpline>();
769 eamAtomData.rho->addPoints(rvals, rhovals);
770 eamAtomData.phiCC = std::make_shared<CubicSpline>();
771 eamAtomData.phiCC->addPoints(rvals, ccvals);
772 eamAtomData.phiCV = std::make_shared<CubicSpline>();
773 eamAtomData.phiCV->addPoints(rvals, cvvals);
776 for (
int i = 0; i < Nrho; i++) {
777 rho = RealType(i) * drho;
778 rhovals.push_back(rho);
780 Zhou2005OxygenFunctional(rho, OrhoLimits, OrhoE, OF));
783 eamAtomData.F = std::make_shared<CubicSpline>();
784 eamAtomData.F->addPoints(rhovals, funcvals);
789 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
790 "EAM::addType found an unknown EAM type for atomType %s\n",
791 atomType->getName().c_str());
792 painCave.severity = OPENMD_ERROR;
793 painCave.isFatal = 1;
800 if (fqa.isFluctuatingCharge()) {
801 if (fqa.isMetallic()) {
802 eamAtomData.isFluctuatingCharge =
true;
803 eamAtomData.nValence = fqa.getNValence();
804 eamAtomData.nMobile = fqa.getNMobile();
806 eamAtomData.isFluctuatingCharge =
false;
809 eamAtomData.isFluctuatingCharge =
false;
813 int atid = atomType->getIdent();
814 int eamtid = EAMtypes.size();
816 pair<set<int>::iterator,
bool> ret;
817 ret = EAMtypes.insert(atid);
818 if (ret.second ==
false) {
819 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
820 "EAM already had a previous entry with ident %d\n", atid);
821 painCave.severity = OPENMD_INFO;
822 painCave.isFatal = 0;
826 EAMtids[atid] = eamtid;
827 EAMdata[eamtid] = eamAtomData;
828 MixingMap[eamtid].resize(nEAM_);
832 std::set<int>::iterator it;
833 for (it = EAMtypes.begin(); it != EAMtypes.end(); ++it) {
834 int eamtid2 = EAMtids[(*it)];
838 mixer.phi = getPhi(atomType, atype2);
839 mixer.rcut = mixer.phi->getLimits().second;
840 mixer.explicitlySet =
false;
842 MixingMap[eamtid2].resize(nEAM_);
844 MixingMap[eamtid][eamtid2] = mixer;
845 if (eamtid2 != eamtid) { MixingMap[eamtid2][eamtid] = mixer; }
852 vector<RealType> phiVals) {
854 CubicSplinePtr cs {std::make_shared<CubicSpline>()};
855 vector<RealType> rVals;
857 for (
int i = 0; i < nr; i++)
858 rVals.push_back(i * dr);
860 cs->addPoints(rVals, phiVals);
862 mixer.rcut = mixer.phi->getLimits().second;
863 mixer.explicitlySet =
true;
865 int atid1 = atype1->getIdent();
866 int atid2 = atype2->getIdent();
868 int eamtid1, eamtid2;
870 pair<set<int>::iterator,
bool> ret;
871 ret = EAMtypes.insert(atid1);
872 if (ret.second ==
false) {
874 eamtid1 = EAMtids[atid1];
878 EAMtids[atid1] = nEAM_;
882 ret = EAMtypes.insert(atid2);
883 if (ret.second ==
false) {
885 eamtid2 = EAMtids[atid2];
889 EAMtids[atid2] = nEAM_;
893 MixingMap.resize(nEAM_);
894 MixingMap[eamtid1].resize(nEAM_);
895 MixingMap[eamtid1][eamtid2] = mixer;
897 if (eamtid2 != eamtid1) {
898 MixingMap[eamtid2].resize(nEAM_);
899 MixingMap[eamtid2][eamtid1] = mixer;
905 RealType re, RealType alpha, RealType beta,
906 RealType A, RealType B, RealType kappa,
908 CubicSplinePtr cs {std::make_shared<CubicSpline>()};
911 std::vector<RealType> rVals;
912 std::vector<RealType> phiVals;
913 std::vector<RealType> jVals;
920 RealType rcut = std::min(12.0, std::max(9.0, 4.0 * re));
921 RealType dr = rcut / (RealType)(Nr - 1);
923 for (
int i = 0; i < Nr; i++) {
924 r = RealType(i) * dr;
926 phiVals.push_back(Phi(r, re, A, B, alpha, beta, kappa, lambda));
928 cs->addPoints(rVals, phiVals);
930 mixer.rcut = mixer.phi->getLimits().second;
931 mixer.explicitlySet =
true;
933 int atid1 = atype1->getIdent();
934 int atid2 = atype2->getIdent();
936 int eamtid1, eamtid2;
938 pair<set<int>::iterator,
bool> ret;
939 ret = EAMtypes.insert(atid1);
940 if (ret.second ==
false) {
942 eamtid1 = EAMtids[atid1];
946 EAMtids[atid1] = nEAM_;
950 ret = EAMtypes.insert(atid2);
951 if (ret.second ==
false) {
953 eamtid2 = EAMtids[atid2];
957 EAMtids[atid2] = nEAM_;
961 MixingMap.resize(nEAM_);
962 MixingMap[eamtid1].resize(nEAM_);
963 MixingMap[eamtid1][eamtid2] = mixer;
964 if (eamtid2 != eamtid1) {
965 MixingMap[eamtid2].resize(nEAM_);
966 MixingMap[eamtid2][eamtid1] = mixer;
972 RealType re, RealType alpha, RealType A,
973 RealType Ci, RealType Cj) {
974 CubicSplinePtr cs {std::make_shared<CubicSpline>()};
977 std::vector<RealType> rVals;
978 std::vector<RealType> phiVals;
984 RealType rcut = std::min(12.0, std::max(9.0, 4.0 * re));
985 RealType dr = rcut / (RealType)(Nr - 1);
987 for (
int i = 0; i < Nr; i++) {
988 r = RealType(i) * dr;
994 phiCC = PhiCoreCore(r, re, A, alpha, kappa);
995 phiVals.push_back(phiCC);
998 cs->addPoints(rVals, phiVals);
1003 mixer.rcut = mixer.phi->getLimits().second;
1008 mixer.explicitlySet =
true;
1010 int atid1 = atype1->getIdent();
1011 int atid2 = atype2->getIdent();
1013 int eamtid1, eamtid2;
1015 pair<set<int>::iterator,
bool> ret;
1016 ret = EAMtypes.insert(atid1);
1017 if (ret.second ==
false) {
1019 eamtid1 = EAMtids[atid1];
1023 EAMtids[atid1] = nEAM_;
1027 ret = EAMtypes.insert(atid2);
1028 if (ret.second ==
false) {
1030 eamtid2 = EAMtids[atid2];
1034 EAMtids[atid2] = nEAM_;
1038 MixingMap.resize(nEAM_);
1039 MixingMap[eamtid1].resize(nEAM_);
1040 MixingMap[eamtid1][eamtid2] = mixer;
1041 if (eamtid2 != eamtid1) {
1042 MixingMap[eamtid2].resize(nEAM_);
1043 MixingMap[eamtid2][eamtid1] = mixer;
1049 if (!initialized_) initialize();
1055 if (haveCutoffRadius_)
1056 if (idat.
rij > eamRcut_)
return;
1058 if (idat.
rij < data1.rcut) {
1060 if (data1.isFluctuatingCharge) {
1061 if (mixMeth_ == eamDream2)
1062 s = gFunc(idat.
flucQ1, data1.nValence, data1.nMobile);
1064 s = (data1.nValence - idat.
flucQ1) / (data1.nValence);
1066 idat.
rho2 += s * data1.rho->getValueAt(idat.
rij);
1069 if (idat.
rij < data2.rcut) {
1071 if (data2.isFluctuatingCharge) {
1072 if (mixMeth_ == eamDream2)
1073 s = gFunc(idat.
flucQ2, data2.nValence, data2.nMobile);
1075 s = (data2.nValence - idat.
flucQ2) / (data2.nValence);
1077 idat.
rho1 += s * data2.rho->getValueAt(idat.
rij);
1083 void EAM::calcFunctional(
SelfData& sdat) {
1084 if (!initialized_) initialize();
1099 if (!initialized_) initialize();
1101 if (haveCutoffRadius_)
1102 if (idat.
rij > eamRcut_)
return;
1104 int eamtid1 = EAMtids[idat.
atid1];
1105 int eamtid2 = EAMtids[idat.
atid2];
1111 RealType rci = data1.rcut;
1112 RealType rcj = data2.rcut;
1113 RealType rcij = MixingMap[eamtid1][eamtid2].rcut;
1115 RealType rha(0.0), drha(0.0), rhb(0.0), drhb(0.0);
1116 RealType pha(0.0), dpha(0.0), phb(0.0), dphb(0.0);
1118 RealType phab(0.0), dvpdr(0.0);
1119 RealType drhoidr(0.0), drhojdr(0.0), dudr(0.0);
1122 RealType Va(0.0), Vb(0.0);
1123 RealType Ma(0.0), Mb(0.0);
1124 RealType si(1.0), sj(1.0);
1125 RealType sip(0.0), sjp(0.0);
1126 RealType Ci(1.0), Cj(1.0);
1128 rhat = idat.
d / idat.
rij;
1129 if (idat.
rij < rci && idat.
rij < rcij) {
1130 data1.rho->getValueAndDerivativeAt(idat.
rij, rha, drha);
1131 CubicSplinePtr phi = MixingMap[eamtid1][eamtid1].phi;
1132 phi->getValueAndDerivativeAt(idat.
rij, pha, dpha);
1135 if (idat.
rij < rcj && idat.
rij < rcij) {
1136 data2.rho->getValueAndDerivativeAt(idat.
rij, rhb, drhb);
1137 CubicSplinePtr phi = MixingMap[eamtid2][eamtid2].phi;
1138 phi->getValueAndDerivativeAt(idat.
rij, phb, dphb);
1141 bool hasFlucQ = data1.isFluctuatingCharge || data2.isFluctuatingCharge;
1142 bool isExplicit = MixingMap[eamtid1][eamtid2].explicitlySet;
1144 if (data1.isFluctuatingCharge) {
1145 Va = data1.nValence;
1147 if (mixMeth_ == eamDream2)
1148 si = gFunc(idat.
flucQ1, Va, Ma);
1150 si = (Va - idat.
flucQ1) / Va;
1152 if (data2.isFluctuatingCharge) {
1153 Vb = data2.nValence;
1155 if (mixMeth_ == eamDream2)
1156 sj = gFunc(idat.
flucQ2, Vb, Mb);
1158 sj = (Vb - idat.
flucQ2) / Vb;
1161 if (mixMeth_ == eamJohnson || mixMeth_ == eamDream1) {
1162 if (idat.
rij < rci && idat.
rij < rcij) {
1163 phab = phab + 0.5 * (sj / si) * (rhb / rha) * pha;
1164 dvpdr = dvpdr + 0.5 * (sj / si) *
1165 ((rhb / rha) * dpha +
1166 pha * ((drhb / rha) - (rhb * drha / rha / rha)));
1168 if (data1.isFluctuatingCharge) {
1169 idat.
dVdFQ1 += 0.5 * (rhb * sj * pha) / (rha * Ma * si * si);
1171 if (data2.isFluctuatingCharge) {
1172 idat.
dVdFQ2 -= 0.5 * (rhb * pha) / (rha * Mb * si);
1176 if (idat.
rij < rcj && idat.
rij < rcij) {
1177 phab = phab + 0.5 * (si / sj) * (rha / rhb) * phb;
1178 dvpdr = dvpdr + 0.5 * (si / sj) *
1179 ((rha / rhb) * dphb +
1180 phb * ((drha / rhb) - (rha * drhb / rhb / rhb)));
1182 if (data1.isFluctuatingCharge) {
1183 idat.
dVdFQ1 -= 0.5 * (rha * phb) / (rhb * Ma * sj);
1185 if (data2.isFluctuatingCharge) {
1186 idat.
dVdFQ2 += 0.5 * (rha * si * phb) / (rhb * Mb * sj * sj);
1193 bool insideCutOff = (idat.
rij < rcij);
1195 CubicSplinePtr phi = MixingMap[eamtid1][eamtid2].phi;
1196 phi->getValueAndDerivativeAt(idat.
rij, phab, dvpdr);
1202 if (idat.
rij < rci && idat.
rij < rcij) {
1203 CubicSplinePtr phiACC = data1.phiCC;
1204 phiACC->getValueAndDerivativeAt(idat.
rij, pha, dpha);
1205 phab += 0.5 * (rhb / rha) * pha;
1206 dvpdr += 0.5 * ((rhb / rha) * dpha +
1207 pha * ((drhb / rha) - (rhb * drha / rha / rha)));
1209 if (idat.
rij < rcj && idat.
rij < rcij) {
1210 CubicSplinePtr phiBCC = data2.phiCC;
1211 phiBCC->getValueAndDerivativeAt(idat.
rij, phb, dphb);
1212 phab += 0.5 * (rha / rhb) * phb;
1213 dvpdr += 0.5 * ((rha / rhb) * dphb +
1214 phb * ((drha / rhb) - (rha * drhb / rhb / rhb)));
1221 Ci = MixingMap[eamtid1][eamtid2].Ci;
1222 Cj = MixingMap[eamtid1][eamtid2].Cj;
1226 if (data1.isFluctuatingCharge) { sip = gPrime(idat.
flucQ1, Va, Ma); }
1227 if (data2.isFluctuatingCharge) { sjp = gPrime(idat.
flucQ2, Vb, Mb); }
1229 if (idat.
rij < rci && idat.
rij < rcij) {
1230 CubicSplinePtr phiACV = data1.phiCV;
1231 phiACV->getValueAndDerivativeAt(idat.
rij, pha, dpha);
1233 phab += 0.5 * sj * Ci * (rhb / rha) * pha;
1234 dvpdr += 0.5 * sj * Ci *
1235 ((rhb / rha) * dpha +
1236 pha * ((drhb / rha) - (rhb * drha / rha / rha)));
1238 if (data2.isFluctuatingCharge) {
1239 idat.
dVdFQ2 += 0.5 * sjp * Ci * (rhb / rha) * pha;
1242 if (idat.
rij < rcj && idat.
rij < rcij) {
1243 CubicSplinePtr phiBCV = data2.phiCV;
1244 phiBCV->getValueAndDerivativeAt(idat.
rij, phb, dphb);
1246 phab += 0.5 * si * Cj * (rha / rhb) * phb;
1247 dvpdr += 0.5 * si * Cj *
1248 ((rha / rhb) * dphb +
1249 phb * ((drha / rhb) - (rha * drhb / rhb / rhb)));
1251 if (data1.isFluctuatingCharge) {
1252 idat.
dVdFQ1 += 0.5 * sip * Cj * (rha / rhb) * phb;
1257 if (idat.
rij < rcij) {
1258 CubicSplinePtr phi = MixingMap[eamtid1][eamtid2].phi;
1259 phi->getValueAndDerivativeAt(idat.
rij, phab, dvpdr);
1262 drhoidr = si * drha;
1263 drhojdr = sj * drhb;
1264 dudr = drhojdr * idat.
dfrho1 + drhoidr * idat.
dfrho2 + dvpdr;
1266 idat.
f1 += rhat * dudr;
1290 if (data1.isFluctuatingCharge) {
1291 if (mixMeth_ == eamDream2)
1296 if (data2.isFluctuatingCharge) {
1297 if (mixMeth_ == eamDream2)
1306 RealType EAM::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
1307 if (!initialized_) initialize();
1311 int atid1 = atypes.first->getIdent();
1312 int atid2 = atypes.second->getIdent();
1313 int eamtid1 = EAMtids[atid1];
1314 int eamtid2 = EAMtids[atid2];
1316 if (eamtid1 != -1) {
1321 if (eamtid2 != -1) {
1323 if (data2.rcut > cut) cut = data2.rcut;
AtomType is what OpenMD looks to for unchanging data about an atom.
EAMInteractionType is one of the basic metallic interactions for representing the bonding in metallic...
AtomType * getAtomType(const std::string &at)
getAtomType by string
NonBondedInteractionType class is responsible for keeping track of static (unchanging) parameters for...
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
@ METALLIC_EMBEDDING_FAMILY
Transition metal interactions involving electron density.
@ METALLIC_PAIR_FAMILY
Transition metal interactions involving pair potentials.
The InteractionData struct.
Vector3d d
interatomic vector (already wrapped into box)
RealType dVdFQ1
fluctuating charge force on atom1
RealType dVdFQ2
fluctuating charge force on atom2
RealType particlePot2
particle potential for atom2
int atid1
atomType ident for atom 1
potVec pot
total potential
potVec selePot
potential energies of the selected sites
RealType flucQ2
fluctuating charge on atom2
RealType rho2
total electron density at second atom
bool isSelected
one of the particles has been selected for selection potential
RealType flucQ1
fluctuating charge on atom1
RealType vpair
pair potential
int atid2
atomType ident for atom 2
RealType dfrho2
derivative of functional for atom 2
RealType frho2
density functional at second atom
bool doParticlePot
should we bother with the particle pot?
RealType dfrho1
derivative of functional for atom 1
RealType frho1
density functional at first atom
Vector3d f1
force between the two atoms
RealType rij
interatomic separation
RealType particlePot1
particle potential for atom1
RealType rho1
total electron density at first atom
potVec selePot
potential energy of the selected site
RealType frho
value of density functional for atom
RealType dfrhodrho
derivative of density functional for atom
potVec selfPot
total potential (including embedding energy)
RealType particlePot
contribution to potential from this particle
RealType rho
electron density
bool isSelected
this site has been selected for selection potential
bool doParticlePot
should we bother with the particle pot?
int atid
atomType ident for the atom