// JL20180114: TO BE REVISED
// TetraMesh.h
// Class for tetrahedral meshes
// James Liu, Graham Harper, ColoState; 2007/01--2018/05

#ifndef TetraMesh_H
#define TetraMesh_H

#include "cell3d.h"
#include "PtVec3d.h"

class TetraMesh {
private: 
  int NumNds, NumEms, NumFcs, NumBndryPcs;
  int BgnLblNd, BgnLblEm, BgnLblFc, BgnLblBndry;
  int *IsBndryNd, *NumNdsNd, *NumEmsNd, *NumFcsNd;
  int **LblNdNd, **LblNdEm, **LblNdFc;
  int *IsBndryFc, (*LblFcNd)[3], (*LblFcEm)[2], (*LblFcFc)[7];
  int (*LblEmNd)[4], (*LblEmFc)[4], (*SignEmFc)[4];
  PtVec3d *nd, *OutNmlBndry;
  int flag;  // 1,2,3 for hierarchy
  int glbLblNd(int i, int j, int k, int nx, int ny);
public:
  TetraMesh();  // Default empty constructor
  TetraMesh(double xa, double xb, int nx,   // A constructor:
            double yc, double yd, int ny,   // generating a uniform
            double ze, double zf, int nz);  // tetrahedral mesh
  ~TetraMesh();  // Destructor
  //
  void fillNodeInfo(int numberNodes, double (*crd)[3], int *boundaryNodeMark);
  void fillFaceInfo(int numberFaces, int (*faceNode)[3],
                    int (*faceElement)[2], int *boundaryFaceMark);
  void fillElementInfo(int numberElements, int (*elementNode)[4]);
  //
  void enrich1();  // Enriching to Type I for CG methods
  void enrich2();  // Enriching to Type II for DG methods
  void enrich3();  // Enriching to Type III for WG methods
  void enrich4();  // Enriching Category IV mesh info
  //
  int numberNodes() const {return NumNds;}
  int numberElements() const {return NumEms;}
  int numberFaces() const {return NumFcs;}
  //
  int beginLabelNode() const {return BgnLblNd;}
  int beginLabelElement() const {return BgnLblEm;}
  int beginLabelFace() const {return BgnLblFc;}
  int endLabelNode() const {return BgnLblNd+NumNds-1;}
  int endLabelElement() const {return BgnLblEm+NumEms-1;}
  int endLabelFace() const {return BgnLblFc+NumFcs-1;}
  //
  int isBoundaryNode(int labeld) const {return IsBndryNd[labeld-BgnLblNd];}
  int isBoundaryFace(int labelc) const {return IsBndryFc[labelc-BgnLblFc];}
  //
  int numberNbrNodesNode(int labeld) const {return NumNdsNd[labeld-BgnLblNd];}
  int numberNbrElementsNode(int labeld) const {return NumEmsNd[labeld-BgnLblNd];}
  int numberNbrFacesNode(int labeld) const {return NumFcsNd[labeld-BgnLblNd];}
  //
  PtVec3d node(int labeld) const {return nd[labeld-BgnLblNd];}
  Tri3d face(int labelc) const;
  Tetra element(int labele) const;
  PtVec3d outerNormalBoundary(int labelc) const {return OutNmlBndry[labelc-1];}
  //
  void getNodeNode(int labeld, int *labelNode) const;
  void getNodeElement(int labeld, int *labelElement) const;
  void getNodeFace(int labeld, int *labelFace) const;
  //
  void getFaceNode(int labelc, int labelNode[3]) const;
  void getFaceElement(int labelc, int &labelElementA, int &labelElementB) const;
  void getFaceFace(int labelc, int labelFace[7]) const;
  //
  void getElementNode(int labele, int labelNode[4]) const;
  void getElementFace(int labele, int labelFace[4]) const;
  void getElementFaceSign(int labele, int sign[4]) const;
  //
  // double maxSize() const;
  // double minSize() const;
  void save2file(char *filename) const;
};

#endif  // TetraMesh_H
// TetraMesh.h
