| 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). | 
| 38 | > | * [3]  Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008). | 
| 39 |  | * [4]  Kuang & Gezelter,  J. Chem. Phys. 133, 164101 (2010). | 
| 40 |  | * [5]  Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011). | 
| 41 |  | */ | 
| 44 |  | * @file ForceManager.cpp | 
| 45 |  | * @author tlin | 
| 46 |  | * @date 11/09/2004 | 
| 47 | – | * @time 10:39am | 
| 47 |  | * @version 1.0 | 
| 48 |  | */ | 
| 49 |  |  | 
| 57 |  | #include "primitives/Torsion.hpp" | 
| 58 |  | #include "primitives/Inversion.hpp" | 
| 59 |  | #include "nonbonded/NonBondedInteraction.hpp" | 
| 60 | < | #include "perturbations/ElectricField.hpp" | 
| 60 | > | #include "perturbations/UniformField.hpp" | 
| 61 |  | #include "parallel/ForceMatrixDecomposition.hpp" | 
| 62 |  |  | 
| 63 |  | #include <cstdio> | 
| 67 |  | using namespace std; | 
| 68 |  | namespace OpenMD { | 
| 69 |  |  | 
| 70 | < | ForceManager::ForceManager(SimInfo * info) : info_(info) { | 
| 70 | > | ForceManager::ForceManager(SimInfo * info) : info_(info), switcher_(NULL), | 
| 71 | > | initialized_(false) { | 
| 72 |  | forceField_ = info_->getForceField(); | 
| 73 |  | interactionMan_ = new InteractionManager(); | 
| 74 |  | fDecomp_ = new ForceMatrixDecomposition(info_, interactionMan_); | 
| 75 | + | thermo = new Thermo(info_); | 
| 76 |  | } | 
| 77 |  |  | 
| 78 | + | ForceManager::~ForceManager() { | 
| 79 | + | perturbations_.clear(); | 
| 80 | + |  | 
| 81 | + | delete switcher_; | 
| 82 | + | delete interactionMan_; | 
| 83 | + | delete fDecomp_; | 
| 84 | + | delete thermo; | 
| 85 | + | } | 
| 86 | + |  | 
| 87 |  | /** | 
| 88 |  | * setupCutoffs | 
| 89 |  | * | 
| 98 |  | *      simulation for suggested cutoff values (e.g. 2.5 * sigma). | 
| 99 |  | *      Use the maximum suggested value that was found. | 
| 100 |  | * | 
| 101 | < | * cutoffMethod : (one of HARD, SWITCHED, SHIFTED_FORCE, | 
| 102 | < | *                        or SHIFTED_POTENTIAL) | 
| 101 | > | * cutoffMethod : (one of HARD, SWITCHED, SHIFTED_FORCE, TAYLOR_SHIFTED, | 
| 102 | > | *                        SHIFTED_POTENTIAL, or EWALD_FULL) | 
| 103 |  | *      If cutoffMethod was explicitly set, use that choice. | 
| 104 |  | *      If cutoffMethod was not explicitly set, use SHIFTED_FORCE | 
| 105 |  | * | 
| 128 |  | else | 
| 129 |  | mdFileVersion = 0; | 
| 130 |  |  | 
| 131 | + | // We need the list of simulated atom types to figure out cutoffs | 
| 132 | + | // as well as long range corrections. | 
| 133 | + |  | 
| 134 | + | set<AtomType*>::iterator i; | 
| 135 | + | set<AtomType*> atomTypes_; | 
| 136 | + | atomTypes_ = info_->getSimulatedAtomTypes(); | 
| 137 | + |  | 
| 138 |  | if (simParams_->haveCutoffRadius()) { | 
| 139 |  | rCut_ = simParams_->getCutoffRadius(); | 
| 140 |  | } else { | 
| 149 |  | rCut_ = 12.0; | 
| 150 |  | } else { | 
| 151 |  | RealType thisCut; | 
| 152 | < | set<AtomType*>::iterator i; | 
| 136 | < | set<AtomType*> atomTypes; | 
| 137 | < | atomTypes = info_->getSimulatedAtomTypes(); | 
| 138 | < | for (i = atomTypes.begin(); i != atomTypes.end(); ++i) { | 
| 152 | > | for (i = atomTypes_.begin(); i != atomTypes_.end(); ++i) { | 
| 153 |  | thisCut = interactionMan_->getSuggestedCutoffRadius((*i)); | 
| 154 |  | rCut_ = max(thisCut, rCut_); | 
| 155 |  | } | 
| 171 |  | stringToCutoffMethod["SWITCHED"] = SWITCHED; | 
| 172 |  | stringToCutoffMethod["SHIFTED_POTENTIAL"] = SHIFTED_POTENTIAL; | 
| 173 |  | stringToCutoffMethod["SHIFTED_FORCE"] = SHIFTED_FORCE; | 
| 174 | + | stringToCutoffMethod["TAYLOR_SHIFTED"] = TAYLOR_SHIFTED; | 
| 175 | + | stringToCutoffMethod["EWALD_FULL"] = EWALD_FULL; | 
| 176 |  |  | 
| 177 |  | if (simParams_->haveCutoffMethod()) { | 
| 178 |  | string cutMeth = toUpperCopy(simParams_->getCutoffMethod()); | 
| 182 |  | sprintf(painCave.errMsg, | 
| 183 |  | "ForceManager::setupCutoffs: Could not find chosen cutoffMethod %s\n" | 
| 184 |  | "\tShould be one of: " | 
| 185 | < | "HARD, SWITCHED, SHIFTED_POTENTIAL, or SHIFTED_FORCE\n", | 
| 185 | > | "HARD, SWITCHED, SHIFTED_POTENTIAL, TAYLOR_SHIFTED,\n" | 
| 186 | > | "\tSHIFTED_FORCE, or EWALD_FULL\n", | 
| 187 |  | cutMeth.c_str()); | 
| 188 |  | painCave.isFatal = 1; | 
| 189 |  | painCave.severity = OPENMD_ERROR; | 
| 227 |  | cutoffMethod_ = SHIFTED_POTENTIAL; | 
| 228 |  | } else if (myMethod == "SHIFTED_FORCE") { | 
| 229 |  | cutoffMethod_ = SHIFTED_FORCE; | 
| 230 | + | } else if (myMethod == "TAYLOR_SHIFTED") { | 
| 231 | + | cutoffMethod_ = TAYLOR_SHIFTED; | 
| 232 | + | } else if (myMethod == "EWALD_FULL") { | 
| 233 | + | cutoffMethod_ = EWALD_FULL; | 
| 234 |  | } | 
| 235 |  |  | 
| 236 |  | if (simParams_->haveSwitchingRadius()) | 
| 237 |  | rSwitch_ = simParams_->getSwitchingRadius(); | 
| 238 |  |  | 
| 239 | < | if (myMethod == "SHIFTED_POTENTIAL" || myMethod == "SHIFTED_FORCE") { | 
| 239 | > | if (myMethod == "SHIFTED_POTENTIAL" || myMethod == "SHIFTED_FORCE" || | 
| 240 | > | myMethod == "TAYLOR_SHIFTED" || myMethod == "EWALD_FULL") { | 
| 241 |  | if (simParams_->haveSwitchingRadius()){ | 
| 242 |  | sprintf(painCave.errMsg, | 
| 243 |  | "ForceManager::setupCutoffs : DEPRECATED ERROR MESSAGE\n" | 
| 392 |  | } | 
| 393 |  | switcher_->setSwitchType(sft_); | 
| 394 |  | switcher_->setSwitch(rSwitch_, rCut_); | 
| 373 | – | interactionMan_->setSwitchingRadius(rSwitch_); | 
| 395 |  | } | 
| 396 |  |  | 
| 376 | – |  | 
| 377 | – |  | 
| 378 | – |  | 
| 397 |  | void ForceManager::initialize() { | 
| 398 |  |  | 
| 399 |  | if (!info_->isTopologyDone()) { | 
| 402 |  | interactionMan_->setSimInfo(info_); | 
| 403 |  | interactionMan_->initialize(); | 
| 404 |  |  | 
| 405 | < | // We want to delay the cutoffs until after the interaction | 
| 406 | < | // manager has set up the atom-atom interactions so that we can | 
| 407 | < | // query them for suggested cutoff values | 
| 405 | > | //! We want to delay the cutoffs until after the interaction | 
| 406 | > | //! manager has set up the atom-atom interactions so that we can | 
| 407 | > | //! query them for suggested cutoff values | 
| 408 |  | setupCutoffs(); | 
| 409 |  |  | 
| 410 |  | info_->prepareTopology(); | 
| 412 |  | doParticlePot_ = info_->getSimParams()->getOutputParticlePotential(); | 
| 413 |  | doHeatFlux_ = info_->getSimParams()->getPrintHeatFlux(); | 
| 414 |  | if (doHeatFlux_) doParticlePot_ = true; | 
| 415 | + |  | 
| 416 | + | doElectricField_ = info_->getSimParams()->getOutputElectricField(); | 
| 417 | + | doSitePotential_ = info_->getSimParams()->getOutputSitePotential(); | 
| 418 |  |  | 
| 419 |  | } | 
| 420 |  |  | 
| 421 |  | ForceFieldOptions& fopts = forceField_->getForceFieldOptions(); | 
| 422 |  |  | 
| 423 | < | // Force fields can set options on how to scale van der Waals and | 
| 424 | < | // electrostatic interactions for atoms connected via bonds, bends | 
| 425 | < | // and torsions in this case the topological distance between | 
| 426 | < | // atoms is: | 
| 427 | < | // 0 = topologically unconnected | 
| 428 | < | // 1 = bonded together | 
| 429 | < | // 2 = connected via a bend | 
| 430 | < | // 3 = connected via a torsion | 
| 423 | > | //! Force fields can set options on how to scale van der Waals and | 
| 424 | > | //! electrostatic interactions for atoms connected via bonds, bends | 
| 425 | > | //! and torsions in this case the topological distance between | 
| 426 | > | //! atoms is: | 
| 427 | > | //! 0 = topologically unconnected | 
| 428 | > | //! 1 = bonded together | 
| 429 | > | //! 2 = connected via a bend | 
| 430 | > | //! 3 = connected via a torsion | 
| 431 |  |  | 
| 432 |  | vdwScale_.reserve(4); | 
| 433 |  | fill(vdwScale_.begin(), vdwScale_.end(), 0.0); | 
| 445 |  | electrostaticScale_[2] = fopts.getelectrostatic13scale(); | 
| 446 |  | electrostaticScale_[3] = fopts.getelectrostatic14scale(); | 
| 447 |  |  | 
| 448 | < | if (info_->getSimParams()->haveElectricField()) { | 
| 449 | < | ElectricField* eField = new ElectricField(info_); | 
| 448 | > | if (info_->getSimParams()->haveUniformField()) { | 
| 449 | > | UniformField* eField = new UniformField(info_); | 
| 450 |  | perturbations_.push_back(eField); | 
| 451 |  | } | 
| 452 |  |  | 
| 453 | + | usePeriodicBoundaryConditions_ = info_->getSimParams()->getUsePeriodicBoundaryConditions(); | 
| 454 | + |  | 
| 455 |  | fDecomp_->distributeInitialData(); | 
| 456 | < |  | 
| 456 | > |  | 
| 457 |  | initialized_ = true; | 
| 458 | < |  | 
| 458 | > |  | 
| 459 |  | } | 
| 460 | < |  | 
| 460 | > |  | 
| 461 |  | void ForceManager::calcForces() { | 
| 462 |  |  | 
| 463 |  | if (!initialized_) initialize(); | 
| 464 | < |  | 
| 464 | > |  | 
| 465 |  | preCalculation(); | 
| 466 |  | shortRangeInteractions(); | 
| 467 |  | longRangeInteractions(); | 
| 635 |  | // Collect from all nodes.  This should eventually be moved into a | 
| 636 |  | // SystemDecomposition, but this is a better place than in | 
| 637 |  | // Thermo to do the collection. | 
| 638 | < | MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &bondPotential, 1, MPI::REALTYPE, | 
| 639 | < | MPI::SUM); | 
| 640 | < | MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &bendPotential, 1, MPI::REALTYPE, | 
| 641 | < | MPI::SUM); | 
| 642 | < | MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &torsionPotential, 1, | 
| 643 | < | MPI::REALTYPE, MPI::SUM); | 
| 644 | < | MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &inversionPotential, 1, | 
| 645 | < | MPI::REALTYPE, MPI::SUM); | 
| 638 | > |  | 
| 639 | > | MPI_Allreduce(MPI_IN_PLACE, &bondPotential, 1, MPI_REALTYPE, | 
| 640 | > | MPI_SUM, MPI_COMM_WORLD); | 
| 641 | > | MPI_Allreduce(MPI_IN_PLACE, &bendPotential, 1, MPI_REALTYPE, | 
| 642 | > | MPI_SUM, MPI_COMM_WORLD); | 
| 643 | > | MPI_Allreduce(MPI_IN_PLACE, &torsionPotential, 1, | 
| 644 | > | MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD); | 
| 645 | > | MPI_Allreduce(MPI_IN_PLACE, &inversionPotential, 1, | 
| 646 | > | MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD); | 
| 647 |  | #endif | 
| 648 |  |  | 
| 649 |  | Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot(); | 
| 661 |  |  | 
| 662 |  | void ForceManager::longRangeInteractions() { | 
| 663 |  |  | 
| 640 | – |  | 
| 664 |  | Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot(); | 
| 665 |  | DataStorage* config = &(curSnapshot->atomData); | 
| 666 |  | DataStorage* cgConfig = &(curSnapshot->cgData); | 
| 667 |  |  | 
| 668 | + |  | 
| 669 |  | //calculate the center of mass of cutoff group | 
| 670 |  |  | 
| 671 |  | SimInfo::MoleculeIterator mi; | 
| 698 |  | RealType vij; | 
| 699 |  | Vector3d fij, fg, f1; | 
| 700 |  | tuple3<RealType, RealType, RealType> cuts; | 
| 701 | < | RealType rCutSq; | 
| 701 | > | RealType rCut, rCutSq, rListSq; | 
| 702 |  | bool in_switching_region; | 
| 703 |  | RealType sw, dswdr, swderiv; | 
| 704 | < | vector<int> atomListColumn, atomListRow, atomListLocal; | 
| 704 | > | vector<int> atomListColumn, atomListRow; | 
| 705 |  | InteractionData idat; | 
| 706 |  | SelfData sdat; | 
| 707 |  | RealType mf; | 
| 708 |  | RealType vpair; | 
| 709 |  | RealType dVdFQ1(0.0); | 
| 710 |  | RealType dVdFQ2(0.0); | 
| 687 | – | Vector3d eField1(0.0); | 
| 688 | – | Vector3d eField2(0.0); | 
| 711 |  | potVec longRangePotential(0.0); | 
| 712 | + | RealType reciprocalPotential(0.0); | 
| 713 |  | potVec workPot(0.0); | 
| 714 |  | potVec exPot(0.0); | 
| 715 | + | Vector3d eField1(0.0); | 
| 716 | + | Vector3d eField2(0.0); | 
| 717 | + | RealType sPot1(0.0); | 
| 718 | + | RealType sPot2(0.0); | 
| 719 | + |  | 
| 720 |  | vector<int>::iterator ia, jb; | 
| 721 |  |  | 
| 722 |  | int loopStart, loopEnd; | 
| 723 | < |  | 
| 723 | > |  | 
| 724 | > | idat.rcut = &rCut; | 
| 725 |  | idat.vdwMult = &vdwMult; | 
| 726 |  | idat.electroMult = &electroMult; | 
| 727 |  | idat.pot = &workPot; | 
| 732 |  | idat.dVdFQ1 = &dVdFQ1; | 
| 733 |  | idat.dVdFQ2 = &dVdFQ2; | 
| 734 |  | idat.eField1 = &eField1; | 
| 735 | < | idat.eField2 = &eField2; | 
| 735 | > | idat.eField2 = &eField2; | 
| 736 | > | idat.sPot1 = &sPot1; | 
| 737 | > | idat.sPot2 = &sPot2; | 
| 738 |  | idat.f1 = &f1; | 
| 739 |  | idat.sw = &sw; | 
| 740 |  | idat.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false; | 
| 741 | < | idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE) ? true : false; | 
| 741 | > | idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE || | 
| 742 | > | cutoffMethod_ == TAYLOR_SHIFTED) ? true : false; | 
| 743 |  | idat.doParticlePot = doParticlePot_; | 
| 744 | + | idat.doElectricField = doElectricField_; | 
| 745 | + | idat.doSitePotential = doSitePotential_; | 
| 746 |  | sdat.doParticlePot = doParticlePot_; | 
| 747 |  |  | 
| 748 |  | loopEnd = PAIR_LOOP; | 
| 755 |  |  | 
| 756 |  | if (iLoop == loopStart) { | 
| 757 |  | bool update_nlist = fDecomp_->checkNeighborList(); | 
| 758 | < | if (update_nlist) | 
| 759 | < | neighborList = fDecomp_->buildNeighborList(); | 
| 760 | < | } | 
| 758 | > | if (update_nlist) { | 
| 759 | > | if (!usePeriodicBoundaryConditions_) | 
| 760 | > | Mat3x3d bbox = thermo->getBoundingBox(); | 
| 761 | > | fDecomp_->buildNeighborList(neighborList_); | 
| 762 | > | } | 
| 763 | > | } | 
| 764 |  |  | 
| 765 | < | for (vector<pair<int, int> >::iterator it = neighborList.begin(); | 
| 766 | < | it != neighborList.end(); ++it) { | 
| 765 | > | for (vector<pair<int, int> >::iterator it = neighborList_.begin(); | 
| 766 | > | it != neighborList_.end(); ++it) { | 
| 767 |  |  | 
| 768 |  | cg1 = (*it).first; | 
| 769 |  | cg2 = (*it).second; | 
| 770 |  |  | 
| 771 | < | cuts = fDecomp_->getGroupCutoffs(cg1, cg2); | 
| 771 | > | fDecomp_->getGroupCutoffs(cg1, cg2, rCut, rCutSq, rListSq); | 
| 772 |  |  | 
| 773 |  | d_grp  = fDecomp_->getIntergroupVector(cg1, cg2); | 
| 774 |  |  | 
| 775 | < | curSnapshot->wrapVector(d_grp); | 
| 775 | > | // already wrapped in the getIntergroupVector call: | 
| 776 | > | // curSnapshot->wrapVector(d_grp); | 
| 777 |  | rgrpsq = d_grp.lengthSquare(); | 
| 740 | – | rCutSq = cuts.second; | 
| 778 |  |  | 
| 779 |  | if (rgrpsq < rCutSq) { | 
| 743 | – | idat.rcut = &cuts.first; | 
| 780 |  | if (iLoop == PAIR_LOOP) { | 
| 781 |  | vij = 0.0; | 
| 782 | < | fij = V3Zero; | 
| 782 | > | fij.zero(); | 
| 783 | > | eField1.zero(); | 
| 784 | > | eField2.zero(); | 
| 785 | > | sPot1 = 0.0; | 
| 786 | > | sPot2 = 0.0; | 
| 787 |  | } | 
| 788 |  |  | 
| 789 |  | in_switching_region = switcher_->getSwitch(rgrpsq, sw, dswdr, | 
| 808 |  | vpair = 0.0; | 
| 809 |  | workPot = 0.0; | 
| 810 |  | exPot = 0.0; | 
| 811 | < | f1 = V3Zero; | 
| 811 | > | f1.zero(); | 
| 812 |  | dVdFQ1 = 0.0; | 
| 813 |  | dVdFQ2 = 0.0; | 
| 814 |  |  | 
| 835 |  |  | 
| 836 |  | r = sqrt( *(idat.r2) ); | 
| 837 |  | idat.rij = &r; | 
| 838 | < |  | 
| 838 | > |  | 
| 839 |  | if (iLoop == PREPAIR_LOOP) { | 
| 840 |  | interactionMan_->doPrePair(idat); | 
| 841 |  | } else { | 
| 931 |  | } | 
| 932 |  | } | 
| 933 |  | } | 
| 934 | < |  | 
| 934 | > |  | 
| 935 |  | // collects pairwise information | 
| 936 |  | fDecomp_->collectData(); | 
| 937 | + | if (cutoffMethod_ == EWALD_FULL) { | 
| 938 | + | interactionMan_->doReciprocalSpaceSum(reciprocalPotential); | 
| 939 | + |  | 
| 940 | + | curSnapshot->setReciprocalPotential(reciprocalPotential); | 
| 941 | + | } | 
| 942 |  |  | 
| 943 |  | if (info_->requiresSelfCorrection()) { | 
| 944 |  | for (unsigned int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) { | 
| 956 |  | curSnapshot->setLongRangePotential(longRangePotential); | 
| 957 |  |  | 
| 958 |  | curSnapshot->setExcludedPotentials(*(fDecomp_->getExcludedSelfPotential()) + | 
| 959 | < | *(fDecomp_->getExcludedPotential())); | 
| 959 | > | *(fDecomp_->getExcludedPotential())); | 
| 960 |  |  | 
| 961 |  | } | 
| 962 |  |  | 
| 918 | – |  | 
| 963 |  | void ForceManager::postCalculation() { | 
| 964 |  |  | 
| 965 |  | vector<Perturbation*>::iterator pi; | 
| 985 |  | } | 
| 986 |  |  | 
| 987 |  | #ifdef IS_MPI | 
| 988 | < | MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, stressTensor.getArrayPointer(), 9, | 
| 989 | < | MPI::REALTYPE, MPI::SUM); | 
| 988 | > | MPI_Allreduce(MPI_IN_PLACE, stressTensor.getArrayPointer(), 9, | 
| 989 | > | MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD); | 
| 990 |  | #endif | 
| 991 |  | curSnapshot->setStressTensor(stressTensor); | 
| 992 |  |  | 
| 993 | + | if (info_->getSimParams()->getUseLongRangeCorrections()) { | 
| 994 | + | /* | 
| 995 | + | RealType vol = curSnapshot->getVolume(); | 
| 996 | + | RealType Elrc(0.0); | 
| 997 | + | RealType Wlrc(0.0); | 
| 998 | + |  | 
| 999 | + | set<AtomType*>::iterator i; | 
| 1000 | + | set<AtomType*>::iterator j; | 
| 1001 | + |  | 
| 1002 | + | RealType n_i, n_j; | 
| 1003 | + | RealType rho_i, rho_j; | 
| 1004 | + | pair<RealType, RealType> LRI; | 
| 1005 | + |  | 
| 1006 | + | for (i = atomTypes_.begin(); i != atomTypes_.end(); ++i) { | 
| 1007 | + | n_i = RealType(info_->getGlobalCountOfType(*i)); | 
| 1008 | + | rho_i = n_i /  vol; | 
| 1009 | + | for (j = atomTypes_.begin(); j != atomTypes_.end(); ++j) { | 
| 1010 | + | n_j = RealType(info_->getGlobalCountOfType(*j)); | 
| 1011 | + | rho_j = n_j / vol; | 
| 1012 | + |  | 
| 1013 | + | LRI = interactionMan_->getLongRangeIntegrals( (*i), (*j) ); | 
| 1014 | + |  | 
| 1015 | + | Elrc += n_i   * rho_j * LRI.first; | 
| 1016 | + | Wlrc -= rho_i * rho_j * LRI.second; | 
| 1017 | + | } | 
| 1018 | + | } | 
| 1019 | + | Elrc *= 2.0 * NumericConstant::PI; | 
| 1020 | + | Wlrc *= 2.0 * NumericConstant::PI; | 
| 1021 | + |  | 
| 1022 | + | RealType lrp = curSnapshot->getLongRangePotential(); | 
| 1023 | + | curSnapshot->setLongRangePotential(lrp + Elrc); | 
| 1024 | + | stressTensor += Wlrc * SquareMatrix3<RealType>::identity(); | 
| 1025 | + | curSnapshot->setStressTensor(stressTensor); | 
| 1026 | + | */ | 
| 1027 | + |  | 
| 1028 | + | } | 
| 1029 |  | } | 
| 1030 | < | } //end namespace OpenMD | 
| 1030 | > | } |