--- trunk/src/brains/SimInfo.cpp 2005/09/07 20:46:46 586 +++ trunk/src/brains/SimInfo.cpp 2007/02/26 04:45:42 1121 @@ -48,64 +48,81 @@ #include #include +#include #include "brains/SimInfo.hpp" #include "math/Vector3.hpp" #include "primitives/Molecule.hpp" +#include "primitives/StuntDouble.hpp" #include "UseTheForce/fCutoffPolicy.h" +#include "UseTheForce/DarkSide/fElectrostaticSummationMethod.h" +#include "UseTheForce/DarkSide/fElectrostaticScreeningMethod.h" +#include "UseTheForce/DarkSide/fSwitchingFunctionType.h" #include "UseTheForce/doForces_interface.h" -#include "UseTheForce/notifyCutoffs_interface.h" +#include "UseTheForce/DarkSide/neighborLists_interface.h" +#include "UseTheForce/DarkSide/electrostatic_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" + #ifdef IS_MPI #include "UseTheForce/mpiComponentPlan.h" #include "UseTheForce/DarkSide/simParallel_interface.h" #endif namespace oopse { + std::set getRigidSet(int index, std::map >& container) { + std::map >::iterator i = container.find(index); + std::set result; + if (i != container.end()) { + result = i->second; + } - SimInfo::SimInfo(MakeStamps* stamps, std::vector >& molStampPairs, - ForceField* ff, Globals* simParams) : - stamps_(stamps), forceField_(ff), simParams_(simParams), - ndf_(0), ndfRaw_(0), ndfTrans_(0), nZconstraint_(0), + return result; + } + + SimInfo::SimInfo(ForceField* ff, Globals* simParams) : + forceField_(ff), simParams_(simParams), + ndf_(0), fdf_local(0), ndfRaw_(0), ndfTrans_(0), nZconstraint_(0), nGlobalMols_(0), nGlobalAtoms_(0), nGlobalCutoffGroups_(0), nGlobalIntegrableObjects_(0), nGlobalRigidBodies_(0), nAtoms_(0), nBonds_(0), nBends_(0), nTorsions_(0), nRigidBodies_(0), nIntegrableObjects_(0), nCutoffGroups_(0), nConstraints_(0), - sman_(NULL), fortranInitialized_(false) { + sman_(NULL), fortranInitialized_(false), calcBoxDipole_(false) { - - std::vector >::iterator i; MoleculeStamp* molStamp; int nMolWithSameStamp; int nCutoffAtoms = 0; // number of atoms belong to cutoff groups - int nGroups = 0; //total cutoff groups defined in meta-data file + int nGroups = 0; //total cutoff groups defined in meta-data file CutoffGroupStamp* cgStamp; RigidBodyStamp* rbStamp; int nRigidAtoms = 0; - - for (i = molStampPairs.begin(); i !=molStampPairs.end(); ++i) { - molStamp = i->first; - nMolWithSameStamp = i->second; + std::vector components = simParams->getComponents(); + + for (std::vector::iterator i = components.begin(); i !=components.end(); ++i) { + molStamp = (*i)->getMoleculeStamp(); + nMolWithSameStamp = (*i)->getNMol(); addMoleculeStamp(molStamp, nMolWithSameStamp); //calculate atoms in molecules nGlobalAtoms_ += molStamp->getNAtoms() *nMolWithSameStamp; - //calculate atoms in cutoff groups int nAtomsInGroups = 0; int nCutoffGroupsInStamp = molStamp->getNCutoffGroups(); for (int j=0; j < nCutoffGroupsInStamp; j++) { - cgStamp = molStamp->getCutoffGroup(j); + cgStamp = molStamp->getCutoffGroupStamp(j); nAtomsInGroups += cgStamp->getNMembers(); } nGroups += nCutoffGroupsInStamp * nMolWithSameStamp; + nCutoffAtoms += nAtomsInGroups * nMolWithSameStamp; //calculate atoms in rigid bodies @@ -113,7 +130,7 @@ namespace oopse { int nRigidBodiesInStamp = molStamp->getNRigidBodies(); for (int j=0; j < nRigidBodiesInStamp; j++) { - rbStamp = molStamp->getRigidBody(j); + rbStamp = molStamp->getRigidBodyStamp(j); nAtomsInRigidBodies += rbStamp->getNMembers(); } @@ -122,18 +139,21 @@ namespace oopse { } - //every free atom (atom does not belong to cutoff groups) is a cutoff group - //therefore the total number of cutoff groups in the system is 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 + //every free atom (atom does not belong to cutoff groups) is a cutoff + //group therefore the total number of cutoff groups in the system is + //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 nGlobalCutoffGroups_ = nGlobalAtoms_ - nCutoffAtoms + nGroups; - //every free atom (atom does not belong to rigid bodies) is an integrable object - //therefore the total number of integrable objects in the system is equal to - //the total number of atoms minus number of atoms belong to rigid body defined in meta-data - //file plus the number of rigid bodies defined in meta-data file - nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms + nGlobalRigidBodies_; - + //every free atom (atom does not belong to rigid bodies) is an + //integrable object therefore the total number of integrable objects + //in the system is equal to the total number of atoms minus number of + //atoms belong to rigid body defined in meta-data file plus the number + //of rigid bodies defined in meta-data file + nGlobalIntegrableObjects_ = nGlobalAtoms_ - nRigidAtoms + + nGlobalRigidBodies_; + nGlobalMols_ = molStampIds_.size(); #ifdef IS_MPI @@ -149,7 +169,6 @@ namespace oopse { } molecules_.clear(); - delete stamps_; delete sman_; delete simParams_; delete forceField_; @@ -256,8 +275,8 @@ namespace oopse { } } - }//end for (integrableObject) - }// end for (mol) + } + } // n_constraints is local, so subtract them on each processor ndf_local -= nConstraints_; @@ -274,6 +293,15 @@ namespace oopse { } + int SimInfo::getFdf() { +#ifdef IS_MPI + MPI_Allreduce(&fdf_local,&fdf_,1,MPI_INT,MPI_SUM, MPI_COMM_WORLD); +#else + fdf_ = fdf_local; +#endif + return fdf_; + } + void SimInfo::calcNdfRaw() { int ndfRaw_local; @@ -336,7 +364,36 @@ namespace oopse { int b; int c; int d; + + std::map > atomGroups; + + Molecule::RigidBodyIterator rbIter; + RigidBody* rb; + Molecule::IntegrableObjectIterator ii; + StuntDouble* integrableObject; + for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL; + integrableObject = mol->nextIntegrableObject(ii)) { + + if (integrableObject->isRigidBody()) { + rb = static_cast(integrableObject); + std::vector atoms = rb->getAtoms(); + std::set rigidAtoms; + for (int i = 0; i < atoms.size(); ++i) { + rigidAtoms.insert(atoms[i]->getGlobalIndex()); + } + for (int i = 0; i < atoms.size(); ++i) { + atomGroups.insert(std::map >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms)); + } + } else { + std::set oneAtomSet; + oneAtomSet.insert(integrableObject->getGlobalIndex()); + atomGroups.insert(std::map >::value_type(integrableObject->getGlobalIndex(), oneAtomSet)); + } + } + + + for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) { a = bond->getAtomA()->getGlobalIndex(); b = bond->getAtomB()->getGlobalIndex(); @@ -347,10 +404,17 @@ namespace oopse { a = bend->getAtomA()->getGlobalIndex(); b = bend->getAtomB()->getGlobalIndex(); c = bend->getAtomC()->getGlobalIndex(); + std::set rigidSetA = getRigidSet(a, atomGroups); + std::set rigidSetB = getRigidSet(b, atomGroups); + std::set rigidSetC = getRigidSet(c, atomGroups); - exclude_.addPair(a, b); - exclude_.addPair(a, c); - exclude_.addPair(b, c); + exclude_.addPairs(rigidSetA, rigidSetB); + exclude_.addPairs(rigidSetA, rigidSetC); + exclude_.addPairs(rigidSetB, rigidSetC); + + //exclude_.addPair(a, b); + //exclude_.addPair(a, c); + //exclude_.addPair(b, c); } for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) { @@ -358,17 +422,36 @@ namespace oopse { b = torsion->getAtomB()->getGlobalIndex(); c = torsion->getAtomC()->getGlobalIndex(); d = torsion->getAtomD()->getGlobalIndex(); + std::set rigidSetA = getRigidSet(a, atomGroups); + std::set rigidSetB = getRigidSet(b, atomGroups); + std::set rigidSetC = getRigidSet(c, atomGroups); + std::set rigidSetD = getRigidSet(d, atomGroups); + exclude_.addPairs(rigidSetA, rigidSetB); + exclude_.addPairs(rigidSetA, rigidSetC); + exclude_.addPairs(rigidSetA, rigidSetD); + exclude_.addPairs(rigidSetB, rigidSetC); + exclude_.addPairs(rigidSetB, rigidSetD); + exclude_.addPairs(rigidSetC, rigidSetD); + + /* + exclude_.addPairs(rigidSetA.begin(), rigidSetA.end(), rigidSetB.begin(), rigidSetB.end()); + exclude_.addPairs(rigidSetA.begin(), rigidSetA.end(), rigidSetC.begin(), rigidSetC.end()); + exclude_.addPairs(rigidSetA.begin(), rigidSetA.end(), rigidSetD.begin(), rigidSetD.end()); + exclude_.addPairs(rigidSetB.begin(), rigidSetB.end(), rigidSetC.begin(), rigidSetC.end()); + exclude_.addPairs(rigidSetB.begin(), rigidSetB.end(), rigidSetD.begin(), rigidSetD.end()); + exclude_.addPairs(rigidSetC.begin(), rigidSetC.end(), rigidSetD.begin(), rigidSetD.end()); + + exclude_.addPair(a, b); exclude_.addPair(a, c); exclude_.addPair(a, d); exclude_.addPair(b, c); exclude_.addPair(b, d); exclude_.addPair(c, d); + */ } - Molecule::RigidBodyIterator rbIter; - RigidBody* rb; for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) { std::vector atoms = rb->getAtoms(); for (int i = 0; i < atoms.size() -1 ; ++i) { @@ -393,7 +476,35 @@ namespace oopse { int b; int c; int d; + + std::map > atomGroups; + + Molecule::RigidBodyIterator rbIter; + RigidBody* rb; + Molecule::IntegrableObjectIterator ii; + StuntDouble* integrableObject; + for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL; + integrableObject = mol->nextIntegrableObject(ii)) { + + if (integrableObject->isRigidBody()) { + rb = static_cast(integrableObject); + std::vector atoms = rb->getAtoms(); + std::set rigidAtoms; + for (int i = 0; i < atoms.size(); ++i) { + rigidAtoms.insert(atoms[i]->getGlobalIndex()); + } + for (int i = 0; i < atoms.size(); ++i) { + atomGroups.insert(std::map >::value_type(atoms[i]->getGlobalIndex(), rigidAtoms)); + } + } else { + std::set oneAtomSet; + oneAtomSet.insert(integrableObject->getGlobalIndex()); + atomGroups.insert(std::map >::value_type(integrableObject->getGlobalIndex(), oneAtomSet)); + } + } + + for (bond= mol->beginBond(bondIter); bond != NULL; bond = mol->nextBond(bondIter)) { a = bond->getAtomA()->getGlobalIndex(); b = bond->getAtomB()->getGlobalIndex(); @@ -405,9 +516,17 @@ namespace oopse { b = bend->getAtomB()->getGlobalIndex(); c = bend->getAtomC()->getGlobalIndex(); - exclude_.removePair(a, b); - exclude_.removePair(a, c); - exclude_.removePair(b, c); + std::set rigidSetA = getRigidSet(a, atomGroups); + std::set rigidSetB = getRigidSet(b, atomGroups); + std::set rigidSetC = getRigidSet(c, atomGroups); + + exclude_.removePairs(rigidSetA, rigidSetB); + exclude_.removePairs(rigidSetA, rigidSetC); + exclude_.removePairs(rigidSetB, rigidSetC); + + //exclude_.removePair(a, b); + //exclude_.removePair(a, c); + //exclude_.removePair(b, c); } for (torsion= mol->beginTorsion(torsionIter); torsion != NULL; torsion = mol->nextTorsion(torsionIter)) { @@ -416,16 +535,36 @@ namespace oopse { c = torsion->getAtomC()->getGlobalIndex(); d = torsion->getAtomD()->getGlobalIndex(); + std::set rigidSetA = getRigidSet(a, atomGroups); + std::set rigidSetB = getRigidSet(b, atomGroups); + std::set rigidSetC = getRigidSet(c, atomGroups); + std::set rigidSetD = getRigidSet(d, atomGroups); + + exclude_.removePairs(rigidSetA, rigidSetB); + exclude_.removePairs(rigidSetA, rigidSetC); + exclude_.removePairs(rigidSetA, rigidSetD); + exclude_.removePairs(rigidSetB, rigidSetC); + exclude_.removePairs(rigidSetB, rigidSetD); + exclude_.removePairs(rigidSetC, rigidSetD); + + /* + exclude_.removePairs(rigidSetA.begin(), rigidSetA.end(), rigidSetB.begin(), rigidSetB.end()); + exclude_.removePairs(rigidSetA.begin(), rigidSetA.end(), rigidSetC.begin(), rigidSetC.end()); + exclude_.removePairs(rigidSetA.begin(), rigidSetA.end(), rigidSetD.begin(), rigidSetD.end()); + exclude_.removePairs(rigidSetB.begin(), rigidSetB.end(), rigidSetC.begin(), rigidSetC.end()); + exclude_.removePairs(rigidSetB.begin(), rigidSetB.end(), rigidSetD.begin(), rigidSetD.end()); + exclude_.removePairs(rigidSetC.begin(), rigidSetC.end(), rigidSetD.begin(), rigidSetD.end()); + + exclude_.removePair(a, b); exclude_.removePair(a, c); exclude_.removePair(a, d); exclude_.removePair(b, c); exclude_.removePair(b, d); exclude_.removePair(c, d); + */ } - Molecule::RigidBodyIterator rbIter; - RigidBody* rb; for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) { std::vector atoms = rb->getAtoms(); for (int i = 0; i < atoms.size() -1 ; ++i) { @@ -463,17 +602,19 @@ namespace oopse { //setup fortran force field /** @deprecate */ int isError = 0; - initFortranFF( &fInfo_.SIM_uses_RF, &fInfo_.SIM_uses_UW, - &fInfo_.SIM_uses_DW, &isError ); + + setupCutoff(); + + setupElectrostaticSummationMethod( isError ); + setupSwitchingFunction(); + setupAccumulateBoxDipole(); + if(isError){ sprintf( painCave.errMsg, "ForceField error: There was an error initializing the forceField in fortran.\n" ); painCave.isFatal = 1; simError(); } - - - setupCutoff(); calcNdf(); calcNdfRaw(); @@ -508,6 +649,7 @@ namespace oopse { int useLennardJones = 0; int useElectrostatic = 0; int useEAM = 0; + int useSC = 0; int useCharge = 0; int useDirectional = 0; int useDipole = 0; @@ -519,16 +661,41 @@ namespace oopse { int useDirectionalAtom = 0; int useElectrostatics = 0; //usePBC and useRF are from simParams - int usePBC = simParams_->getPBC(); - int useRF = simParams_->getUseRF(); - int useUW = simParams_->getUseUndampedWolf(); - int useDW = simParams_->getUseDampedWolf(); + int usePBC = simParams_->getUsePeriodicBoundaryConditions(); + int useRF; + int useSF; + int useSP; + int useBoxDipole; + std::string myMethod; + // set the useRF logical + useRF = 0; + useSF = 0; + useSP = 0; + + + if (simParams_->haveElectrostaticSummationMethod()) { + std::string myMethod = simParams_->getElectrostaticSummationMethod(); + toUpper(myMethod); + if (myMethod == "REACTION_FIELD"){ + useRF = 1; + } else if (myMethod == "SHIFTED_FORCE"){ + useSF = 1; + } else if (myMethod == "SHIFTED_POTENTIAL"){ + useSP = 1; + } + } + + if (simParams_->haveAccumulateBoxDipole()) + if (simParams_->getAccumulateBoxDipole()) + useBoxDipole = 1; + //loop over all of the atom types for (i = atomTypes.begin(); i != atomTypes.end(); ++i) { useLennardJones |= (*i)->isLennardJones(); useElectrostatic |= (*i)->isElectrostatic(); useEAM |= (*i)->isEAM(); + useSC |= (*i)->isSC(); useCharge |= (*i)->isCharge(); useDirectional |= (*i)->isDirectional(); useDipole |= (*i)->isDipole(); @@ -579,6 +746,9 @@ namespace oopse { temp = useEAM; MPI_Allreduce(&temp, &useEAM, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD); + temp = useSC; + MPI_Allreduce(&temp, &useSC, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD); + temp = useShape; MPI_Allreduce(&temp, &useShape, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD); @@ -588,12 +758,15 @@ namespace oopse { temp = useRF; MPI_Allreduce(&temp, &useRF, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD); - temp = useUW; - MPI_Allreduce(&temp, &useUW, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD); + temp = useSF; + MPI_Allreduce(&temp, &useSF, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD); - temp = useDW; - MPI_Allreduce(&temp, &useDW, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD); - + temp = useSP; + MPI_Allreduce(&temp, &useSP, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD); + + temp = useBoxDipole; + MPI_Allreduce(&temp, &useBoxDipole, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD); + #endif fInfo_.SIM_uses_PBC = usePBC; @@ -606,29 +779,13 @@ namespace oopse { fInfo_.SIM_uses_StickyPower = useStickyPower; fInfo_.SIM_uses_GayBerne = useGayBerne; fInfo_.SIM_uses_EAM = useEAM; + fInfo_.SIM_uses_SC = useSC; fInfo_.SIM_uses_Shapes = useShape; fInfo_.SIM_uses_FLARB = useFLARB; fInfo_.SIM_uses_RF = useRF; - fInfo_.SIM_uses_UW = useUW; - fInfo_.SIM_uses_DW = useDW; - - if( fInfo_.SIM_uses_Dipoles && fInfo_.SIM_uses_RF) { - - if (simParams_->haveDielectric()) { - fInfo_.dielect = simParams_->getDielectric(); - } else { - sprintf(painCave.errMsg, - "SimSetup Error: No Dielectric constant was set.\n" - "\tYou are trying to use Reaction Field without" - "\tsetting a dielectric constant!\n"); - painCave.isFatal = 1; - simError(); - } - - } else { - fInfo_.dielect = 0.0; - } - + fInfo_.SIM_uses_SF = useSF; + fInfo_.SIM_uses_SP = useSP; + fInfo_.SIM_uses_BoxDipole = useBoxDipole; } void SimInfo::setupFortranSim() { @@ -645,14 +802,14 @@ namespace oopse { } //calculate mass ratio of cutoff group - std::vector mfact; + std::vector mfact; SimInfo::MoleculeIterator mi; Molecule* mol; Molecule::CutoffGroupIterator ci; CutoffGroup* cg; Molecule::AtomIterator ai; Atom* atom; - double totalMass; + RealType totalMass; //to avoid memory reallocation, reserve enough space for mfact mfact.reserve(getNCutoffGroups()); @@ -662,7 +819,11 @@ namespace oopse { totalMass = cg->getMass(); for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) { - mfact.push_back(atom->getMass()/totalMass); + // Check for massless groups - set mfact to 1 if true + if (totalMass != 0) + mfact.push_back(atom->getMass()/totalMass); + else + mfact.push_back( 1.0 ); } } @@ -709,6 +870,14 @@ namespace oopse { "succesfully sent the simulation information to fortran.\n"); MPIcheckPoint(); #endif // is_mpi + + // Setup number of neighbors in neighbor list if present + if (simParams_->haveNeighborListNeighbors()) { + int nlistNeighbors = simParams_->getNeighborListNeighbors(); + setNeighbors(&nlistNeighbors); + } + + } @@ -771,86 +940,22 @@ namespace oopse { #endif - double SimInfo::calcMaxCutoffRadius() { + void SimInfo::setupCutoff() { + + ForceFieldOptions& forceFieldOptions_ = forceField_->getForceFieldOptions(); + // Check the cutoff policy + int cp = TRADITIONAL_CUTOFF_POLICY; // Set to traditional by default - std::set atomTypes; - std::set::iterator i; - std::vector cutoffRadius; - - //get the unique atom types - atomTypes = getUniqueAtomTypes(); - - //query the max cutoff radius among these atom types - for (i = atomTypes.begin(); i != atomTypes.end(); ++i) { - cutoffRadius.push_back(forceField_->getRcutFromAtomType(*i)); + std::string myPolicy; + if (forceFieldOptions_.haveCutoffPolicy()){ + myPolicy = forceFieldOptions_.getCutoffPolicy(); + }else if (simParams_->haveCutoffPolicy()) { + myPolicy = simParams_->getCutoffPolicy(); } - double maxCutoffRadius = *(std::max_element(cutoffRadius.begin(), cutoffRadius.end())); -#ifdef IS_MPI - //pick the max cutoff radius among the processors -#endif - - return maxCutoffRadius; - } - - void SimInfo::getCutoff(double& rcut, double& rsw) { - - if (fInfo_.SIM_uses_Charges | fInfo_.SIM_uses_Dipoles | fInfo_.SIM_uses_RF) { - - if (!simParams_->haveRcut()){ - sprintf(painCave.errMsg, - "SimCreator Warning: No value was set for the cutoffRadius.\n" - "\tOOPSE will use a default value of 15.0 angstroms" - "\tfor the cutoffRadius.\n"); - painCave.isFatal = 0; - simError(); - rcut = 15.0; - } else{ - rcut = simParams_->getRcut(); - } - - if (!simParams_->haveRsw()){ - sprintf(painCave.errMsg, - "SimCreator Warning: No value was set for switchingRadius.\n" - "\tOOPSE will use a default value of\n" - "\t0.95 * cutoffRadius for the switchingRadius\n"); - painCave.isFatal = 0; - simError(); - rsw = 0.95 * rcut; - } else{ - rsw = simParams_->getRsw(); - } - - } else { - // if charge, dipole or reaction field is not used and the cutofff radius is not specified in - //meta-data file, the maximum cutoff radius calculated from forcefiled will be used - - if (simParams_->haveRcut()) { - rcut = simParams_->getRcut(); - } else { - //set cutoff radius to the maximum cutoff radius based on atom types in the whole system - rcut = calcMaxCutoffRadius(); - } - - if (simParams_->haveRsw()) { - rsw = simParams_->getRsw(); - } else { - rsw = rcut; - } - - } - } - - void SimInfo::setupCutoff() { - getCutoff(rcut_, rsw_); - double rnblist = rcut_ + 1; // skin of neighbor list - - //Pass these cutoff radius etc. to fortran. This function should be called once and only once - - int cp = TRADITIONAL_CUTOFF_POLICY; - if (simParams_->haveCutoffPolicy()) { - std::string myPolicy = simParams_->getCutoffPolicy(); + if (!myPolicy.empty()){ + toUpper(myPolicy); if (myPolicy == "MIX") { cp = MIX_CUTOFF_POLICY; } else { @@ -868,10 +973,232 @@ namespace oopse { } } } + } + notifyFortranCutoffPolicy(&cp); + + // Check the Skin Thickness for neighborlists + RealType skin; + if (simParams_->haveSkinThickness()) { + skin = simParams_->getSkinThickness(); + notifyFortranSkinThickness(&skin); + } + + // Check if the cutoff was set explicitly: + if (simParams_->haveCutoffRadius()) { + rcut_ = simParams_->getCutoffRadius(); + if (simParams_->haveSwitchingRadius()) { + rsw_ = simParams_->getSwitchingRadius(); + } else { + if (fInfo_.SIM_uses_Charges | + fInfo_.SIM_uses_Dipoles | + fInfo_.SIM_uses_RF) { + + rsw_ = 0.85 * rcut_; + sprintf(painCave.errMsg, + "SimCreator Warning: No value was set for the switchingRadius.\n" + "\tOOPSE will use a default value of 85 percent of the cutoffRadius.\n" + "\tswitchingRadius = %f. for this simulation\n", rsw_); + painCave.isFatal = 0; + simError(); + } else { + rsw_ = rcut_; + sprintf(painCave.errMsg, + "SimCreator Warning: No value was set for the switchingRadius.\n" + "\tOOPSE will use the same value as the cutoffRadius.\n" + "\tswitchingRadius = %f. for this simulation\n", rsw_); + painCave.isFatal = 0; + simError(); + } + } + + notifyFortranCutoffs(&rcut_, &rsw_); + + } else { + + // For electrostatic atoms, we'll assume a large safe value: + if (fInfo_.SIM_uses_Charges | fInfo_.SIM_uses_Dipoles | fInfo_.SIM_uses_RF) { + sprintf(painCave.errMsg, + "SimCreator Warning: No value was set for the cutoffRadius.\n" + "\tOOPSE will use a default value of 15.0 angstroms" + "\tfor the cutoffRadius.\n"); + painCave.isFatal = 0; + simError(); + rcut_ = 15.0; + + if (simParams_->haveElectrostaticSummationMethod()) { + std::string myMethod = simParams_->getElectrostaticSummationMethod(); + toUpper(myMethod); + if (myMethod == "SHIFTED_POTENTIAL" || myMethod == "SHIFTED_FORCE") { + if (simParams_->haveSwitchingRadius()){ + sprintf(painCave.errMsg, + "SimInfo Warning: A value was set for the switchingRadius\n" + "\teven though the electrostaticSummationMethod was\n" + "\tset to %s\n", myMethod.c_str()); + painCave.isFatal = 1; + simError(); + } + } + } + + if (simParams_->haveSwitchingRadius()){ + rsw_ = simParams_->getSwitchingRadius(); + } else { + sprintf(painCave.errMsg, + "SimCreator Warning: No value was set for switchingRadius.\n" + "\tOOPSE will use a default value of\n" + "\t0.85 * cutoffRadius for the switchingRadius\n"); + painCave.isFatal = 0; + simError(); + rsw_ = 0.85 * rcut_; + } + notifyFortranCutoffs(&rcut_, &rsw_); + } else { + // We didn't set rcut explicitly, and we don't have electrostatic atoms, so + // We'll punt and let fortran figure out the cutoffs later. + + notifyFortranYouAreOnYourOwn(); + + } } - notifyFortranCutoffs(&rcut_, &rsw_, &rnblist, &cp); } + void SimInfo::setupElectrostaticSummationMethod( int isError ) { + + int errorOut; + int esm = NONE; + int sm = UNDAMPED; + RealType alphaVal; + RealType dielectric; + + errorOut = isError; + + if (simParams_->haveElectrostaticSummationMethod()) { + std::string myMethod = simParams_->getElectrostaticSummationMethod(); + toUpper(myMethod); + if (myMethod == "NONE") { + esm = NONE; + } else { + if (myMethod == "SWITCHING_FUNCTION") { + esm = SWITCHING_FUNCTION; + } else { + if (myMethod == "SHIFTED_POTENTIAL") { + esm = SHIFTED_POTENTIAL; + } else { + if (myMethod == "SHIFTED_FORCE") { + esm = SHIFTED_FORCE; + } else { + if (myMethod == "REACTION_FIELD") { + esm = REACTION_FIELD; + dielectric = simParams_->getDielectric(); + if (!simParams_->haveDielectric()) { + // throw warning + sprintf( painCave.errMsg, + "SimInfo warning: dielectric was not specified in the input file\n\tfor the reaction field correction method.\n" + "\tA default value of %f will be used for the dielectric.\n", dielectric); + painCave.isFatal = 0; + simError(); + } + } else { + // throw error + sprintf( painCave.errMsg, + "SimInfo error: Unknown electrostaticSummationMethod.\n" + "\t(Input file specified %s .)\n" + "\telectrostaticSummationMethod must be one of: \"none\",\n" + "\t\"shifted_potential\", \"shifted_force\", or \n" + "\t\"reaction_field\".\n", myMethod.c_str() ); + painCave.isFatal = 1; + simError(); + } + } + } + } + } + } + + if (simParams_->haveElectrostaticScreeningMethod()) { + std::string myScreen = simParams_->getElectrostaticScreeningMethod(); + toUpper(myScreen); + if (myScreen == "UNDAMPED") { + sm = UNDAMPED; + } else { + if (myScreen == "DAMPED") { + sm = DAMPED; + if (!simParams_->haveDampingAlpha()) { + // first set a cutoff dependent alpha value + // we assume alpha depends linearly with rcut from 0 to 20.5 ang + alphaVal = 0.5125 - rcut_* 0.025; + // for values rcut > 20.5, alpha is zero + if (alphaVal < 0) alphaVal = 0; + + // throw warning + sprintf( painCave.errMsg, + "SimInfo warning: dampingAlpha was not specified in the input file.\n" + "\tA default value of %f (1/ang) will be used for the cutoff of\n\t%f (ang).\n", alphaVal, rcut_); + painCave.isFatal = 0; + simError(); + } else { + alphaVal = simParams_->getDampingAlpha(); + } + + } else { + // throw error + sprintf( painCave.errMsg, + "SimInfo error: Unknown electrostaticScreeningMethod.\n" + "\t(Input file specified %s .)\n" + "\telectrostaticScreeningMethod must be one of: \"undamped\"\n" + "or \"damped\".\n", myScreen.c_str() ); + painCave.isFatal = 1; + simError(); + } + } + } + + // let's pass some summation method variables to fortran + setElectrostaticSummationMethod( &esm ); + setFortranElectrostaticMethod( &esm ); + setScreeningMethod( &sm ); + setDampingAlpha( &alphaVal ); + setReactionFieldDielectric( &dielectric ); + initFortranFF( &errorOut ); + } + + void SimInfo::setupSwitchingFunction() { + int ft = CUBIC; + + if (simParams_->haveSwitchingFunctionType()) { + std::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); + + } + + void SimInfo::setupAccumulateBoxDipole() { + + // we only call setAccumulateBoxDipole if the accumulateBoxDipole parameter is true + if ( simParams_->haveAccumulateBoxDipole() ) + if ( simParams_->getAccumulateBoxDipole() ) { + setAccumulateBoxDipole(); + calcBoxDipole_ = true; + } + + } + void SimInfo::addProperty(GenericData* genData) { properties_.addProperty(genData); } @@ -928,20 +1255,20 @@ namespace oopse { Molecule* mol; Vector3d comVel(0.0); - double totalMass = 0.0; + RealType totalMass = 0.0; for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) { - double mass = mol->getMass(); + RealType mass = mol->getMass(); totalMass += mass; comVel += mass * mol->getComVel(); } #ifdef IS_MPI - double tmpMass = totalMass; + RealType tmpMass = totalMass; Vector3d tmpComVel(comVel); - MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD); #endif comVel /= totalMass; @@ -954,19 +1281,19 @@ namespace oopse { Molecule* mol; Vector3d com(0.0); - double totalMass = 0.0; + RealType totalMass = 0.0; for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) { - double mass = mol->getMass(); + RealType mass = mol->getMass(); totalMass += mass; com += mass * mol->getCom(); } #ifdef IS_MPI - double tmpMass = totalMass; + RealType tmpMass = totalMass; Vector3d tmpCom(com); - MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD); #endif com /= totalMass; @@ -990,23 +1317,23 @@ namespace oopse { Molecule* mol; - double totalMass = 0.0; + RealType totalMass = 0.0; for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) { - double mass = mol->getMass(); + RealType mass = mol->getMass(); totalMass += mass; com += mass * mol->getCom(); comVel += mass * mol->getComVel(); } #ifdef IS_MPI - double tmpMass = totalMass; + RealType tmpMass = totalMass; Vector3d tmpCom(com); Vector3d tmpComVel(comVel); - MPI_Allreduce(&tmpMass,&totalMass,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(&tmpMass,&totalMass,1,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(tmpCom.getArrayPointer(), com.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(tmpComVel.getArrayPointer(), comVel.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD); #endif com /= totalMass; @@ -1025,12 +1352,12 @@ namespace oopse { void SimInfo::getInertiaTensor(Mat3x3d &inertiaTensor, Vector3d &angularMomentum){ - double xx = 0.0; - double yy = 0.0; - double zz = 0.0; - double xy = 0.0; - double xz = 0.0; - double yz = 0.0; + RealType xx = 0.0; + RealType yy = 0.0; + RealType zz = 0.0; + RealType xy = 0.0; + RealType xz = 0.0; + RealType yz = 0.0; Vector3d com(0.0); Vector3d comVel(0.0); @@ -1042,7 +1369,7 @@ namespace oopse { Vector3d thisq(0.0); Vector3d thisv(0.0); - double thisMass = 0.0; + RealType thisMass = 0.0; @@ -1080,8 +1407,8 @@ namespace oopse { #ifdef IS_MPI Mat3x3d tmpI(inertiaTensor); Vector3d tmpAngMom; - MPI_Allreduce(tmpI.getArrayPointer(), inertiaTensor.getArrayPointer(),9,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(tmpI.getArrayPointer(), inertiaTensor.getArrayPointer(),9,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD); #endif return; @@ -1102,7 +1429,7 @@ namespace oopse { Vector3d thisr(0.0); Vector3d thisp(0.0); - double thisMass; + RealType thisMass; for (mol = beginMolecule(i); mol != NULL; mol = nextMolecule(i)) { thisMass = mol->getMass(); @@ -1115,12 +1442,67 @@ namespace oopse { #ifdef IS_MPI Vector3d tmpAngMom; - MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(tmpAngMom.getArrayPointer(), angularMomentum.getArrayPointer(),3,MPI_REALTYPE,MPI_SUM, MPI_COMM_WORLD); #endif return angularMomentum; } - + StuntDouble* SimInfo::getIOIndexToIntegrableObject(int index) { + return IOIndexToIntegrableObject.at(index); + } + + void SimInfo::setIOIndexToIntegrableObject(const std::vector& v) { + IOIndexToIntegrableObject= v; + } + + /* Returns the Volume of the simulation based on a ellipsoid with semi-axes + based on the radius of gyration V=4/3*Pi*R_1*R_2*R_3 + where R_i are related to the principle inertia moments R_i = sqrt(C*I_i/N), this reduces to + V = 4/3*Pi*(C/N)^3/2*sqrt(det(I)). See S.E. Baltazar et. al. Comp. Mat. Sci. 37 (2006) 526-536. + */ + void SimInfo::getGyrationalVolume(RealType &volume){ + Mat3x3d intTensor; + RealType det; + Vector3d dummyAngMom; + RealType sysconstants; + RealType geomCnst; + + geomCnst = 3.0/2.0; + /* Get the inertial tensor and angular momentum for free*/ + getInertiaTensor(intTensor,dummyAngMom); + + det = intTensor.determinant(); + sysconstants = geomCnst/(RealType)nGlobalIntegrableObjects_; + volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,3.0/2.0)*sqrt(det); + return; + } + + void SimInfo::getGyrationalVolume(RealType &volume, RealType &detI){ + Mat3x3d intTensor; + Vector3d dummyAngMom; + RealType sysconstants; + RealType geomCnst; + + geomCnst = 3.0/2.0; + /* Get the inertial tensor and angular momentum for free*/ + getInertiaTensor(intTensor,dummyAngMom); + + detI = intTensor.determinant(); + sysconstants = geomCnst/(RealType)nGlobalIntegrableObjects_; + volume = 4.0/3.0*NumericConstant::PI*pow(sysconstants,3.0/2.0)*sqrt(detI); + return; + } +/* + void SimInfo::setStuntDoubleFromGlobalIndex(std::vector v) { + assert( v.size() == nAtoms_ + nRigidBodies_); + sdByGlobalIndex_ = v; + } + + StuntDouble* SimInfo::getStuntDoubleFromGlobalIndex(int index) { + //assert(index < nAtoms_ + nRigidBodies_); + return sdByGlobalIndex_.at(index); + } +*/ }//end namespace oopse