/*
** (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 _COORDSYS_H_
#define _COORDSYS_H_ 

//
// $Id: CoordSys.H,v 1.11 2001/08/15 19:23:55 lijewski Exp $
//

#include <REAL.H>
#include <Array.H>
#include <Box.H>

class FArrayBox;

//
//@Man:
//@Memo: Coordinate System
/*@Doc:

  Routines for mapping between physical coordinate system and index space.
*/

class CoordSys
{
public:

    enum CoordType { undef = -1, cartesian = 0, RZ = 1, SPHERICAL = 2 };
    //
    //@ManDoc: Nice ASCII output.
    //
    friend std::ostream& operator<< (std::ostream&, const CoordSys& );
    //
    //@ManDoc: Nice ASCII input.
    //
    friend std::istream& operator>> (std::istream&, CoordSys& );
    //
    //@ManDoc: Default constructor to undefined state.
    //
    CoordSys ();
    //
    //@ManDoc: Construct, specify a cell size, and low end of index range.
    //
    CoordSys (const Real* cell_dx);
    //
    //@ManDoc: The destructor.
    //
    ~CoordSys ();
    //
    //@ManDoc: Initialize after construction.
    //
    void define (const Real* cell_dx);
    //
    //@ManDoc: Set the CoordType.
    //
    static void SetCoord (CoordType coord);
    //
    //@ManDoc: Returns the CoordType.
    //
    static CoordType Coord ();
    //
    //@ManDoc: Is CoordType == SPHERICAL?
    //
    static bool IsSPHERICAL ();
    //
    //@ManDoc: Is CoordType == RZ?
    //
    static bool IsRZ ();
    //
    //@ManDoc: Is CoordType == cartesion?
    //
    static bool IsCartesian ();
    //
    //@ManDoc: Sets the offset for each coordinate direction.
    //
    static void SetOffset (const Real* x_lo);
    //
    //@ManDoc: Returns the offset.
    //
    static const Real* Offset ();
    //
    //@ManDoc: Returns the offset for the specified coordinate direction.
    //
    static Real Offset (int dir);
    //
    //@ManDoc: Returns the cellsize for each coordinate direction.
    //
    const Real* CellSize () const;
    //
    //@ManDoc: Returns the cellsize for the specified coordinate direction.
    //
    Real CellSize (int dir) const;
    //
    //@ManDoc: Returns location of cell center in specified direction.
    //
    Real CellCenter (int point, int dir) const;
    //
    //@ManDoc: Return location of cell center.
    //
    void CellCenter (const IntVect& point, Array<Real>& loc) const;
    //
    //@ManDoc: Return location of cell center.
    //
    void CellCenter (const IntVect& point, Real* loc) const;
    //
    //@ManDoc: Returns location of lo edge in specified direction.
    //
    Real LoEdge (int point, int dir) const;
    //
    //@ManDoc: Equivalent to LoEdge(point[dir], dir).
    //
    Real LoEdge (const IntVect& point, int dir) const;
    //
    //@ManDoc: Returns location of hi edge in specified direction.
    //
    Real HiEdge (int point, int dir) const;
    //
    //@ManDoc: Equivalent to HiEdge(point[dir], dir).
    //
    Real HiEdge (const IntVect& point, int dir) const;
    //
    //@ManDoc: Sets location of lo face into `loc'.
    //
    void LoFace (const IntVect& point, int dir, Array<Real>& loc) const;
    //
    //@ManDoc: Sets location of lo face into `loc'.
    //
    void LoFace (const IntVect& point, int dir, Real* loc) const;
    //
    //@ManDoc: Sets location of hi face into `loc'.
    //
    void HiFace (const IntVect& point, int dir, Array<Real>& loc) const;
    //
    //@ManDoc: Sets location of hi face into `loc'.
    //
    void HiFace (const IntVect& point, int dir, Real* loc) const;
    //
    //@ManDoc: Return location of lower left hand corner.
    //
    void LoNode (const IntVect& point, Array<Real>& loc) const;
    //
    //@ManDoc: Return location of lower left hand corner.
    //
    void LoNode (const IntVect& point, Real* loc) const;
    //
    //@ManDoc: Return location of upper right hand corner.
    //
    void HiNode (const IntVect& point, Array<Real>& loc) const;
    //
    //@ManDoc: Return location of upper right hand corner.
    //
    void HiNode (const IntVect& point, Real* loc) const;

    /*@ManDoc: Returns cell centered index of cell containing point.
               This may return undesired results if point
               is on a cell boundary.
    */ 
    IntVect CellIndex (const Real* point) const;

    /*@ManDoc: Returns node centered index of lower left hand corner of
               cell containing this point.
    */
    IntVect LowerIndex (const Real* point) const;

    /*@ManDoc: Returns node centered index of upper right hand corner of
               cell containing this point.
    */
    IntVect UpperIndex (const Real* point) const;

    /*@ManDoc: Compute cell volumes in given region and place them into
               resize()d input FAB.
    */
    void GetVolume (FArrayBox& vol, const Box& region) const;

    /*@ManDoc: Compute cell volumes in given region and place them into
               new()d FAB.  It is the user's respoinsibility to delete
               the returned FAB.
    */
    FArrayBox* GetVolume (const Box& region) const;
    
    /*@ManDoc: Compute d(log(A))/dr at cell centers in given region and
               return the results in the resize()d input FAB.
    */
    void GetDLogA (FArrayBox& dloga, const Box& region, int dir) const;

    /*@ManDoc: Compute d(log(A))/dr at cell centers in given region and
               return the results in a new()d FAB.  It is the user's
               responsibility to delete the returned FAB.
    */
    FArrayBox* GetDLogA (const Box& region, int dir) const;
    //
    //@ManDoc: Return the volume of the specified cell.
    //
    Real Volume (const IntVect& point) const;
    //
    //@ManDoc: Return the volume of the specified cell.
    //
    Real Volume (const Real xlo[BL_SPACEDIM],
                 const Real xhi[BL_SPACEDIM]) const;

    /*@ManDoc: Compute area of cell faces in given region and given
               index direction and return the result in resize()d input FAB.
    */
    void GetFaceArea (FArrayBox& area, const Box& region, int dir) const;

    /*@ManDoc: Compute area of cell faces in given region and given
               index direction and return the result in new()d FAB.
               It is the user's responsibility to delete the FAB.
    */
    FArrayBox* GetFaceArea (const Box& region, int dir) const;
    //
    //@ManDoc: Returns lo face area of given cell in direction dir.
    //
    Real AreaLo (const IntVect& point, int dir) const;
    //
    //@ManDoc: Returns hi face area of given cell in direction dir.
    //
    Real AreaHi (const IntVect& point, int dir) const;

    /*@ManDoc: Return array of physical locations of cell edges
               in the resize()d input array.
    */
    void GetEdgeLoc (Array<Real>& loc, const Box& region, int dir) const;

    /*@ManDoc: Return array of physical locations of cell centers
               in the resize()d input array.
    */
    void GetCellLoc (Array<Real>& loc, const Box& region, int dir) const;

    /*@ManDoc: Return array of volume coordinates at cell edges
               for region in given direction.
    */
    void GetEdgeVolCoord (Array<Real>& loc, const Box& region, int dir) const;

    /*@ManDoc: Return array of volume coordinates at cell centers
               for region in given direction.
    */
    void GetCellVolCoord (Array<Real>& loc, const Box& region, int dir) const;

protected:
    //
    // Static data.
    //
    static CoordType c_sys;
    static Real      offset[BL_SPACEDIM];
    //
    // Non-static data.
    //  
    Real dx[BL_SPACEDIM];
    bool ok;
};

#endif /*_COORDSYS_H_*/
