/*
* 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 .
*/
/*
* SamplingGrid.cpp
*
* Created on: 25.07.2012
* Author: heber
*/
// include config.h
#ifdef HAVE_CONFIG_H
#include
#endif
// include headers that implement a archive in simple text format
// otherwise BOOST_CLASS_EXPORT_IMPLEMENT has no effect
#include
#include
#include "CodePatterns/MemDebug.hpp"
#include "Jobs/Grid/SamplingGrid.hpp"
#include
#include "CodePatterns/Assert.hpp"
#include "CodePatterns/Log.hpp"
// static instances
const double SamplingGrid::zeroOffset[3] = { 0., 0., 0. };
SamplingGrid::SamplingGrid() :
SamplingGridProperties()
{
setWindowSize(zeroOffset, zeroOffset);
ASSERT( getWindowGridPoints() == (size_t)0,
"SamplingGrid::SamplingGrid() - incorrect number of samples given for the window.");
}
SamplingGrid::SamplingGrid(const double _begin[3],
const double _end[3],
const int _level,
const sampledvalues_t &_sampled_grid) :
SamplingGridProperties(_begin, _end, _level),
sampled_grid(_sampled_grid)
{
setWindowSize(_begin, _end);
ASSERT( getWindowGridPoints() == (size_t)_sampled_grid.size(),
"SamplingGrid::SamplingGrid() - incorrect number of samples given for the window.");
}
SamplingGrid::SamplingGrid(const SamplingGrid &_grid) :
SamplingGridProperties(_grid),
sampled_grid(_grid.sampled_grid)
{
setWindowSize(_grid.begin, _grid.end);
}
SamplingGrid::SamplingGrid(const SamplingGridProperties &_props) :
SamplingGridProperties(_props)
{
setWindowSize(_props.begin, _props.end);
}
SamplingGrid::SamplingGrid(
const SamplingGridProperties &_props,
const sampledvalues_t &_sampled_grid) :
SamplingGridProperties(_props),
sampled_grid(_sampled_grid)
{
setWindowSize(_props.begin, _props.end);
ASSERT( getWindowGridPoints() == (size_t)_sampled_grid.size(),
"SamplingGrid::SamplingGrid() - incorrect number of samples given for the window.");
}
SamplingGrid::~SamplingGrid()
{}
SamplingGrid& SamplingGrid::operator=(const SamplingGrid& other)
{
// check for self-assignment
if (this != &other) {
static_cast(*this) = other;
setWindowSize(other.begin_window, other.end_window);
sampled_grid = other.sampled_grid;
}
return *this;
}
SamplingGrid& SamplingGrid::operator*=(const SamplingGrid& other)
{
// check that grids are compatible
if (isCompatible(other)) {
sampledvalues_t::iterator iter = sampled_grid.begin();
sampledvalues_t::const_iterator otheriter = other.sampled_grid.begin();
for(; iter != sampled_grid.end(); ++iter, ++otheriter )
*iter *= (*otheriter);
} else {
ASSERT(0, "SamplingGrid::operator*=() - superposing incompatible grids is so far not in the cards.");
}
return *this;
}
void SamplingGrid::superposeOtherGrids(const SamplingGrid &other, const double prefactor)
{
/// check that grids are compatible
if (isCompatible(other)) {
/// get maximum of window
double max_begin_window[3];
double max_end_window[3];
bool doExtend = false;
for (size_t index=0; index<3;++index) {
if (begin_window[index] >= other.begin_window[index]) {
max_begin_window[index] = other.begin_window[index];
doExtend = true;
} else {
max_begin_window[index] = begin_window[index];
}
if (end_window[index] >= other.end_window[index]) {
max_end_window[index] = end_window[index];
} else {
max_end_window[index] = other.end_window[index];
doExtend = true;
}
}
if (doExtend)
extendWindow(max_begin_window, max_end_window);
/// and copy other into larger window, too
addOntoWindow(other.begin_window, other.end_window, other.sampled_grid);
// then add other's grid onto this one
sampledvalues_t::iterator iter = sampled_grid.begin();
sampledvalues_t::const_iterator otheriter = other.sampled_grid.begin();
for(; iter != sampled_grid.end(); ++iter, ++otheriter )
*iter += prefactor * (*otheriter);
} else {
ASSERT(0, "SamplingGrid::superposeOtherGrids() - superposing incompatible grids is so far not in the cards.");
}
}
const double SamplingGrid::getVolume() const
{
double volume = 1.;
for (size_t i=0;i<3;++i)
volume *= end[i]-begin[i];
return volume;
}
const double SamplingGrid::getWindowVolume() const
{
double volume = 1.;
for (size_t i=0;i<3;++i)
volume *= end_window[i]-begin_window[i];
return volume;
}
const size_t SamplingGrid::getTotalGridPoints() const
{
return pow(getGridPointsPerAxis(),3);
}
const size_t SamplingGrid::getGridPointsPerAxis() const
{
return pow(2, level);
}
const size_t SamplingGrid::getWindowGridPoints() const
{
const double volume = getVolume();
if (fabs(volume) < std::numeric_limits::epsilon())
return 0;
else
return (getWindowVolume()*getTotalGridPoints())/volume;
}
double SamplingGrid::integral() const
{
const double volume_element = getVolume()/(double)getTotalGridPoints();
double int_value = 0.;
for (sampledvalues_t::const_iterator iter = sampled_grid.begin();
iter != sampled_grid.end();
++iter)
int_value += *iter;
int_value *= volume_element;
LOG(2, "DEBUG: SamplingGrid::integral() is " << scientific << setprecision(13) << int_value << ".");
return int_value;
}
double SamplingGrid::integral(const SamplingGrid &weight) const
{
if (isCompatible(weight)) {
const double volume_element = getVolume()/(double)getTotalGridPoints();
double int_value = 0.;
sampledvalues_t::const_iterator iter = sampled_grid.begin();
sampledvalues_t::const_iterator weightiter = weight.sampled_grid.begin();
for (;iter != sampled_grid.end();++iter,++weightiter)
int_value += (*weightiter) * (*iter);
int_value *= volume_element;
//LOG(2, "DEBUG: SamplingGrid::integral() is " << scientific << setprecision(13) << int_value << ".");
return int_value;
} else
return 0.;
}
void SamplingGrid::setWindowSize(
const double _begin_window[3],
const double _end_window[3])
{
for (size_t index=0;index<3;++index) {
ASSERT( _begin_window[index] >= begin[index],
"SamplingGrid::setWindowSize() - window starts earlier than domain on "
+toString(index)+"th component.");
begin_window[index] = _begin_window[index];
ASSERT( _end_window[index] <= end[index],
"SamplingGrid::setWindowSize() - window ends later than domain on "
+toString(index)+"th component.");
end_window[index] = _end_window[index];
}
}
void SamplingGrid::setWindow(
const double _begin_window[3],
const double _end_window[3])
{
setWindowSize(_begin_window, _end_window);
const size_t gridpoints_window = getWindowGridPoints();
sampled_grid.resize(gridpoints_window, 0.);
}
void SamplingGrid::setDomainSize(
const double _begin[3],
const double _end[3])
{
for (size_t index=0;index<3;++index) {
begin[index] = _begin[index];
end[index] = _end[index];
}
}
void SamplingGrid::setDomain(
const double _begin[3],
const double _end[3])
{
setDomainSize(_begin, _end);
setWindowSize(_begin, _end);
const size_t gridpoints = getTotalGridPoints();
sampled_grid.resize(gridpoints, 0.);
}
void SamplingGrid::extendWindow(
const double _begin_window[3],
const double _end_window[3])
{
// check that we truly have to extend the window
#ifndef NDEBUG
for(size_t index=0;index < 3; ++index) {
ASSERT ( begin_window[index] >= _begin_window[index],
"SamplingGrid::extendWindow() - component "+toString(index)+
" of window start is greater than old value.");
ASSERT ( end_window[index] <= _end_window[index],
"SamplingGrid::extendWindow() - component "+toString(index)+
" of window end is less than old value.");
}
#endif
// copy old window size and values
double old_begin_window[3];
double old_end_window[3];
for(size_t index=0;index<3;++index) {
old_begin_window[index] = begin_window[index];
old_end_window[index] = end_window[index];
}
sampledvalues_t old_values(sampled_grid);
// now extend it ...
addOntoWindow(old_begin_window, old_end_window, old_values);
}
void SamplingGrid::addOntoWindow(
const double _begin_window[3],
const double _end_window[3],
const sampledvalues_t &_sampled_grid)
{
#ifndef NDEBUG
for(size_t index=0;index<3;++index) {
ASSERT( _begin_window[index] >= begin_window[index],
"SamplingGrid::addOntoWindow() - given window starts earlier in component "
+toString(index)+".");
ASSERT( _end_window[index] <= end_window[index],
"SamplingGrid::addOntoWindow() - given window ends later in component "
+toString(index)+".");
}
#endif
// the only issue are indices
const size_t gridpoints_axis = pow(2, level);
size_t offset[3];
size_t length[3];
for(size_t index=0;index<3;++index) {
offset[index] = gridpoints_axis*(_begin_window[index] - begin_window[index]);
length[index] = gridpoints_axis*(_end_window[index] - _begin_window[index]);
}
ASSERT( length[0]*length[1]*length[2] == _sampled_grid.size(),
"SamplingGrid::addOntoWindow() - not enough sampled values given.");
size_t N[3];
// sampledvalues_t::iterator griditer = sampled_grid.begin();
sampledvalues_t::const_iterator copyiter = _sampled_grid.begin();
for(N[0]=offset[0]; N[0] < length[0]; ++N[0]) {
for(N[1]=offset[1]; N[1] < length[1]; ++N[1]) {
for(N[2]=offset[2]; N[2] < length[2]; ++N[2]) {
const size_t index =
(N[0]*gridpoints_axis+N[1])*gridpoints_axis+N[2];
sampled_grid[index] += *copyiter;
}
}
}
}
std::ostream & operator<<(std::ostream &ost, const SamplingGrid& other)
{
ost << "SamplingGrid";
ost << " starting at " << other.begin[0] << "," << other.begin[1] << "," << other.begin[2];
ost << " ending at " << other.end[0] << "," << other.end[1] << "," << other.end[2];
ost << ", window starting at " << other.begin_window[0] << "," << other.begin_window[1] << "," << other.begin_window[2];
ost << ", window ending at " << other.end_window[0] << "," << other.end_window[1] << "," << other.end_window[2];
ost << ", level of " << other.level;
ost << " and integrated value of " << other.integral();
return ost;
}
template<> SamplingGrid ZeroInstance()
{
SamplingGrid returnvalue;
return returnvalue;
}
// we need to explicitly instantiate the serialization functions as
// its is only serialized through its base class FragmentJob
BOOST_CLASS_EXPORT_IMPLEMENT(SamplingGrid)