/*  This file is part of the OpenLB library
 *
 *  Copyright (C) 2006, 2007, 2008 Jonas Latt
 *  E-mail contact: info@openlb.net
 *  The most recent release of OpenLB can be downloaded at
 *  
 *
 *  This program 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.
 *
 *  This program 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, write to the Free
 *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA  02110-1301, USA.
*/
#ifndef POST_PROCESSING_HH
#define POST_PROCESSING_HH
#include "blockLattice2D.h"
#include "blockLattice3D.h"
//#include 
//#include 
//#include 
//#include "util.h"
namespace olb {
////////////////////// Class PostProcessorGenerator2D /////////////////
template
PostProcessorGenerator2D::PostProcessorGenerator2D (
  int x0_, int x1_, int y0_, int y1_)
  : x0(x0_), x1(x1_), y0(y0_), y1(y1_)
{ }
template
void PostProcessorGenerator2D::shift(int deltaX, int deltaY)
{
  x0 += deltaX;
  x1 += deltaX;
  y0 += deltaY;
  y1 += deltaY;
}
template
bool PostProcessorGenerator2D::
extract(int x0_, int x1_, int y0_, int y1_)
{
  int newX0, newX1, newY0, newY1;
  if ( util::intersect (
         x0, x1, y0, y1,
         x0_, x1_, y0_, y1_,
         newX0, newX1, newY0, newY1 ) ) {
    x0 = newX0;
    x1 = newX1;
    y0 = newY0;
    y1 = newY1;
    return true;
  } else {
    return false;
  }
}
////////////////////// Class LatticeCouplingGenerator2D /////////////////
template
LatticeCouplingGenerator2D::LatticeCouplingGenerator2D (
  int x0_, int x1_, int y0_, int y1_)
  : x0(x0_), x1(x1_), y0(y0_), y1(y1_)
{ }
template
void LatticeCouplingGenerator2D::shift(int deltaX, int deltaY)
{
  x0 += deltaX;
  x1 += deltaX;
  y0 += deltaY;
  y1 += deltaY;
}
template
bool LatticeCouplingGenerator2D::extract(int x0_, int x1_, int y0_, int y1_)
{
  int newX0, newX1, newY0, newY1;
  if ( util::intersect (
         x0, x1, y0, y1,
         x0_, x1_, y0_, y1_,
         newX0, newX1, newY0, newY1 ) ) {
    x0 = newX0;
    x1 = newX1;
    y0 = newY0;
    y1 = newY1;
    return true;
  } else {
    return false;
  }
}
template
void LatticeCouplingGenerator2D::reset(int x0_, int x1_, int y0_, int y1_)
{
  x0 = x0_;
  x1 = x1_;
  y0 = y0_;
  y1 = y1_;
}
////////////////////// Class StatisticsPostProcessor2D //////////////
template
StatisticsPostProcessor2D::StatisticsPostProcessor2D()
{ }
#ifndef PARALLEL_MODE_OMP
template
void StatisticsPostProcessor2D::process (
  BlockLattice2D& blockLattice )
{
  blockLattice.getStatistics().reset();
}
#endif
#ifdef PARALLEL_MODE_OMP
template
void StatisticsPostProcessor2D::process (
  BlockLattice2D& blockLattice )
{
  #pragma omp parallel
  blockLattice.getStatistics().reset();
  int numCells     = 0;
  T avRho    = T();
  T avEnergy = T();
  T maxU     = T();
  #pragma omp parallel
  {
    #pragma omp critical
    {
      numCells       += blockLattice.getStatistics().getNumCells();
      avRho          += blockLattice.getStatistics().getAverageRho()
      *blockLattice.getStatistics().getNumCells();
      avEnergy       += blockLattice.getStatistics().getAverageEnergy()
      *blockLattice.getStatistics().getNumCells();
      if (maxU
StatPPGenerator2D::StatPPGenerator2D()
  : PostProcessorGenerator2D(-1,-1,-1,-1)
{ }
template
PostProcessor2D* StatPPGenerator2D::generate() const
{
  return new StatisticsPostProcessor2D;
}
template
PostProcessorGenerator2D*
StatPPGenerator2D::clone() const
{
  return new StatPPGenerator2D;
}
////////////////////// Class PostProcessorGenerator3D /////////////////
template
PostProcessorGenerator3D::PostProcessorGenerator3D (
  int x0_, int x1_, int y0_, int y1_, int z0_, int z1_)
  : x0(x0_), x1(x1_), y0(y0_), y1(y1_), z0(z0_), z1(z1_)
{ }
template
void PostProcessorGenerator3D::shift (
  int deltaX, int deltaY, int deltaZ )
{
  x0 += deltaX;
  x1 += deltaX;
  y0 += deltaY;
  y1 += deltaY;
  z0 += deltaZ;
  z1 += deltaZ;
}
template
bool PostProcessorGenerator3D::
extract(int x0_, int x1_, int y0_, int y1_, int z0_, int z1_)
{
  int newX0, newX1, newY0, newY1, newZ0, newZ1;
  if ( util::intersect (
         x0, x1, y0, y1, z0, z1,
         x0_, x1_, y0_, y1_, z0_, z1_,
         newX0, newX1, newY0, newY1, newZ0, newZ1 ) ) {
    x0 = newX0;
    x1 = newX1;
    y0 = newY0;
    y1 = newY1;
    z0 = newZ0;
    z1 = newZ1;
    return true;
  } else {
    return false;
  }
}
////////////////////// Class LatticeCouplingGenerator3D /////////////////
template
LatticeCouplingGenerator3D::LatticeCouplingGenerator3D (
  int x0_, int x1_, int y0_, int y1_, int z0_, int z1_)
  : x0(x0_), x1(x1_), y0(y0_), y1(y1_), z0(z0_), z1(z1_)
{ }
template
void LatticeCouplingGenerator3D::shift (
  int deltaX, int deltaY, int deltaZ, int iC_)
{
  x0 += deltaX;
  x1 += deltaX;
  y0 += deltaY;
  y1 += deltaY;
  z0 += deltaZ;
  z1 += deltaZ;
  iC = iC_;
}
template
bool LatticeCouplingGenerator3D::
extract(int x0_, int x1_, int y0_, int y1_, int z0_, int z1_)
{
  int newX0, newX1, newY0, newY1, newZ0, newZ1;
  if ( util::intersect (
         x0, x1, y0, y1, z0, z1,
         x0_, x1_, y0_, y1_, z0_, z1_,
         newX0, newX1, newY0, newY1, newZ0, newZ1 ) ) {
    x0 = newX0;
    x1 = newX1;
    y0 = newY0;
    y1 = newY1;
    z0 = newZ0;
    z1 = newZ1;
    return true;
  } else {
    return false;
  }
}
template
void LatticeCouplingGenerator3D::
reset(int x0_, int x1_, int y0_, int y1_, int z0_, int z1_)
{
  x0 = x0_;
  x1 = x1_;
  y0 = y0_;
  y1 = y1_;
  z0 = z0_;
  z1 = z1_;
}
////////////////////// Class StatisticsPostProcessor3D //////////////
template
StatisticsPostProcessor3D::StatisticsPostProcessor3D()
{ }
#ifndef PARALLEL_MODE_OMP
template
void StatisticsPostProcessor3D::process (
  BlockLattice3D& blockLattice )
{
  blockLattice.getStatistics().reset();
}
#endif
#ifdef PARALLEL_MODE_OMP
template
void StatisticsPostProcessor3D::process (
  BlockLattice3D& blockLattice )
{
  #pragma omp parallel
  blockLattice.getStatistics().reset();
  int numCells     = 0;
  T avRho    = T();
  T avEnergy = T();
  T maxU     = T();
  #pragma omp parallel
  {
    #pragma omp critical
    {
      numCells       += blockLattice.getStatistics().getNumCells();
      avRho          += blockLattice.getStatistics().getAverageRho()
      *blockLattice.getStatistics().getNumCells();
      avEnergy       += blockLattice.getStatistics().getAverageEnergy()
      *blockLattice.getStatistics().getNumCells();
      if (maxU
StatPPGenerator3D::StatPPGenerator3D()
  : PostProcessorGenerator3D(-1,-1,-1,-1,-1,-1)
{ }
template
PostProcessor3D* StatPPGenerator3D::generate() const
{
  return new StatisticsPostProcessor3D;
}
template
PostProcessorGenerator3D* StatPPGenerator3D::clone() const
{
  return new StatPPGenerator3D;
}
}  // namespace olb
#endif