/* $Id: triang.h,v 1.3 1996/10/11 15:15:36 bzferdma Exp $ */

#ifndef TRIANG_H
#define TRIANG_H

#include "general.h"

#include "kvector.h"
#include "matrix.h"
#include "varalloc.h"

class Parser;
class BufferedParser;
class Timer;
class PT;
class EDG;
class TR3;
class TET3;
class MESH1;
class MESH2;
class MESH3;

class FEPlot;

//-------------------------------------------------------------------------


class Jacobian
{
  public:
    Real 	  detJ;
    Matrix<Real>  J;		// Jacobian
    Matrix<Real>  Jinv;		// inverse Jacobian

    Jacobian();
};
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------


// --		abstract base class for all elements


class PATCH
{

  public:

    // 			 the nodal operations:

    int  node;			// number of the (single) node

    int  getNode()  const { return node; }	
    void setNode(int no)  { node = no; }	

    virtual int  MLNode(int depth) const;
    virtual void getNodeCoord(Vector<Real>& x) const;

    virtual void getFaceNodes(Vector<int>& nodes) const;

    virtual int& getFaceNode(int face);			// for EFTET3
    virtual int& getMyFaceNode(PATCH* patch);		// for EFTET3

    virtual void print(ostream& os) const = 0;


    // 		   ... and many, many virtual functions:

  public:

    PATCH() { node = 0; }
    virtual ~PATCH() { }
 
    virtual void reset() = 0;

    virtual PATCH* Next() = 0;
    virtual int spaceDim() const = 0;
    virtual int Class() const = 0;
    virtual int Depth() const = 0;

    virtual PATCH* getMidPoint() const;		// returns pm of an edge

    virtual int NoOfSons() const;

    virtual PATCH* Partner() const;
    virtual void setPartner(PATCH* p);

    virtual void realCoordinates(const Vector<Real>& u, Vector<Real>& x) const;
    virtual void unitCoordinates(const Vector<Real>& u, Vector<Real>& x) const;

    virtual void getCoordinates(Vector<Real>& p1) const;
    virtual void getCoordinates(Vector<Real>& p1, Vector<Real>& p2) const;
    virtual void getCoordinates(Vector<Real>& p1, Vector<Real>& p2,
				Vector<Real>& p3)   const;
    virtual void getCoordinates(Vector<Real>& p1, Vector<Real>& p2,
				Vector<Real>& p3, Vector<Real>& p4) const;

    virtual void centerOfGravity(Vector<Real>& xG) const;

    virtual void compJ(Jacobian& J, Bool checkDetJ=True)  const;
    virtual void compJinv(Jacobian& J) const;

    virtual Bool onBoundary()  const;
    virtual Bool isDirichlet() const;
    virtual Bool isNeumann() const;
    virtual Bool isCauchy() const;
    virtual PATCH* Father()   const;
    virtual PATCH* FirstSon() const;

    virtual Real volume() const;
    virtual Bool refined() const {return False;}  // allows use of List Iterator
    virtual Bool isGreen() const;
    virtual Bool isVolatile() const;

    virtual void setMark();
    virtual void unMark();
    virtual Bool marked() const;

    virtual int noOfPoints() const;
    virtual int noOfEdges()  const;
    virtual int noOfFaces()  const;
    virtual int noOfNeighbours() const;

    virtual const Vector<PT*>&    getPoints() const;
    virtual const Vector<EDG*>&   getEdges()  const;

    virtual const Vector<PATCH*>& getFaces () const;
    virtual void getAllFaces (Vector<PATCH*>& faces) const;
    virtual void returnFaces (Vector<PATCH*>& faces) const;

    virtual void getNeighbours(Vector<PATCH*>& neighbours) const;
    virtual void getEdgeOrientation(Vector<Bool>& orient)  const;


    virtual const PATCH* findPatch(const Vector<Real>& x, Vector<Real>& xUnit) 
  									const;
    virtual PATCH* findPartner(const Vector<Real>& xG, int maxDepth);
    virtual Bool inPatch(const Vector<Real>& x, Vector<Real>& xUnit) const;

    virtual Real hMax() const;

    virtual float getError() const;
    virtual void  setError(float x);

    virtual PT*   castToPT()   { return 0; }
    virtual TR3*  castToTR3()  { return 0; }
    virtual TET3* castToTET3() { return 0; }

 protected:

    void readBCValues(char* boundP, char* classA,char* isoP, BufferedParser& parser);
    void readBCValues(char* boundP, char* classA, BufferedParser& parser);

    virtual void notImplemented(const char* s) const;
};
//-------------------------------------------------------------------------


class NodeStack
{
  protected:

    VarSizeAllocator* varAlloc;
    short l, h, top;
    int*  v;						 
   
  public:

    void init(VarSizeAllocator* varAlloc0, int depth, int targetDepth);
    ~NodeStack() { }			// deletions done by VarSizeAllocator

    void push(int node);
    int  Top() const { return v[h]; }

    const int& operator[] (int i) const
    { 
	if (CheckBoundsFlag) checkBounds(i);
	return v[i]; 
    }

    void print() const;

  protected:
    void checkBounds(int i) const;
    void extend();

    friend class PT;
};
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------


class PT : public PATCH			// abstract base class for points
{
  public:

    // 	--		    the node stack:

    NodeStack* nodeStack;			// stack for node numbers

    virtual int MLNode(int depth) const { return (*nodeStack)[depth]; }
    void pushNode(int no) 	{ nodeStack->push(no); }

    int minDepth() { return nodeStack->l; }
    int maxDepth() { return nodeStack->h; }


    // 			---------

    PT() { reset(); }
    virtual void reset() { nodeStack = 0; }
    virtual ~PT() { }			// nodeStack deleted by allocator

    virtual Bool equal(const PT& pt) const;
    virtual void print(ostream& os) const;

    virtual PT* castToPT() { return this; }

  protected:

    friend ostream& operator << (ostream& os, const PT& pt);
    friend Bool	    operator == (const PT& p1, const PT& p2);
};
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------


class MESH
{
  protected:

    char*  fileName;
    int    infoRefinement, timeRefinement, accTimeRefinement;
    Real   accTime;

    VarSizeAllocator varAllocator;


  public:

    int   maxDepth, refStep;

    Bool   innerBoundary;

    enum RefinementType { T_ZERO, T_WHITE, T_RED, T_BLUE,
                          T_GREEN, T_GREEN_1, T_GREEN_2A, T_GREEN_2B, T_GREEN_3,
			  T_RED1, T_RED2, T_RED3, T_VOLATILE };

    MESH(const char* inFileName);
    virtual ~MESH();

    virtual FEPlot* newFEPlot(int /*plotType*/, char* /*caption*/, float /*size*/) 
    								{ return 0; }

    virtual MESH1* castToMESH1() { return 0; }
    virtual MESH2* castToMESH2() { return 0; }
    virtual MESH3* castToMESH3() { return 0; }

    virtual void writeTriangulation(const char* outFileText,
				    const Vector<Real>& u) const;

    int MaxDepth() const { return maxDepth; }

    virtual void Refine()  = 0;
    virtual void Flatten();

    virtual int  noOfElements() = 0;
    virtual int  spaceDim() const = 0;
    virtual void Info() = 0;
    virtual int  MemSpace() = 0;

    void setPartners();			// for transient applications
    void setInitialPartners(MESH* prevMesh);

    virtual const PATCH* findPatch(const Vector<Real>& x, Vector<Real>& xUnit,
				   const PATCH* newPatch) const;
    virtual void newNodeStack(PT* p, int depth, int targetDepth);


    // --		general list iterators

    PATCH* elemIter;					// elements
    int    iterLevel;
    virtual void  resetElemIter(Bool lastStep=False) = 0;
    virtual PATCH* elemIterAll() = 0;
    virtual PATCH* elemIterAllOfHistory() = 0;

    PATCH*  ptIter;
    int     ptIterLevel;
    virtual void  resetPtIter();
    virtual PATCH* ptIterAll() = 0;

    PATCH* edgIter;
    int    edgIterLevel;
    virtual void  resetEdgIter();
    virtual PATCH* edgIterAll() = 0;
    virtual PATCH* edgIterAllOfHistory() = 0;


  protected:

    void missingItem(const char* item, const char* fileName);
    void pointIndexError(int no);
    void checkMaxIndex(int maxIndex);
    void boundaryWarning(int pNo1, int pNo2=0, int pNo3=0);

    void patchNotFound() const;

    void timeInfo(Timer& timer, Timer& accTimer);
    void notImplemented(const char* s) const;
};

#endif
