/*
** (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: Class for diffusive/viscous solves
//@Doc: Class to handle Crank-Nicholson diffusive/viscous solves

class diffuser {

//@ManDoc: Problem domain in index space, broken up into multiple boxes
  BoxArray grids;

//@ManDoc: Geometry object.
  Geometry geom;

//@ManDoc: Area array.
  MultiFab* area;

//@ManDoc: Volume array.
  MultiFab& vol;

//@ManDoc: Tolerance for multigrid iterative solve
  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 extra ghost cells.
  static int ng;

 public:

//@ManDoc: Constructor
  diffuser(const BoxArray& grids, const Geometry& geom, 
           MultiFab* area, MultiFab& vol);

//@ManDoc: Destructor
  ~diffuser();

//@ManDoc: Solve for the new-time velocity
  void solveVel(MultiFab * staten, 
                MultiFab * rho, 
                Real mu);

//@ManDoc: Solve for the new-time scalar field
  void solveScal(MultiFab * staten, 
                 Real mu,
                 int n);

//@ManDoc: Put the equations into residual-correction form.
  Real rescorr(MultiFab * phi,  MultiFab * source, MultiFab * resid,
               MultiFab* local_area[], MultiFab* alpha, int idir, Real mu);
};

//@ManDoc: Multigrid solver for the Crank-Nicholson discretization
class diffuser_mg : public multigrid {

//@Memo: Multigrid solver for diffusive/viscous solves.

//@ManDoc: Multigrid level
  int level;

//@ManDoc: Which component of velocity is being solved for
  int idir;

//@ManDoc: Diffusion coefficient.
  Real mu;

//@ManDoc: Area arrays.
  MultiFab* area[BL_SPACEDIM];

//@ManDoc: Alpha = rho * volume.
  MultiFab * alpha;

//@ManDoc: Pointer to the next coarsest multigrid level
  diffuser_mg *Next;

//@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
  diffuser_mg(const BoxArray & Grids,
              const Geometry& Geom,
              MultiFab*  Phi,
              MultiFab* Source,
              MultiFab* Resid,
              MultiFab* Area[],
              MultiFab* Alpha,
              const Real* Dx,
              int Level,
              int Idir,
              Real Mu);

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