/** Like the strip action, closest will modify the current parm keeping info * for atoms in mask plus the closestWaters solvent molecules. Set up the * vector of MolDist objects, one for every solvent molecule in the original * parm file. Atom masks for each solvent molecule will be set up. */ Action_Closest::RetType Action_Closest::Setup(Topology const& topIn, CoordinateInfo const& cInfoIn) { // If there are no solvent molecules this action is not valid. if (topIn.Nsolvent()==0) { mprintf("Warning: Parm %s does not contain solvent.\n",topIn.c_str()); return Action_Closest::SKIP; } // If # solvent to keep >= solvent in this parm the action is not valid. if (closestWaters_ >= topIn.Nsolvent()) { mprintf("Warning: # solvent to keep (%i) >= # solvent molecules in '%s' (%i)\n", closestWaters_, topIn.c_str(), topIn.Nsolvent()); return Action_Closest::SKIP; } image_.SetupImaging( cInfoIn.TrajBox().Type() ); if (image_.ImagingEnabled()) mprintf("\tDistances will be imaged.\n"); else mprintf("\tImaging off.\n"); // LOOP OVER MOLECULES // 1: Check that all solvent molecules contain same # atoms. Solvent // molecules must be identical for the command to work properly; // the prmtop strip occurs only once so the solvent params become fixed. // 2: Set up a mask for all solvent molecules. SolventMols_.clear(); // NOTE: May not be necessary to init 'solvent' MolDist solvent; solvent.D = 0.0; solvent.mol = 0; SolventMols_.resize(topIn.Nsolvent(), solvent); std::vector<MolDist>::iterator mdist = SolventMols_.begin(); // 3: Set up the soluteMask for all non-solvent molecules. int molnum = 1; int nclosest = 0; int NsolventAtoms = -1; for (Topology::mol_iterator Mol = topIn.MolStart(); Mol != topIn.MolEnd(); ++Mol) { if ( Mol->IsSolvent() ) { // Solvent, check for same # of atoms. if (NsolventAtoms == -1) NsolventAtoms = Mol->NumAtoms(); else if ( NsolventAtoms != Mol->NumAtoms() ) { mprinterr("Error: Solvent molecules in '%s' are not of uniform size.\n" "Error: First solvent mol = %i atoms, solvent mol %i = %i atoms.\n", topIn.c_str(), NsolventAtoms, molnum, (*Mol).NumAtoms()); return Action_Closest::ERR; } // mol here is the output molecule number which is why it starts from 1. mdist->mol = molnum; // Solvent molecule mask mdist->mask.AddAtomRange( Mol->BeginAtom(), Mol->EndAtom() ); // Atoms in the solvent molecule to actually calculate distances to. if (firstAtom_) { mdist->solventAtoms.assign(1, Mol->BeginAtom() ); } else { mdist->solventAtoms.clear(); mdist->solventAtoms.reserve( Mol->NumAtoms() ); for (int svatom = Mol->BeginAtom(); svatom < Mol->EndAtom(); svatom++) mdist->solventAtoms.push_back( svatom ); } if (debug_ > 0) { mprintf("DEBUG:\tSet up mol %i:", mdist->mol); // DEBUG mdist->mask.PrintMaskAtoms("solvent"); // DEBUG mprintf("\n"); // DEBUG } ++mdist; } ++molnum; } // Setup distance atom mask // NOTE: Should ensure that no solvent atoms are selected! if ( topIn.SetupIntegerMask(distanceMask_) ) return Action_Closest::ERR; if (distanceMask_.None()) { mprintf("Warning: Distance mask '%s' contains no atoms.\n", distanceMask_.MaskString()); return Action_Closest::SKIP; } distanceMask_.MaskInfo(); // Check the total number of solvent atoms to be kept. NsolventAtoms *= closestWaters_; mprintf("\tKeeping %i solvent atoms.\n",NsolventAtoms); if (NsolventAtoms < 1) { mprintf("Warning: # of solvent atoms to be kept is < 1.\n"); return Action_Closest::SKIP; } NsolventMolecules_ = (int)SolventMols_.size(); return Action_Closest::OK; }