/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 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 . */ /* * Filler.cpp * * Created on: Jan 16, 2012 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif //#include "CodePatterns/MemDebug.hpp" #include #include #include #include #include #include "Filler.hpp" #include "CodePatterns/Assert.hpp" #include "CodePatterns/Log.hpp" #include "Atom/atom.hpp" #include "Box.hpp" #include "ClusterInterface.hpp" #include "Descriptors/AtomIdDescriptor.hpp" #include "Inserter/Inserter.hpp" #include "LinearAlgebra/RealSpaceMatrix.hpp" #include "LinearAlgebra/Vector.hpp" #include "molecule.hpp" #include "NodeTypes.hpp" #include "Predicates/FillPredicate.hpp" #include "Predicates/Ops_FillPredicate.hpp" #include "World.hpp" Filler::Filler(const Mesh &_mesh, const FillPredicate &_predicate, const Inserter &_inserter) : mesh(_mesh), predicate(!_predicate), inserter(_inserter) {} Filler::~Filler() {} bool Filler::operator()( CopyAtomsInterface ©Method, ClusterInterface::Cluster_impl cluster, ClusterVector_t &ClonedClusters) const { const NodeSet &nodes = mesh.getNodes(); std::stringstream output; std::for_each( nodes.begin(), nodes.end(), output << boost::lambda::_1 << " "); LOG(3, "DEBUG: Listing nodes to check: " << output.str()); if (nodes.size() == 0) return false; NodeSet FillNodes(nodes.size(), zeroVec); // evaluate predicates at each FillNode { // move filler cluster's atoms out of domain such that it does not disturb the predicate. // we only move the atoms as otherwise two translate ShapeOps will be on top of the Shape // which is subsequently copied to all other cloned Clusters ... Vector BoxDiagonal; { const RealSpaceMatrix &M = World::getInstance().getDomain().getM(); BoxDiagonal = (M * Vector(1.,1.,1.)); BoxDiagonal -= cluster->getShape().getCenter(); BoxDiagonal *= 1. + 2.*cluster->getShape().getRadius()/BoxDiagonal.Norm(); // extend it a little further AtomIdSet atoms = cluster->getAtoms(); for (AtomIdSet::iterator iter = atoms.begin(); iter != atoms.end(); ++iter) (*iter)->setPosition( (*iter)->getPosition() + BoxDiagonal ); LOG(1, "INFO: Translating original cluster's atoms by " << BoxDiagonal << "."); } // evaluate predicate and gather into new set NodeSet::iterator transform_end = std::remove_copy_if(nodes.begin(), nodes.end(), FillNodes.begin(), predicate ); FillNodes.erase(transform_end, FillNodes.end()); // shift cluster back to original place { AtomIdSet atoms = cluster->getAtoms(); for (AtomIdSet::iterator iter = atoms.begin(); iter != atoms.end(); ++iter) (*iter)->setPosition( (*iter)->getPosition() - BoxDiagonal ); LOG(1, "INFO: Translating original cluster's atoms back."); } } if (FillNodes.size() == 0) { ELOG(2, "For none of the nodes did the predicate return true."); return false; } else { LOG(1, "INFO: " << FillNodes.size() << " out of " << nodes.size() << " returned true from predicate."); } // clone clusters ClonedClusters.resize(FillNodes.size()); { std::vector::iterator clusteriter = ClonedClusters.begin(); *clusteriter = cluster; clusteriter++; std::generate_n(clusteriter, FillNodes.size()-1, boost::bind(&ClusterInterface::clone, boost::cref(cluster), boost::ref(copyMethod), zeroVec) ); } // insert each cluster by abusing std::search a bit: { // we look for the subsequence of FillNodes inside clusters. If Inserter always // returns true, we'll have the iterator pointing at first cluster std::vector::const_iterator inserteriter = std::search(ClonedClusters.begin(), ClonedClusters.end(), FillNodes.begin(), FillNodes.end(), boost::bind(&Inserter::operator(), boost::cref(inserter), _1, _2)); if( inserteriter != ClonedClusters.begin()) { ELOG(1, "Not all cloned clusters could be successfully inserted."); return false; } } // create molecules for each cluster and fill in atoms { std::vector molecules(ClonedClusters.size()-1, NULL); std::generate_n(molecules.begin(), FillNodes.size()-1, boost::bind(&World::createMolecule, World::getPointer()) ); std::vector::const_iterator clusteriter = ClonedClusters.begin(); ++clusteriter; std::vector::iterator moliter = molecules.begin(); for (;moliter != molecules.end(); ++clusteriter, ++moliter) { AtomIdSet atoms = (*clusteriter)->getAtoms(); for (AtomIdSet::iterator iter = atoms.begin(); iter != atoms.end(); ++iter) (*moliter)->AddAtom(*iter); } } // give final statment on whether at least \a single cluster has been placed return ( FillNodes.size() != 0); }