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


#ifndef _GRID_H_
#define _GRID_H_ 

#include <string>

#include <Box.H>
#include <FArrayBox.H>
#include <hgproj.H>
#include <macproj.H>
#include <diffuser.H>

enum StateNames { Xvel=0, Yvel, Zvel, Density, Tracer};

//
//@Man:
//@Doc: This class is called from main and handles all the work
//@Memo: Handles all the time-stepping
class Grid {
   protected:

//@ManDoc: Pointer to a nodal projection operator
      hg_projector* proj;

//@ManDoc: Pointer to a MAC projection operator
      mac_projector* macproj;

//@ManDoc: Pointer to a solver for the Crank-Nicholson diffusive/viscous update
      diffuser* diffuse_op;

//@ManDoc: Pointer to the old-time x-velocity
      Real* u;

//@ManDoc: Pointer to the old-time y-velocity
      Real* v;

//@ManDoc: Pointer to the old-time z-velocity
      Real* w;

//@ManDoc: Pointer to the old-time density
      Real* rho;

//@ManDoc: Pointer to the old-time x-velocity
      Real* un;

//@ManDoc: Pointer to the new-time y-velocity
      Real* vn;

//@ManDoc: Pointer to the new-time z-velocity
      Real* wn;

//@ManDoc: Pointer to the new-time density
      Real* rhon;

//@ManDoc: Pointer to the density at time (n+1/2)
      Real* rhohalf;

//@ManDoc: Pointer to the x-component of pressure gradient
      Real* px;

//@ManDoc: Pointer to the y-component of pressure gradient
      Real* py;

//@ManDoc: Pointer to the z-component of pressure gradient
      Real* pz;

//@ManDoc: Pointer to the normal advection velocity on x-faces
      Real *uadv;

//@ManDoc: Pointer to the normal advection velocity on y-faces
      Real *vadv;

//@ManDoc: Pointer to the normal advection velocity on z-faces
      Real *wadv;

//@ManDoc: Pointer to the x-velocity used for transverse derivatives.
      Real *utrans;

//@ManDoc: Pointer to the y-velocity used for transverse derivatives.
      Real *vtrans;

//@ManDoc: Pointer to the z-velocity used for transverse derivatives.
      Real *wtrans;

//@ManDoc: Order of the slope calculation (1st, 2nd, or 4th)
      static int slope_order;

//@ManDoc: How many initial iterations to do
      static int init_iter;

//@ManDoc:: fixed time step
      static Real fixed_dt;

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

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

//@ManDoc: Mesh spacing in the z-direction
      Real _hz;

//@ManDoc: File name of the checkpoint file to read from
      std::string restart_file;

//@ManDoc: Read and parse the inputs file
    void parseInputs();

//@ManDoc: Build aliases to state variable components
    void buildLinks();

//@ManDoc: Restart calculation from checkpoint file
    void restart(std::string& filename, int& nstep, Real& time, Real& dt);

      Box         prob_domain;
      Real        prob_size[BL_SPACEDIM];
      Real        prob_lo[BL_SPACEDIM];
      Real        prob_hi[BL_SPACEDIM];
      Real        dx[BL_SPACEDIM];

      std::string     probin_file;

      FArrayBox state;
      FArrayBox staten;
      FArrayBox slopex;
      FArrayBox slopey;
      FArrayBox slopez;
      FArrayBox rhonph;
      FArrayBox pressure;
      FArrayBox gradp;
      FArrayBox force;
      FArrayBox scalforce;
      FArrayBox divu_src;
      FArrayBox visc;
      FArrayBox diff;
      FArrayBox edgex;
      FArrayBox edgey;
      FArrayBox edgez;

/*@ManDoc: Array holds flags as to whether scalars should be conservatively
           or convectively updated 
*/
      Array<int> is_conserv;  

/*@ManDoc: Array holds diffusion coefficients of advected scalars
*/
      Array<Real> diff_coef;  

//@ManDoc: Coefficient of dynamic viscosity.
      Real visc_coef;  

//@ManDoc: Number of scalars, defined as N_STATE - NDIM
      int numscal;

   protected:
//@ManDoc: Allocate and initialize state variables
      void initialInit(int& nstep, Real& time, Real& dt);

//@ManDoc: Do all the work to advance state 
      void timeStep(Real time, Real dt);

//@ManDoc: Calculate the slopes of all state variables 
      void getSlopes(int first_comp, int num_comp);

//@ManDoc: Calculate the viscous terms for the momentum equations
      void getViscTerm();

//@ManDoc: Calculate the diffusive terms for the scalar update equations
      void getDiffTerm();

//@ManDoc: Calculate the pressure gradient
      void getGradP();

//@ManDoc: Define the forcing terms in the momentum equation
      void getForce(Real current_time);

//@ManDoc: Define the forcing terms in the scalar equations
      void getScalForce(Real current_time);

//@ManDoc: Create the edge-based half-time advection velocities
      void makeAdvVels(Real dt, Real time);

//@ManDoc: Update the scalar quantities
      void updateScalars(Real dt, Real time);

//@ManDoc: Update velocity
      void updateVelocity(Real dt, Real time);

//@ManDoc: Calculate the half-time density = avg of rho and rhon
      void getRhoHalf(Real time, Real dt);

   public:
//@ManDoc: Constructor
      Grid(std::string probin_file);

//@ManDoc: Destructor
      ~Grid();

//@ManDoc: Calculate dt for the next time step
      Real estimateDt(Real & dt, Real cfl);

//@ManDoc: Decide whether to init with initialInit or restart
      void init(int& nstep, Real& time, Real& dt);

//@ManDoc: Perform the initial iterations to calculate an initial pressure
      void initialIter(Real time, Real dt);

//@ManDoc: Call timeStep and swap staten with state.
      void advance(Real time, Real dt);

//@ManDoc: Write a checkpoint file to be used for restart
      void writeCheckPoint(int nstep, Real time, Real dt,
			   std::string& check_file_root);

//@ManDoc: Write a pltfile to be used for viewing data
      void writePlotFile(int nstep, Real time,
			 std::string& plot_file_root);

//@ManDoc: Worker function to write a plotfile
      void writePlotFile(std::string& dir, std::ostream& HeaderFile,
			 int nstep, Real time);

//@ManDoc: Keep track of which style plotfiles you are using
      std::string thePlotFileType();

//@ManDoc: Derive the necesary quantity for the contour plots and plt files
      void deriveData(FArrayBox& data, const std::string& varname, Real time);

//@ManDoc: Return the cell size
      const Real* cellSize() const { return dx; }

//@ManDoc: Return the problem size
      const Real* probSize() const { return prob_size; }

//@ManDoc: Return the problem domain
      const Box& probDomain() { return prob_domain;  }
};
#endif
