/*
** (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.
*/


//
//@Man:
//@Memo: Class for diffusive/viscous solves
//@Doc: Class to handle Crank-Nicholson diffusive/viscous solves

class diffuser {

//@ManDoc: Problem domain in index space
  Box domain;

//@ManDoc: Mesh spacing in x-direction
  Real hx;

//@ManDoc: Mesh spacing in y-direction
  Real hy;

//@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;

 public:

//@ManDoc: Constructor
  diffuser(const Box& Domain, Real * dx);

//@ManDoc: Destructor
  ~diffuser();

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

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

//@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: Dynamic viscosity coefficient
  Real mu;

//@ManDoc: One-dimensional radius array at cell centers
  Real *x_mg;

//@ManDoc: One-dimensional radius array at nodes
  Real *xhalf_mg;

//@ManDoc: Inflow values along the low x-edge
  Real *uinx_lo;

//@ManDoc: Inflow values along the high x-edge
  Real *uinx_hi;

//@ManDoc: Inflow values along the low y-edge
  Real *uiny_lo;

//@ManDoc: Inflow values along the high y-edge
  Real *uiny_hi;

//@ManDoc: Coefficients 1/rho 
  FArrayBox *sigma;

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

//@ManDoc: Scratch space for the conjugate gradient bottom solver
  FArrayBox *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
  diffuser_mg(const Box & Domain,
                FArrayBox * Phi,
                FArrayBox * Source,
                FArrayBox * Resid,
                FArrayBox * Sigma,
                Real * X,
                Real * Xhalf,
                Real * Uinx_lo,
                Real * Uinx_hi,
                Real * Uiny_lo,
                Real * Uiny_hi,
                Real Hx,
                Real Hy,
                int Level,
                int Idir);

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