/*
 * 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 .
 */
/*
 * VMGDebugGridJob.cpp
 *
 *  Created on: Jul 13, 2012
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#ifdef HAVE_MPI
#include "mpi.h"
#endif
// include headers that implement a archive in simple text format
// otherwise BOOST_CLASS_EXPORT_IMPLEMENT has no effect
#include 
#include 
#include "mg.hpp"
#include "base/object.hpp"
#include "base/defs.hpp"
#ifdef HAVE_MPI
#include "comm/comm_mpi.hpp"
#include "comm/domain_decomposition_mpi.hpp"
#else
#include "comm/comm_serial.hpp"
#endif
#include "cycles/cycle_cs_periodic.hpp"
#include "grid/multigrid.hpp"
//#include "grid/tempgrid.hpp"
#include "level/level_operator_cs.hpp"
#include "level/stencils.hpp"
#include "samples/discretization_poisson_fd.hpp"
#include "smoother/gsrb_poisson_4.hpp"
#include "solver/givens.hpp"
//#include "solver/solver_regular.hpp"
#include "solver/solver_singular.hpp"
//#include "units/particle/comm_mpi_particle.hpp"
#include "CodePatterns/MemDebug.hpp"
#include "Jobs/VMGDebugGridJob.hpp"
#include "LinearAlgebra/defs.hpp"
#include "Jobs/InterfaceVMGDebugGridJob.hpp"
using namespace VMG;
VMGDebugGridJob::VMGDebugGridJob(
    const JobId_t _JobId,
    const SamplingGrid &_density_grid) :
  FragmentJob(_JobId),
  density_grid(_density_grid)
{}
VMGDebugGridJob::VMGDebugGridJob() :
  FragmentJob(JobId::IllegalJob)
{}
VMGDebugGridJob::~VMGDebugGridJob()
{}
FragmentResult::ptr VMGDebugGridJob::Work()
{
  // initialize VMG library solver
  InitVMG();
  /*
   * Start the multigrid solver,
   * hence calling InterfaceVMGDebugGridJob::ImportRightHandSide()
   */
  MG::Solve();
  /*
   * Delete all data.
   */
  MG::Destroy();
  std::stringstream returnstream;
  boost::archive::text_oarchive oa(returnstream);
  std::string message("Sampled Grid");
  oa << message;
  FragmentResult::ptr ptr( new FragmentResult(getId(), returnstream.str()) );
  return ptr;
}
/** Initialization of VMG library.
 *
 * The contents is heavily inspired from interface_fcs.cpp: VMG_fcs_init() of
 * the ScaFaCoS project.
 *
 */
void VMGDebugGridJob::InitVMG()
{
  // TODO: As a matter of fact should use open boundary conditions
  const Boundary boundary(Periodic, Periodic, Periodic);
  /*
   * Choose multigrid components
   */
#ifdef HAVE_MPI
  new CommMPI(boundary, new DomainDecompositionMPI());
#else
  new CommSerial(boundary);
#endif
  new DiscretizationPoissonFD(4);
  new VMGInterfaces::InterfaceVMGDebugGridJob(
      density_grid,
      boundary,
      2,
      density_grid.level,
      Vector(density_grid.begin),
      density_grid.end[0]-density_grid.begin[0],
      5);
  new LevelOperatorCS(Stencils::RestrictionFullWeight, Stencils::InterpolationTrilinear);
  new Givens();
  const int cycle_type = 1; // V-type
  new CycleCSPeriodic(cycle_type);
  new GaussSeidelRBPoisson4();
  /*
   * Register required parameters.
   * We don't actually want solve anything here
   */
  new ObjectStorage("PRESMOOTHSTEPS", 1);
  new ObjectStorage("POSTSMOOTHSTEPS", 1);
  new ObjectStorage("PRECISION", 1.0e-0);
  new ObjectStorage("MAX_ITERATION", 1);
  new ObjectStorage("PARTICLE_NEAR_FIELD_CELLS", 3);
  new ObjectStorage("PARTICLE_INTERPOLATION_DEGREE", 3);
  /*
   * Post init
   */
  MG::PostInit();
  /*
   * Check whether the library is correctly initialized now.
   */
  MG::IsInitialized();
}
// we need to explicitly instantiate the serialization functions as
// its is only serialized through its base class FragmentJob
BOOST_CLASS_EXPORT_IMPLEMENT(VMGDebugGridJob)