/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010 University of Bonn. All rights reserved. * Please see the LICENSE file or "Copyright notice" in builder.cpp for details. */ /* * 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.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(Vector Repeater, const std::vector &AllMolecules) { int count; const element ** Elements; int j = 0; atom *Walker = NULL; MoleculeListClass *molecules = World::getInstance().getMolecules(); 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; int n[NDIM]; RealSpaceMatrix repMat; for (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; 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) { const molecule *mol = *MolRunner; LOG(2, "INFO: Current mol is " << mol->name << "."); count = mol->getAtomCount(); // is changed becausing of adding, thus has to be stored away beforehand if (count != 0) { // if there is more than none Elements = new const element *[count]; vectors.resize(count); j = 0; for(molecule::const_iterator AtomRunner = mol->begin(); AtomRunner != mol->end(); ++AtomRunner) { Elements[j] = (*AtomRunner)->getType(); vectors[j] = (*AtomRunner)->getPosition(); j++; } if (count != j) ELOG(1, "AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!"); x = y; x *= M; newmol = World::getInstance().createMolecule(); // TODO: Remove this when World don't has deprecated MoleculeListClass anymore molecules->insert(newmol); for (int k=count;k--;) { // go through every atom of the original cell Walker = World::getInstance().createAtom(); // create a new body Walker->setPosition((vectors[k]) + x); Walker->setType(Elements[k]); // insert original element cout << "new atom is " << *Walker << endl; newmol->AddAtom(Walker); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...) } // free memory delete[](Elements); } else { LOG(1, "\t ... is empty."); } } } } } } Action::state_ptr WorldRepeatBoxAction::performCall() { molecule *mol = NULL; // obtain information getParametersfromValueStorage(); std::vector AllMolecules; if (mol != NULL) { LOG(0, "Using molecule " << mol->name << "."); AllMolecules = World::getInstance().getAllMolecules(MoleculeByPtr(mol)); } else { LOG(0, "Using all molecules."); 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, 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, 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 ====================== */