/*
** (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 <MultiFab.H>
#include <Geometry.H>
#include <names.H>
#include <hgproj.H>
#include <macproj.H>
#include <diffuser.H>
#include <VisMF.H>

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

//@ManDoc: BoxArray which covers the domain
      BoxArray grids;

//@ManDoc: Geometry object
      Geometry geom;

//@ManDoc: Mesh spacing array.
      const Real* dx;

//@ManDoc: Is the coordinate system r-z?
      int is_rz;

//@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: 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: File name of the checkpoint file to read from
      std::string restart_file;

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

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

      std::string     probin_file;

      MultiFab state;
      MultiFab staten;
      MultiFab slopex;
      MultiFab slopey;
#if (BL_SPACEDIM == 3)
      MultiFab slopez;
#endif
      MultiFab rhonph;
      MultiFab pressure;
      MultiFab gradp;
      MultiFab force;
      MultiFab scalforce;
      MultiFab visc;
      MultiFab diff;
      MultiFab edgex;
      MultiFab edgey;
#if (BL_SPACEDIM == 3)
      MultiFab edgez;
#endif
      MultiFab uadv;
      MultiFab vadv;
#if (BL_SPACEDIM == 3)
      MultiFab wadv;
#endif
      MultiFab utrans;
      MultiFab vtrans;
#if (BL_SPACEDIM == 3)
      MultiFab wtrans;
#endif
      MultiFab area[BL_SPACEDIM];
      MultiFab vol;

      static int verbose;
      static int writeTurb;

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

/*@ManDoc: Array holds diffusive coefficients for 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: Print out the max and min of the current state.
      void printMaxMin();

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

//@ManDoc: Calculate the viscous term for momentum equation
      void getViscTerm();

//@ManDoc: Calculate the diffusive term for scalar update equation
      void getDiffTerm();

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

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

//@ManDoc: Compute the kinetic energy
      void getKinetic(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(BoxArray Grids, Geometry& geom, 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: Set up the data structures.
      void init_data_structures();

//@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: Worker function to write a checkPoint file
      void checkPoint(const std::string& dir, std::ostream& os, 
                      VisMF::How how = VisMF::OneFilePerCPU);

//@ManDoc: Worker function to write a plotfile
      void writePlotFile(MultiFab& plotMF, Real time);

//@ManDoc: Derive the necesary quantity for the plot files
      void deriveData(MultiFab& data, const std::string& varname, Real time);

//@ManDoc: Return the number of state variables
      int NumState();

//@ManDoc: Return the number of derived variables
      int NumDerive();
};
#endif
