--- branches/development/src/brains/SimInfo.cpp 2010/12/17 20:11:05 1528 +++ branches/development/src/brains/SimInfo.cpp 2011/05/26 13:55:04 1569 @@ -54,24 +54,13 @@ #include "math/Vector3.hpp" #include "primitives/Molecule.hpp" #include "primitives/StuntDouble.hpp" -#include "UseTheForce/fCutoffPolicy.h" -#include "UseTheForce/DarkSide/fSwitchingFunctionType.h" -#include "UseTheForce/doForces_interface.h" -#include "UseTheForce/DarkSide/neighborLists_interface.h" -#include "UseTheForce/DarkSide/switcheroo_interface.h" #include "utils/MemoryUtils.hpp" #include "utils/simError.h" #include "selection/SelectionManager.hpp" #include "io/ForceFieldOptions.hpp" #include "UseTheForce/ForceField.hpp" -#include "nonbonded/InteractionManager.hpp" +#include "nonbonded/SwitchingFunction.hpp" - -#ifdef IS_MPI -#include "UseTheForce/mpiComponentPlan.h" -#include "UseTheForce/DarkSide/simParallel_interface.h" -#endif - using namespace std; namespace OpenMD { @@ -82,7 +71,7 @@ namespace OpenMD { nGlobalIntegrableObjects_(0), nGlobalRigidBodies_(0), nAtoms_(0), nBonds_(0), nBends_(0), nTorsions_(0), nInversions_(0), nRigidBodies_(0), nIntegrableObjects_(0), nCutoffGroups_(0), - nConstraints_(0), sman_(NULL), fortranInitialized_(false), + nConstraints_(0), sman_(NULL), topologyDone_(false), calcBoxDipole_(false), useAtomicVirial_(true) { MoleculeStamp* molStamp; @@ -136,7 +125,13 @@ namespace OpenMD { //equal to the total number of atoms minus number of atoms belong to //cutoff group defined in meta-data file plus the number of cutoff //groups defined in meta-data file + std::cerr << "nGA = " << nGlobalAtoms_ << "\n"; + std::cerr << "nCA = " << nCutoffAtoms << "\n"; + std::cerr << "nG = " << nGroups << "\n"; + nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups; + + std::cerr << "nGCG = " << nGlobalCutoffGroups_ << "\n"; //every free atom (atom does not belong to rigid bodies) is an //integrable object therefore the total number of integrable objects @@ -656,27 +651,28 @@ namespace OpenMD { molStampIds_.insert(molStampIds_.end(), nmol, curStampId); } - void SimInfo::update() { - setupSimType(); - setupCutoffRadius(); - setupSwitchingRadius(); - setupCutoffMethod(); - setupSkinThickness(); - setupSwitchingFunction(); - setupAccumulateBoxDipole(); - -#ifdef IS_MPI - setupFortranParallel(); -#endif - setupFortranSim(); - fortranInitialized_ = true; - + /** + * update + * + * Performs the global checks and variable settings after the + * objects have been created. + * + */ + void SimInfo::update() { + setupSimVariables(); calcNdf(); calcNdfRaw(); calcNdfTrans(); } + /** + * getSimulatedAtomTypes + * + * Returns an STL set of AtomType* that are actually present in this + * simulation. Must query all processors to assemble this information. + * + */ set SimInfo::getSimulatedAtomTypes() { SimInfo::MoleculeIterator mi; Molecule* mol; @@ -684,118 +680,75 @@ namespace OpenMD { Atom* atom; set atomTypes; - for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) { - + for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) { for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) { atomTypes.insert(atom->getAtomType()); - } - - } + } + } + +#ifdef IS_MPI + + // loop over the found atom types on this processor, and add their + // numerical idents to a vector: + + vector foundTypes; + set::iterator i; + for (i = atomTypes.begin(); i != atomTypes.end(); ++i) + foundTypes.push_back( (*i)->getIdent() ); + + // count_local holds the number of found types on this processor + int count_local = foundTypes.size(); + + // count holds the total number of found types on all processors + // (some will be redundant with the ones found locally): + int count; + MPI::COMM_WORLD.Allreduce(&count_local, &count, 1, MPI::INT, MPI::SUM); + + // create a vector to hold the globally found types, and resize it: + vector ftGlobal; + ftGlobal.resize(count); + vector counts; + + int nproc = MPI::COMM_WORLD.Get_size(); + counts.resize(nproc); + vector disps; + disps.resize(nproc); + + // now spray out the foundTypes to all the other processors: + MPI::COMM_WORLD.Allgatherv(&foundTypes[0], count_local, MPI::INT, + &ftGlobal[0], &counts[0], &disps[0], MPI::INT); + + // foundIdents is a stl set, so inserting an already found ident + // will have no effect. + set foundIdents; + vector::iterator j; + for (j = ftGlobal.begin(); j != ftGlobal.end(); ++j) + foundIdents.insert((*j)); + + // now iterate over the foundIdents and get the actual atom types + // that correspond to these: + set::iterator it; + for (it = foundIdents.begin(); it != foundIdents.end(); ++it) + atomTypes.insert( forceField_->getAtomType((*it)) ); + +#endif + return atomTypes; } - /** - * setupCutoffRadius - * - * If the cutoffRadius was explicitly set, use that value. - * If the cutoffRadius was not explicitly set: - * Are there electrostatic atoms? Use 12.0 Angstroms. - * No electrostatic atoms? Poll the atom types present in the - * simulation for suggested cutoff values (e.g. 2.5 * sigma). - * Use the maximum suggested value that was found. - */ - void SimInfo::setupCutoffRadius() { - - if (simParams_->haveCutoffRadius()) { - cutoffRadius_ = simParams_->getCutoffRadius(); - } else { - if (usesElectrostaticAtoms_) { - sprintf(painCave.errMsg, - "SimInfo Warning: No value was set for the cutoffRadius.\n" - "\tOpenMD will use a default value of 12.0 angstroms" - "\tfor the cutoffRadius.\n"); - painCave.isFatal = 0; - simError(); - cutoffRadius_ = 12.0; - } else { - RealType thisCut; - set::iterator i; - set atomTypes; - atomTypes = getSimulatedAtomTypes(); - for (i = atomTypes.begin(); i != atomTypes.end(); ++i) { - thisCut = InteractionManager::Instance()->getSuggestedCutoffRadius((*i)); - cutoffRadius_ = max(thisCut, cutoffRadius_); - } - sprintf(painCave.errMsg, - "SimInfo Warning: No value was set for the cutoffRadius.\n" - "\tOpenMD will use %lf angstroms.\n", - cutoffRadius_); - painCave.isFatal = 0; - simError(); - } - } - - InteractionManager::Instance()->setCutoffRadius(cutoffRadius_); - } - - /** - * setupSwitchingRadius - * - * If the switchingRadius was explicitly set, use that value (but check it) - * If the switchingRadius was not explicitly set: use 0.85 * cutoffRadius_ - */ - void SimInfo::setupSwitchingRadius() { - - if (simParams_->haveSwitchingRadius()) { - switchingRadius_ = simParams_->getSwitchingRadius(); - if (switchingRadius_ > cutoffRadius_) { - sprintf(painCave.errMsg, - "SimInfo Error: switchingRadius (%f) is larger than cutoffRadius(%f)\n", - switchingRadius_, cutoffRadius_); - painCave.isFatal = 1; - simError(); - + void SimInfo::setupSimVariables() { + useAtomicVirial_ = simParams_->getUseAtomicVirial(); + // we only call setAccumulateBoxDipole if the accumulateBoxDipole parameter is true + calcBoxDipole_ = false; + if ( simParams_->haveAccumulateBoxDipole() ) + if ( simParams_->getAccumulateBoxDipole() ) { + calcBoxDipole_ = true; } - } else { - switchingRadius_ = 0.85 * cutoffRadius_; - sprintf(painCave.errMsg, - "SimInfo Warning: No value was set for the switchingRadius.\n" - "\tOpenMD will use a default value of 85 percent of the cutoffRadius.\n" - "\tswitchingRadius = %f. for this simulation\n", switchingRadius_); - painCave.isFatal = 0; - simError(); - } - InteractionManager::Instance()->setSwitchingRadius(switchingRadius_); - } - /** - * setupSkinThickness - * - * If the skinThickness was explicitly set, use that value (but check it) - * If the skinThickness was not explicitly set: use 1.0 angstroms - */ - void SimInfo::setupSkinThickness() { - if (simParams_->haveSkinThickness()) { - skinThickness_ = simParams_->getSkinThickness(); - } else { - skinThickness_ = 1.0; - sprintf(painCave.errMsg, - "SimInfo Warning: No value was set for the skinThickness.\n" - "\tOpenMD will use a default value of %f Angstroms\n" - "\tfor this simulation\n", skinThickness_); - painCave.isFatal = 0; - simError(); - } - } - - void SimInfo::setupSimType() { set::iterator i; set atomTypes; - atomTypes = getSimulatedAtomTypes(); - - useAtomicVirial_ = simParams_->getUseAtomicVirial(); - + atomTypes = getSimulatedAtomTypes(); int usesElectrostatic = 0; int usesMetallic = 0; int usesDirectional = 0; @@ -817,34 +770,52 @@ namespace OpenMD { temp = usesElectrostatic; MPI_Allreduce(&temp, &usesElectrostaticAtoms_, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD); #endif - fInfo_.SIM_uses_PBC = usesPeriodicBoundaries_; - fInfo_.SIM_uses_DirectionalAtoms = usesDirectionalAtoms_; - fInfo_.SIM_uses_MetallicAtoms = usesMetallicAtoms_; - fInfo_.SIM_requires_SkipCorrection = usesElectrostaticAtoms_; - fInfo_.SIM_requires_SelfCorrection = usesElectrostaticAtoms_; - fInfo_.SIM_uses_AtomicVirial = usesAtomicVirial_; } - void SimInfo::setupFortranSim() { - int isError; - int nExclude, nOneTwo, nOneThree, nOneFour; - vector fortranGlobalGroupMembership; - - notifyFortranSkinThickness(&skinThickness_); - int ljsp = cutoffMethod_ == SHIFTED_POTENTIAL ? 1 : 0; - int ljsf = cutoffMethod_ == SHIFTED_FORCE ? 1 : 0; - notifyFortranCutoffs(&cutoffRadius_, &switchingRadius_, &ljsp, &ljsf); + vector SimInfo::getGlobalAtomIndices() { + SimInfo::MoleculeIterator mi; + Molecule* mol; + Molecule::AtomIterator ai; + Atom* atom; - isError = 0; + vector GlobalAtomIndices(getNAtoms(), 0); + + for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) { + + for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) { + GlobalAtomIndices[atom->getLocalIndex()] = atom->getGlobalIndex(); + } + } + return GlobalAtomIndices; + } - //globalGroupMembership_ is filled by SimCreator - for (int i = 0; i < nGlobalAtoms_; i++) { - fortranGlobalGroupMembership.push_back(globalGroupMembership_[i] + 1); + + vector SimInfo::getGlobalGroupIndices() { + SimInfo::MoleculeIterator mi; + Molecule* mol; + Molecule::CutoffGroupIterator ci; + CutoffGroup* cg; + + vector GlobalGroupIndices; + + for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) { + + //local index of cutoff group is trivial, it only depends on the + //order of travesing + for (cg = mol->beginCutoffGroup(ci); cg != NULL; + cg = mol->nextCutoffGroup(ci)) { + GlobalGroupIndices.push_back(cg->getGlobalIndex()); + } } + return GlobalGroupIndices; + } + + void SimInfo::prepareTopology() { + int nExclude, nOneTwo, nOneThree, nOneFour; + //calculate mass ratio of cutoff group - vector mfact; SimInfo::MoleculeIterator mi; Molecule* mol; Molecule::CutoffGroupIterator ci; @@ -853,43 +824,36 @@ namespace OpenMD { Atom* atom; RealType totalMass; - //to avoid memory reallocation, reserve enough space for mfact - mfact.reserve(getNCutoffGroups()); + //to avoid memory reallocation, reserve enough space for massFactors_ + massFactors_.clear(); + massFactors_.reserve(getNCutoffGroups()); for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) { - for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) { + for (cg = mol->beginCutoffGroup(ci); cg != NULL; + cg = mol->nextCutoffGroup(ci)) { totalMass = cg->getMass(); for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) { // Check for massless groups - set mfact to 1 if true if (totalMass != 0) - mfact.push_back(atom->getMass()/totalMass); + massFactors_.push_back(atom->getMass()/totalMass); else - mfact.push_back( 1.0 ); + massFactors_.push_back( 1.0 ); } } } - //fill ident array of local atoms (it is actually ident of AtomType, it is so confusing !!!) - vector identArray; + // Build the identArray_ - //to avoid memory reallocation, reserve enough space identArray - identArray.reserve(getNAtoms()); - + identArray_.clear(); + identArray_.reserve(getNAtoms()); for(mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) { for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) { - identArray.push_back(atom->getIdent()); + identArray_.push_back(atom->getIdent()); } } - - //fill molMembershipArray - //molMembershipArray is filled by SimCreator - vector molMembershipArray(nGlobalAtoms_); - for (int i = 0; i < nGlobalAtoms_; i++) { - molMembershipArray[i] = globalMolMembership_[i] + 1; - } - //setup fortran simulation + //scan topology nExclude = excludedInteractions_.getSize(); nOneTwo = oneTwoInteractions_.getSize(); @@ -901,132 +865,17 @@ namespace OpenMD { int* oneThreeList = oneThreeInteractions_.getPairList(); int* oneFourList = oneFourInteractions_.getPairList(); - setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray[0], - &nExclude, excludeList, - &nOneTwo, oneTwoList, - &nOneThree, oneThreeList, - &nOneFour, oneFourList, - &molMembershipArray[0], &mfact[0], &nCutoffGroups_, - &fortranGlobalGroupMembership[0], &isError); + //setFortranSim( &fInfo_, &nGlobalAtoms_, &nAtoms_, &identArray_[0], + // &nExclude, excludeList, + // &nOneTwo, oneTwoList, + // &nOneThree, oneThreeList, + // &nOneFour, oneFourList, + // &molMembershipArray[0], &mfact[0], &nCutoffGroups_, + // &fortranGlobalGroupMembership[0], &isError); - if( isError ){ - - sprintf( painCave.errMsg, - "There was an error setting the simulation information in fortran.\n" ); - painCave.isFatal = 1; - painCave.severity = OPENMD_ERROR; - simError(); - } - - - sprintf( checkPointMsg, - "succesfully sent the simulation information to fortran.\n"); - - errorCheckPoint(); - - // Setup number of neighbors in neighbor list if present - if (simParams_->haveNeighborListNeighbors()) { - int nlistNeighbors = simParams_->getNeighborListNeighbors(); - setNeighbors(&nlistNeighbors); - } - - - } - - - void SimInfo::setupFortranParallel() { -#ifdef IS_MPI - //SimInfo is responsible for creating localToGlobalAtomIndex and localToGlobalGroupIndex - vector localToGlobalAtomIndex(getNAtoms(), 0); - vector localToGlobalCutoffGroupIndex; - SimInfo::MoleculeIterator mi; - Molecule::AtomIterator ai; - Molecule::CutoffGroupIterator ci; - Molecule* mol; - Atom* atom; - CutoffGroup* cg; - mpiSimData parallelData; - int isError; - - for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) { - - //local index(index in DataStorge) of atom is important - for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) { - localToGlobalAtomIndex[atom->getLocalIndex()] = atom->getGlobalIndex() + 1; - } - - //local index of cutoff group is trivial, it only depends on the order of travesing - for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) { - localToGlobalCutoffGroupIndex.push_back(cg->getGlobalIndex() + 1); - } - - } - - //fill up mpiSimData struct - parallelData.nMolGlobal = getNGlobalMolecules(); - parallelData.nMolLocal = getNMolecules(); - parallelData.nAtomsGlobal = getNGlobalAtoms(); - parallelData.nAtomsLocal = getNAtoms(); - parallelData.nGroupsGlobal = getNGlobalCutoffGroups(); - parallelData.nGroupsLocal = getNCutoffGroups(); - parallelData.myNode = worldRank; - MPI_Comm_size(MPI_COMM_WORLD, &(parallelData.nProcessors)); - - //pass mpiSimData struct and index arrays to fortran - setFsimParallel(¶llelData, &(parallelData.nAtomsLocal), - &localToGlobalAtomIndex[0], &(parallelData.nGroupsLocal), - &localToGlobalCutoffGroupIndex[0], &isError); - - if (isError) { - sprintf(painCave.errMsg, - "mpiRefresh errror: fortran didn't like something we gave it.\n"); - painCave.isFatal = 1; - simError(); - } - - sprintf(checkPointMsg, " mpiRefresh successful.\n"); - errorCheckPoint(); - -#endif - } - - - void SimInfo::setupSwitchingFunction() { - int ft = CUBIC; - - if (simParams_->haveSwitchingFunctionType()) { - string funcType = simParams_->getSwitchingFunctionType(); - toUpper(funcType); - if (funcType == "CUBIC") { - ft = CUBIC; - } else { - if (funcType == "FIFTH_ORDER_POLYNOMIAL") { - ft = FIFTH_ORDER_POLY; - } else { - // throw error - sprintf( painCave.errMsg, - "SimInfo error: Unknown switchingFunctionType. (Input file specified %s .)\n\tswitchingFunctionType must be one of: \"cubic\" or \"fifth_order_polynomial\".", funcType.c_str() ); - painCave.isFatal = 1; - simError(); - } - } - } - - // send switching function notification to switcheroo - setFunctionType(&ft); - + topologyDone_ = true; } - void SimInfo::setupAccumulateBoxDipole() { - - // we only call setAccumulateBoxDipole if the accumulateBoxDipole parameter is true - if ( simParams_->haveAccumulateBoxDipole() ) - if ( simParams_->getAccumulateBoxDipole() ) { - calcBoxDipole_ = true; - } - - } - void SimInfo::addProperty(GenericData* genData) { properties_.addProperty(genData); } @@ -1061,9 +910,11 @@ namespace OpenMD { Molecule* mol; RigidBody* rb; Atom* atom; + CutoffGroup* cg; SimInfo::MoleculeIterator mi; Molecule::RigidBodyIterator rbIter; - Molecule::AtomIterator atomIter;; + Molecule::AtomIterator atomIter; + Molecule::CutoffGroupIterator cgIter; for (mol = beginMolecule(mi); mol != NULL; mol = nextMolecule(mi)) { @@ -1074,6 +925,10 @@ namespace OpenMD { for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) { rb->setSnapshotManager(sman_); } + + for (cg = mol->beginCutoffGroup(cgIter); cg != NULL; cg = mol->nextCutoffGroup(cgIter)) { + cg->setSnapshotManager(sman_); + } } }