/*
* 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;
}