/** * connection to LinkResetEvent */ void HoomdMove::update(const LinkResetEvent& event) { if (!HoomdIsInitialized_) return; Link *linkPtr = event.get(); // First remove the link from the HOOMD bond table int linkTag = linkPtr->tag(); boost::unordered_map<int, unsigned>::iterator it; it = linkBondMap_.find(linkTag); assert(it != linkBondMap_.end()); unsigned int oldBondTag = it ->second; bondDataSPtr_->removeBond(oldBondTag); // Add the modified link // link type ids are mapped according to // HOOMD bond id = nBondType + link type id ::Bond bond(simulation().nBondType()+linkPtr->typeId(), linkPtr->atom0().id(), linkPtr->atom1().id()); bondDataSPtr_->addBond(bond); // Update link-bond mapping unsigned int newBondTag = bondDataSPtr_->getLastTag(); it->second = newBondTag; }
/** * Remove a Link. */ void LinkMaster::removeLink(int id) { Link* linkPtr = &link(id); int atom0Id; int atom1Id; if (!link(id).isActive()) { UTIL_THROW("Attempt to remove a nonactive link"); } atom0Id = linkPtr->atom0().id(); atom1Id = linkPtr->atom1().id(); // Remove link from atom0 and atom1 link sets if (!atomLinkSets_[atom0Id].isElement(*linkPtr)) { UTIL_THROW("Link is not in atomLinkSets of atom0"); } if (!atomLinkSets_[atom1Id].isElement(*linkPtr)) { UTIL_THROW("Link is not in atomLinkSets of atom1"); } atomLinkSets_[atom0Id].remove(*linkPtr); atomLinkSets_[atom1Id].remove(*linkPtr); // Notify observers of removal of this Link. // Notify before clearing Link so atomPtrs and typeId are available. LinkRemoveEvent event(linkPtr); Notifier<LinkRemoveEvent>::notifyObservers(event); // Clear the link: nullify atomPtrs, set typeId = -1, isActive = false linkPtr->clear(); // Return link to reservoir linkSet_.remove(*linkPtr); reservoir_.push(*linkPtr); }
/* * Modify one atom attached to a link */ void LinkMaster::reSetAtom(Link& link, Atom& atom, int endId) { int atomId = atom.id(); int oldAtomId; if (endId==0){ oldAtomId = link.atom0().id(); } else { oldAtomId = link.atom1().id(); } // Check preconditions if (!link.isActive()) { UTIL_THROW("Attempt to reset an atom for a nonactive link"); } if (atomId < 0 || atomId >= atomCapacity_) { Log::file() << "AtomId = " << atomId << std::endl; Log::file() << "atomCapacity = " << atomCapacity_ << std::endl; UTIL_THROW("Invalid atom id"); } // Remove link from oldAtom link sets if (!atomLinkSets_[oldAtomId].isElement(link)) { UTIL_THROW("Link is not in atomLinkSets of atom"); } atomLinkSets_[oldAtomId].remove(link); // Change the atom if (endId==0){ link.setAtoms(atom,link.atom1()); } else { link.setAtoms(link.atom0(),atom); } atomLinkSets_[atomId].append(link); ReSetAtomEvent event(&link, endId); Notifier<ReSetAtomEvent>::notifyObservers(event); }
/* * Modify the atoms attached to a link */ void LinkMaster::reSetAtoms(Link& link, Atom& atom0, Atom& atom1) { int atom0Id = atom0.id(); int atom1Id = atom1.id(); int oldAtom0Id = link.atom0().id(); int oldAtom1Id = link.atom1().id(); // Check preconditions if (!link.isActive()) { UTIL_THROW("Attempt to reset atoms for a nonactive link"); } if (atom0Id < 0 || atom0Id >= atomCapacity_) { Log::file() << "Atom0Id = " << atom0Id << std::endl; Log::file() << "atomCapacity = " << atomCapacity_ << std::endl; UTIL_THROW("Invalid atom0 id"); } if (atom1Id < 0 || atom1Id >= atomCapacity_) { Log::file() << "Atom1Id = " << atom1Id << std::endl; Log::file() << "atomCapacity = " << atomCapacity_ << std::endl; UTIL_THROW("Invalid atom1 id"); } // Remove link from oldAtom0 and oldAtom1 link sets if (!atomLinkSets_[oldAtom0Id].isElement(link)) { UTIL_THROW("Link is not in atomLinkSets of atom0"); } if (!atomLinkSets_[oldAtom1Id].isElement(link)) { UTIL_THROW("Link is not in atomLinkSets of atom1"); } atomLinkSets_[oldAtom0Id].remove(link); atomLinkSets_[oldAtom1Id].remove(link); // Change the atoms link.setAtoms(atom0,atom1); atomLinkSets_[atom0Id].append(link); atomLinkSets_[atom1Id].append(link); LinkResetEvent event(&link); Notifier<LinkResetEvent>::notifyObservers(event); }
/** * connection to LinkAddEvent */ void HoomdMove::update(const LinkAddEvent& event) { if (!HoomdIsInitialized_) return; // Add a link as a HOOMD bond Link *linkPtr = event.get(); ::Bond bond(simulation().nBondType()+linkPtr->typeId(), linkPtr->atom0().id(), linkPtr->atom1().id()); bondDataSPtr_->addBond(bond); // keep track of bond unsigned int bondTag = bondDataSPtr_->getLastTag(); int linkTag = linkPtr->tag(); #ifdef UTIL_DEBUG std::pair<boost::unordered_map<int, unsigned int>::iterator,bool> ret; ret= #endif linkBondMap_.insert(std::pair<int,unsigned int>(linkTag,bondTag)); assert(ret.second); }
/* * Write the configuration file. */ void McMdConfigIo::write(std::ostream &out) { using std::endl; // Write Boundary dimensions out << "BOUNDARY" << endl << endl; out << boundary() << endl; // Write atomic positions System::ConstMoleculeIterator molIter; Molecule::ConstAtomIterator atomIter; Species* speciesPtr; int iSpecies, iMolecule; out << endl << "MOLECULES" << endl; for (iSpecies = 0; iSpecies < simulation().nSpecies(); ++iSpecies) { out << endl; out << "species " << iSpecies << endl; out << "nMolecule " << system().nMolecule(iSpecies) << endl; speciesPtr = &simulation().species(iSpecies); iMolecule = 0; system().begin(iSpecies, molIter); for ( ; molIter.notEnd(); ++molIter) { out << endl; out << "molecule " << iMolecule << endl; if (speciesPtr->isMutable()) { speciesPtr->mutator().writeMoleculeState(out, *molIter); } for (molIter->begin(atomIter); atomIter.notEnd(); ++atomIter) { //out << atomIter->position() << endl; writeAtom(out, *atomIter); } ++iMolecule; } } #ifdef INTER_TETHER { // Scope for local variables // Write Tethers Tether* tetherPtr; Atom* atomPtr; Molecule* molPtr; int iTether, nTether, iAtom; out << std::endl; out << "TETHERS" << endl << endl; nTether = system().tetherMaster().nTether(); out << Label("nTether") << nTether << std::endl; for (iTether = 0; iTether < nTether; ++iTether) { tetherPtr = &(system().tetherMaster().tether(iTether)); atomPtr = &tetherPtr->atom(); molPtr = &atomPtr->molecule(); iAtom = atomPtr->indexInMolecule(); iMolecule = system().moleculeId(*molPtr); iSpecies = molPtr->species().id(); out << Int(iSpecies,5) << Int(iMolecule,9) << Int(iAtom,6) << tetherPtr->anchor() << std::endl; } } #endif #ifdef MCMD_LINK { // Scope for local variables // Write Links Link* linkPtr; Atom* atomPtr; Molecule* molPtr; int iLink, nLink, iAtom; out << std::endl; out << "LINKS" << endl << endl; nLink = system().linkMaster().nLink(); out << Label("nLink") << nLink << std::endl; for (iLink = 0; iLink < nLink; ++iLink) { linkPtr = &(system().linkMaster().link(iLink)); // Output species, molecule, atom ids for atom 0 atomPtr = &(linkPtr->atom0()); molPtr = &atomPtr->molecule(); iAtom = atomPtr->indexInMolecule(); iMolecule = system().moleculeId(*molPtr); iSpecies = molPtr->species().id(); out << Int(iSpecies,8) << Int(iMolecule,8) << Int(iAtom,8); out << " "; // Output species, molecule, atom ids for atom 1 atomPtr = &(linkPtr->atom1()); molPtr = &atomPtr->molecule(); iAtom = atomPtr->indexInMolecule(); iMolecule = system().moleculeId(*molPtr); iSpecies = molPtr->species().id(); out << Int(iSpecies,8) << Int(iMolecule,8) << Int(iAtom,8); out << " "; out << Int(linkPtr->typeId(),8) << std::endl; } } #endif }
// Create or destroy the slip-springs. bool SliplinkerAll::move() { System::MoleculeIterator molIter; Molecule::AtomIterator atomIter; Atom *atom0Ptr, *atom1Ptr; Atom* atomPtr; Molecule *mol0Ptr, *mol1Ptr; Molecule* molIPtr; double prob, dRSq, mindRSq=cutoff_*cutoff_, rnd, norm; int i, ntrials, j, nNeighbor, idLink, iAtom, id1, id0; int iAtom0, iAtom1, iMolecule0, iMolecule1, n0; Link* linkPtr; static const int maxNeighbor = CellList::MaxNeighbor; double cdf[maxNeighbor], energy, sum; int idneighbors[maxNeighbor]; ntrials = 2 * system().simulation().atomCapacity(); for (i=0; i < ntrials; ++i){ //Choose to create or destroy a link with prob 0.5 if (random().uniform(0.0, 1.0) > 0.5){ // Try to create a link. incrementNAttempt(); // Choose a molecule and atom at random molIPtr = &(system().randomMolecule(speciesId_)); iMolecule0 = system().moleculeId(*molIPtr); iAtom = random().uniformInt(0, molIPtr->nAtom()); atomPtr = &molIPtr->atom(iAtom); id0 = atomPtr->id(); // Get array of neighbors system().pairPotential().cellList().getNeighbors(atomPtr->position(), neighbors_); nNeighbor = neighbors_.size(); n0 = 0; sum = 0; // Loop over neighboring atoms for (j = 0; j < nNeighbor; ++j) { atom1Ptr = neighbors_[j]; mol1Ptr = &atom1Ptr->molecule(); iMolecule1 = system().moleculeId(*mol1Ptr); id1 = atom1Ptr->id(); // Check if atoms are the same if (id0 != id1){ // Exclude masked pairs if (!atomPtr->mask().isMasked(*atom1Ptr)) { // Identify possible partners and calculate the cumulative distribution function dRSq = system().boundary().distanceSq(atomPtr->position(), atom1Ptr->position()); if (dRSq <= mindRSq) { energy = system().linkPotential().energy(dRSq, 0); //energy = 0.5*dRSq; sum = sum + boltzmann(energy); cdf[n0] = sum; idneighbors[n0] = j; n0++; } } } } // If at least 1 candidate has been found. if (n0 > 0) { // Choose a partner with probability cdf[j]/cdf[n0-1] j = 0; rnd = random().uniform(0.0, 1.0); norm = 1.0/cdf[n0-1]; while (rnd > cdf[j]*norm ){ j = j + 1; } atom1Ptr = neighbors_[idneighbors[j]]; // Create a slip-link between the selected atoms with probability = prob prob = 2.0 * (system().linkMaster().nLink() + 1.0); prob = system().simulation().atomCapacity() * boltzmann(-mu_) * cdf[n0-1]/ prob ; //prob = 2.0 * system().nMolecule(speciesId_) * boltzmann(-mu_) * cdf[n0-1]/ prob ; if (system().simulation().random().uniform(0.0, 1.0) < prob) { system().linkMaster().addLink(*atomPtr, *atom1Ptr, 0); incrementNAccept(); } } } else { // Try to destroy a link incrementNAttempt(); // Choose a link at random if (system().linkMaster().nLink() > 0){ idLink = random().uniformInt(0, system().linkMaster().nLink()); // Indentify the atoms for this link. linkPtr = &(system().linkMaster().link(idLink)); atom0Ptr = &(linkPtr->atom0()); mol0Ptr = &atom0Ptr->molecule(); iMolecule0 = system().moleculeId(*mol0Ptr); iAtom0 = atom0Ptr->indexInMolecule(); atom1Ptr = &(linkPtr->atom1()); mol1Ptr = &atom1Ptr->molecule(); iMolecule1 = system().moleculeId(*mol1Ptr); iAtom1 = atom1Ptr->indexInMolecule(); // try to delete the slip-spring dRSq = system().boundary().distanceSq(atom0Ptr->position(), atom1Ptr->position()); // try to delete the link if the bond is smaller than the cutoff if (dRSq <= mindRSq) { // Get array of neighbors system().pairPotential().cellList().getNeighbors(atom0Ptr->position(), neighbors_); nNeighbor = neighbors_.size(); id0 = atom0Ptr->id(); n0 = 0; sum = 0; // Loop over neighboring atoms for (j = 0; j < nNeighbor; ++j) { atom1Ptr = neighbors_[j]; mol1Ptr = &atom1Ptr->molecule(); iMolecule1 = system().moleculeId(*mol1Ptr); id1 = atom1Ptr->id(); // Check if atoms are the same if (id0 != id1){ // Exclude masked pairs if (!atom0Ptr->mask().isMasked(*atom1Ptr)) { // Identify possible partners and calculate the cumulative distribution function dRSq = system().boundary().distanceSq(atom0Ptr->position(), atom1Ptr->position()); if (dRSq <= mindRSq) { energy = system().linkPotential().energy(dRSq, 0); //energy = 0.5*dRSq; sum = sum + boltzmann(energy); cdf[n0] = sum; idneighbors[n0] = j; n0++; } } } } // Destroy the slip-link between the selected atoms with probability = prob //prob = 2.0 * system().nMolecule(speciesId_) * boltzmann(-mu_) * cdf[n0-1]; prob = system().simulation().atomCapacity() * boltzmann(-mu_) * cdf[n0-1]; prob = 2.0 * system().linkMaster().nLink() / prob; if (system().simulation().random().uniform(0.0, 1.0) < prob) { system().linkMaster().removeLink(idLink); incrementNAccept(); } } } } } return true; }