/*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy.  Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov.  NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly.  Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/


#include "multigrid.H"

//
//@Man:
//@Memo: Nodal projection class for end-of-time-step nodal projection
/*@ManDoc: This class handles the nodal projection of the new-time
           velocity.  It computes RHS = D(V), and sends the RHS
           and coefficients sigma = 1/rho to the hgprojection_mg
           class, which solves the linear system using multigrid.
*/

class hg_projector {

//@ManDoc: Problem domain broken down into grids.
  BoxArray grids;

//@ManDoc: Geometry object.
  Geometry geom;

//@ManDoc: area arrays.
  const MultiFab* area;

//@ManDoc: Volume arrays.
  const MultiFab& vol;

//@ManDoc: Tolerance to which DG(phi) = RHS should be solved
  Real tol;

//@ManDoc: number of smoothing steps as you coarsen
  static int numSmoothCoarsen;

//@ManDoc: number of smoothing steps as you refine
  static int numSmoothRefine;

//@ManDoc: Number of ghost cells = max of numSmoothCoarsen/Refine
  static int ng;

 public:

//@ManDoc: Constructor 
  hg_projector(const BoxArray& Grids, const Geometry& Geom,
               MultiFab* area, MultiFab& volume);

//@ManDoc: Destructor
  ~hg_projector();

//@ManDoc: Do the nodal projection
  void project(MultiFab * state, 
               MultiFab * gradp,
               MultiFab * rho, 
               MultiFab * divu_src,
               Real        time, 
               Real        dt);

//@ManDoc: Compute the pressure gradient at cell centers
  void gradient(MultiFab * gradp, 
                MultiFab * pressure);

};

//@ManDoc: The multigrid solver for the nodal projection
class hgprojection_mg : public multigrid {

//@Memo: Multigrid solver for nodal projection

//@ManDoc: Coefficient array = 1 / rho
  MultiFab * sigma;

//@ManDoc: Coefficient array built of sigmas and used only in 3-d.
  MultiFab * coeff;

//@ManDoc: Next coarser multigrid level
  hgprojection_mg *Next;

//@ManDoc: Scratch space for the conjugate gradient bottom solver
  MultiFab * cgwork;

//@ManDoc: Compute the residual R = RHS - DG(phi)
  Real residual();

//@ManDoc: Relax on the residual equation, updating phi
  void step(int);

//@ManDoc: Coarsen the residual to the next coarser multigrid level
  void Restrict();

//@ManDoc: Interpolate the solution from the next coarser multigrid level
  void interpolate();

 public:
//@ManDoc: Constructor
  hgprojection_mg(const BoxArray & Grids,
                  const Geometry & Geom,
                  MultiFab * Phi,
                  MultiFab * Source,
                  MultiFab * Residual,
                  MultiFab * Sigma, 
#if (BL_SPACEDIM == 3)
                  MultiFab * Coeff, 
#endif
                  const Real* Dx);


//@ManDoc: Destructor
  ~hgprojection_mg();
};
