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; } }