| 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" | 
| 61 |  | #include "parallel/ForceMatrixDecomposition.hpp" | 
| 62 |  |  | 
| 63 |  | #include <cstdio> | 
| 110 |  | Globals* simParams_ = info_->getSimParams(); | 
| 111 |  | ForceFieldOptions& forceFieldOptions_ = forceField_->getForceFieldOptions(); | 
| 112 |  | int mdFileVersion; | 
| 113 | + | rCut_ = 0.0; //Needs a value for a later max() call; | 
| 114 |  |  | 
| 115 |  | if (simParams_->haveMDfileVersion()) | 
| 116 |  | mdFileVersion = simParams_->getMDfileVersion(); | 
| 117 |  | else | 
| 118 |  | mdFileVersion = 0; | 
| 119 |  |  | 
| 120 | + | // We need the list of simulated atom types to figure out cutoffs | 
| 121 | + | // as well as long range corrections. | 
| 122 | + |  | 
| 123 | + | set<AtomType*>::iterator i; | 
| 124 | + | set<AtomType*> atomTypes_; | 
| 125 | + | atomTypes_ = info_->getSimulatedAtomTypes(); | 
| 126 | + |  | 
| 127 |  | if (simParams_->haveCutoffRadius()) { | 
| 128 |  | rCut_ = simParams_->getCutoffRadius(); | 
| 129 |  | } else { | 
| 138 |  | rCut_ = 12.0; | 
| 139 |  | } else { | 
| 140 |  | RealType thisCut; | 
| 141 | < | set<AtomType*>::iterator i; | 
| 134 | < | set<AtomType*> atomTypes; | 
| 135 | < | atomTypes = info_->getSimulatedAtomTypes(); | 
| 136 | < | for (i = atomTypes.begin(); i != atomTypes.end(); ++i) { | 
| 141 | > | for (i = atomTypes_.begin(); i != atomTypes_.end(); ++i) { | 
| 142 |  | thisCut = interactionMan_->getSuggestedCutoffRadius((*i)); | 
| 143 |  | rCut_ = max(thisCut, rCut_); | 
| 144 |  | } | 
| 373 |  | } | 
| 374 |  | switcher_->setSwitchType(sft_); | 
| 375 |  | switcher_->setSwitch(rSwitch_, rCut_); | 
| 371 | – | interactionMan_->setSwitchingRadius(rSwitch_); | 
| 376 |  | } | 
| 377 |  |  | 
| 378 |  |  | 
| 396 |  | doParticlePot_ = info_->getSimParams()->getOutputParticlePotential(); | 
| 397 |  | doHeatFlux_ = info_->getSimParams()->getPrintHeatFlux(); | 
| 398 |  | if (doHeatFlux_) doParticlePot_ = true; | 
| 399 | + |  | 
| 400 | + | doElectricField_ = info_->getSimParams()->getOutputElectricField(); | 
| 401 |  |  | 
| 402 |  | } | 
| 403 |  |  | 
| 428 |  | electrostaticScale_[2] = fopts.getelectrostatic13scale(); | 
| 429 |  | electrostaticScale_[3] = fopts.getelectrostatic14scale(); | 
| 430 |  |  | 
| 431 | + | if (info_->getSimParams()->haveElectricField()) { | 
| 432 | + | ElectricField* eField = new ElectricField(info_); | 
| 433 | + | perturbations_.push_back(eField); | 
| 434 | + | } | 
| 435 | + |  | 
| 436 |  | fDecomp_->distributeInitialData(); | 
| 437 |  |  | 
| 438 |  | initialized_ = true; | 
| 459 |  | Molecule::CutoffGroupIterator ci; | 
| 460 |  | CutoffGroup* cg; | 
| 461 |  |  | 
| 462 | < | // forces are zeroed here, before any are accumulated. | 
| 462 | > | // forces and potentials are zeroed here, before any are | 
| 463 | > | // accumulated. | 
| 464 |  |  | 
| 465 | + | Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot(); | 
| 466 | + |  | 
| 467 | + | snap->setBondPotential(0.0); | 
| 468 | + | snap->setBendPotential(0.0); | 
| 469 | + | snap->setTorsionPotential(0.0); | 
| 470 | + | snap->setInversionPotential(0.0); | 
| 471 | + |  | 
| 472 | + | potVec zeroPot(0.0); | 
| 473 | + | snap->setLongRangePotential(zeroPot); | 
| 474 | + | snap->setExcludedPotentials(zeroPot); | 
| 475 | + |  | 
| 476 | + | snap->setRestraintPotential(0.0); | 
| 477 | + | snap->setRawPotential(0.0); | 
| 478 | + |  | 
| 479 |  | for (mol = info_->beginMolecule(mi); mol != NULL; | 
| 480 |  | mol = info_->nextMolecule(mi)) { | 
| 481 |  | for(atom = mol->beginAtom(ai); atom != NULL; | 
| 611 |  | } | 
| 612 |  | } | 
| 613 |  | } | 
| 614 | < |  | 
| 615 | < | RealType  shortRangePotential = bondPotential + bendPotential + | 
| 616 | < | torsionPotential +  inversionPotential; | 
| 614 | > |  | 
| 615 | > | #ifdef IS_MPI | 
| 616 | > | // Collect from all nodes.  This should eventually be moved into a | 
| 617 | > | // SystemDecomposition, but this is a better place than in | 
| 618 | > | // Thermo to do the collection. | 
| 619 | > | MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &bondPotential, 1, MPI::REALTYPE, | 
| 620 | > | MPI::SUM); | 
| 621 | > | MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &bendPotential, 1, MPI::REALTYPE, | 
| 622 | > | MPI::SUM); | 
| 623 | > | MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &torsionPotential, 1, | 
| 624 | > | MPI::REALTYPE, MPI::SUM); | 
| 625 | > | MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &inversionPotential, 1, | 
| 626 | > | MPI::REALTYPE, MPI::SUM); | 
| 627 | > | #endif | 
| 628 | > |  | 
| 629 |  | Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot(); | 
| 630 | < | curSnapshot->statData[Stats::SHORT_RANGE_POTENTIAL] = shortRangePotential; | 
| 631 | < | curSnapshot->statData[Stats::BOND_POTENTIAL] = bondPotential; | 
| 632 | < | curSnapshot->statData[Stats::BEND_POTENTIAL] = bendPotential; | 
| 633 | < | curSnapshot->statData[Stats::DIHEDRAL_POTENTIAL] = torsionPotential; | 
| 634 | < | curSnapshot->statData[Stats::INVERSION_POTENTIAL] = inversionPotential; | 
| 630 | > |  | 
| 631 | > | curSnapshot->setBondPotential(bondPotential); | 
| 632 | > | curSnapshot->setBendPotential(bendPotential); | 
| 633 | > | curSnapshot->setTorsionPotential(torsionPotential); | 
| 634 | > | curSnapshot->setInversionPotential(inversionPotential); | 
| 635 | > |  | 
| 636 | > | // RealType shortRangePotential = bondPotential + bendPotential + | 
| 637 | > | //   torsionPotential +  inversionPotential; | 
| 638 | > |  | 
| 639 | > | // curSnapshot->setShortRangePotential(shortRangePotential); | 
| 640 |  | } | 
| 641 |  |  | 
| 642 |  | void ForceManager::longRangeInteractions() { | 
| 685 |  | InteractionData idat; | 
| 686 |  | SelfData sdat; | 
| 687 |  | RealType mf; | 
| 645 | – | RealType lrPot; | 
| 688 |  | RealType vpair; | 
| 689 |  | RealType dVdFQ1(0.0); | 
| 690 |  | RealType dVdFQ2(0.0); | 
| 691 |  | potVec longRangePotential(0.0); | 
| 692 |  | potVec workPot(0.0); | 
| 693 | + | potVec exPot(0.0); | 
| 694 | + | Vector3d eField1(0.0); | 
| 695 | + | Vector3d eField2(0.0); | 
| 696 |  | vector<int>::iterator ia, jb; | 
| 697 |  |  | 
| 698 |  | int loopStart, loopEnd; | 
| 700 |  | idat.vdwMult = &vdwMult; | 
| 701 |  | idat.electroMult = &electroMult; | 
| 702 |  | idat.pot = &workPot; | 
| 703 | + | idat.excludedPot = &exPot; | 
| 704 |  | sdat.pot = fDecomp_->getEmbeddingPotential(); | 
| 705 | + | sdat.excludedPot = fDecomp_->getExcludedSelfPotential(); | 
| 706 |  | idat.vpair = &vpair; | 
| 707 |  | idat.dVdFQ1 = &dVdFQ1; | 
| 708 |  | idat.dVdFQ2 = &dVdFQ2; | 
| 709 | + | idat.eField1 = &eField1; | 
| 710 | + | idat.eField2 = &eField2; | 
| 711 |  | idat.f1 = &f1; | 
| 712 |  | idat.sw = &sw; | 
| 713 |  | idat.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false; | 
| 714 |  | idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE) ? true : false; | 
| 715 |  | idat.doParticlePot = doParticlePot_; | 
| 716 | + | idat.doElectricField = doElectricField_; | 
| 717 |  | sdat.doParticlePot = doParticlePot_; | 
| 718 |  |  | 
| 719 |  | loopEnd = PAIR_LOOP; | 
| 749 |  | if (iLoop == PAIR_LOOP) { | 
| 750 |  | vij = 0.0; | 
| 751 |  | fij = V3Zero; | 
| 752 | + | eField1 = V3Zero; | 
| 753 | + | eField2 = V3Zero; | 
| 754 |  | } | 
| 755 |  |  | 
| 756 |  | in_switching_region = switcher_->getSwitch(rgrpsq, sw, dswdr, | 
| 757 |  | rgrp); | 
| 758 | + |  | 
| 759 |  | atomListRow = fDecomp_->getAtomsInGroupRow(cg1); | 
| 760 |  | atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2); | 
| 761 |  |  | 
| 770 |  | jb != atomListColumn.end(); ++jb) { | 
| 771 |  | atom2 = (*jb); | 
| 772 |  |  | 
| 773 | < | if (!fDecomp_->skipAtomPair(atom1, atom2)) { | 
| 773 | > | if (!fDecomp_->skipAtomPair(atom1, atom2, cg1, cg2)) { | 
| 774 | > |  | 
| 775 |  | vpair = 0.0; | 
| 776 |  | workPot = 0.0; | 
| 777 | + | exPot = 0.0; | 
| 778 |  | f1 = V3Zero; | 
| 779 |  | dVdFQ1 = 0.0; | 
| 780 |  | dVdFQ2 = 0.0; | 
| 825 |  | fij += fg; | 
| 826 |  |  | 
| 827 |  | if (atomListRow.size() == 1 && atomListColumn.size() == 1) { | 
| 828 | < | stressTensor -= outProduct( *(idat.d), fg); | 
| 829 | < | if (doHeatFlux_) | 
| 830 | < | fDecomp_->addToHeatFlux(*(idat.d) * dot(fg, vel2)); | 
| 831 | < |  | 
| 828 | > | if (!fDecomp_->skipAtomPair(atomListRow[0], | 
| 829 | > | atomListColumn[0], | 
| 830 | > | cg1, cg2)) { | 
| 831 | > | stressTensor -= outProduct( *(idat.d), fg); | 
| 832 | > | if (doHeatFlux_) | 
| 833 | > | fDecomp_->addToHeatFlux(*(idat.d) * dot(fg, vel2)); | 
| 834 | > | } | 
| 835 |  | } | 
| 836 |  |  | 
| 837 |  | for (ia = atomListRow.begin(); | 
| 888 |  |  | 
| 889 |  | fDecomp_->collectIntermediateData(); | 
| 890 |  |  | 
| 891 | < | for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) { | 
| 891 | > | for (unsigned int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) { | 
| 892 |  | fDecomp_->fillSelfData(sdat, atom1); | 
| 893 |  | interactionMan_->doPreForce(sdat); | 
| 894 |  | } | 
| 899 |  | } | 
| 900 |  | } | 
| 901 |  |  | 
| 902 | + | // collects pairwise information | 
| 903 |  | fDecomp_->collectData(); | 
| 904 |  |  | 
| 905 |  | if (info_->requiresSelfCorrection()) { | 
| 906 | < |  | 
| 848 | < | for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) { | 
| 906 | > | for (unsigned int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) { | 
| 907 |  | fDecomp_->fillSelfData(sdat, atom1); | 
| 908 |  | interactionMan_->doSelfCorrection(sdat); | 
| 909 |  | } | 
| 852 | – |  | 
| 910 |  | } | 
| 911 |  |  | 
| 912 | + | // collects single-atom information | 
| 913 | + | fDecomp_->collectSelfData(); | 
| 914 | + |  | 
| 915 |  | longRangePotential = *(fDecomp_->getEmbeddingPotential()) + | 
| 916 |  | *(fDecomp_->getPairwisePotential()); | 
| 917 |  |  | 
| 918 | < | lrPot = longRangePotential.sum(); | 
| 918 | > | curSnapshot->setLongRangePotential(longRangePotential); | 
| 919 | > |  | 
| 920 | > | curSnapshot->setExcludedPotentials(*(fDecomp_->getExcludedSelfPotential()) + | 
| 921 | > | *(fDecomp_->getExcludedPotential())); | 
| 922 |  |  | 
| 860 | – | //store the stressTensor and long range potential | 
| 861 | – | curSnapshot->statData[Stats::LONG_RANGE_POTENTIAL] = lrPot; | 
| 862 | – | curSnapshot->statData[Stats::VANDERWAALS_POTENTIAL] = longRangePotential[VANDERWAALS_FAMILY]; | 
| 863 | – | curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_FAMILY]; | 
| 923 |  | } | 
| 924 |  |  | 
| 925 |  |  | 
| 926 |  | void ForceManager::postCalculation() { | 
| 927 | + |  | 
| 928 | + | vector<Perturbation*>::iterator pi; | 
| 929 | + | for (pi = perturbations_.begin(); pi != perturbations_.end(); ++pi) { | 
| 930 | + | (*pi)->applyPerturbation(); | 
| 931 | + | } | 
| 932 | + |  | 
| 933 |  | SimInfo::MoleculeIterator mi; | 
| 934 |  | Molecule* mol; | 
| 935 |  | Molecule::RigidBodyIterator rbIter; | 
| 936 |  | RigidBody* rb; | 
| 937 |  | Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot(); | 
| 938 | < |  | 
| 938 | > |  | 
| 939 |  | // collect the atomic forces onto rigid bodies | 
| 940 |  |  | 
| 941 |  | for (mol = info_->beginMolecule(mi); mol != NULL; | 
| 948 |  | } | 
| 949 |  |  | 
| 950 |  | #ifdef IS_MPI | 
| 886 | – |  | 
| 951 |  | MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, stressTensor.getArrayPointer(), 9, | 
| 952 |  | MPI::REALTYPE, MPI::SUM); | 
| 953 |  | #endif | 
| 954 |  | curSnapshot->setStressTensor(stressTensor); | 
| 955 |  |  | 
| 956 | < | } | 
| 956 | > | if (info_->getSimParams()->getUseLongRangeCorrections()) { | 
| 957 | > | /* | 
| 958 | > | RealType vol = curSnapshot->getVolume(); | 
| 959 | > | RealType Elrc(0.0); | 
| 960 | > | RealType Wlrc(0.0); | 
| 961 |  |  | 
| 962 | < | } //end namespace OpenMD | 
| 962 | > | set<AtomType*>::iterator i; | 
| 963 | > | set<AtomType*>::iterator j; | 
| 964 | > |  | 
| 965 | > | RealType n_i, n_j; | 
| 966 | > | RealType rho_i, rho_j; | 
| 967 | > | pair<RealType, RealType> LRI; | 
| 968 | > |  | 
| 969 | > | for (i = atomTypes_.begin(); i != atomTypes_.end(); ++i) { | 
| 970 | > | n_i = RealType(info_->getGlobalCountOfType(*i)); | 
| 971 | > | rho_i = n_i /  vol; | 
| 972 | > | for (j = atomTypes_.begin(); j != atomTypes_.end(); ++j) { | 
| 973 | > | n_j = RealType(info_->getGlobalCountOfType(*j)); | 
| 974 | > | rho_j = n_j / vol; | 
| 975 | > |  | 
| 976 | > | LRI = interactionMan_->getLongRangeIntegrals( (*i), (*j) ); | 
| 977 | > |  | 
| 978 | > | Elrc += n_i   * rho_j * LRI.first; | 
| 979 | > | Wlrc -= rho_i * rho_j * LRI.second; | 
| 980 | > | } | 
| 981 | > | } | 
| 982 | > | Elrc *= 2.0 * NumericConstant::PI; | 
| 983 | > | Wlrc *= 2.0 * NumericConstant::PI; | 
| 984 | > |  | 
| 985 | > | RealType lrp = curSnapshot->getLongRangePotential(); | 
| 986 | > | curSnapshot->setLongRangePotential(lrp + Elrc); | 
| 987 | > | stressTensor += Wlrc * SquareMatrix3<RealType>::identity(); | 
| 988 | > | curSnapshot->setStressTensor(stressTensor); | 
| 989 | > | */ | 
| 990 | > |  | 
| 991 | > | } | 
| 992 | > | } | 
| 993 | > | } |