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


//
// $Id: AmrData.H,v 1.23 2002/02/26 01:00:01 vince Exp $
//

// ---------------------------------------------------------------
// AmrData.H
// ---------------------------------------------------------------
#ifndef _AMRDATA_H_
#define _AMRDATA_H_

#include "AmrvisConstants.H"
#include "Array.H"
#include "MultiFab.H"
#include "VisMF.H"

#include <vector>
#include <fstream>
#include <list>
#include <string>
using std::list;
using std::string;
using std::vector;
using std::istream;
using std::ostream;

class Interpolater;

class AmrData {
  
 protected: 
  // List of grids at each level, level 0 being coarsest.
  Array<Array<MultiFab *> > dataGrids;    // [level][component]
  //Array<Array<Array<bool> > > dataGridsDefined;  // [level][component][index]
  vector<vector<vector<bool> > > dataGridsDefined;  // [level][component][index]
  // ^^^^^^^^^^^^^^^^^^^^^^^^ need to put these in a class which handles
  //                          setting defined/not defined
  Array<Array<VisMF *> > visMF;    // [level][whichMultiFab]
  Array<int> compIndexToVisMFMap;  // [nComp]
  Array<int> compIndexToVisMFComponentMap;  // [nComp]
  
  int finestLevel;   // most refined level available
  Array<int> refRatio; // refinement ratio between level L and L+1
  Array< Array<Real> > dxLevel;  // [level][dim];   // grid spacing
  Array< Array< Array<Real> > > gridLocLo, gridLocHi;
  Array<Box>  probDomain;
  Array<Box>  maxDomain;        // max problem domain size
  Array<Real> probSize, probLo, probHi;
  Real time;
  Array<string> plotVars;
  Array<Real> vfEps, afEps;
  int nComp, nGrow;
  int nRegions;         // number of boundary regions
  int boundaryWidth;    // number of zones in the boundary regions
  int coordSys;
  Array< Array< FArrayBox *> > regions; // [lev][nReg]  ptrs to bndry data
  BoxArray fabBoxArray;  // used only for fileType == FAB
  string plotFileVersion;
  
  FileType fileType;
  bool bCartGrid;
  bool bTerrain;
  
 public:
  AmrData();
  ~AmrData();
  
  bool ReadData(const string &filename, FileType filetype);
  bool ReadNonPlotfileData(const string &filename, FileType filetype);
  
  const Array<string> &PlotVarNames() const { return plotVars; }
  
  int FinestLevel() const		{ return finestLevel; }
  const Array<int> &RefRatio() const      { return refRatio; }
  const BoxArray &boxArray(int level) const {
    if(fileType == FAB || (fileType == MULTIFAB && level == 0)) {
      return fabBoxArray;
    } else {
      // use visMF[][0]:  all boxArrays are
      // guaranteed to be the same for each MultiFab
      return visMF[level][0]->boxArray();
    }
  }
  
  // limits of interior region of computational domain at each level
  const Array<Box> &ProbDomain() const { return probDomain; }
  // physical size of computational domain
  const Array<Real> &ProbSize() const    { return probSize; }
  const Array<Real> &ProbLo()   const    { return probLo;   }
  const Array<Real> &ProbHi()   const    { return probHi;   }
  
  // return physical location of cell at index ix, level lev
  // cellLoc   = location of cell center
  // loNodeLoc = location of node (vertex) on lower left hand corner
  // hiNodeLoc = location of node (vertex) on upper right hand corner
  void  CellLoc(int lev,   IntVect ix, Array<Real> &pos) const;
  void  LoNodeLoc(int lev, IntVect ix, Array<Real> &pos) const;
  void  HiNodeLoc(int lev, IntVect ix, Array<Real> &pos) const;

  // find the IntVect given a physical location
  // returns the intvect, the finest level it is contained on,
  // and the intvect at the given finest level
  void IntVectFromLocation(const int finestFillLevel, const Array<Real> &location,
                           IntVect &ivLoc, int &ivLevel, IntVect &ivFinestFillLev);
  
  const Array< Array< Array<Real> > > &GridLocLo() const { return gridLocLo; }
  const Array< Array< Array<Real> > > &GridLocHi() const { return gridLocHi; }
  const Array< Array<Real> > &DxLevel() const { return dxLevel; }
  
  int NComp() const		{ return nComp; }
  int BoundaryWidth() const	{ return boundaryWidth; }
  int NGrow() const	        { return nGrow; }
  int CoordSys() const	        { return coordSys; }
  Real Time() const	        { return time; }
  const string &PlotFileVersion() { return plotFileVersion; }
  
  // fill a databox using conservative interpolation
  void FillVar(FArrayBox *destFab, const Box &destBox,
               int finestFillLevel, const string &varName, int procWithFabs);
  void FillVar(Array<FArrayBox *> &destFabs, const Array<Box> &destBoxes,
               int finestFillLevel, const string &varName, int procWithFabs);
  void FillVar(MultiFab &destMultiFab, int finestFillLevel,
	       const Array<string> &varNames, const Array<int> &destFillComps);
  void FillVar(MultiFab &destMultiFab, int finestFillLevel,
	       const string &varname, int destcomp = 0);
  
  const string &GetFileName() const { return fileName; }
  
  void SetFileType(FileType type);
  FileType GetFileType() const     { return fileType;  }
  bool CartGrid() const            { return bCartGrid; }
  Real VfEps(int level) const      { return vfEps[level]; }
  void SetVfEps(Real *newvfeps, int finestlev);
  bool Terrain()  const            { return bTerrain; }

  void SetBoundaryWidth(int width) { boundaryWidth = width; }
  
  bool CanDerive(const string &name) const;
  int  NumDeriveFunc() const;
  void ListDeriveFunc(ostream &os) const;
  int  StateNumber(const string &statename) const;
  
  // return the finest level <= startLevel that fully contains box b
  // b is defined on startLevel
  int FinestContainingLevel(const Box &b, int startLevel) const;
  
  // return the finest level <= startLevel that intersects box b
  // b is defined on startLevel
  int FinestIntersectingLevel(const Box &b, int startLevel) const;
  
  // number of grids at level which intersect b
  int NIntersectingGrids(int level, const Box &b) const;
  MultiFab &GetGrids(int level, int componentIndex);
  MultiFab &GetGrids(int level, int componentIndex, const Box &onBox);
  void FlushGrids(int componentIndex);
  
  // calculate the min and max values of derived on onBox at level
  // return false if onBox did not intersect any grids
  bool MinMax(const Box &onBox, const string &derived, int level,
              Real &dataMin, Real &dataMax);
  
  static void SetVerbose(bool tf)       { verbose = tf; }
  static void SetSkipPltLines(int spl)  { skipPltLines = spl; }
  static void SetStaticBoundaryWidth(int bw)  { sBoundaryWidth = bw; }
  
 private:
  string fileName;
  static FileType defaultFileType;
  static bool verbose;
  static int  skipPltLines;
  static int  sBoundaryWidth;
  
  // fill on interior by piecewise constant interpolation
  void FillInterior(FArrayBox &dest, int level, const Box &subbox);
  void Interp(FArrayBox &fine, FArrayBox &crse,
              const Box &fine_box, int lrat);
  void PcInterp(FArrayBox &fine, const FArrayBox &crse,
                const Box &subbox, int lrat);
  FArrayBox *ReadGrid(istream &is, int numVar);
  bool DefineFab(int level, int componentIndex, int fabIndex);
};

#endif
