/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2013 University of Bonn. All rights reserved. * Copyright (C) 2013 Frederik Heber. All rights reserved. * * * This file is part of MoleCuilder. * * MoleCuilder is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * MoleCuilder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MoleCuilder. If not, see . */ /* * HydrogenPool.cpp * * Created on: Mar 3, 2013 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/MemDebug.hpp" #include "HydrogenPool.hpp" #include "CodePatterns/Assert.hpp" #include "CodePatterns/Log.hpp" #include "Atom/atom.hpp" #include "Atom/AtomObserver.hpp" #include "Descriptors/AtomIdDescriptor.hpp" #include "Element/periodentafel.hpp" #include "World.hpp" #include "WorldTime.hpp" HydrogenPool::HydrogenPool() : HydrogenCount(0) {} HydrogenPool::~HydrogenPool() { cleanup(); } void HydrogenPool::requestHydrogenIntoPool() { // get new hydrogen from world, but remove its observers atom * const Walker = World::getInstance().createAtom(); Walker->setType(HYDROGEN); // set element Walker->setName(std::string("H_")+toString(HydrogenCount)); Walker->signOff(AtomObserver::getPointer(), AtomObservable::PositionChanged); Walker->signOff(AtomObserver::getPointer(), AtomObservable::ElementChanged); HydrogenQueue.push_back(Walker); ++HydrogenCount; // give warning if pool has more than threshold if (HydrogenCount >= WARNINGTHRESHOLD) { ELOG(2, "HydrogenPool contains more hydrogen atoms than limit."); ELOG(2, "Either someone requesting too eagerly, or another not returning them."); } // final check ASSERT(!HydrogenQueue.empty(), "HydrogenPool::requestHydrogenIntoPool() - failed to request more hydrogens."); } atom * HydrogenPool::leaseHydrogen() { // check the queue, if empty, add more hydrogens if (HydrogenQueue.empty()) requestHydrogenIntoPool(); // pop hydrogen, mark down, and deliver atom * const Walker = HydrogenQueue.front(); ASSERT( HydrogenInUse.count(Walker->getId()) == 0, "HydrogenPool::leaseHydrogen() - hydrogen "+toString(*Walker) +" from pool is already in use."); LOG(3, "DEBUG: Leasing " << *Walker << "."); UpdateSteps(Walker); HydrogenInUse.insert( std::make_pair( Walker->getId(), Walker) ); HydrogenQueue.pop_front(); return Walker; } void HydrogenPool::UpdateSteps(atom * _atom) const { // make sure we are up to current time step const size_t CurrentTime = WorldTime::getTime(); for (size_t step = _atom->getTrajectorySize(); step <= CurrentTime; ++step) _atom->UpdateStep(step); } void HydrogenPool::releaseHydrogen(atom * _atom) { if (_atom == NULL) { ASSERT( 0, "HydrogenPool::releaseHydrogen() - got NULL atom."); return; } // check that it is marked down { HydrogenInUse_t::iterator iter = HydrogenInUse.find(_atom->getId()); if (iter == HydrogenInUse.end()) { ASSERT( 0, "HydrogenPool::releaseHydrogen() - got unknown atom "+toString(_atom)+"."); return; } LOG(3, "DEBUG: Releasing " << *_atom << "."); HydrogenInUse.erase(iter); } // check into queue HydrogenQueue.push_back(_atom); } void HydrogenPool::releaseHydrogen(atomId_t _atom) { atom * const Walker = World::getInstance().getAtom(AtomById(_atom)); ASSERT( Walker != NULL, "HydrogenPool::releaseHydrogen() - id " +toString(_atom)+" unknown to World."); releaseHydrogen(Walker); } void HydrogenPool::cleanup() { ASSERT(HydrogenInUse.empty(), "HydrogenPool::cleanup() - cleanup called, but still hydrogens in use."); for (HydrogenQueue_t::iterator iter = HydrogenQueue.begin(); !HydrogenQueue.empty(); iter = HydrogenQueue.begin()) { atom * const Walker = *iter; HydrogenQueue.erase(iter); World::getInstance().destroyAtom(Walker); } }