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