Skip to content
Snippets Groups Projects
Select Git revision
  • fc7161e74381601d61001631964853234f94da61
  • 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

meshRefine.cpp

Blame
  • Forked from gmsh / gmsh
    Source project has a limited visibility.
    meshRefine.cpp 29.37 KiB
    // Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
    //
    // See the LICENSE.txt file for license information. Please report all
    // bugs and problems to the public mailing list <gmsh@onelab.info>.
    //
    // Contributor(s):
    //   Brian Helenbrook
    //
    
    #include "HighOrder.h"
    #include "MLine.h"
    #include "MTriangle.h"
    #include "MQuadrangle.h"
    #include "MTetrahedron.h"
    #include "MHexahedron.h"
    #include "MPrism.h"
    #include "MPyramid.h"
    #include "GmshMessage.h"
    #include "OS.h"
    #include "Context.h"
    #include "meshGFaceOptimize.h"
    
    void subdivide_pyramid(MElement* element,
    		       GRegion* gr,
    		       faceContainer &faceVertices,
    		       std::vector<MHexahedron*> &dwarfs88);
    
    class MVertexLessThanParam{
     public:
      bool operator()(const MVertex *v1, const MVertex *v2) const
      {
        double u1 = 0., u2 = 1.;
        v1->getParameter(0, u1);
        v2->getParameter(0, u2);
        return u1 < u2;
      }
    };
    
    // Set BM data on vertex
    static void setBLData(MVertex *v)
    {
      switch (v->onWhat()->dim()) {
        case 1: {
          MEdgeVertex *ve = dynamic_cast<MEdgeVertex*>(v);
          if (ve) ve->bl_data = new MVertexBoundaryLayerData();
          break;
        }
        case 2: {
          MFaceVertex *vf = dynamic_cast<MFaceVertex*>(v);
          if (vf) vf->bl_data = new MVertexBoundaryLayerData();
          break;
        }
      }
    }
    
    // If all low-order nodes in are marked as BL, then mark high-order nodes as BL (only works in 2D)
    static bool setBLData(MElement *el)
    {
      // Check whether all low-order nodes are marked as BL nodes (only works in 2D)
      for(int i=0; i<el->getNumPrimaryVertices(); i++) {
        MVertex *v = el->getVertex(i);
        bool isBL = false;
        switch (v->onWhat()->dim()) {
          case 0:
            isBL = true;
            break;
          case 1: {
            MEdgeVertex *ve = dynamic_cast<MEdgeVertex*>(v);
            if (ve && ve->bl_data) isBL = true;
            break;
          }
          case 2: {
            MFaceVertex *vf = dynamic_cast<MFaceVertex*>(v);
            if (vf && vf->bl_data) isBL = true;
            break;
          }
        }
        if (!isBL) return false;
      }
      // Mark high-order nodes as BL nodes (only works in 2D)
      for(int i=el->getNumPrimaryVertices(); i<el->getNumVertices(); i++)
        setBLData(el->getVertex(i));
      return true;
    }
    
    static void Subdivide(GEdge *ge)
    {
      std::vector<MLine*> lines2;
      for(unsigned int i = 0; i < ge->lines.size(); i++){
        MLine *l = ge->lines[i];
        if(l->getNumVertices() == 3){
          lines2.push_back(new MLine(l->getVertex(0), l->getVertex(2)));
          lines2.push_back(new MLine(l->getVertex(2), l->getVertex(1)));
          setBLData(l);
        }
        delete l;
      }
      ge->lines = lines2;
    
      // 2nd order meshing destroyed the ordering of the vertices on the edge
      std::sort(ge->mesh_vertices.begin(), ge->mesh_vertices.end(),
                MVertexLessThanParam());
      for(unsigned int i = 0; i < ge->mesh_vertices.size(); i++)
        ge->mesh_vertices[i]->setPolynomialOrder(1);
      ge->deleteVertexArrays();
    }
    
    static void Subdivide(GFace *gf, bool splitIntoQuads, bool splitIntoHexas,
                          faceContainer &faceVertices)
    {
    
      if(!splitIntoQuads && !splitIntoHexas){
        std::vector<MTriangle*> triangles2;
        for(unsigned int i = 0; i < gf->triangles.size(); i++){
          MTriangle *t = gf->triangles[i];
          if(t->getNumVertices() == 6){
            triangles2.push_back
              (new MTriangle(t->getVertex(0), t->getVertex(3), t->getVertex(5)));
            triangles2.push_back
              (new MTriangle(t->getVertex(3), t->getVertex(4), t->getVertex(5)));
            triangles2.push_back
              (new MTriangle(t->getVertex(3), t->getVertex(1), t->getVertex(4)));
            triangles2.push_back
              (new MTriangle(t->getVertex(5), t->getVertex(4), t->getVertex(2)));
            setBLData(t);
          }
          delete t;
        }
        gf->triangles = triangles2;
      }
    
      std::vector<MQuadrangle*> quadrangles2;
      for(unsigned int i = 0; i < gf->quadrangles.size(); i++){
        MQuadrangle *q = gf->quadrangles[i];
        if(q->getNumVertices() == 9){
          quadrangles2.push_back
            (new MQuadrangle(q->getVertex(0), q->getVertex(4), q->getVertex(8), q->getVertex(7)));
          quadrangles2.push_back
            (new MQuadrangle(q->getVertex(4), q->getVertex(1), q->getVertex(5), q->getVertex(8)));
          quadrangles2.push_back
            (new MQuadrangle(q->getVertex(8), q->getVertex(5), q->getVertex(2), q->getVertex(6)));
          quadrangles2.push_back
            (new MQuadrangle(q->getVertex(7), q->getVertex(8), q->getVertex(6), q->getVertex(3)));
          setBLData(q);
        }
        delete q;
      }
      if(splitIntoQuads || splitIntoHexas){
        for(unsigned int i = 0; i < gf->triangles.size(); i++){
          MTriangle *t = gf->triangles[i];
          if(t->getNumVertices() == 6){
            SPoint2 pt;
            SPoint3 ptx; t->pnt(0.5, 0.5, 0, ptx);
            bool reparamOK = true;
            for(int k = 0; k < 6; k++){
              SPoint2 temp;
              reparamOK &= reparamMeshVertexOnFace(t->getVertex(k), gf, temp);
              pt[0] += temp[0] / 6.;
              pt[1] += temp[1] / 6.;
            }
            MVertex *newv;
            if (reparamOK){
              GPoint gp = gf->point(pt);
              newv = new MFaceVertex(gp.x(), gp.y(), gp.z(), gf, pt[0], pt[1]);
            }
            else {
              newv = new MVertex(ptx.x(), ptx.y(), ptx.z(), gf);
            }
            gf->mesh_vertices.push_back(newv);
            if(splitIntoHexas) faceVertices[t->getFace(0)].push_back(newv);
            quadrangles2.push_back
              (new MQuadrangle(t->getVertex(0), t->getVertex(3), newv, t->getVertex(5)));
            quadrangles2.push_back
              (new MQuadrangle(t->getVertex(3), t->getVertex(1), t->getVertex(4), newv));
            quadrangles2.push_back
              (new MQuadrangle(t->getVertex(5), newv,t->getVertex(4), t->getVertex(2)));
            if (setBLData(t)) setBLData(newv);
            delete t;
          }
        }
        gf->triangles.clear();
      }
      gf->quadrangles = quadrangles2;
    
      for(unsigned int i = 0; i < gf->mesh_vertices.size(); i++)
        gf->mesh_vertices[i]->setPolynomialOrder(1);
      gf->deleteVertexArrays();
    }
    
    static void Subdivide(GRegion *gr, bool splitIntoHexas, faceContainer &faceVertices)
    {
      if(!splitIntoHexas){
        // Split tets into other tets
        std::vector<MTetrahedron*> tetrahedra2;
        for(unsigned int i = 0; i < gr->tetrahedra.size(); i++){
          MTetrahedron *t = gr->tetrahedra[i];
          // FIXME: we should choose the template to maximize the quality
          if(t->getNumVertices() == 10){
            tetrahedra2.push_back
              (new MTetrahedron(t->getVertex(0), t->getVertex(4), t->getVertex(7), t->getVertex(6)));
            tetrahedra2.push_back
              (new MTetrahedron(t->getVertex(1), t->getVertex(4), t->getVertex(5), t->getVertex(9)));
            tetrahedra2.push_back
              (new MTetrahedron(t->getVertex(2), t->getVertex(5), t->getVertex(6), t->getVertex(8)));
            tetrahedra2.push_back
              (new MTetrahedron(t->getVertex(3), t->getVertex(7), t->getVertex(9), t->getVertex(8)));
            tetrahedra2.push_back
              (new MTetrahedron(t->getVertex(5), t->getVertex(8), t->getVertex(7), t->getVertex(9)));
            tetrahedra2.push_back
              (new MTetrahedron(t->getVertex(5), t->getVertex(7), t->getVertex(4), t->getVertex(9)));
            tetrahedra2.push_back
              (new MTetrahedron(t->getVertex(7), t->getVertex(8), t->getVertex(5), t->getVertex(6)));
            tetrahedra2.push_back
              (new MTetrahedron(t->getVertex(4), t->getVertex(7), t->getVertex(5), t->getVertex(6)));
            setBLData(t);
          }
          delete t;
        }
        gr->tetrahedra = tetrahedra2;
      }
    
      // Split hexes into other hexes.
      std::vector<MHexahedron*> hexahedra2;
      for(unsigned int i = 0; i < gr->hexahedra.size(); i++){
        MHexahedron *h = gr->hexahedra[i];
        if(h->getNumVertices() == 27){
          hexahedra2.push_back
            (new MHexahedron(h->getVertex(0), h->getVertex(8), h->getVertex(20), h->getVertex(9),
                             h->getVertex(10), h->getVertex(21), h->getVertex(26), h->getVertex(22)));
          hexahedra2.push_back
            (new MHexahedron(h->getVertex(10), h->getVertex(21), h->getVertex(26), h->getVertex(22),
                             h->getVertex(4), h->getVertex(16), h->getVertex(25), h->getVertex(17)));
          hexahedra2.push_back
            (new MHexahedron(h->getVertex(8), h->getVertex(1), h->getVertex(11), h->getVertex(20),
                             h->getVertex(21), h->getVertex(12), h->getVertex(23), h->getVertex(26)));
          hexahedra2.push_back
            (new MHexahedron(h->getVertex(21), h->getVertex(12), h->getVertex(23), h->getVertex(26),
                             h->getVertex(16), h->getVertex(5), h->getVertex(18), h->getVertex(25)));
          hexahedra2.push_back
            (new MHexahedron(h->getVertex(9), h->getVertex(20), h->getVertex(13), h->getVertex(3),
                             h->getVertex(22), h->getVertex(26), h->getVertex(24), h->getVertex(15)));
          hexahedra2.push_back
            (new MHexahedron(h->getVertex(22), h->getVertex(26), h->getVertex(24), h->getVertex(15),
                             h->getVertex(17), h->getVertex(25), h->getVertex(19), h->getVertex(7)));
          hexahedra2.push_back
            (new MHexahedron(h->getVertex(20), h->getVertex(11), h->getVertex(2), h->getVertex(13),
                             h->getVertex(26), h->getVertex(23), h->getVertex(14), h->getVertex(24)));
          hexahedra2.push_back
            (new MHexahedron(h->getVertex(26), h->getVertex(23), h->getVertex(14), h->getVertex(24),
                             h->getVertex(25), h->getVertex(18), h->getVertex(6), h->getVertex(19)));
          setBLData(h);
        }
        delete h;
      }
    
      // Split tets into other hexes.
      if(splitIntoHexas){
        for(unsigned int i = 0; i < gr->tetrahedra.size(); i++){
          MTetrahedron *t = gr->tetrahedra[i];
          if(t->getNumVertices() == 10){
            std::vector<MVertex*> newv;
            for(int j = 0; j < t->getNumFaces(); j++){
              MFace face = t->getFace(j);
              faceContainer::iterator fIter = faceVertices.find(face);
              if (fIter != faceVertices.end()){
                newv.push_back(fIter->second[0]);
              }
              else{
                SPoint3 pc = face.barycenter();
                newv.push_back(new MVertex(pc.x(), pc.y(), pc.z(), gr));
                faceVertices[face].push_back(newv.back());
                gr->mesh_vertices.push_back(newv.back());
              }
            }
            SPoint3 pc = t->barycenter();
            newv.push_back(new MVertex(pc.x(), pc.y(), pc.z(), gr));
            gr->mesh_vertices.push_back(newv.back());
            hexahedra2.push_back
              (new MHexahedron(t->getVertex(0), t->getVertex(4), newv[0], t->getVertex(6),
                               t->getVertex(7), newv[1], newv[4], newv[2]));
            hexahedra2.push_back
              (new MHexahedron(t->getVertex(4), t->getVertex(1), t->getVertex(5), newv[0],
                               newv[1], t->getVertex(9), newv[3], newv[4]));
            hexahedra2.push_back
              (new MHexahedron(t->getVertex(6),  newv[0], t->getVertex(5), t->getVertex(2),
                               newv[2], newv[4], newv[3], t->getVertex(8)));
            hexahedra2.push_back
              (new MHexahedron(t->getVertex(3),  t->getVertex(9), newv[1], t->getVertex(7),
                               t->getVertex(8), newv[3], newv[4], newv[2]));
            if (setBLData(t)) {
              setBLData(newv[0]); setBLData(newv[1]);
              setBLData(newv[2]); setBLData(newv[3]); setBLData(newv[4]);
            }
            delete t;
          }
        }
        gr->tetrahedra.clear();
    
        for(unsigned int i = 0; i < gr->prisms.size(); i++){
          MPrism *p = gr->prisms[i];
          if(p->getNumVertices() == 18){
            std::vector<MVertex*> newv;
            for(int j = 0; j < 2; j++){
              MFace face = p->getFace(j);
              faceContainer::iterator fIter = faceVertices.find(face);
              if (fIter != faceVertices.end()){
                newv.push_back(fIter->second[0]);
              }
              else{
                SPoint3 pc = face.barycenter();
                newv.push_back(new MVertex(pc.x(), pc.y(), pc.z(), gr));
                faceVertices[face].push_back(newv.back());
                gr->mesh_vertices.push_back(newv.back());
              }
            }
            SPoint3 pc = p->barycenter();
            newv.push_back(new MVertex(pc.x(), pc.y(), pc.z(), gr));
            gr->mesh_vertices.push_back(newv.back());
            hexahedra2.push_back
              (new MHexahedron(p->getVertex(0), p->getVertex(6), newv[0], p->getVertex(7),
                               p->getVertex(8), p->getVertex(15), newv[2], p->getVertex(16)));
            hexahedra2.push_back
              (new MHexahedron(p->getVertex(1), p->getVertex(9), newv[0], p->getVertex(6),
                               p->getVertex(10), p->getVertex(17), newv[2], p->getVertex(15)));
            hexahedra2.push_back
              (new MHexahedron(p->getVertex(2), p->getVertex(7), newv[0], p->getVertex(9),
                               p->getVertex(11), p->getVertex(16), newv[2], p->getVertex(17)));
            hexahedra2.push_back
              (new MHexahedron(p->getVertex(8), p->getVertex(15), newv[2], p->getVertex(16),
                               p->getVertex(3), p->getVertex(12), newv[1], p->getVertex(13)));
            hexahedra2.push_back
              (new MHexahedron(p->getVertex(10), p->getVertex(17), newv[2], p->getVertex(15),
                               p->getVertex(4), p->getVertex(14), newv[1], p->getVertex(12)));
            hexahedra2.push_back
              (new MHexahedron(p->getVertex(11), p->getVertex(16), newv[2], p->getVertex(17),
                               p->getVertex(5), p->getVertex(13), newv[1], p->getVertex(14)));
            if (setBLData(p)) {
              setBLData(newv[0]); setBLData(newv[1]); setBLData(newv[2]);
            }
          }
        }
        gr->prisms.clear();
        // --------------------------------------------------
        // YAMAKAWA DIVISION OF A PYRAMID INTO 88 HEXES !!!!!
        // --------------------------------------------------
        std::vector<MHexahedron*> dwarfs88;
        for(unsigned int i = 0; i < gr->pyramids.size(); i++){
          MPyramid *p = gr->pyramids[i];
          if(p->getNumVertices() == 14){
    	subdivide_pyramid(p,gr,faceVertices,dwarfs88);
    	for (int j=0;j<88;j++)hexahedra2.push_back(dwarfs88[j]);
          }
        }
        gr->pyramids.clear();
        // --------------------------------------------------
        // ---- THANKS TO TRISTAN CARRIER BAUDOUIN ----------
        // --------------------------------------------------
      }
      gr->hexahedra = hexahedra2;
    
      std::vector<MPrism*> prisms2;
      for(unsigned int i = 0; i < gr->prisms.size(); i++){
        MPrism *p = gr->prisms[i];
        if(p->getNumVertices() == 18){
          prisms2.push_back
            (new MPrism(p->getVertex(0), p->getVertex(6), p->getVertex(7),
                        p->getVertex(8), p->getVertex(15), p->getVertex(16)));
          prisms2.push_back
            (new MPrism(p->getVertex(8), p->getVertex(15), p->getVertex(16),
                        p->getVertex(3), p->getVertex(12), p->getVertex(13)));
          prisms2.push_back
            (new MPrism(p->getVertex(6), p->getVertex(1), p->getVertex(9),
                        p->getVertex(15), p->getVertex(10), p->getVertex(17)));
          prisms2.push_back
            (new MPrism(p->getVertex(15), p->getVertex(10), p->getVertex(17),
                        p->getVertex(12), p->getVertex(4), p->getVertex(14)));
          prisms2.push_back
            (new MPrism(p->getVertex(7), p->getVertex(9), p->getVertex(2),
                        p->getVertex(16), p->getVertex(17), p->getVertex(11)));
          prisms2.push_back
            (new MPrism(p->getVertex(16), p->getVertex(17), p->getVertex(11),
                        p->getVertex(13), p->getVertex(14), p->getVertex(5)));
          prisms2.push_back
            (new MPrism(p->getVertex(9), p->getVertex(7), p->getVertex(6),
                        p->getVertex(17), p->getVertex(16), p->getVertex(15)));
          prisms2.push_back
            (new MPrism(p->getVertex(17), p->getVertex(16), p->getVertex(15),
                        p->getVertex(14), p->getVertex(13), p->getVertex(12)));
          setBLData(p);
        }
        delete p;
      }
      gr->prisms = prisms2;
    
      std::vector<MPyramid*> pyramids2;
      for(unsigned int i = 0; i < gr->pyramids.size(); i++){
        if(splitIntoHexas){
          Msg::Error("Full hexahedron subdivision is not implemented for pyramids");
          return;
        }
        MPyramid *p = gr->pyramids[i];
        if(p->getNumVertices() == 14){
          // Base
          pyramids2.push_back
            (new MPyramid(p->getVertex(0), p->getVertex(5), p->getVertex(13),
                          p->getVertex(6), p->getVertex(7)));
          pyramids2.push_back
            (new MPyramid(p->getVertex(5), p->getVertex(1), p->getVertex(8),
                          p->getVertex(13), p->getVertex(9)));
          pyramids2.push_back
            (new MPyramid(p->getVertex(13), p->getVertex(8), p->getVertex(2),
                          p->getVertex(10), p->getVertex(11)));
          pyramids2.push_back
            (new MPyramid(p->getVertex(6), p->getVertex(13), p->getVertex(10),
                          p->getVertex(3), p->getVertex(12)));
    
          // Split remaining into tets
          // Top
          gr->tetrahedra.push_back
            ((new MTetrahedron(p->getVertex(7), p->getVertex(9), p->getVertex(12), p->getVertex(4))));
          gr->tetrahedra.push_back
            ((new MTetrahedron(p->getVertex(9), p->getVertex(11), p->getVertex(12), p->getVertex(4))));
    
          // Upside down one
          gr->tetrahedra.push_back
            ((new MTetrahedron(p->getVertex(9), p->getVertex(12), p->getVertex(11), p->getVertex(13))));
          gr->tetrahedra.push_back
            ((new MTetrahedron(p->getVertex(7), p->getVertex(12), p->getVertex(9), p->getVertex(13))));
    
          // Four tets around bottom perimeter
          gr->tetrahedra.push_back
            ((new MTetrahedron(p->getVertex(7), p->getVertex(9), p->getVertex(5), p->getVertex(13))));
          gr->tetrahedra.push_back
            ((new MTetrahedron(p->getVertex(9), p->getVertex(11), p->getVertex(8), p->getVertex(13))));
          gr->tetrahedra.push_back
            ((new MTetrahedron(p->getVertex(12), p->getVertex(10), p->getVertex(11), p->getVertex(13))));
          gr->tetrahedra.push_back
            ((new MTetrahedron(p->getVertex(7), p->getVertex(6), p->getVertex(12), p->getVertex(13))));
          setBLData(p);
        }
        delete p;
      }
      gr->pyramids = pyramids2;
    
      for(unsigned int i = 0; i < gr->mesh_vertices.size(); i++)
        gr->mesh_vertices[i]->setPolynomialOrder(1);
      gr->deleteVertexArrays();
    }
    
    void RefineMesh(GModel *m, bool linear, bool splitIntoQuads, bool splitIntoHexas)
    {
      //  splitIntoQuads = true;
      //  splitIntoHexas = true;
    
      Msg::StatusBar(true, "Refining mesh...");
      double t1 = Cpu();
    
      // Create 2nd order mesh (using "2nd order complete" elements) to
      // generate vertex positions
      SetOrderN(m, 2, linear, false);
    
      // only used when splitting tets into hexes
      faceContainer faceVertices;
    
      // Subdivide the second order elements to create the refined linear
      // mesh
      for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); ++it)
        Subdivide(*it);
      for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it){
        Subdivide(*it, splitIntoQuads, splitIntoHexas, faceVertices);
        //if(splitIntoQuads) recombineIntoQuads(*it, true, true);
      }
      for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); ++it)
        Subdivide(*it, splitIntoHexas, faceVertices);
    
      // Check all 3D elements for negative volume and reverse if needed
      m->setAllVolumesPositive();
    
      CTX::instance()->mesh.changed = ENT_ALL;
      double t2 = Cpu();
      Msg::StatusBar(true, "Done refining mesh (%g s)", t2 - t1);
    }
    
    
    ///------ Tristan Carrier Baudouin's Contribution on Full Hex Meshing
    
    static double schneiders_x(int i){
      double coord[105] = {
        0.500000,
        0.666667,
        0.500000,
        1.000000,
        1.000000,
        1.000000,
        0.289057,
        0.324970,
        0.276710,
        0.337200,
        0.364878,
        0.325197,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        -0.289057,
        -0.324970,
        -0.276710,
        -0.337200,
        -0.364878,
        -0.325197,
        -0.500000,
        -0.666667,
        -0.500000,
        -1.000000,
        -1.000000,
        -1.000000,
        0.084599,
        0.263953,
        0.442960,
        0.310954,
        0.000000,
        0.000000,
        0.118244,
        0.212082,
        0.244049,
        0.213940,
        0.040495,
        0.110306,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        -0.118244,
        -0.212082,
        -0.244049,
        -0.213940,
        -0.040495,
        -0.110306,
        -0.084599,
        -0.263953,
        -0.442960,
        -0.310954,
        0.650493,
        0.454537,
        0.000000,
        0.000000,
        0.320508,
        0.264129,
        0.063695,
        0.092212,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        -0.320508,
        -0.264129,
        -0.063695,
        -0.092212,
        -0.650493,
        -0.454537,
        0.619616,
        0.000000,
        0.277170,
        0.124682,
        0.000000,
        0.000000,
        -0.277170,
        -0.124682,
        -0.619616,
        0.128101,
        0.000000,
        0.176104,
        0.084236,
        0.000000,
        0.000000,
        -0.176104,
        -0.084236,
        -0.128101,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        0.000000,
        0.000000
      };
    
      return coord[i];
    }
    
    static double schneiders_y(int i){
      double coord[105] = {
        0.707107,
        0.471405,
        0.707107,
        0.000000,
        0.000000,
        0.000000,
        0.474601,
        0.421483,
        0.463847,
        0.367090,
        0.344843,
        0.361229,
        0.429392,
        0.410339,
        0.435001,
        0.407674,
        0.401208,
        0.404164,
        0.474601,
        0.421483,
        0.463847,
        0.367090,
        0.344843,
        0.361229,
        0.707107,
        0.471405,
        0.707107,
        0.000000,
        0.000000,
        0.000000,
        0.536392,
        0.697790,
        0.569124,
        0.742881,
        0.558045,
        0.946690,
        0.497378,
        0.532513,
        0.500133,
        0.541479,
        0.530503,
        0.666252,
        0.463274,
        0.465454,
        0.430972,
        0.451135,
        0.515274,
        0.589713,
        0.497378,
        0.532513,
        0.500133,
        0.541479,
        0.530503,
        0.666252,
        0.536392,
        0.697790,
        0.569124,
        0.742881,
        0.080018,
        0.104977,
        0.216381,
        0.200920,
        0.326416,
        0.339933,
        0.280915,
        0.305725,
        0.396502,
        0.394423,
        0.310617,
        0.337499,
        0.326416,
        0.339933,
        0.280915,
        0.305725,
        0.080018,
        0.104977,
        0.081443,
        0.204690,
        0.354750,
        0.334964,
        0.403611,
        0.367496,
        0.354750,
        0.334964,
        0.081443,
        0.501199,
        0.538575,
        0.447454,
        0.486224,
        0.431723,
        0.470065,
        0.447454,
        0.486224,
        0.501199,
        0.488701,
        0.471405,
        0.017336,
        0.000000,
        0.452197,
        0.471405,
        0.057682,
        0.000000,
        1.414213,
        0.015731,
        0.000000
      };
    
      return coord[i];
    }
    
    static double schneiders_z(int i){
      double coord[105] = {
        0.500000,
        0.000000,
        -0.500000,
        1.000000,
        0.000000,
        -1.000000,
        0.051666,
        -0.058015,
        -0.148140,
        0.071987,
        -0.057896,
        -0.181788,
        -0.016801,
        -0.054195,
        -0.104114,
        -0.015276,
        -0.054392,
        -0.110605,
        0.051666,
        -0.058015,
        -0.148140,
        0.071987,
        -0.057896,
        -0.181788,
        0.500000,
        0.000000,
        -0.500000,
        1.000000,
        0.000000,
        -1.000000,
        -0.208673,
        -0.162945,
        0.021476,
        0.389516,
        -0.157646,
        0.159885,
        -0.142645,
        -0.073557,
        -0.032793,
        0.060339,
        -0.136482,
        0.043449,
        -0.111103,
        -0.079664,
        -0.047879,
        -0.008734,
        -0.124554,
        0.008560,
        -0.142645,
        -0.073557,
        -0.032793,
        0.060339,
        -0.136482,
        0.043449,
        -0.208673,
        -0.162945,
        0.021476,
        0.389516,
        -0.041899,
        -0.680880,
        -0.103504,
        -0.392255,
        -0.065989,
        -0.212535,
        -0.093142,
        -0.227139,
        -0.056201,
        -0.124443,
        -0.087185,
        -0.182164,
        -0.065989,
        -0.212535,
        -0.093142,
        -0.227139,
        -0.041899,
        -0.680880,
        0.786284,
        0.443271,
        0.104202,
        0.144731,
        -0.005330,
        0.073926,
        0.104202,
        0.144731,
        0.786284,
        -0.364254,
        -0.282882,
        -0.189794,
        -0.182143,
        -0.127036,
        -0.148665,
        -0.189794,
        -0.182143,
        -0.364254,
        0.642222,
        0.666667,
        0.959658,
        1.000000,
        -0.455079,
        -0.666667,
        -0.844452,
        -1.000000,
        0.000000,
        -0.009020,
        0.000000
      };
    
      return coord[i];
    }
    
    static int schneiders_connect(int i,int j){
      int n0[88] = {
        0,1,6,7,12,13,18,19,41,39,37,
        41,36,40,47,45,43,47,42,46,53,51,
        49,53,48,52,35,57,55,35,54,34,34,
        35,65,63,64,62,69,67,68,66,73,71,
        72,70,61,75,60,74,60,61,79,78,81,
        80,83,82,77,84,77,88,87,90,89,92,
        91,86,93,86,57,24,95,85,2,99,84,
        74,97,104,104,97,26,35,35,24,35,24
      };
    
      int n1[88] = {
        1,2,7,8,13,14,19,20,39,6,38,
        37,37,36,45,12,44,43,43,42,51,18,
        50,49,49,48,57,24,56,55,55,54,40,
        41,63,11,62,10,67,17,66,16,71,23,
        70,22,75,29,74,28,64,65,78,9,80,
        15,82,21,84,27,79,87,8,89,14,91,
        20,93,26,88,35,57,94,86,85,98,77,
        60,96,103,28,27,99,55,102,25,31,102
      };
    
      int n2[88] = {
        4,5,10,11,16,17,22,23,38,7,7,
        36,8,87,44,13,13,42,14,89,50,19,
        19,48,20,91,56,25,25,54,26,93,46,
        47,62,10,78,9,66,16,80,15,70,22,
        82,21,74,28,84,27,68,69,39,6,45,
        12,51,18,57,24,81,63,11,67,17,71,
        23,75,29,90,33,94,33,93,98,93,76,
        58,76,58,74,84,2,26,2,26,2,0
      };
    
      int n3[88] = {
        3,4,9,10,15,16,21,22,37,38,8,
        40,87,88,43,44,14,46,89,90,49,50,
        20,52,91,92,55,56,26,34,93,86,52,
        53,64,62,79,78,68,66,81,80,72,70,
        83,82,60,74,77,84,72,73,41,39,47,
        45,53,51,35,57,83,65,63,69,67,73,
        71,61,75,92,94,95,0,98,99,26,96,
        103,3,4,103,96,102,102,31,102,102,95
      };
    
      int n4[88] = {
        6,7,12,13,18,19,24,25,35,33,31,
        35,30,34,41,39,37,41,36,40,47,45,
        43,47,42,46,53,51,49,53,48,52,86,
        34,61,59,60,58,65,63,64,62,69,67,
        68,66,73,71,72,70,77,60,77,76,79,
        78,81,80,83,82,35,86,85,88,87,90,
        89,92,91,61,84,27,97,59,5,101,74,
        75,104,101,101,104,93,34,34,57,33,57
      };
    
      int n5[88] = {
        7,8,13,14,19,20,25,26,33,0,32,
        31,31,30,39,6,38,37,37,36,45,12,
        44,43,43,42,51,18,50,49,49,48,88,
        40,59,5,58,4,63,11,62,10,67,17,
        66,16,71,23,70,22,79,64,76,3,78,
        9,80,15,82,21,41,85,2,87,8,89,
        14,91,20,65,77,84,96,61,59,100,60,
        61,103,100,29,28,98,54,86,56,32,35
      };
    
      int n6[88] = {
        10,11,16,17,22,23,28,29,32,1,1,
        30,2,85,38,7,7,36,8,87,44,13,
        13,42,14,89,50,19,19,48,20,91,90,
        46,58,4,76,3,62,10,78,9,66,16,
        80,15,70,22,82,21,81,68,33,0,39,
        6,45,12,51,18,47,59,5,63,11,67,
        17,71,23,69,76,96,76,75,100,75,58,
        59,58,59,75,74,85,93,85,55,1,33
      };
    
      int n7[88] = {
        9,10,15,16,21,22,27,28,31,32,2,
        34,85,86,37,38,8,40,87,88,43,44,
        14,46,89,90,49,50,20,52,91,92,92,
        52,60,58,77,76,64,62,79,78,68,66,
        81,80,72,70,83,82,83,72,35,33,41,
        39,47,45,53,51,53,61,59,65,63,69,
        67,73,71,73,96,97,3,100,101,29,103,
        100,4,5,100,103,86,86,30,35,0,94
      };
    
      if(i==0){
        return n0[j];
      }
      else if(i==1){
        return n1[j];
      }
      else if(i==2){
        return n2[j];
      }
      else if(i==3){
        return n3[j];
      }
      else if(i==4){
        return n4[j];
      }
      else if(i==5){
        return n5[j];
      }
      else if(i==6){
        return n6[j];
      }
      else{
        return n7[j];
      }
    }
    
    
    void subdivide_pyramid(MElement* element,
    		       GRegion* gr,
    		       faceContainer &faceVertices,
    		       std::vector<MHexahedron*> &dwarfs88)
    {
      unsigned int i;
      int index1,index2,index3,index4;
      int index5,index6,index7,index8;
      SPoint3 point;
      std::vector<MVertex*> v;
    
      dwarfs88.resize(88);
      v.resize(105);
    
      for (int i=0;i<105;i++)v[i] = NULL;
    
      v[29] = element->getVertex(0);
      v[27] = element->getVertex(1);
      v[3] = element->getVertex(2);
      v[5] = element->getVertex(3);
      v[102] = element->getVertex(4);
    
      v[28] = element->getVertex(5);
      v[97] = element->getVertex(8);
      v[4] = element->getVertex(10);
      v[101] = element->getVertex(6);
      v[26] = element->getVertex(7);
      v[24] = element->getVertex(9);
      v[0] = element->getVertex(11);
      v[2] = element->getVertex(12);
    
      // the one in the middle of rect face
      v[104] = element->getVertex(13);
    
      faceContainer::iterator fIter;
    
      fIter = faceVertices.find(MFace(v[29],v[27],v[102]));
      if (fIter != faceVertices.end())
        v[25] = fIter->second[0];
      else {
        element->pnt(0.0,-0.666667,0.471405/1.414213,point);
        v[25] = new MVertex(point.x(),point.y(),point.z(),gr);
        gr->addMeshVertex(v[25]);
        faceVertices[MFace(v[29],v[27],v[102])].push_back(v[25]);
      }
    
      fIter = faceVertices.find(MFace(v[27],v[3],v[102]));
      if (fIter != faceVertices.end())
        v[95] = fIter->second[0];
      else {
        element->pnt(0.666667,0.0,0.471405/1.414213,point);
        v[95] = new MVertex(point.x(),point.y(),point.z(),gr);
        gr->addMeshVertex(v[95]);
        faceVertices[MFace(v[27],v[3],v[102])].push_back(v[95]);
      }
    
      fIter = faceVertices.find(MFace(v[3],v[5],v[102]));
      if (fIter != faceVertices.end())
        v[1] = fIter->second[0];
      else {
        element->pnt(0.0,0.666667,0.471405/1.414213,point);
        v[1] = new MVertex(point.x(),point.y(),point.z(),gr);
        gr->addMeshVertex(v[1]);
        faceVertices[MFace(v[3],v[5],v[102])].push_back(v[1]);
      }
    
      fIter = faceVertices.find(MFace(v[5],v[29],v[102]));
      if (fIter != faceVertices.end())
        v[99] = fIter->second[0];
      else {
        element->pnt(-0.666667,0.0,0.471405/1.414213,point);
        v[99] = new MVertex(point.x(),point.y(),point.z(),gr);
        gr->addMeshVertex(v[99]);
        faceVertices[MFace(v[5],v[29],v[102])].push_back(v[99]);
      }
    
      for(i=0;i<105;i++){
        if (!v[i]){
          element->pnt(schneiders_z(i),schneiders_x(i),schneiders_y(i)/1.414213,point);
          v[i] = new MVertex(point.x(),point.y(),point.z(),gr);
          gr->addMeshVertex(v[i]);
        }
      }
    
      for(i=0;i<88;i++){
        index1 = schneiders_connect(0,i);
        index2 = schneiders_connect(1,i);
        index3 = schneiders_connect(2,i);
        index4 = schneiders_connect(3,i);
        index5 = schneiders_connect(4,i);
        index6 = schneiders_connect(5,i);
        index7 = schneiders_connect(6,i);
        index8 = schneiders_connect(7,i);
    
        dwarfs88[i]=(new MHexahedron(v[index1],v[index2],
    				v[index3],v[index4],
    				v[index5],v[index6],
    				v[index7],v[index8]));
      }
    }