/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010-2012 University of Bonn. 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 . */ /* * RepeatBoxAction.cpp * * Created on: May 12, 2010 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/MemDebug.hpp" #include "Descriptors/MoleculePtrDescriptor.hpp" #include "Atom/atom.hpp" #include "CodePatterns/Log.hpp" #include "molecule.hpp" #include "MoleculeListClass.hpp" #include "LinearAlgebra/Vector.hpp" #include "LinearAlgebra/RealSpaceMatrix.hpp" #include "CodePatterns/Verbose.hpp" #include "World.hpp" #include "Box.hpp" #include #include #include #include #include "Actions/WorldAction/RepeatBoxAction.hpp" using namespace MoleCuilder; // and construct the stuff #include "RepeatBoxAction.def" #include "Action_impl_pre.hpp" /** =========== define the function ====================== */ void repeatMoleculesinDomain( std::vector< unsigned int > Repeater, const std::vector &AllMolecules) { LOG(0, "STATUS: Repeating box " << Repeater << " times for (x,y,z) axis."); // set new domain RealSpaceMatrix M = World::getInstance().getDomain().getM(); RealSpaceMatrix newM = M; Vector x,y; unsigned int n[NDIM]; RealSpaceMatrix repMat; for (unsigned int axis = 0; axis < NDIM; axis++) { Repeater[axis] = floor(Repeater[axis]); if (Repeater[axis] < 1) { ELOG(1, "Repetition factor must be greater than 1!"); Repeater[axis] = 1; } repMat.at(axis,axis) = Repeater[axis]; } newM *= repMat; World::getInstance().setDomain(newM); // add molecules in each repeated domain part molecule *newmol = NULL; std::vector vectors; MoleculeListClass *molecules = World::getInstance().getMolecules(); for (n[0] = 0; n[0] < Repeater[0]; n[0]++) { y[0] = n[0]; for (n[1] = 0; n[1] < Repeater[1]; n[1]++) { y[1] = n[1]; for (n[2] = 0; n[2] < Repeater[2]; n[2]++) { y[2] = n[2]; if ((n[0] == 0) && (n[1] == 0) && (n[2] == 0)) continue; for (vector::const_iterator MolRunner = AllMolecules.begin(); MolRunner != AllMolecules.end(); ++MolRunner) { molecule * const mol = *MolRunner; LOG(2, "DEBUG: Current mol is " << mol->name << "." << endl); newmol = mol->CopyMolecule(); // TODO: remove this when World does not have MoleculeListClass anymore. molecules->insert(newmol); x = y; x *= M; // shift each atom into new position for(molecule::iterator iter = newmol->begin(); iter != newmol->end(); ++iter) (*iter)->setPosition((*iter)->getPosition() + x); } } } } } Action::state_ptr WorldRepeatBoxAction::performCall() { std::vector AllMolecules; DoLog(0) && (Log() << Verbose(0) << "Using all molecules." << endl); AllMolecules = World::getInstance().getAllMolecules(); // prepare undo state RealSpaceMatrix olddomain = World::getInstance().getDomain().getM(); std::set oldmolecules; for(std::vector::const_iterator iter = AllMolecules.begin(); iter != AllMolecules.end(); ++iter) oldmolecules.insert(*iter); WorldRepeatBoxState *undostate = new WorldRepeatBoxState(olddomain, oldmolecules, params); repeatMoleculesinDomain(params.Repeater.get(), AllMolecules); // give final box size LOG(0, "Box domain is now " << World::getInstance().getDomain().getM()); return Action::state_ptr(undostate); } Action::state_ptr WorldRepeatBoxAction::performUndo(Action::state_ptr _state) { WorldRepeatBoxState *state = assert_cast(_state.get()); MoleculeListClass *molecules = World::getInstance().getMolecules(); // set old domain World::getInstance().setDomain(state->olddomain); // remove all added molecules (and their atoms) std::vector allmolecules = World::getInstance().getAllMolecules(); for (std::vector::iterator iter = allmolecules.begin(); iter != allmolecules.end(); ++iter) { if (state->oldmolecules.find(*iter) == state->oldmolecules.end()) { (*iter)->removeAtomsinMolecule(); // TODO: Remove this when World don't has deprecated MoleculeListClass anymore molecules->erase(*iter); World::getInstance().destroyMolecule(*iter); } } // give final box size LOG(0, "Box domain restored to " << World::getInstance().getDomain().getM()); return Action::state_ptr(_state); } Action::state_ptr WorldRepeatBoxAction::performRedo(Action::state_ptr _state){ WorldRepeatBoxState *state = assert_cast(_state.get()); std::vector originalmolecules; for(std::set::const_iterator iter = state->oldmolecules.begin(); iter != state->oldmolecules.end(); ++iter) originalmolecules.push_back(*iter); repeatMoleculesinDomain(state->params.Repeater.get(), originalmolecules); // give final box size LOG(0, "Box domain is again " << World::getInstance().getDomain().getM()); return Action::state_ptr(_state); } bool WorldRepeatBoxAction::canUndo() { return true; } bool WorldRepeatBoxAction::shouldUndo() { return true; } /** =========== end of function ====================== */