/*
** (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: Prob.cpp,v 1.52 2003/02/07 18:04:08 lijewski Exp $
//

#include <Prob.H>
#include <ParmParse.H>
#include <ErrorList.H>
#include <PROB_F.H>
#include <DERIVE_F.H>
#include <integrator.fh>
#include <TagBox.H>

#include <cstdio>
#include <iomanip>

using std::ofstream;
using std::cerr;
using std::cout;
using std::ios;

static bool do_group_bndry_fills = true;

#if 0
#include <ArrayView.H>
#include <TagBox.H>

void
TagBoxView (const TagBox& tb)
{
    Box bx(tb.box());
    FArrayBox fab(bx);

    for (IntVect iv = bx.smallEnd(); iv <= bx.bigEnd(); bx.next(iv))
    {
        fab(iv,0) = tb(iv);
    }
    ArrayView(&fab);
}

#else
void
inspectFAB (FArrayBox& unfab)
{
    char filename[256];
    sprintf(filename,"inspect.fab");
    std::ofstream osout(filename,std::ios::out);
    unfab.writeOn(osout);
    osout.close();
    system("/usr/local/bin/amrvis2d -fab inspect.fab&");
}

void
inspectFAB (FArrayBox& unfab,
            int        n)
{
    char filename[256];
    sprintf(filename,"inspect%d.fab",n);
    std::ofstream osout(filename,std::ios::out);
    unfab.writeOn(osout);
    osout.close();
}

void
inspectTAG (const TagBox& tb)
{
    Box bx(tb.box());
    FArrayBox fab(bx);

    for (IntVect iv = bx.smallEnd(); iv <= bx.bigEnd(); bx.next(iv))
    {
        fab(iv,0) = tb(iv);
    }
    inspectFAB( fab );
}

void
inspectTAG (const TagBox& tb,
            int           n)
{
    Box bx(tb.box());
    FArrayBox fab(bx);

    for (IntVect iv = bx.smallEnd(); iv <= bx.bigEnd(); bx.next(iv))
    {
        fab(iv,0) = tb(iv);
    }
    inspectFAB( fab,n );
}

void
inspectTAGArray (const TagBoxArray& tba)
{
    MFIter fai(tba);

    for ( ; fai.isValid(); ++fai)
        inspectTAG(tba[fai], fai.index());
}
#endif

//
// ProbBld class instantiation
//

ProbBld blobbld;

LevelBld* getLevelBld() 
{
    return &blobbld;
}

//
// ProbBld class implementation
//

void
ProbBld::variableSetUp()
{
    Prob::variableSetUp();
}

void
ProbBld::variableCleanUp()
{
    Prob::variableCleanUp();
}

AmrLevel*
ProbBld::operator() ()
{
    return new Prob;
}

AmrLevel*
ProbBld::operator() (Amr&            papa,
                     int             lev,
                     const Geometry& level_geom,
                     const BoxArray& ba,
                     Real            time)
{
    return new Prob(papa, lev, level_geom, ba, time);
}

typedef StateDescriptor::BndryFunc BndryFunc;
#ifdef BL_USE_CHEM

extern "C"
{
//
// Function called by BCRec for user-supplied boundary data.
//
typedef void (*ChemBndryFunc_FortBndryFunc)(Real* data, ARLIM_P(lo), ARLIM_P(hi),
					    const int* dom_lo, const int* dom_hi,
					    const Real* dx, const Real* grd_lo,
					    const Real* time, const int* bc,
					    const int* stateID);
}

class ChemBndryFunc
    :
    public BndryFunc
{
public:
    //
    // Bogus constructor.
    //
    ChemBndryFunc()
	:
        m_func(0),
        m_stateID(-1) {}
    //
    // Constructor.
    //
    ChemBndryFunc (ChemBndryFunc_FortBndryFunc  inFunc,
                   const std::string& stateName)
	:
        m_func(inFunc),
        m_stateName(stateName)
    {
	m_stateID = getStateID(m_stateName);
	BL_ASSERT(m_stateID >= 0);
    }
    //
    // Another Constructor which sets "regular" and "group" fill routines..
    //
    ChemBndryFunc (ChemBndryFunc_FortBndryFunc  inFunc,
                   const std::string&           stateName,
                   BndryFuncDefault             gFunc)
	:
        BndryFunc(gFunc,gFunc),
        m_func(inFunc),
        m_stateName(stateName)
    {
	m_stateID = getStateID(m_stateName);
	BL_ASSERT(m_stateID >= 0);
    }
    //
    // Destructor.
    //
    virtual ~ChemBndryFunc () {}
    
    virtual StateDescriptor::BndryFunc* clone () const
    {
        //
	// Bitwise copy ok here, no copy ctr required.
        //
	return new ChemBndryFunc(*this);
    }
    //
    // Fill boundary cells.
    // The other virtual function in BndryFunc will
    // give us the appropriate call for "group" fills.
    //
    virtual void operator () (Real* data, const int* lo, const int* hi,
			      const int* dom_lo, const int* dom_hi,
			      const Real* dx, const Real* grd_lo,
			      const Real* time, const int* bc) const
    {
	BL_ASSERT(m_func != 0);
	m_func(data,ARLIM(lo),ARLIM(hi),dom_lo,dom_hi,dx,grd_lo,time,bc,&m_stateID);
    }
    //
    // Access.
    //
    int getStateID () const              { return m_stateID;   }
    const std::string& getStateName () const { return m_stateName; }
    ChemBndryFunc_FortBndryFunc getBndryFunc () const  { return m_func;      }
    
protected:

    static int getStateID (const std::string& stateName)
    {
	const Array<std::string>& names = HyperCLaw::getChemDriver().speciesNames();
	for (int i(0); i < names.size(); ++i) {
	    if (names[i] == stateName) {
		return i;
	    }
	}
	return -1;
    }
    
private:

    ChemBndryFunc_FortBndryFunc m_func;
    std::string       m_stateName;
    int           m_stateID;
};

#endif

//
// Box Map function(s) for derived types.
//
static Box the_same_box (const Box& b) { return b; }

//
// Components are  Interior, Inflow, Outflow, Symmetry, SlipWall, NoSlipWall
//
static int scalar_bc[] =
{
    INT_DIR, EXT_DIR, FOEXTRAP, REFLECT_EVEN, REFLECT_EVEN, REFLECT_EVEN
};

static int norm_vel_bc[] =
{
    INT_DIR, EXT_DIR, FOEXTRAP, REFLECT_ODD, REFLECT_ODD, REFLECT_ODD
};

static int tang_vel_bc[] =
{
    INT_DIR, EXT_DIR, FOEXTRAP, REFLECT_EVEN, REFLECT_EVEN, REFLECT_EVEN
};

#ifdef BL_USE_CHEM
static int species_bc[] =
{
    INT_DIR, EXT_DIR, FOEXTRAP, REFLECT_EVEN, REFLECT_EVEN, REFLECT_EVEN
};
#endif

static
void
set_scalar_bc (BCRec& bc, const BCRec& phys_bc)
{
    const int* lo_bc = phys_bc.lo();
    const int* hi_bc = phys_bc.hi();
    for (int i = 0; i < BL_SPACEDIM; i++)
    {
        bc.setLo(i,scalar_bc[lo_bc[i]]);
        bc.setHi(i,scalar_bc[hi_bc[i]]);
    }
}

static
void
set_x_vel_bc(BCRec& bc, const BCRec& phys_bc)
{
    const int* lo_bc = phys_bc.lo();
    const int* hi_bc = phys_bc.hi();
    bc.setLo(0,norm_vel_bc[lo_bc[0]]);
    bc.setHi(0,norm_vel_bc[hi_bc[0]]);
    bc.setLo(1,tang_vel_bc[lo_bc[1]]);
    bc.setHi(1,tang_vel_bc[hi_bc[1]]);
#if (BL_SPACEDIM == 3)
    bc.setLo(2,tang_vel_bc[lo_bc[2]]);
    bc.setHi(2,tang_vel_bc[hi_bc[2]]);
#endif
}

static
void
set_y_vel_bc(BCRec& bc, const BCRec& phys_bc)
{
    const int* lo_bc = phys_bc.lo();
    const int* hi_bc = phys_bc.hi();
    bc.setLo(0,tang_vel_bc[lo_bc[0]]);
    bc.setHi(0,tang_vel_bc[hi_bc[0]]);
    bc.setLo(1,norm_vel_bc[lo_bc[1]]);
    bc.setHi(1,norm_vel_bc[hi_bc[1]]);
#if (BL_SPACEDIM == 3)
    bc.setLo(2,tang_vel_bc[lo_bc[2]]);
    bc.setHi(2,tang_vel_bc[hi_bc[2]]);
#endif
}

#if (BL_SPACEDIM == 3)
static
void
set_z_vel_bc(BCRec& bc, const BCRec& phys_bc)
{
    const int* lo_bc = phys_bc.lo();
    const int* hi_bc = phys_bc.hi();
    bc.setLo(0,tang_vel_bc[lo_bc[0]]);
    bc.setHi(0,tang_vel_bc[hi_bc[0]]);
    bc.setLo(1,tang_vel_bc[lo_bc[1]]);
    bc.setHi(1,tang_vel_bc[hi_bc[1]]);
    bc.setLo(2,norm_vel_bc[lo_bc[2]]);
    bc.setHi(2,norm_vel_bc[hi_bc[2]]);
}
#endif

#ifdef BL_USE_CHEM
static
void
set_species_bc (BCRec&       bc,
                const BCRec& phys_bc)
{
    const int* lo_bc = phys_bc.lo();
    const int* hi_bc = phys_bc.hi();
    for (int i = 0; i < BL_SPACEDIM; i++)
    {
	bc.setLo(i,species_bc[lo_bc[i]]);
	bc.setHi(i,species_bc[hi_bc[i]]);
    }
}
#endif

void
Prob::variableSetUp ()
{
    BL_ASSERT(desc_lst.size() == 0);

    phys_bc.setLo(0,Outflow);
    phys_bc.setLo(1,SlipWall);
    phys_bc.setHi(0,Outflow);
    phys_bc.setHi(1,SlipWall);
#if(BL_SPACEDIM==3)
    phys_bc.setLo(2,SlipWall);
    phys_bc.setHi(2,SlipWall);
#endif
    //
    // By reading parmparse, can override phys_bc.
    //
    read_params();
    //
    // Define the physical bndry conditions here.
    //
    if (CoordSys::IsRZ())
        phys_bc.setLo(0,Symmetry);
    //
    // Set up projector bndry.
    //
    const int* lo_bc = phys_bc.lo();
    const int* hi_bc = phys_bc.hi();
    //
    // Check phys_bc against possible periodic geometry
    // if periodic, must have internal BC marked.
    //
    if (Geometry::isAnyPeriodic())
    {
        //
        // Do idiot check.  Periodic means interior in those directions.
        //
        for (int dir = 0; dir<BL_SPACEDIM; dir++)
        {
            if (Geometry::isPeriodic(dir))
            {
                if (lo_bc[dir] != Interior)
                {
                    std::cerr << "Prob::variableSetUp:periodic in direction "
                         << dir
                         << " but low BC is not Interior\n";
                    BoxLib::Error();
                }
                if (hi_bc[dir] != Interior)
                {
                    std::cerr << "Prob::variableSetUp:periodic in direction "
                         << dir
                         << " but high BC is not Interior\n";
                    BoxLib::Error();
                }
            }
        }
    }
    else
    {
        //
        // Do idiot check.  If not periodic, should be no interior.
        //
        for (int dir=0; dir<BL_SPACEDIM; dir++)
        {
            if (lo_bc[dir] == Interior)
            {
                std::cerr << "Prob::variableSetUp:interior bc in direction "
                     << dir
                     << " but no periodic\n";
                BoxLib::Error();
            }
            if (hi_bc[dir] == Interior)
            {
                std::cerr << "Prob::variableSetUp:interior bc in direction "
                     << dir
                     << " but no periodic\n";
                BoxLib::Error();
            }
        }
    }

    BCRec bc;
    //
    // Set number of state variables
    //
    int counter = (int)Density + 1;
    int Xmom = counter++;
    int Ymom = counter++;
#if(BL_SPACEDIM==3)
    int Zmom = counter++;
#endif
    int Eden = counter++;
#if(NADV>0)
    int Tracer = counter++;
#if(NADV>1)
    BoxLib::Error("Prob::variableSetUp: Only one Advected quantity allowed");
#endif
#endif
#ifdef BL_USE_CHEM
    NumSpec = getChemDriver().numSpecies();
    if (NumSpec > 0)
    {
        FirstSpec = counter++;
        counter += NumSpec - 2;
        LastSpec = counter++;
    }

    const int tmp = (int)Density;
    FORT_SETCOMPS (&tmp, &Xmom,&Ymom,&Zmom,&Eden, &FirstSpec,&Tracer);

    const Array<std::string>& names = getChemDriver().speciesNames();    
    if (ParallelDescriptor::IOProcessor())
    {
        std::cout << NumSpec << " Chemical species interpreted:\n { ";
        for (int i = 0; i < names.size(); i++)
            std::cout << names[i] << ' ' << ' ';
        std::cout << '}' << '\n' << '\n';
    }    
#endif

    NUM_STATE = counter;
    //
    // DEFINE SCALAR VARIABLES
    //
    desc_lst.addDescriptor(State_Type,IndexType::TheCellType(),
                           StateDescriptor::Point,1,NUM_STATE,
                           &cell_cons_interp);

    const int nsc = BL_SPACEDIM==3 ? 5 : 4;

    Array<BCRec>       bcs(nsc);
    Array<std::string> name(nsc);

    set_scalar_bc(bc,phys_bc);
    bcs[0]   = bc;
    name[0] = "density";
    desc_lst.setComponent(State_Type,Density,"density",bc,BndryFunc(FORT_DENFILL));
    set_x_vel_bc(bc,phys_bc);
    bcs[1]   = bc;
    name[1] = "xmom";
    desc_lst.setComponent(State_Type,Xmom,"xmom",bc,BndryFunc(FORT_XMOMFILL));
    set_y_vel_bc(bc,phys_bc);
    bcs[2]   = bc;
    name[2] = "ymom";
    desc_lst.setComponent(State_Type,Ymom,"ymom",bc,BndryFunc(FORT_YMOMFILL));
#if(BL_SPACEDIM==3)
    set_z_vel_bc(bc,phys_bc);
    bcs[3]   = bc;
    name[3] = "zmom";
    desc_lst.setComponent(State_Type,Zmom,"zmom",bc,BndryFunc(FORT_ZMOMFILL));
#endif
    set_scalar_bc(bc,phys_bc);
    bcs[nsc-1]   = bc;
    name[nsc-1] = "eden";
    desc_lst.setComponent(State_Type,Eden,"eden",bc,BndryFunc(FORT_EDENFILL));
    //
    // To enable "group" operations on filling species, we need to
    // overwrite the first component specifing how to do "regular"
    // and "group" fill operations.
    //
    if (do_group_bndry_fills)
    {
        desc_lst.setComponent(State_Type,
                              Density,
                              name,
                              bcs,
                              BndryFunc(FORT_DENFILL,FORT_HYPFILL));
    }

#ifdef BL_USE_CHEM
    bcs.resize(NumSpec);
    name.resize(NumSpec);
    set_species_bc(bc,phys_bc);
    for (int i=0; i<NumSpec; i++)
    {
        bcs[i]  = bc;
	name[i] = "rho.Y(" + names[i] + ")";

	desc_lst.setComponent(State_Type,
                              FirstSpec+i,  
                              name[i].c_str(),
                              bc,
                              ChemBndryFunc(FORT_CHEMFILL,names[i]));
    }
    //
    // To enable "group" operations on filling species, we need to
    // overwrite the first component specifing how to do "regular"
    // and "group" fill operations.
    //
#if 0
    if (do_group_bndry_fills)
    {
        desc_lst.setComponent(State_Type,
                              FirstSpec,
                              name,
                              bcs,
                              ChemBndryFunc(FORT_CHEMFILL,names[0],FORT_ALLCHEMFILL));
    }
#endif
#endif /*BL_USE_CHEM*/

#if(NADV > 0)
    set_scalar_bc(bc,phys_bc);
    desc_lst.setComponent(State_Type,Tracer,"tracer",bc,BndryFunc(FORT_TRACFILL));
#endif
    //
    // DEFINE DERIVED QUANTITIES
    //
    // log of Density
    //
    derive_lst.add("log_den",IndexType::TheCellType(),1,FORT_DERLOGS,the_same_box);
    derive_lst.addComponent("log_den",desc_lst,State_Type,Density,1);
    //
    // Pressure
    //
#ifdef BL_USE_CHEM
    const int nWorkPres = 4 + NumSpec;
#else
    const int nWorkPres = 4;
#endif
    derive_lst.add("pressure",IndexType::TheCellType(),nWorkPres,
                   FORT_DERPRES,the_same_box);
    derive_lst.addComponent("pressure",desc_lst,State_Type,Density,NUM_STATE);
    //
    // Xvel
    //
    derive_lst.add("xvel",IndexType::TheCellType(),1,FORT_DERVEL,the_same_box);
    derive_lst.addComponent("xvel",desc_lst,State_Type,Density,2);
    //
    // Yvel
    //
    derive_lst.add("yvel",IndexType::TheCellType(),1,FORT_DERVEL,the_same_box);
    derive_lst.addComponent("yvel",desc_lst,State_Type,Density,1);
    derive_lst.addComponent("yvel",desc_lst,State_Type,Ymom,1);

#if(BL_SPACEDIM==3)
    //
    // Zvel
    //
    derive_lst.add("zvel",IndexType::TheCellType(),1,FORT_DERVEL,the_same_box);
    derive_lst.addComponent("zvel",desc_lst,State_Type,Density,1);
    derive_lst.addComponent("zvel",desc_lst,State_Type,Zmom,1);
#endif
    //
    // log of Eden
    //
    derive_lst.add("log_eden",IndexType::TheCellType(),1,FORT_DERLOGS,the_same_box);
    derive_lst.addComponent("log_eden",desc_lst,State_Type,Eden,1);
    //
    // A derived quantity equal to all the state variables.
    //
    derive_lst.add("FULLSTATE",IndexType::TheCellType(),NUM_STATE,FORT_DERCOPY,the_same_box);
    derive_lst.addComponent("FULLSTATE",desc_lst,State_Type,Density,NUM_STATE);
    //
    // DEFINE ERROR ESTIMATION QUANTITIES
    //
    err_list.add("FULLSTATE",1,ErrorRec::Special,FORT_DENERROR);
#if(NADV>0)
    //err_list.add("tracer",1,Special,FORT_TRCERROR);
#endif

#if 0
    //
    // DEFINE SLAB STATISTICS
    //
    Array<std::string> vars(4);

    vars[0] = "density"; vars[1] = "xvel"; vars[2] = "yvel"; vars[3] = "zvel";

    AmrLevel::get_slabstat_lst().add("VelStats0",
                                     4*vars.size(),
                                     vars,
                                     0,
                                     FORT_FAVREAVG_FIRST4MOMS);

    AmrLevel::get_slabstat_lst().add("VelStats1",
                                     4*vars.size(),
                                     vars,
                                     0,
                                     FORT_FAVREAVG_FIRST4MOMS);
#endif
}

Prob::~Prob () {}

void
Prob::variableCleanUp ()
{
    HyperCLaw::variableCleanUp();
}

Prob::Prob ()
    :
    HyperCLaw() 
{}

Prob::Prob(Amr&            papa,
           int             lev,
           const Geometry& level_geom,
           const BoxArray& bl,
           Real            time)
    :
    HyperCLaw(papa,lev,level_geom,bl,time) 
{}

void
Prob::read_params ()
{
    HyperCLaw::read_params();
    //
    // Read parameters from input file and command line.
    //
    ParmParse pp("Prob");

    pp.query("do_group_bndry_fills",do_group_bndry_fills);

    Array<int> lo_bc(BL_SPACEDIM), hi_bc(BL_SPACEDIM);
    pp.getarr("lo_bc",lo_bc,0,BL_SPACEDIM);
    pp.getarr("hi_bc",hi_bc,0,BL_SPACEDIM);
    for (int i = 0; i < BL_SPACEDIM; i++)
    {
        phys_bc.setLo(i,lo_bc[i]);
        phys_bc.setHi(i,hi_bc[i]);
    }
}


#ifdef BL_USE_CHEM
void
Prob::sum_integrated_quantities ()
{
    int finest_level = parent->finestLevel();
    Real time        = state[State_Type].curTime();
    const Array<std::string>& names = HyperCLaw::getChemDriver().speciesNames();
    NumSpec = getChemDriver().numSpecies();
    Real * Integral = new Real[NumSpec];
    for (int i=0; i<NumSpec; i++)
       {
            Integral[i]=0;
       }
    for (int lev = 0; lev <= finest_level; lev++)
    {
        Prob& blob_lev = getLevel(lev);
        for (int i=0; i<NumSpec; i++)
        {
          ChemBndryFunc bndryFunc(FORT_CHEMFILL, names[i]);
          std::string name = "rho.Y(" + names[i] + ")";
          Integral[i] += blob_lev.volWgtSum(name, time);
        }
    }
#if 0
    Real density     = 0.0;
    Real xmom        = 0.0;
    Real ymom        = 0.0;
    Real eden        = 0.0;
    Real pres        = 0.0;
#if (BL_SPACEDIM==3)
    Real zmom        = 0.0;
#endif

    for (int lev = 0; lev <= finest_level; lev++)
    {
        Prob& blob_lev = getLevel(lev);

        density  += blob_lev.volWgtSum("density", time);
        xmom     += blob_lev.volWgtSum("xmom", time);
        ymom     += blob_lev.volWgtSum("ymom", time);
#if (BL_SPACEDIM==3)
        zmom     += blob_lev.volWgtSum("zmom", time);
#endif
        eden     += blob_lev.volWgtSum("eden", time);
        pres     += blob_lev.volWgtSum("pressure", time);
    }
#endif

    if (ParallelDescriptor::IOProcessor())
    {
        std::cout << '\n';
#if 0
        std::cout << "TIME= " << time << " DENSITY= "  << density  << '\n';
        std::cout << "TIME= " << time << " XMOM= "     << xmom     << '\n';
        std::cout << "TIME= " << time << " YMOM= "     << ymom     << '\n';
#if (BL_SPACEDIM==3)
        std::cout << "TIME= " << time << " ZMOM= "     << zmom     << '\n';
#endif
        std::cout << "TIME= " << time << " EDEN= "     << eden     << '\n';
        std::cout << "TIME= " << time << " PRESSURE= " << pres     << '\n';
        std::ofstream outfile("Mass.out", std::ios::out|std::ios::app);

        outfile << setprecision(12);

        outfile << time << ' ' << density << '\n';
#endif
        for (int i=0; i<NumSpec; i++)
        {
          ChemBndryFunc bndryFunc(FORT_CHEMFILL, names[i]);
          std::string name = "rho.Y(" + names[i] + ")";
          std::cout << "TIME= " << time << " "<< name <<" = "<< Integral[i] << '\n';
        }
    }
    delete [] Integral;
}


#else
//    no chemistry version

void
Prob::sum_integrated_quantities ()
{
    int finest_level = parent->finestLevel();
    Real time        = state[State_Type].curTime();
    Real density     = 0.0;
    Real xmom        = 0.0;
    Real ymom        = 0.0;
    Real eden        = 0.0;
    Real pres        = 0.0;
#if (BL_SPACEDIM==3)
    Real zmom        = 0.0;
#endif

    for (int lev = 0; lev <= finest_level; lev++)
    {
        Prob& blob_lev = getLevel(lev);

        density  += blob_lev.volWgtSum("density", time);
        xmom     += blob_lev.volWgtSum("xmom", time);
        ymom     += blob_lev.volWgtSum("ymom", time);
#if (BL_SPACEDIM==3)
        zmom     += blob_lev.volWgtSum("zmom", time);
#endif
        eden     += blob_lev.volWgtSum("eden", time);
        pres     += blob_lev.volWgtSum("pressure", time);
    }

    if (ParallelDescriptor::IOProcessor())
    {
        std::cout << '\n';
        std::cout << "TIME= " << time << " DENSITY= "  << density  << '\n';
        std::cout << "TIME= " << time << " XMOM= "     << xmom     << '\n';
        std::cout << "TIME= " << time << " YMOM= "     << ymom     << '\n';
#if (BL_SPACEDIM==3)
        std::cout << "TIME= " << time << " ZMOM= "     << zmom     << '\n';
#endif
        std::cout << "TIME= " << time << " EDEN= "     << eden     << '\n';
        std::cout << "TIME= " << time << " PRESSURE= " << pres     << '\n';
        std::ofstream outfile("Mass.out", std::ios::out|std::ios::app);

        outfile << std::setprecision(12);

        outfile << time << ' ' << density << '\n';
    }
}
// end of no chem version

#endif




#if(BL_SPACEDIM==2)
void
indexFAB (FArrayBox& a,int i,int j,int ncomp = 0)
{
    IntVect v(i,j);
    printf("i = %d , j = %d , a(v,ncomp) = %le \n",i,j,a(v,ncomp));
}
void
indexMF (MultiFab& a,int i,int j,int ngrid=0,int ncomp = 0)
{
    IntVect v(i,j);
    printf("i = %d , j = %d , a[ngrid](v,ncomp) = %le \n",i,j,a[ngrid](v,ncomp));
}
#elif(BL_SPACEDIM==3)
void
indexFAB (FArrayBox& a,int i,int j,int k,int ncomp = 0)
{
    IntVect v(i,j,k);
    printf("i = %d , j = %d , k = %d , a(v,ncomp) = %le \n",i,j,k,a(v,ncomp));
}
void
indexMF (MultiFab& a,int i,int j,int k,int ngrid=0,int ncomp = 0)
{
    IntVect v(i,j,k);
    printf("i = %d , j = %d ,k = %d, a[ngrid](v,ncomp) = %le \n",i,j,k,a[ngrid](v,ncomp));
}
#endif
