Atom::Atom(AtomType* at) : StuntDouble(otAtom, &Snapshot::atomData), atomType_(at) { mass_ = at->getMass(); if (at->isFluctuatingCharge()) { FluctuatingChargeAdapter fca = FluctuatingChargeAdapter(at); chargeMass_ = fca.getChargeMass(); } else { chargeMass_ = NumericConstant::infinity; } }
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 FluctuatingChargeAtomTypesSectionParser::parseLine(ForceField& ff, const string& line, int lineNo){ StringTokenizer tokenizer(line); int nTokens = tokenizer.countTokens(); if (nTokens < 3) { sprintf(painCave.errMsg, "FluctuatingChargeAtomTypesSectionParser Error: " "Not enough tokens at line %d\n", lineNo); painCave.isFatal = 1; simError(); } string atomTypeName = tokenizer.nextToken(); AtomType* atomType = ff.getAtomType(atomTypeName); if (atomType != NULL) { FixedChargeAdapter fca = FixedChargeAdapter(atomType); // All fluctuating charges are charges, and if we haven't // already set values for the charge, then start with zero. if (! fca.isFixedCharge()) { RealType charge = 0.0; fca.makeFixedCharge(charge); } } else { sprintf(painCave.errMsg, "FluctuatingChargeAtomTypesSectionParser Error: Atom Type [%s] " "has not been created yet\n", atomTypeName.c_str()); painCave.isFatal = 1; simError(); } RealType chargeMass = tokenizer.nextTokenAsDouble(); FluctuatingTypeEnum fqt = getFluctuatingTypeEnum(tokenizer.nextToken()); nTokens -= 3; switch(fqt) { case fqtHardness: // For Rick, Stuart, Berne style fluctuating charges, there's a // self charge potential defined by electronegativity and // hardness. On molecular structures, the slater-type overlap // integral is used to compute the hardness. // atomTypeName, chargeMass, Hardness, electronegativity, // hardness (Jii), slaterN, slaterZeta if (nTokens < 4) { sprintf(painCave.errMsg, "FluctuatingChargeAtomTypesSectionParser Error: " "Not enough tokens at line %d\n", lineNo); painCave.isFatal = 1; simError(); } else { RealType chi = tokenizer.nextTokenAsDouble(); RealType Jii = tokenizer.nextTokenAsDouble(); int slaterN = tokenizer.nextTokenAsInt(); RealType slaterZeta = tokenizer.nextTokenAsDouble(); FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(atomType); fqa.makeFluctuatingCharge(chargeMass, chi, Jii, slaterN, slaterZeta); } break; case fqtMultipleMinima: if (nTokens < 4 || nTokens % 2 != 0) { sprintf(painCave.errMsg, "FluctuatingChargeAtomTypesSectionParser Error: " "Not enough tokens at line %d\n", lineNo); painCave.isFatal = 1; simError(); } else { std::vector<std::pair<RealType, RealType> > diabaticStates; RealType curvature = tokenizer.nextTokenAsDouble(); RealType coupling = tokenizer.nextTokenAsDouble(); nTokens -= 2; int nStates = nTokens / 2; RealType charge; RealType ionizationEnergy; for (int i = 0; i < nStates; ++i) { charge = tokenizer.nextTokenAsDouble(); ionizationEnergy = tokenizer.nextTokenAsDouble(); diabaticStates.push_back( std::make_pair( charge, ionizationEnergy )); } FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(atomType); fqa.makeFluctuatingCharge(chargeMass, curvature, coupling, diabaticStates); } break; case fqtMetal: if (nTokens < 5 || nTokens % 2 != 1) { sprintf(painCave.errMsg, "FluctuatingChargeAtomTypesSectionParser Error: " "Not enough tokens at line %d\n", lineNo); painCave.isFatal = 1; simError(); } else { int nValence = tokenizer.nextTokenAsInt(); nTokens -= 1; std::vector<std::pair<RealType, RealType> > diabaticStates; RealType curvature = tokenizer.nextTokenAsDouble(); RealType coupling = tokenizer.nextTokenAsDouble(); nTokens -= 2; int nStates = nTokens / 2; RealType charge; RealType ionizationEnergy; for (int i = 0; i < nStates; ++i) { charge = tokenizer.nextTokenAsDouble(); ionizationEnergy = tokenizer.nextTokenAsDouble(); diabaticStates.push_back( std::make_pair( charge, ionizationEnergy )); } FluctuatingChargeAdapter fqa = FluctuatingChargeAdapter(atomType); fqa.makeFluctuatingCharge(chargeMass, nValence, curvature, coupling, diabaticStates); } break; case fqtUnknown: default: sprintf(painCave.errMsg, "FluctuatingChargeAtomTypesSectionParser Error: " "Unknown Fluctuating Charge Type at line %d\n", lineNo); painCave.isFatal = 1; simError(); break; } }
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(); }