| 54 |  | #include "math/Vector3.hpp" | 
| 55 |  | #include "primitives/Molecule.hpp" | 
| 56 |  | #include "primitives/StuntDouble.hpp" | 
| 57 | – | #include "UseTheForce/doForces_interface.h" | 
| 57 |  | #include "UseTheForce/DarkSide/neighborLists_interface.h" | 
| 58 |  | #include "utils/MemoryUtils.hpp" | 
| 59 |  | #include "utils/simError.h" | 
| 655 |  | /** | 
| 656 |  | * update | 
| 657 |  | * | 
| 658 | < | *  Performs the global checks and variable settings after the objects have been | 
| 659 | < | *  created. | 
| 658 | > | *  Performs the global checks and variable settings after the | 
| 659 | > | *  objects have been created. | 
| 660 |  | * | 
| 661 |  | */ | 
| 662 | < | void SimInfo::update() { | 
| 664 | < |  | 
| 662 | > | void SimInfo::update() { | 
| 663 |  | setupSimVariables(); | 
| 666 | – | setupCutoffs(); | 
| 667 | – | setupSwitching(); | 
| 668 | – | setupElectrostatics(); | 
| 669 | – | setupNeighborlists(); | 
| 670 | – |  | 
| 671 | – | #ifdef IS_MPI | 
| 672 | – | setupFortranParallel(); | 
| 673 | – | #endif | 
| 674 | – | setupFortranSim(); | 
| 675 | – | fortranInitialized_ = true; | 
| 676 | – |  | 
| 664 |  | calcNdf(); | 
| 665 |  | calcNdfRaw(); | 
| 666 |  | calcNdfTrans(); | 
| 667 |  | } | 
| 668 |  |  | 
| 669 | + | /** | 
| 670 | + | * getSimulatedAtomTypes | 
| 671 | + | * | 
| 672 | + | * Returns an STL set of AtomType* that are actually present in this | 
| 673 | + | * simulation.  Must query all processors to assemble this information. | 
| 674 | + | * | 
| 675 | + | */ | 
| 676 |  | set<AtomType*> SimInfo::getSimulatedAtomTypes() { | 
| 677 |  | SimInfo::MoleculeIterator mi; | 
| 678 |  | Molecule* mol; | 
| 685 |  | atomTypes.insert(atom->getAtomType()); | 
| 686 |  | } | 
| 687 |  | } | 
| 694 | – | return atomTypes; | 
| 695 | – | } | 
| 688 |  |  | 
| 689 | < | /** | 
| 698 | < | * setupCutoffs | 
| 699 | < | * | 
| 700 | < | * Sets the values of cutoffRadius and cutoffMethod | 
| 701 | < | * | 
| 702 | < | * cutoffRadius : realType | 
| 703 | < | *  If the cutoffRadius was explicitly set, use that value. | 
| 704 | < | *  If the cutoffRadius was not explicitly set: | 
| 705 | < | *      Are there electrostatic atoms?  Use 12.0 Angstroms. | 
| 706 | < | *      No electrostatic atoms?  Poll the atom types present in the | 
| 707 | < | *      simulation for suggested cutoff values (e.g. 2.5 * sigma). | 
| 708 | < | *      Use the maximum suggested value that was found. | 
| 709 | < | * | 
| 710 | < | * cutoffMethod : (one of HARD, SWITCHED, SHIFTED_FORCE, SHIFTED_POTENTIAL) | 
| 711 | < | *      If cutoffMethod was explicitly set, use that choice. | 
| 712 | < | *      If cutoffMethod was not explicitly set, use SHIFTED_FORCE | 
| 713 | < | */ | 
| 714 | < | void SimInfo::setupCutoffs() { | 
| 715 | < |  | 
| 716 | < | if (simParams_->haveCutoffRadius()) { | 
| 717 | < | cutoffRadius_ = simParams_->getCutoffRadius(); | 
| 718 | < | } else { | 
| 719 | < | if (usesElectrostaticAtoms_) { | 
| 720 | < | sprintf(painCave.errMsg, | 
| 721 | < | "SimInfo: No value was set for the cutoffRadius.\n" | 
| 722 | < | "\tOpenMD will use a default value of 12.0 angstroms" | 
| 723 | < | "\tfor the cutoffRadius.\n"); | 
| 724 | < | painCave.isFatal = 0; | 
| 725 | < | painCave.severity = OPENMD_INFO; | 
| 726 | < | simError(); | 
| 727 | < | cutoffRadius_ = 12.0; | 
| 728 | < | } else { | 
| 729 | < | RealType thisCut; | 
| 730 | < | set<AtomType*>::iterator i; | 
| 731 | < | set<AtomType*> atomTypes; | 
| 732 | < | atomTypes = getSimulatedAtomTypes(); | 
| 733 | < | for (i = atomTypes.begin(); i != atomTypes.end(); ++i) { | 
| 734 | < | thisCut = InteractionManager::Instance()->getSuggestedCutoffRadius((*i)); | 
| 735 | < | cutoffRadius_ = max(thisCut, cutoffRadius_); | 
| 736 | < | } | 
| 737 | < | sprintf(painCave.errMsg, | 
| 738 | < | "SimInfo: No value was set for the cutoffRadius.\n" | 
| 739 | < | "\tOpenMD will use %lf angstroms.\n", | 
| 740 | < | cutoffRadius_); | 
| 741 | < | painCave.isFatal = 0; | 
| 742 | < | painCave.severity = OPENMD_INFO; | 
| 743 | < | simError(); | 
| 744 | < | } | 
| 745 | < | } | 
| 689 | > | #ifdef IS_MPI | 
| 690 |  |  | 
| 691 | < | map<string, CutoffMethod> stringToCutoffMethod; | 
| 692 | < | stringToCutoffMethod["HARD"] = HARD; | 
| 693 | < | stringToCutoffMethod["SWITCHING_FUNCTION"] = SWITCHING_FUNCTION; | 
| 694 | < | stringToCutoffMethod["SHIFTED_POTENTIAL"] = SHIFTED_POTENTIAL; | 
| 695 | < | stringToCutoffMethod["SHIFTED_FORCE"] = SHIFTED_FORCE; | 
| 696 | < |  | 
| 697 | < | if (simParams_->haveCutoffMethod()) { | 
| 698 | < | string cutMeth = toUpperCopy(simParams_->getCutoffMethod()); | 
| 699 | < | map<string, CutoffMethod>::iterator i; | 
| 700 | < | i = stringToCutoffMethod.find(cutMeth); | 
| 701 | < | if (i == stringToCutoffMethod.end()) { | 
| 702 | < | sprintf(painCave.errMsg, | 
| 703 | < | "SimInfo: Could not find chosen cutoffMethod %s\n" | 
| 704 | < | "\tShould be one of: " | 
| 705 | < | "HARD, SWITCHING_FUNCTION, SHIFTED_POTENTIAL, or SHIFTED_FORCE\n", | 
| 706 | < | cutMeth.c_str()); | 
| 707 | < | painCave.isFatal = 1; | 
| 708 | < | painCave.severity = OPENMD_ERROR; | 
| 709 | < | simError(); | 
| 710 | < | } else { | 
| 711 | < | cutoffMethod_ = i->second; | 
| 712 | < | } | 
| 713 | < | } else { | 
| 714 | < | sprintf(painCave.errMsg, | 
| 715 | < | "SimInfo: No value was set for the cutoffMethod.\n" | 
| 716 | < | "\tOpenMD will use SHIFTED_FORCE.\n"); | 
| 717 | < | painCave.isFatal = 0; | 
| 774 | < | painCave.severity = OPENMD_INFO; | 
| 775 | < | simError(); | 
| 776 | < | cutoffMethod_ = SHIFTED_FORCE; | 
| 777 | < | } | 
| 778 | < | } | 
| 779 | < |  | 
| 780 | < | /** | 
| 781 | < | * setupSwitching | 
| 782 | < | * | 
| 783 | < | * Sets the values of switchingRadius and | 
| 784 | < | *  If the switchingRadius was explicitly set, use that value (but check it) | 
| 785 | < | *  If the switchingRadius was not explicitly set: use 0.85 * cutoffRadius_ | 
| 786 | < | */ | 
| 787 | < | void SimInfo::setupSwitching() { | 
| 691 | > | // loop over the found atom types on this processor, and add their | 
| 692 | > | // numerical idents to a vector: | 
| 693 | > |  | 
| 694 | > | vector<int> foundTypes; | 
| 695 | > | set<AtomType*>::iterator i; | 
| 696 | > | for (i = atomTypes.begin(); i != atomTypes.end(); ++i) | 
| 697 | > | foundTypes.push_back( (*i)->getIdent() ); | 
| 698 | > |  | 
| 699 | > | // count_local holds the number of found types on this processor | 
| 700 | > | int count_local = foundTypes.size(); | 
| 701 | > |  | 
| 702 | > | // count holds the total number of found types on all processors | 
| 703 | > | // (some will be redundant with the ones found locally): | 
| 704 | > | int count; | 
| 705 | > | MPI::COMM_WORLD.Allreduce(&count_local, &count, 1, MPI::INT, MPI::SUM); | 
| 706 | > |  | 
| 707 | > | // create a vector to hold the globally found types, and resize it: | 
| 708 | > | vector<int> ftGlobal; | 
| 709 | > | ftGlobal.resize(count); | 
| 710 | > | vector<int> counts; | 
| 711 | > |  | 
| 712 | > | int nproc = MPI::COMM_WORLD.Get_size(); | 
| 713 | > | counts.resize(nproc); | 
| 714 | > | vector<int> disps; | 
| 715 | > | disps.resize(nproc); | 
| 716 | > |  | 
| 717 | > | // now spray out the foundTypes to all the other processors: | 
| 718 |  |  | 
| 719 | < | if (simParams_->haveSwitchingRadius()) { | 
| 720 | < | switchingRadius_ = simParams_->getSwitchingRadius(); | 
| 791 | < | if (switchingRadius_ > cutoffRadius_) { | 
| 792 | < | sprintf(painCave.errMsg, | 
| 793 | < | "SimInfo: switchingRadius (%f) is larger than cutoffRadius(%f)\n", | 
| 794 | < | switchingRadius_, cutoffRadius_); | 
| 795 | < | painCave.isFatal = 1; | 
| 796 | < | painCave.severity = OPENMD_ERROR; | 
| 797 | < | simError(); | 
| 798 | < | } | 
| 799 | < | } else { | 
| 800 | < | switchingRadius_ = 0.85 * cutoffRadius_; | 
| 801 | < | sprintf(painCave.errMsg, | 
| 802 | < | "SimInfo: No value was set for the switchingRadius.\n" | 
| 803 | < | "\tOpenMD will use a default value of 85 percent of the cutoffRadius.\n" | 
| 804 | < | "\tswitchingRadius = %f. for this simulation\n", switchingRadius_); | 
| 805 | < | painCave.isFatal = 0; | 
| 806 | < | painCave.severity = OPENMD_WARNING; | 
| 807 | < | simError(); | 
| 808 | < | } | 
| 809 | < |  | 
| 810 | < | if (simParams_->haveSwitchingFunctionType()) { | 
| 811 | < | string funcType = simParams_->getSwitchingFunctionType(); | 
| 812 | < | toUpper(funcType); | 
| 813 | < | if (funcType == "CUBIC") { | 
| 814 | < | sft_ = cubic; | 
| 815 | < | } else { | 
| 816 | < | if (funcType == "FIFTH_ORDER_POLYNOMIAL") { | 
| 817 | < | sft_ = fifth_order_poly; | 
| 818 | < | } else { | 
| 819 | < | // throw error | 
| 820 | < | sprintf( painCave.errMsg, | 
| 821 | < | "SimInfo : Unknown switchingFunctionType. (Input file specified %s .)\n" | 
| 822 | < | "\tswitchingFunctionType must be one of: " | 
| 823 | < | "\"cubic\" or \"fifth_order_polynomial\".", | 
| 824 | < | funcType.c_str() ); | 
| 825 | < | painCave.isFatal = 1; | 
| 826 | < | painCave.severity = OPENMD_ERROR; | 
| 827 | < | simError(); | 
| 828 | < | } | 
| 829 | < | } | 
| 830 | < | } | 
| 831 | < | } | 
| 719 | > | MPI::COMM_WORLD.Allgatherv(&foundTypes[0], count_local, MPI::INT, | 
| 720 | > | &ftGlobal[0], &counts[0], &disps[0], MPI::INT); | 
| 721 |  |  | 
| 722 | < | /** | 
| 723 | < | * setupNeighborlists | 
| 724 | < | * | 
| 725 | < | *  If the skinThickness was explicitly set, use that value (but check it) | 
| 726 | < | *  If the skinThickness was not explicitly set: use 1.0 angstroms | 
| 727 | < | */ | 
| 728 | < | void SimInfo::setupNeighborlists() { | 
| 729 | < | if (simParams_->haveSkinThickness()) { | 
| 730 | < | skinThickness_ = simParams_->getSkinThickness(); | 
| 731 | < | } else { | 
| 732 | < | skinThickness_ = 1.0; | 
| 733 | < | sprintf(painCave.errMsg, | 
| 734 | < | "SimInfo: No value was set for the skinThickness.\n" | 
| 735 | < | "\tOpenMD will use a default value of %f Angstroms\n" | 
| 736 | < | "\tfor this simulation\n", skinThickness_); | 
| 737 | < | painCave.severity = OPENMD_INFO; | 
| 849 | < | painCave.isFatal = 0; | 
| 850 | < | simError(); | 
| 851 | < | } | 
| 722 | > | // foundIdents is a stl set, so inserting an already found ident | 
| 723 | > | // will have no effect. | 
| 724 | > | set<int> foundIdents; | 
| 725 | > | vector<int>::iterator j; | 
| 726 | > | for (j = ftGlobal.begin(); j != ftGlobal.end(); ++j) | 
| 727 | > | foundIdents.insert((*j)); | 
| 728 | > |  | 
| 729 | > | // now iterate over the foundIdents and get the actual atom types | 
| 730 | > | // that correspond to these: | 
| 731 | > | set<int>::iterator it; | 
| 732 | > | for (it = foundIdents.begin(); it != foundIdents.end(); ++it) | 
| 733 | > | atomTypes.insert( forceField_->getAtomType((*it)) ); | 
| 734 | > |  | 
| 735 | > | #endif | 
| 736 | > |  | 
| 737 | > | return atomTypes; | 
| 738 |  | } | 
| 739 |  |  | 
| 740 |  | void SimInfo::setupSimVariables() { | 
| 778 |  | fInfo_.SIM_uses_AtomicVirial = usesAtomicVirial_; | 
| 779 |  | } | 
| 780 |  |  | 
| 781 | < | void SimInfo::setupFortranSim() { | 
| 781 | > | void SimInfo::setupFortran() { | 
| 782 |  | int isError; | 
| 783 |  | int nExclude, nOneTwo, nOneThree, nOneFour; | 
| 784 |  | vector<int> fortranGlobalGroupMembership; | 
| 785 |  |  | 
| 900 | – | notifyFortranSkinThickness(&skinThickness_); | 
| 901 | – |  | 
| 902 | – | int ljsp = cutoffMethod_ == SHIFTED_POTENTIAL ? 1 : 0; | 
| 903 | – | int ljsf = cutoffMethod_ == SHIFTED_FORCE ? 1 : 0; | 
| 904 | – | notifyFortranCutoffs(&cutoffRadius_, &switchingRadius_, &ljsp, &ljsf); | 
| 905 | – |  | 
| 786 |  | isError = 0; | 
| 787 |  |  | 
| 788 |  | //globalGroupMembership_ is filled by SimCreator | 
| 817 |  | } | 
| 818 |  | } | 
| 819 |  |  | 
| 820 | < | //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!) | 
| 820 | > | //fill ident array of local atoms (it is actually ident of | 
| 821 | > | //AtomType, it is so confusing !!!) | 
| 822 |  | vector<int> identArray; | 
| 823 |  |  | 
| 824 |  | //to avoid memory reallocation, reserve enough space identArray | 
| 878 |  | setNeighbors(&nlistNeighbors); | 
| 879 |  | } | 
| 880 |  |  | 
| 1000 | – |  | 
| 1001 | – | } | 
| 1002 | – |  | 
| 1003 | – |  | 
| 1004 | – | void SimInfo::setupFortranParallel() { | 
| 881 |  | #ifdef IS_MPI | 
| 882 | < | //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex | 
| 882 | > | //SimInfo is responsible for creating localToGlobalAtomIndex and | 
| 883 | > | //localToGlobalGroupIndex | 
| 884 |  | vector<int> localToGlobalAtomIndex(getNAtoms(), 0); | 
| 885 |  | vector<int> localToGlobalCutoffGroupIndex; | 
| 1009 | – | SimInfo::MoleculeIterator mi; | 
| 1010 | – | Molecule::AtomIterator ai; | 
| 1011 | – | Molecule::CutoffGroupIterator ci; | 
| 1012 | – | Molecule* mol; | 
| 1013 | – | Atom* atom; | 
| 1014 | – | CutoffGroup* cg; | 
| 886 |  | mpiSimData parallelData; | 
| 1016 | – | int isError; | 
| 887 |  |  | 
| 888 |  | for (mol = beginMolecule(mi); mol != NULL; mol  = nextMolecule(mi)) { | 
| 889 |  |  | 
| 923 |  |  | 
| 924 |  | sprintf(checkPointMsg, " mpiRefresh successful.\n"); | 
| 925 |  | errorCheckPoint(); | 
| 1056 | – |  | 
| 926 |  | #endif | 
| 927 | < | } | 
| 1059 | < |  | 
| 1060 | < |  | 
| 1061 | < | void SimInfo::setupAccumulateBoxDipole() { | 
| 1062 | < |  | 
| 1063 | < |  | 
| 927 | > | fortranInitialized_ = true; | 
| 928 |  | } | 
| 929 |  |  | 
| 930 |  | void SimInfo::addProperty(GenericData* genData) { |