Skip to content
Snippets Groups Projects
Select Git revision
  • a62c9c42a4c1b802ea51c26d5e2c92593b95bdf5
  • master default
  • cgnsUnstructured
  • partitioning
  • poppler
  • HighOrderBLCurving
  • gmsh_3_0_4
  • gmsh_3_0_3
  • gmsh_3_0_2
  • gmsh_3_0_1
  • gmsh_3_0_0
  • gmsh_2_16_0
  • gmsh_2_15_0
  • gmsh_2_14_1
  • gmsh_2_14_0
  • gmsh_2_13_2
  • gmsh_2_13_1
  • gmsh_2_12_0
  • gmsh_2_11_0
  • gmsh_2_10_1
  • gmsh_2_10_0
  • gmsh_2_9_3
  • gmsh_2_9_2
  • gmsh_2_9_1
  • gmsh_2_9_0
  • gmsh_2_8_6
26 results

MElement.h

Blame
  • Forked from gmsh / gmsh
    Source project has a limited visibility.
    MElement.h 20.91 KiB
    #ifndef _MELEMENT_H_
    #define _MELEMENT_H_
    
    #include <stdio.h>
    #include <algorithm>
    #include "GmshDefines.h"
    #include "MVertex.h"
    #include "Numeric.h"
    
    // the reference topology is defined in Mesh/{Edge,Face}.cpp
    extern int edges_tetra[6][2];
    extern int edges_quad[4][2];
    extern int edges_hexa[12][2];
    extern int edges_prism[9][2];
    extern int edges_pyramid[8][2];
    extern int trifaces_tetra[4][3];
    extern int trifaces_prism[2][3];
    extern int trifaces_pyramid[4][3];
    extern int quadfaces_hexa[6][4];
    extern int quadfaces_prism[3][4];
    extern int quadfaces_pyramid[1][4];
    
    class MElement 
    {
     private:
      static int _globalNum;
      int _num, _partition;
      char _visible;
    
     public :
      MElement(int num=0, int part=0) 
        : _partition(part), _visible(true) 
      {
        if(num){
          _num = num;
          _globalNum = std::max(_globalNum, _num);
        }
        else{
          _num = ++_globalNum;
        }
      }
      virtual ~MElement(){}
    
      // returns the tag of the element
      virtual int getNum(){ return _num; }
    
      // returns the polynomial order the element
      virtual int getPolynomialOrder(){ return 1; }
    
      // returns the partition to which the element belongs
      virtual int getPartition(){ return _partition; }
    
      // get/set the visibility flag
      virtual char getVisibility(){ return _visible; }
      virtual void setVisibility(char val){ _visible = val; }
    
      // get the vertices
      virtual int getNumVertices() = 0;
      virtual MVertex *getVertex(int num) = 0;
    
      // get the number of vertices associated with edges, faces and
      // volumes (nonzero only for higher order elements)
      virtual int getNumEdgeVertices(){ return 0; }
      virtual int getNumFaceVertices(){ return 0; }
      virtual int getNumVolumeVertices(){ return 0; }
    
      // get the edges
      virtual int getNumEdges() = 0;
      virtual void getEdge(int num, MVertex *v[2]) = 0;
    
      // get an edge representation for drawing
      virtual int getNumEdgesRep(){ return getNumEdges(); }
      virtual void getEdgeRep(int num, MVertex *v[2]){ getEdgeRep(num, v); }
    
      // get the faces
      virtual int getNumFaces() = 0;
      virtual void getFace(int num, MVertex *v[4]) = 0;
    
      // get a face representation for drawing
      virtual int getNumFacesRep(){ return getNumFaces(); }
      virtual void getFaceRep(int num, MVertex *v[4], double n[3]=0)
      { 
        getFace(num, v); 
        if(n) normal3points(v[0]->x(), v[0]->y(), v[0]->y(),
    			v[1]->x(), v[1]->y(), v[1]->y(),
    			v[2]->x(), v[2]->y(), v[2]->y(), n);
      }
    
      // get the max/min edge length
      virtual double maxEdge();
      virtual double minEdge();
    
      // get the quality measures
      virtual double rhoShapeMeasure();
      virtual double gammaShapeMeasure(){ return 0.; }
      virtual double etaShapeMeasure(){ return 0.; }
    
      // computes the barycenter
      virtual void cog(double &x, double &y, double &z);
    
      // compute and change the orientation of 3D elements to get
      // positive volume
      virtual double getVolume(){ return 0.; }
      virtual int getVolumeSign(){ return 1; }
      virtual void setVolumePositive(){}
    
      // IO routines
      virtual void writeMSH(FILE *fp, double version=1.0, int num=0, 
    			int elementary=1, int physical=1);
      virtual void writePOS(FILE *fp, double scalingFactor=1.0,
    			int elementary=1);
      virtual void writeSTL(FILE *fp, double scalingFactor=1.0);
      virtual void writeVRML(FILE *fp);
      virtual void writeUNV(FILE *fp, int elementary);
      virtual void writeMESH(FILE *fp, int elementary);
      virtual char *getStringForPOS() = 0;
      virtual int getTypeForMSH() = 0;
      virtual int getTypeForUNV() = 0;
    };
    
    class MLine : public MElement {
     protected:
      MVertex *_v[2];
     public :
      MLine(MVertex *v0, MVertex *v1, int num=0, int part=0) 
        : MElement(num, part)
      {
        _v[0] = v0; _v[1] = v1;
      }
      ~MLine(){}
      inline int getNumVertices(){ return 2; }
      inline MVertex *getVertex(int num){ return _v[num]; }
      virtual int getNumEdges(){ return 1; }
      virtual void getEdge(int num, MVertex *v[2])
      {
        v[0] = _v[0]; v[1] = _v[1];
      }
      virtual int getNumFaces(){ return 0; }
      virtual void getFace(int num, MVertex *v[4]) 
      { 
        v[0] = v[1] = v[2] = v[3] = 0; 
      }
      int getTypeForMSH(){ return LGN1; }
      int getTypeForUNV(){ return 21; } // BEAM
      char *getStringForPOS(){ return "SL"; }
    };
    
    class MLine2 : public MLine {
     protected:
      MVertex *_vs[1];
     public :
      MLine2(MVertex *v0, MVertex *v1, MVertex *v2, int num=0, int part=0) 
        : MLine(v0, v1, num, part)
      {
        _vs[0] = v2;
      }
      ~MLine2(){}
      inline int getPolynomialOrder(){ return 2; }
      inline int getNumVertices(){ return 3; }
      inline MVertex *getVertex(int num){ return num < 2 ? _v[num] : _vs[num - 2]; }
      inline int getNumEdgeVertices(){ return 1; }
      int getNumEdgesRep(){ return 2; }
      void getEdgeRep(int num, MVertex *v[2])
      { 
        static int edges_lin2[2][2] = {
          {0, 2}, {2, 1},
        };
        int i0 = edges_lin2[num][0];
        int i1 = edges_lin2[num][1];
        v[0] = i0 < 2? _v[i0] : _vs[i0 - 2];
        v[1] = i1 < 2? _v[i1] : _vs[i1 - 2];
      }
      int getTypeForMSH(){ return LGN2; }
      int getTypeForUNV(){ return 24; } // BEAM2
      char *getStringForPOS(){ return "SL2"; }
    };
    
    class MTriangle : public MElement {
     protected:
      MVertex *_v[3];
     public :
      MTriangle(MVertex *v0, MVertex *v1, MVertex *v2, int num=0, int part=0) 
        : MElement(num, part)
      {
        _v[0] = v0; _v[1] = v1; _v[2] = v2;
      }
      ~MTriangle(){}
      inline int getNumVertices(){ return 3; }
      inline MVertex *getVertex(int num){ return _v[num]; }
      virtual int getNumEdges(){ return 3; }
      virtual void getEdge(int num, MVertex *v[2])
      {
        v[0] = _v[edges_tetra[num][0]];
        v[1] = _v[edges_tetra[num][1]];
      }
      virtual int getNumFaces(){ return 1; }
      virtual void getFace(int num, MVertex *v[4])
      {
        v[0] = _v[0]; v[1] = _v[1]; v[2] = _v[2]; v[3] = 0;
      }
      int getTypeForMSH(){ return TRI1; }
      int getTypeForUNV(){ return 91; } // THINSHLL
      char *getStringForPOS(){ return "ST"; }
    };
    
    class MTriangle2 : public MTriangle {
     protected:
      MVertex *_vs[3];
     public :
      MTriangle2(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4,
    	     MVertex *v5, int num=0, int part=0) 
        : MTriangle(v0, v1, v2, num, part)
      {
        _vs[0] = v3; _vs[1] = v4; _vs[2] = v5;
      }
      ~MTriangle2(){}
      inline int getPolynomialOrder(){ return 2; }
      inline int getNumVertices(){ return 6; }
      inline MVertex *getVertex(int num){ return num < 3 ? _v[num] : _vs[num - 3]; }
      inline int getNumEdgeVertices(){ return 3; }
      int getNumEdgesRep(){ return 6; }
      void getEdgeRep(int num, MVertex *v[2])
      { 
        static int edges_tri2[6][2] = {
          {0, 3}, {3, 1},
          {1, 4}, {4, 2},
          {2, 5}, {5, 0},
        };
        int i0 = edges_tri2[num][0];
        int i1 = edges_tri2[num][1];
        v[0] = i0 < 3? _v[i0] : _vs[i0 - 3];
        v[1] = i1 < 3? _v[i1] : _vs[i1 - 3];
      }
      int getNumFacesRep(){ return 4; }
      void getFaceRep(int num, MVertex *v[4], double n[3]=0)
      { 
        static int trifaces_tri2[4][3] = {
          {0, 3, 5},
          {1, 4, 3},
          {2, 5, 4},
          {3, 4, 5},
        };
        int i0 = trifaces_tri2[num][0];
        int i1 = trifaces_tri2[num][1];
        int i2 = trifaces_tri2[num][2];
        v[0] = i0 < 3? _v[i0] : _vs[i0 - 3];
        v[1] = i1 < 3? _v[i1] : _vs[i1 - 3];
        v[2] = i2 < 3? _v[i2] : _vs[i2 - 3];
        v[3] = 0;
        if(n) normal3points(v[0]->x(), v[0]->y(), v[0]->y(),
    			v[1]->x(), v[1]->y(), v[1]->y(),
    			v[2]->x(), v[2]->y(), v[2]->y(), n);
      }
      int getTypeForMSH(){ return TRI2; }
      int getTypeForUNV(){ return 92; } // THINSHLL2
      char *getStringForPOS(){ return "ST2"; }
    };
    
    class MQuadrangle : public MElement {
     protected:
      MVertex *_v[4];
     public :
      MQuadrangle(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, int num=0, int part=0) 
        : MElement(num, part)
      {
        _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3;
      }
      ~MQuadrangle(){}
      inline int getNumVertices(){ return 4; }
      inline MVertex *getVertex(int num){ return _v[num]; }
      virtual int getNumEdges(){ return 4; }
      virtual void getEdge(int num, MVertex *v[2])
      {
        v[0] = _v[edges_quad[num][0]];
        v[1] = _v[edges_quad[num][1]];
      }
      virtual int getNumFaces(){ return 1; }
      virtual void getFace(int num, MVertex *v[4])
      {
        v[0] = _v[0]; v[1] = _v[1]; v[2] = _v[2]; v[3] = _v[3];
      }
      int getTypeForMSH(){ return QUA1; }
      int getTypeForUNV(){ return 94; } // QUAD
      char *getStringForPOS(){ return "SQ"; }
    };
    
    class MQuadrangle2 : public MQuadrangle {
     protected:
      MVertex *_vs[5];
     public :
      MQuadrangle2(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
    	       MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, int num=0, int part=0) 
        : MQuadrangle(v0, v1, v2, v3, num, part)
      {
        _vs[0] = v4; _v[1] = v5; _v[2] = v6; _v[3] = v7; _v[4] = v8;
      }
      ~MQuadrangle2(){}
      inline int getPolynomialOrder(){ return 2; }
      inline int getNumVertices(){ return 9; }
      inline MVertex *getVertex(int num){ return num < 4 ? _v[num] : _vs[num - 4]; }
      inline int getNumEdgeVertices(){ return 4; }
      inline int getNumFaceVertices(){ return 1; }
      // TODO: edgeRep, faceRep
      int getTypeForMSH(){ return QUA2; }
      int getTypeForUNV(){ return 95; } // ???? QUAD2
      char *getStringForPOS(){ return "SQ2"; }
    };
    
    class MTetrahedron : public MElement {
     protected:
      MVertex *_v[4];
     public :
      MTetrahedron(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, int num=0, int part=0) 
        : MElement(num, part)
      {
        _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3;
      }
      ~MTetrahedron(){}
      inline int getNumVertices(){ return 4; }
      inline MVertex *getVertex(int num){ return _v[num]; }
      virtual int getNumEdges(){ return 4; }
      virtual void getEdge(int num, MVertex *v[2])
      {
        v[0] = _v[edges_tetra[num][0]];
        v[1] = _v[edges_tetra[num][1]];
      }
      virtual int getNumFaces(){ return 4; }
      virtual void getFace(int num, MVertex *v[4])
      {
        v[0] = _v[trifaces_tetra[num][0]];
        v[1] = _v[trifaces_tetra[num][1]];
        v[2] = _v[trifaces_tetra[num][2]];
        v[3] = 0;
      }
      int getTypeForMSH(){ return TET1; }
      int getTypeForUNV(){ return 111; } // SOLIDFEM
      char *getStringForPOS(){ return "SS"; }
      virtual double getVolume()
      { 
        double mat[3][3];
        mat[0][0] = _v[1]->x() - _v[0]->x();
        mat[0][1] = _v[2]->x() - _v[0]->x();
        mat[0][2] = _v[3]->x() - _v[0]->x();
        mat[1][0] = _v[1]->y() - _v[0]->y();
        mat[1][1] = _v[2]->y() - _v[0]->y();
        mat[1][2] = _v[3]->y() - _v[0]->y();
        mat[2][0] = _v[1]->z() - _v[0]->z();
        mat[2][1] = _v[2]->z() - _v[0]->z();
        mat[2][2] = _v[3]->z() - _v[0]->z();
        return det3x3(mat) / 6.;
      }
      virtual int getVolumeSign(){ return sign(getVolume()); }
      void setVolumePositive()
      {
        if(getVolumeSign() < 0){
          MVertex *tmp;
          tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
        }
      }
      virtual double gammaShapeMeasure();
      virtual double etaShapeMeasure();
    };
    
    class MTetrahedron2 : public MTetrahedron {
     protected:
      MVertex *_vs[6];
     public :
      MTetrahedron2(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
    		MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
    		int num=0, int part=0) 
        : MTetrahedron(v0, v1, v2, v3, num, part)
      {
        _vs[0] = v4; _vs[1] = v5; _vs[2] = v6; _vs[3] = v7; _vs[4] = v8; _vs[5] = v9;
      }
      ~MTetrahedron2(){}
      inline int getPolynomialOrder(){ return 2; }
      inline int getNumVertices(){ return 10; }
      inline MVertex *getVertex(int num){ return num < 4 ? _v[num] : _vs[num - 4]; }
      inline int getNumEdgeVertices(){ return 6; }
      // TODO: edgeRep, faceRep
      int getTypeForMSH(){ return TET2; }
      int getTypeForUNV(){ return 118; } // SOLIDFEM2
      char *getStringForPOS(){ return "SS2"; }
      void setVolumePositive()
      {
        if(getVolumeSign() < 0){
          MVertex *tmp;
          tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
          tmp = _vs[1]; _vs[1] = _vs[2]; _vs[2] = tmp;
          tmp = _vs[5]; _vs[5] = _vs[3]; _vs[3] = tmp;
        }
      }
    };
    
    class MHexahedron : public MElement {
     protected:
      MVertex *_v[8];
     public :
      MHexahedron(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
    	      MVertex *v5, MVertex *v6, MVertex *v7, int num=0, int part=0) 
        : MElement(num, part)
      {
        _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3;
        _v[4] = v4; _v[5] = v5; _v[6] = v6; _v[7] = v7;
      }
      ~MHexahedron(){}
      inline int getNumVertices(){ return 8; }
      inline MVertex *getVertex(int num){ return _v[num]; }
      virtual int getNumEdges(){ return 12; }
      virtual void getEdge(int num, MVertex *v[2])
      {
        v[0] = _v[edges_hexa[num][0]];
        v[1] = _v[edges_hexa[num][1]];
      }
      int getNumFaces(){ return 6; }
      void getFace(int num, MVertex *v[4])
      {
        v[0] = _v[quadfaces_hexa[num][0]];
        v[1] = _v[quadfaces_hexa[num][1]];
        v[2] = _v[quadfaces_hexa[num][2]];
        v[3] = _v[quadfaces_hexa[num][3]];
      }
      int getTypeForMSH(){ return HEX1; }
      int getTypeForUNV(){ return 115; } // BRICK
      char *getStringForPOS(){ return "SH"; }
      virtual int getVolumeSign()
      { 
        double mat[3][3];
        mat[0][0] = _v[1]->x() - _v[0]->x();
        mat[0][1] = _v[3]->x() - _v[0]->x();
        mat[0][2] = _v[4]->x() - _v[0]->x();
        mat[1][0] = _v[1]->y() - _v[0]->y();
        mat[1][1] = _v[3]->y() - _v[0]->y();
        mat[1][2] = _v[4]->y() - _v[0]->y();
        mat[2][0] = _v[1]->z() - _v[0]->z();
        mat[2][1] = _v[3]->z() - _v[0]->z();
        mat[2][2] = _v[4]->z() - _v[0]->z();
        return sign(det3x3(mat));
      }
      void setVolumePositive()
      {
        if(getVolumeSign() < 0){
          MVertex *tmp;
          tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
          tmp = _v[4]; _v[4] = _v[6]; _v[6] = tmp;
        }
      }
    };
    
    class MHexahedron2 : public MHexahedron {
     protected:
      MVertex *_vs[19];
     public :
      MHexahedron2(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
    	       MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
    	       MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, MVertex *v14,
    	       MVertex *v15, MVertex *v16, MVertex *v17, MVertex *v18, MVertex *v19,
    	       MVertex *v20, MVertex *v21, MVertex *v22, MVertex *v23, MVertex *v24,
    	       MVertex *v25, MVertex *v26, int num=0, int part=0) 
        : MHexahedron(v0, v1, v2, v3, v4, v5, v6, v7, num, part)
      {
        _vs[0] = v8; _vs[1] = v9; _vs[2] = v10; _vs[3] = v11; _vs[4] = v12; 
        _vs[5] = v13; _vs[6] = v14; _vs[7] = v15; _vs[8] = v16; _vs[9] = v17; 
        _vs[10] = v18; _vs[11] = v19; _vs[12] = v20; _vs[13] = v21; _vs[14] = v22;
        _vs[15] = v23; _vs[16] = v24; _vs[17] = v25; _vs[18] = v26;
      }
      ~MHexahedron2(){}
      inline int getPolynomialOrder(){ return 2; }
      inline int getNumVertices(){ return 27; }
      inline MVertex *getVertex(int num){ return num < 8 ? _v[num] : _vs[num - 8]; }
      inline int getNumEdgeVertices(){ return 12; }
      inline int getNumFaceVertices(){ return 6; }
      inline int getNumVolumeVertices(){ return 1; }
      // TODO: edgeRep, faceRep
      int getTypeForMSH(){ return HEX2; }
      int getTypeForUNV(){ return 116; } // ???? BRICK2
      char *getStringForPOS(){ return "SH2"; }
      void setVolumePositive()
      {
        if(getVolumeSign() < 0){
          MVertex *tmp;
          tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
          tmp = _v[4]; _v[4] = _v[6]; _v[6] = tmp;
          MVertex *old[12];
          for(int i = 0; i < 12; i++) old[i] = _vs[i];
          _vs[0] = old[3]; _vs[1] = old[5]; _vs[2] = old[6];
          _vs[3] = old[0]; _vs[4] = old[4]; _vs[5] = old[1];
          _vs[6] = old[2]; _vs[7] = old[7]; _vs[8] = old[10];
          _vs[9] = old[11]; _vs[10] = old[8]; _vs[11] = old[9];
        }
      }
    };
    
    class MPrism : public MElement {
     protected:
      MVertex *_v[6];
     public :
      MPrism(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
    	 MVertex *v5, int num=0, int part=0) 
        : MElement(num, part)
      {
        _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3;
        _v[4] = v4; _v[5] = v5; 
      }
      ~MPrism(){}
      inline int getNumVertices(){ return 6; }
      inline MVertex *getVertex(int num){ return _v[num]; }
      virtual int getNumEdges(){ return 9; }
      virtual void getEdge(int num, MVertex *v[2])
      {
        v[0] = _v[edges_prism[num][0]];
        v[1] = _v[edges_prism[num][1]];
      }
      int getNumFaces(){ return 5; }
      void getFace(int num, MVertex *v[4])
      {
        if(num < 3){
          v[0] = _v[trifaces_prism[num][0]];
          v[1] = _v[trifaces_prism[num][1]];
          v[2] = _v[trifaces_prism[num][2]];
          v[3] = 0;
        }
        else{
          v[0] = _v[quadfaces_prism[num - 3][0]];
          v[1] = _v[quadfaces_prism[num - 3][1]];
          v[2] = _v[quadfaces_prism[num - 3][2]];
          v[3] = _v[quadfaces_prism[num - 3][3]];
        }
      }
      int getTypeForMSH(){ return PRI1; }
      int getTypeForUNV(){ return 112; } // WEDGE
      char *getStringForPOS(){ return "SI"; }
      virtual int getVolumeSign()
      { 
        double mat[3][3];
        mat[0][0] = _v[1]->x() - _v[0]->x();
        mat[0][1] = _v[2]->x() - _v[0]->x();
        mat[0][2] = _v[3]->x() - _v[0]->x();
        mat[1][0] = _v[1]->y() - _v[0]->y();
        mat[1][1] = _v[2]->y() - _v[0]->y();
        mat[1][2] = _v[3]->y() - _v[0]->y();
        mat[2][0] = _v[1]->z() - _v[0]->z();
        mat[2][1] = _v[2]->z() - _v[0]->z();
        mat[2][2] = _v[3]->z() - _v[0]->z();
        return sign(det3x3(mat));
      }
      void setVolumePositive()
      {
        if(getVolumeSign() < 0){
          MVertex *tmp;
          tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
          tmp = _v[3]; _v[3] = _v[4]; _v[4] = tmp;
        }
      }
    };
    
    class MPrism2 : public MPrism {
     protected:
      MVertex *_vs[12];
     public :
      MPrism2(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
    	  MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
    	  MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, MVertex *v14,
    	  MVertex *v15, MVertex *v16, MVertex *v17, int num=0, int part=0) 
        : MPrism(v0, v1, v2, v3, v4, v5, num, part)
      {
        _vs[0] = v6; _vs[1] = v7; _vs[2] = v8; _vs[3] = v9; _vs[4] = v10; 
        _vs[5] = v11; _vs[6] = v12; _vs[7] = v13; _vs[8] = v14; _vs[9] = v15; 
        _vs[10] = v16; _vs[11] = v17; 
      }
      ~MPrism2(){}
      inline int getPolynomialOrder(){ return 2; }
      inline int getNumVertices(){ return 18; }
      inline MVertex *getVertex(int num){ return num < 6 ? _v[num] : _vs[num - 6]; }
      inline int getNumEdgeVertices(){ return 9; }
      inline int getNumFaceVertices(){ return 3; }
      // TODO: edgeRep, faceRep
      int getTypeForMSH(){ return PRI2; }
      int getTypeForUNV(){ return 113; } // ???? WEDGE2
      char *getStringForPOS(){ return "SI2"; }
      void setVolumePositive()
      {
        if(getVolumeSign() < 0){
          MVertex *tmp;
          tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
          tmp = _v[3]; _v[3] = _v[4]; _v[4] = tmp;
          tmp = _vs[1]; _vs[1] = _vs[3]; _vs[3] = tmp;
          tmp = _vs[2]; _vs[2] = _vs[4]; _vs[4] = tmp;
          tmp = _vs[7]; _vs[7] = _vs[8]; _vs[8] = tmp;
        }
      }
    };
    
    class MPyramid : public MElement {
     protected:
      MVertex *_v[5];
     public :
      MPyramid(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
    	   int num=0, int part=0) 
        : MElement(num, part)
      {
        _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3; _v[4] = v4;
      }
      ~MPyramid(){}
      inline int getNumVertices(){ return 5; }
      inline MVertex *getVertex(int num){ return _v[num]; }
      virtual int getNumEdges(){ return 8; }
      virtual void getEdge(int num, MVertex *v[2])
      {
        v[0] = _v[edges_pyramid[num][0]];
        v[1] = _v[edges_pyramid[num][1]];
      }
      int getNumFaces(){ return 5; }
      void getFace(int num, MVertex *v[4])
      {
        if(num < 4){
          v[0] = _v[trifaces_pyramid[num][0]];
          v[1] = _v[trifaces_pyramid[num][1]];
          v[2] = _v[trifaces_pyramid[num][2]];
          v[3] = 0;
        }
        else{
          v[0] = _v[quadfaces_pyramid[num - 4][0]];
          v[1] = _v[quadfaces_pyramid[num - 4][1]];
          v[2] = _v[quadfaces_pyramid[num - 4][2]];
          v[3] = _v[quadfaces_pyramid[num - 4][3]];
        }
      }
      int getTypeForMSH(){ return PYR1; }
      int getTypeForUNV(){ throw; }
      char *getStringForPOS(){ return "SY"; }
      virtual int getVolumeSign()
      { 
        double mat[3][3];
        mat[0][0] = _v[1]->x() - _v[0]->x();
        mat[0][1] = _v[3]->x() - _v[0]->x();
        mat[0][2] = _v[4]->x() - _v[0]->x();
        mat[1][0] = _v[1]->y() - _v[0]->y();
        mat[1][1] = _v[3]->y() - _v[0]->y();
        mat[1][2] = _v[4]->y() - _v[0]->y();
        mat[2][0] = _v[1]->z() - _v[0]->z();
        mat[2][1] = _v[3]->z() - _v[0]->z();
        mat[2][2] = _v[4]->z() - _v[0]->z();
        return sign(det3x3(mat));
      }
      void setVolumePositive()
      {
        if(getVolumeSign() < 0){
          MVertex *tmp;
          tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
        }
      }
    };
    
    class MPyramid2 : public MPyramid {
     protected:
      MVertex *_vs[9];
     public :
      MPyramid2(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
    	    MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
    	    MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, 
    	    int num=0, int part=0) 
        : MPyramid(v0, v1, v2, v3, v4, num, part)
      {
        _vs[0] = v5; _vs[1] = v6; _vs[2] = v7; _vs[3] = v8; _vs[4] = v9; 
        _vs[5] = v10; _vs[6] = v11; _vs[7] = v12; _vs[8] = v13; 
      }
      ~MPyramid2(){}
      inline int getPolynomialOrder(){ return 2; }
      inline int getNumVertices(){ return 14; }
      inline MVertex *getVertex(int num){ return num < 5 ? _v[num] : _vs[num - 5]; }
      inline int getNumEdgeVertices(){ return 8; }
      inline int getNumFaceVertices(){ return 1; }
      // TODO: edgeRep, faceRep
      int getTypeForMSH(){ return PYR2; }
      int getTypeForUNV(){ throw; }
      char *getStringForPOS(){ return "SY2"; }
      void setVolumePositive()
      {
        if(getVolumeSign() < 0){
          MVertex *tmp;
          tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
          tmp = _vs[0]; _vs[0] = _vs[3]; _vs[3] = tmp;
          tmp = _vs[1]; _vs[1] = _vs[5]; _vs[5] = tmp;
          tmp = _vs[2]; _vs[2] = _vs[6]; _vs[6] = tmp;
        }
      }
    };
    
    #endif