/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2017 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 . */ /* * BondVectors.cpp * * Created on: Jun 13, 2017 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif //#include "CodePatterns/MemDebug.hpp" #include "BondVectors.hpp" #include #include #include #include #include "CodePatterns/Assert.hpp" #include "CodePatterns/Log.hpp" #include "Atom/atom.hpp" #include "Bond/bond.hpp" #include "Helpers/defs.hpp" void BondVectors::recalculateBondVectorsAtStep( const size_t &_step) const { current_mapped_vectors.clear(); ASSERT( !container.empty(), "BondVectors::getBondVectors() - container empty, not set properly?"); for (container_t::const_iterator iter = container.begin(); iter != container.end(); ++iter) { const bond::ptr ¤t_bond = *iter; Vector BondVector = current_bond->leftatom->getPositionAtStep(_step) - current_bond->rightatom->getPositionAtStep(_step); BondVector.Normalize(); current_mapped_vectors.insert( std::make_pair(current_bond, BondVector) ); } ASSERT( current_mapped_vectors.size() == container.size(), "BondVectors::getBondVectors() - not same amount of bond vectors as bonds?"); map_is_dirty = false; current_step_for_map = _step; } size_t BondVectors::getIndexForBond(const bond::ptr &_bond) const { std::pair< container_t::const_iterator, container_t::const_iterator> iters = std::equal_range(container.begin(), container.end(), _bond); if (iters.first != container.end()) return std::distance(container.begin(), iters.first); else return (size_t)-1; } std::vector BondVectors::getAtomsBondVectorsAtStep( const atom &_walker, const size_t &_step) const { if (map_is_dirty || (current_step_for_map != _step)) recalculateBondVectorsAtStep(_step); std::vector BondVectors; // gather subset of BondVectors for the current atom const BondList& ListOfBonds = _walker.getListOfBonds(); for(BondList::const_iterator bonditer = ListOfBonds.begin(); bonditer != ListOfBonds.end(); ++bonditer) { const bond::ptr ¤t_bond = *bonditer; const BondVectors::mapped_t::const_iterator bviter = current_mapped_vectors.find(current_bond); ASSERT( bviter != current_mapped_vectors.end(), "ForceAnnealing() - cannot find current_bond ?"); ASSERT( bviter != current_mapped_vectors.end(), "ForceAnnealing - cannot find current bond "+toString(*current_bond) +" in bonds."); BondVectors.push_back(bviter->second); } LOG(4, "DEBUG: BondVectors for atom #" << _walker.getId() << ": " << BondVectors); return BondVectors; } BondVectors::weights_t BondVectors::getWeightsForAtomAtStep( const atom &_walker, const size_t &_step) const { const std::vector BondVectors = getAtomsBondVectorsAtStep(_walker, _step); weights_t weights; for (std::vector::const_iterator iter = BondVectors.begin(); iter != BondVectors.end(); ++iter) { std::vector scps; scps.reserve(BondVectors.size()); std::transform( BondVectors.begin(), BondVectors.end(), std::back_inserter(scps), boost::bind(static_cast< double (*)(double) >(&fabs), boost::bind(&Vector::ScalarProduct, boost::cref(*iter), _1)) ); const double scp_sum = std::accumulate(scps.begin(), scps.end(), 0.); ASSERT( (scp_sum-1.) > -MYEPSILON, "ForceAnnealing() - sum of weights must be equal or larger one but is " +toString(scp_sum)); weights.push_back( 1./scp_sum ); } LOG(4, "DEBUG: Weights for atom #" << _walker.getId() << ": " << weights); // for testing we check whether all weighted scalar products now come out as 1. #ifndef NDEBUG for (std::vector::const_iterator iter = BondVectors.begin(); iter != BondVectors.end(); ++iter) { std::vector scps; scps.reserve(BondVectors.size()); std::transform( BondVectors.begin(), BondVectors.end(), weights.begin(), std::back_inserter(scps), boost::bind(static_cast< double (*)(double) >(&fabs), boost::bind(std::multiplies(), boost::bind(&Vector::ScalarProduct, boost::cref(*iter), _1), _2)) ); const double scp_sum = std::accumulate(scps.begin(), scps.end(), 0.); ASSERT( fabs(scp_sum - 1.) < MYEPSILON, "ForceAnnealing::operator() - for BondVector "+toString(*iter) +" we have weighted scalar product of "+toString(scp_sum)+" != 1."); } #endif return weights; }