PotDiff::PotDiff(SimInfo* info, const std::string& filename, const std::string& sele) : StaticAnalyser(info, filename), selectionScript_(sele), seleMan_(info), evaluator_(info) { StuntDouble* sd; int i; setOutputName(getPrefix(filename) + ".potDiff"); // The PotDiff is computed by negating the charge on the atom type // using fluctuating charge values. If we don't have any // fluctuating charges in the simulation, we need to expand // storage to hold them. int storageLayout = info_->getStorageLayout(); storageLayout |= DataStorage::dslFlucQPosition; storageLayout |= DataStorage::dslFlucQVelocity; storageLayout |= DataStorage::dslFlucQForce; info_->setStorageLayout(storageLayout); info_->setSnapshotManager(new SimSnapshotManager(info_, storageLayout)); // now we have to figure out which AtomTypes to convert to fluctuating // charges evaluator_.loadScriptString(sele); seleMan_.setSelectionSet(evaluator_.evaluate()); for (sd = seleMan_.beginSelected(i); sd != NULL; sd = seleMan_.nextSelected(i)) { AtomType* at = static_cast<Atom*>(sd)->getAtomType(); FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(at); if (fqa.isFluctuatingCharge()) { selectionWasFlucQ_.push_back(true); } else { selectionWasFlucQ_.push_back(false); // make a fictitious fluctuating charge with an unphysical // charge mass and slaterN, but we need to zero out the // electronegativity and hardness to remove the self // contribution: fqa.makeFluctuatingCharge(1.0e9, 0.0, 0.0, 1); sd->setFlucQPos(0.0); } } info_->getSnapshotManager()->advance(); }
void EAM::addType(AtomType* atomType){ EAMAdapter ea = EAMAdapter(atomType); EAMAtomData eamAtomData; eamAtomData.rho = ea.getRho(); eamAtomData.F = ea.getF(); eamAtomData.Z = ea.getZ(); eamAtomData.rcut = ea.getRcut(); FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(atomType); if (fqa.isFluctuatingCharge()) { if (fqa.isMetallic()) { eamAtomData.isFluctuatingCharge = true; eamAtomData.nValence = fqa.getNValence(); } else { eamAtomData.isFluctuatingCharge = false; } } // add it to the map: int atid = atomType->getIdent(); int eamtid = EAMtypes.size(); pair<set<int>::iterator,bool> ret; ret = EAMtypes.insert( atid ); if (ret.second == false) { sprintf( painCave.errMsg, "EAM already had a previous entry with ident %d\n", atid); painCave.severity = OPENMD_INFO; painCave.isFatal = 0; simError(); } EAMtids[atid] = eamtid; EAMdata[eamtid] = eamAtomData; MixingMap[eamtid].resize(nEAM_); // Now, iterate over all known types and add to the mixing map: std::set<int>::iterator it; for( it = EAMtypes.begin(); it != EAMtypes.end(); ++it) { int eamtid2 = EAMtids[ (*it) ]; AtomType* atype2 = forceField_->getAtomType( (*it) ); EAMInteractionData mixer; mixer.phi = getPhi(atomType, atype2); mixer.rcut = mixer.phi->getLimits().second; mixer.explicitlySet = false; MixingMap[eamtid2].resize( nEAM_ ); MixingMap[eamtid][eamtid2] = mixer; if (eamtid2 != eamtid) { MixingMap[eamtid2][eamtid] = mixer; } } return; }
void PotDiff::process() { Molecule* mol; RigidBody* rb; SimInfo::MoleculeIterator mi; Molecule::RigidBodyIterator rbIter; StuntDouble* sd; int j; diff_.clear(); DumpReader reader(info_, dumpFilename_); int nFrames = reader.getNFrames(); // We'll need the force manager to compute the potential ForceManager* forceMan = new ForceManager(info_); // We'll need thermo to report the potential Thermo* thermo = new Thermo(info_); for (int i = 0; i < nFrames; i += step_) { reader.readFrame(i); currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot(); for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi)) { //change the positions of atoms which belong to the rigidbodies for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) { rb->updateAtoms(); } } for (sd = seleMan_.beginSelected(j); sd != NULL; sd = seleMan_.nextSelected(j)) { if (!selectionWasFlucQ_[j]) { sd->setFlucQPos(0.0); } } forceMan->calcForces(); RealType pot1 = thermo->getPotential(); if (evaluator_.isDynamic()) { seleMan_.setSelectionSet(evaluator_.evaluate()); } for (sd = seleMan_.beginSelected(j); sd != NULL; sd = seleMan_.nextSelected(j)) { AtomType* at = static_cast<Atom*>(sd)->getAtomType(); FixedChargeAdapter fca = FixedChargeAdapter(at); FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(at); RealType charge = 0.0; if (fca.isFixedCharge()) charge += fca.getCharge(); if (fqa.isFluctuatingCharge()) charge += sd->getFlucQPos(); sd->setFlucQPos(-charge); } currentSnapshot_->clearDerivedProperties(); forceMan->calcForces(); RealType pot2 = thermo->getPotential(); RealType diff = pot2-pot1; data_.add(diff); diff_.push_back(diff); times_.push_back(currentSnapshot_->getTime()); info_->getSnapshotManager()->advance(); } writeDiff(); }