/*
 *    vmg - a versatile multigrid solver
 *    Copyright (C) 2012 Institute for Numerical Simulation, University of Bonn
 *
 *  vmg 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 3 of the License, or
 *  (at your option) any later version.
 *
 *  vmg 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 this program.  If not, see .
 */
/**
 * @file   helper.cpp
 * @author Julian Iseringhausen 
 * @date   Tue Apr  5 21:03:47 2011
 *
 * @brief  Provides various helper functions.
 *
 */
#ifdef HAVE_CONFIG_H
#include 
#endif
#include 
#include 
#include "base/helper.hpp"
#include "base/index.hpp"
#include "base/vector.hpp"
#include "grid/grid.hpp"
using namespace VMG;
char* Helper::GetCharArray(const std::string& str)
{
  int size = str.size();
  char* rval = new char[size+1];
  strncpy(rval, str.c_str(), size);
  rval[size] = '\0';
  return rval;
}
std::string Helper::ReplaceWhitespaces(const char* buffer, const char* replace)
{
  size_t pos;
  std::string str(buffer);
  while ((pos = str.find(' ')) != std::string::npos)
    str.replace(pos, 1, replace);
  return str;
}
vmg_float Helper::InterpolateTrilinear(const Vector& point, const Grid& grid)
{
  vmg_float interpolate_vals[4], grid_vals[8];
  const Index index_global = (point - grid.Extent().Begin()) / grid.Extent().MeshWidth();
  const Index index_local = index_global - grid.Global().LocalBegin() + grid.Local().Begin();
  const Vector coord = (point - grid.Extent().Begin() - index_global * grid.Extent().MeshWidth()) / grid.Extent().MeshWidth();
  grid_vals[0] = grid.GetVal(index_local.X()  , index_local.Y()  , index_local.Z()  );
  grid_vals[1] = grid.GetVal(index_local.X()+1, index_local.Y()  , index_local.Z()  );
  grid_vals[2] = grid.GetVal(index_local.X()  , index_local.Y()+1, index_local.Z()  );
  grid_vals[3] = grid.GetVal(index_local.X()+1, index_local.Y()+1, index_local.Z()  );
  grid_vals[4] = grid.GetVal(index_local.X()  , index_local.Y()  , index_local.Z()+1);
  grid_vals[5] = grid.GetVal(index_local.X()+1, index_local.Y()  , index_local.Z()+1);
  grid_vals[6] = grid.GetVal(index_local.X()  , index_local.Y()+1, index_local.Z()+1);
  grid_vals[7] = grid.GetVal(index_local.X()+1, index_local.Y()+1, index_local.Z()+1);
  for (int i=0; i<4; ++i)
    interpolate_vals[i] = (1.0 - coord.X()) * grid_vals[2*i] + coord.X() * grid_vals[2*i+1];
  for (int i=0; i<2; ++i)
    interpolate_vals[i] = (1.0 - coord.Y()) * interpolate_vals[2*i] + coord.Y() * interpolate_vals[2*i+1];
  return (1.0 - coord.Z()) * interpolate_vals[0] + coord.Z() * interpolate_vals[1];
}
bool Helper::AssertVectorsEqual(const Vector& pos_1, const Vector& pos_2, const vmg_float& tol)
{
  // create factor with similar magnitude as pos1 but always greater equal 1
  const VMG::Vector factor( abs(pos_1.X())+1, abs(pos_1.Y())+1, abs(pos_1.Z())+1);
  const VMG::Vector temp = (pos_1 - pos_2).Abs() / factor;
  bool equal = temp.IsComponentwiseLessOrEqual(tol);
  assert(equal);
  return equal;
}