Date: 2013-07-02T14:53:09+00:00

Actual source code: Generator.hh
petsc-3.4.2 2013-07-02

      1: #ifndef included_ALE_Generator_hh
      2: #define included_ALE_Generator_hh

      4: #ifndef  included_ALE_Distribution_hh
      5: #include <sieve/Distribution.hh>
      6: #endif

      8: #ifdef PETSC_HAVE_TRIANGLE
      9: #include <triangle.h>
     10: #endif
     11: #ifdef PETSC_HAVE_TETGEN
     12: #include <tetgen.h>
     13: #endif

     15: namespace ALE {
     16: #ifdef PETSC_HAVE_TRIANGLE
     17:   namespace Triangle {
     18:     template<typename Mesh>
     19:     class Generator {
     20:       class SegmentVisitor {
     21:       protected:
     22:         const int dim;
     23:         int *segmentlist;
     24:         typename Mesh::numbering_type& vNumbering;
     25:         int idx, v;
     26:       public:
     27:         SegmentVisitor(const int dim, int segmentlist[], typename Mesh::numbering_type& vNumbering) : dim(dim), segmentlist(segmentlist), vNumbering(vNumbering), idx(0), v(0) {};
     28:         ~SegmentVisitor() {};
     29:       public:
     30:         template<typename Point>
     31:         void visitPoint(const Point& point) {
     32:           this->segmentlist[this->idx*dim + (this->v++)] = this->vNumbering.getIndex(point);
     33:         }
     34:         template<typename Arrow>
     35:         void visitArrow(const Arrow& arrow) {}
     36:         void setIndex(const int idx) {this->idx = idx; this->v = 0;};
     37:       };
     38:     public:
     39:       static void initInput(struct triangulateio *inputCtx) {
     40:         inputCtx->numberofpoints = 0;
     41:         inputCtx->numberofpointattributes = 0;
     42:         inputCtx->pointlist = NULL;
     43:         inputCtx->pointattributelist = NULL;
     44:         inputCtx->pointmarkerlist = NULL;
     45:         inputCtx->numberofsegments = 0;
     46:         inputCtx->segmentlist = NULL;
     47:         inputCtx->segmentmarkerlist = NULL;
     48:         inputCtx->numberoftriangleattributes = 0;
     49:         inputCtx->trianglelist = NULL;
     50:         inputCtx->numberofholes = 0;
     51:         inputCtx->holelist = NULL;
     52:         inputCtx->numberofregions = 0;
     53:         inputCtx->regionlist = NULL;
     54:       };
     55:       static void initOutput(struct triangulateio *outputCtx) {
     56:         outputCtx->numberofpoints = 0;
     57:         outputCtx->pointlist = NULL;
     58:         outputCtx->pointattributelist = NULL;
     59:         outputCtx->pointmarkerlist = NULL;
     60:         outputCtx->numberoftriangles = 0;
     61:         outputCtx->trianglelist = NULL;
     62:         outputCtx->triangleattributelist = NULL;
     63:         outputCtx->neighborlist = NULL;
     64:         outputCtx->segmentlist = NULL;
     65:         outputCtx->segmentmarkerlist = NULL;
     66:         outputCtx->edgelist = NULL;
     67:         outputCtx->edgemarkerlist = NULL;
     68:       };
     69:       static void finiOutput(struct triangulateio *outputCtx) {
     70:         free(outputCtx->pointmarkerlist);
     71:         free(outputCtx->edgelist);
     72:         free(outputCtx->edgemarkerlist);
     73:         free(outputCtx->trianglelist);
     74:         free(outputCtx->neighborlist);
     75:       };
     78:       static Obj<Mesh> generateMesh(const Obj<Mesh>& boundary, const bool interpolate = false, const bool constrained = false) {
     79:         int                          dim   = 2;
     80:         Obj<Mesh>                    mesh  = new Mesh(boundary->comm(), dim, boundary->debug());
     81:         const Obj<typename Mesh::sieve_type>& sieve = boundary->getSieve();
     82:         const bool                   createConvexHull = false;
     83:         struct triangulateio in;
     84:         struct triangulateio out;

     87:         initInput(&in);
     88:         initOutput(&out);
     89:         const Obj<typename Mesh::label_sequence>&    vertices    = boundary->depthStratum(0);
     90:         const Obj<typename Mesh::label_type>&        markers     = boundary->getLabel("marker");
     91:         const Obj<typename Mesh::real_section_type>& coordinates = boundary->getRealSection("coordinates");
     92:         const Obj<typename Mesh::numbering_type>&    vNumbering  = boundary->getFactory()->getLocalNumbering(boundary, 0);

     94:         in.numberofpoints = vertices->size();
     95:         if (in.numberofpoints > 0) {
     96:           const typename Mesh::label_sequence::iterator vEnd = vertices->end();

     98:           PetscMalloc(in.numberofpoints * dim * sizeof(double), &in.pointlist);CHKERRXX(ierr);
     99:           PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRXX(ierr);
    100:           for(typename Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vEnd; ++v_iter) {
    101:             const typename Mesh::real_section_type::value_type *array = coordinates->restrictPoint(*v_iter);
    102:             const int                                  idx   = vNumbering->getIndex(*v_iter);

    104:             for(int d = 0; d < dim; d++) {
    105:               in.pointlist[idx*dim + d] = array[d];
    106:             }
    107:             in.pointmarkerlist[idx] = boundary->getValue(markers, *v_iter);
    108:           }
    109:         }
    110:         const Obj<typename Mesh::label_sequence>& edges      = boundary->depthStratum(1);
    111:         const Obj<typename Mesh::numbering_type>& eNumbering = boundary->getFactory()->getLocalNumbering(boundary, 1);

    113:         in.numberofsegments = edges->size();
    114:         if (in.numberofsegments > 0) {
    115:           const typename Mesh::label_sequence::iterator eEnd = edges->end();

    117:           PetscMalloc(in.numberofsegments * 2 * sizeof(int), &in.segmentlist);CHKERRXX(ierr);
    118:           PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRXX(ierr);
    119:           for(typename Mesh::label_sequence::iterator e_iter = edges->begin(); e_iter != eEnd; ++e_iter) {
    120:             const Obj<typename Mesh::sieve_type::traits::coneSequence>&     cone = sieve->cone(*e_iter);
    121:             const typename Mesh::sieve_type::traits::coneSequence::iterator cEnd = cone->end();
    122:             const int                                                       idx  = eNumbering->getIndex(*e_iter);
    123:             int                                                             v    = 0;

    125:             for(typename Mesh::sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cEnd; ++c_iter) {
    126:               in.segmentlist[idx*dim + (v++)] = vNumbering->getIndex(*c_iter);
    127:             }
    128:             in.segmentmarkerlist[idx] = boundary->getValue(markers, *e_iter);
    129:           }
    130:         }
    131:         const typename Mesh::holes_type& holes = boundary->getHoles();

    133:         in.numberofholes = holes.size();
    134:         if (in.numberofholes > 0) {
    135:           PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRXX(ierr);
    136:           for(int h = 0; h < in.numberofholes; ++h) {
    137:             for(int d = 0; d < dim; ++d) {
    138:               in.holelist[h*dim+d] = holes[h][d];
    139:             }
    140:           }
    141:         }
    142:         if (mesh->commRank() == 0) {
    143:           std::string args("pqezQ");

    145:           if (createConvexHull) {
    146:             args += "c";
    147:           }
    148:           if (constrained) {
    149:             args = "zepDQ";
    150:           }
    151:           triangulate((char *) args.c_str(), &in, &out, NULL);
    152:         }

    154:         if (in.pointlist)         {PetscFree(in.pointlist);CHKERRXX(ierr);}
    155:         if (in.pointmarkerlist)   {PetscFree(in.pointmarkerlist);CHKERRXX(ierr);}
    156:         if (in.segmentlist)       {PetscFree(in.segmentlist);CHKERRXX(ierr);}
    157:         if (in.segmentmarkerlist) {PetscFree(in.segmentmarkerlist);CHKERRXX(ierr);}
    158:         if (in.holelist)          {PetscFree(in.holelist);CHKERRXX(ierr);}
    159:         const Obj<typename Mesh::sieve_type> newSieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
    160:         int     numCorners  = 3;
    161:         int     numCells    = out.numberoftriangles;
    162:         int    *cells       = out.trianglelist;
    163:         int     numVertices = out.numberofpoints;
    164:         double *coords      = out.pointlist;

    166:         ALE::SieveBuilder<Mesh>::buildTopology(newSieve, dim, numCells, cells, numVertices, interpolate, numCorners, -1, mesh->getArrowSection("orientation"));
    167:         mesh->setSieve(newSieve);
    168:         mesh->stratify();
    169:         ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, dim, coords);
    170:         const Obj<typename Mesh::label_type>& newMarkers = mesh->createLabel("marker");

    172:         if (mesh->commRank() == 0) {
    173:           for(int v = 0; v < out.numberofpoints; v++) {
    174:             if (out.pointmarkerlist[v]) {
    175:               mesh->setValue(newMarkers, v+out.numberoftriangles, out.pointmarkerlist[v]);
    176:             }
    177:           }
    178:           if (interpolate) {
    179:             for(int e = 0; e < out.numberofedges; e++) {
    180:               if (out.edgemarkerlist[e]) {
    181:                 const typename Mesh::point_type vertexA(out.edgelist[e*2+0]+out.numberoftriangles);
    182:                 const typename Mesh::point_type vertexB(out.edgelist[e*2+1]+out.numberoftriangles);
    183:                 const Obj<typename Mesh::sieve_type::supportSet> edge = newSieve->nJoin(vertexA, vertexB, 1);

    185:                 mesh->setValue(newMarkers, *(edge->begin()), out.edgemarkerlist[e]);
    186:               }
    187:             }
    188:           }
    189:         }
    190:         mesh->copyHoles(boundary);
    191:         finiOutput(&out);
    192:         return mesh;
    193:       };
    196:       static Obj<Mesh> generateMeshV(const Obj<Mesh>& boundary, const bool interpolate = false, const bool constrained = false, const bool renumber = false) {
    197:         typedef ALE::Mesh<PetscInt,PetscScalar> FlexMesh;
    198:         typedef typename Mesh::real_section_type::value_type real;
    199:         int                                   dim   = 2;
    200:         const Obj<Mesh>                       mesh  = new Mesh(boundary->comm(), dim, boundary->debug());
    201:         const Obj<typename Mesh::sieve_type>& sieve = boundary->getSieve();
    202:         const bool                            createConvexHull = false;
    203:         struct triangulateio in;
    204:         struct triangulateio out;
    205:         PetscErrorCode       ierr;

    207:         initInput(&in);
    208:         initOutput(&out);
    209:         const Obj<typename Mesh::label_sequence>&    vertices    = boundary->depthStratum(0);
    210:         const Obj<typename Mesh::label_type>&        markers     = boundary->getLabel("marker");
    211:         const Obj<typename Mesh::real_section_type>& coordinates = boundary->getRealSection("coordinates");
    212:         const Obj<typename Mesh::numbering_type>&    vNumbering  = boundary->getFactory()->getLocalNumbering(boundary, 0);

    214:         in.numberofpoints = vertices->size();
    215:         if (in.numberofpoints > 0) {
    216:           const typename Mesh::label_sequence::iterator vEnd = vertices->end();

    218:           PetscMalloc(in.numberofpoints * dim * sizeof(double), &in.pointlist);CHKERRXX(ierr);
    219:           PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRXX(ierr);
    220:           for(typename Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vEnd; ++v_iter) {
    221:             const typename Mesh::real_section_type::value_type *array = coordinates->restrictPoint(*v_iter);
    222:             const int                                           idx   = vNumbering->getIndex(*v_iter);

    224:             for(int d = 0; d < dim; ++d) {
    225:               in.pointlist[idx*dim + d] = array[d];
    226:             }
    227:             in.pointmarkerlist[idx] = boundary->getValue(markers, *v_iter);
    228:           }
    229:         }
    230:         const Obj<typename Mesh::label_sequence>& edges      = boundary->depthStratum(1);
    231:         const Obj<typename Mesh::numbering_type>& eNumbering = boundary->getFactory()->getLocalNumbering(boundary, 1);

    233:         in.numberofsegments = edges->size();
    234:         if (in.numberofsegments > 0) {
    235:           const typename Mesh::label_sequence::iterator eEnd = edges->end();

    237:           PetscMalloc(in.numberofsegments * 2 * sizeof(int), &in.segmentlist);CHKERRXX(ierr);
    238:           PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRXX(ierr);
    239:           SegmentVisitor sV(dim, in.segmentlist, *vNumbering);
    240:           for(typename Mesh::label_sequence::iterator e_iter = edges->begin(); e_iter != eEnd; ++e_iter) {
    241:             const int idx = eNumbering->getIndex(*e_iter);

    243:             sV.setIndex(idx);
    244:             sieve->cone(*e_iter, sV);
    245:             in.segmentmarkerlist[idx] = boundary->getValue(markers, *e_iter);
    246:           }
    247:         }
    248:         const typename Mesh::holes_type& holes = boundary->getHoles();

    250:         in.numberofholes = holes.size();
    251:         if (in.numberofholes > 0) {
    252:           PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRXX(ierr);
    253:           for(int h = 0; h < in.numberofholes; ++h) {
    254:             for(int d = 0; d < dim; ++d) {
    255:               in.holelist[h*dim+d] = holes[h][d];
    256:             }
    257:           }
    258:         }
    259:         if (mesh->commRank() == 0) {
    260:           std::string args("pqezQ");

    262:           if (createConvexHull) {
    263:             args += "c";
    264:           }
    265:           if (constrained) {
    266:             args = "zepDQ";
    267:           }
    268:           triangulate((char *) args.c_str(), &in, &out, NULL);
    269:         }
    270:         if (in.pointlist)         {PetscFree(in.pointlist);CHKERRXX(ierr);}
    271:         if (in.pointmarkerlist)   {PetscFree(in.pointmarkerlist);CHKERRXX(ierr);}
    272:         if (in.segmentlist)       {PetscFree(in.segmentlist);CHKERRXX(ierr);}
    273:         if (in.segmentmarkerlist) {PetscFree(in.segmentmarkerlist);CHKERRXX(ierr);}
    274:         if (in.holelist)          {PetscFree(in.holelist);CHKERRXX(ierr);}
    275:         const Obj<typename Mesh::sieve_type> newSieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
    276:         const Obj<FlexMesh>                  m        = new FlexMesh(boundary->comm(), dim, boundary->debug());
    277:         const Obj<FlexMesh::sieve_type>      newS     = new FlexMesh::sieve_type(m->comm(), m->debug());
    278:         int     numCorners  = 3;
    279:         int     numCells    = out.numberoftriangles;
    280:         int    *cells       = out.trianglelist;
    281:         int     numVertices = out.numberofpoints;
    282:         double *coords      = out.pointlist;
    283:         real   *coordsR;

    285:         ALE::SieveBuilder<FlexMesh>::buildTopology(newS, dim, numCells, cells, numVertices, interpolate, numCorners, -1, m->getArrowSection("orientation"));
    286:         m->setSieve(newS);
    287:         m->stratify();
    288:         mesh->setSieve(newSieve);
    289:         std::map<typename Mesh::point_type,typename Mesh::point_type> renumbering;
    290:         ALE::ISieveConverter::convertSieve(*newS, *newSieve, renumbering, renumber);
    291:         mesh->stratify();
    292:         ALE::ISieveConverter::convertOrientation(*newS, *newSieve, renumbering,
    293:         m->getArrowSection("orientation").ptr());
    294:         {
    295:           if (sizeof(double) == sizeof(real)) {
    296:             coordsR = (real *) coords;
    297:           } else {
    298:             coordsR = new real[numVertices*dim];
    299:             for(int i = 0; i < numVertices*dim; ++i) coordsR[i] = coords[i];
    300:           }
    301:         }
    302:         ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, dim, coordsR);
    303:         {
    304:           if (sizeof(double) != sizeof(real)) {
    305:             delete [] coordsR;
    306:           }
    307:         }
    308:         const Obj<typename Mesh::label_type>& newMarkers = mesh->createLabel("marker");

    310:         if (mesh->commRank() == 0) {
    311: #ifdef IMESH_NEW_LABELS
    312:           int size = 0;

    314:           newMarkers->setChart(mesh->getSieve()->getChart());
    315:           for(int v = 0; v < out.numberofpoints; v++) {
    316:             if (out.pointmarkerlist[v]) {
    317:               newMarkers->setConeSize(v+out.numberoftriangles, 1);
    318:               size++;
    319:             }
    320:           }
    321:           if (interpolate) {
    322:             for(int e = 0; e < out.numberofedges; e++) {
    323:               if (out.edgemarkerlist[e]) {
    324:                 const typename Mesh::point_type vertexA(out.edgelist[e*2+0]+out.numberoftriangles);
    325:                 const typename Mesh::point_type vertexB(out.edgelist[e*2+1]+out.numberoftriangles);
    326:                 const Obj<typename Mesh::sieve_type::supportSet> edge = newS->nJoin(vertexA, vertexB, 1);

    328:                 newMarkers->setConeSize(*edge->begin(), 1);
    329:                 size++;
    330:               }
    331:             }
    332:           }
    333:           newMarkers->setSupportSize(0, size);
    334:           newMarkers->allocate();
    335: #endif
    336:           for(int v = 0; v < out.numberofpoints; v++) {
    337:             if (out.pointmarkerlist[v]) {
    338:               if (renumber) {
    339:                 mesh->setValue(newMarkers, renumbering[v+out.numberoftriangles], out.pointmarkerlist[v]);
    340:               } else {
    341:                 mesh->setValue(newMarkers, v+out.numberoftriangles, out.pointmarkerlist[v]);
    342:               }
    343:             }
    344:           }
    345:           if (interpolate) {
    346:             for(int e = 0; e < out.numberofedges; e++) {
    347:               if (out.edgemarkerlist[e]) {
    348:                 const typename Mesh::point_type vertexA(out.edgelist[e*2+0]+out.numberoftriangles);
    349:                 const typename Mesh::point_type vertexB(out.edgelist[e*2+1]+out.numberoftriangles);
    350:                 const Obj<typename Mesh::sieve_type::supportSet> edge = newS->nJoin(vertexA, vertexB, 1);

    352:                 mesh->setValue(newMarkers, *(edge->begin()), out.edgemarkerlist[e]);
    353:               }
    354:             }
    355:           }
    356: #ifdef IMESH_NEW_LABELS
    357:           newMarkers->recalculateLabel();
    358: #endif
    359:         }
    360:         mesh->copyHoles(boundary);
    361:         finiOutput(&out);
    362:         return mesh;
    363:       };
    364:     };
    365:     template<typename Mesh>
    366:     class Refiner {
    367:     public:
    368:       static Obj<Mesh> refineMesh(const Obj<Mesh>& serialMesh, const double maxVolumes[], const bool interpolate = false, const bool forceSerial = false) {
    369:         const int                    dim         = serialMesh->getDimension();
    370:         const Obj<Mesh>              refMesh     = new Mesh(serialMesh->comm(), dim, serialMesh->debug());
    371:         const Obj<typename Mesh::sieve_type>& serialSieve = serialMesh->getSieve();
    372:         struct triangulateio in;
    373:         struct triangulateio out;
    374:         PetscErrorCode       ierr;

    376:         Generator<Mesh>::initInput(&in);
    377:         Generator<Mesh>::initOutput(&out);
    378:         const Obj<typename Mesh::label_sequence>&    vertices    = serialMesh->depthStratum(0);
    379:         const Obj<typename Mesh::label_type>&        markers     = serialMesh->getLabel("marker");
    380:         const Obj<typename Mesh::real_section_type>& coordinates = serialMesh->getRealSection("coordinates");
    381:         const Obj<typename Mesh::numbering_type>&    vNumbering  = serialMesh->getFactory()->getLocalNumbering(serialMesh, 0);

    383:         in.numberofpoints = vertices->size();
    384:         if (in.numberofpoints > 0) {
    385:           const typename Mesh::label_sequence::iterator vEnd = vertices->end();

    387:           PetscMalloc(in.numberofpoints * dim * sizeof(double), &in.pointlist);CHKERRXX(ierr);
    388:           PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRXX(ierr);
    389:           for(typename Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vEnd; ++v_iter) {
    390:             const typename Mesh::real_section_type::value_type *array = coordinates->restrictPoint(*v_iter);
    391:             const int                                  idx   = vNumbering->getIndex(*v_iter);

    393:             for(int d = 0; d < dim; d++) {
    394:               in.pointlist[idx*dim + d] = array[d];
    395:             }
    396:             in.pointmarkerlist[idx] = serialMesh->getValue(markers, *v_iter);
    397:           }
    398:         }
    399:         const Obj<typename Mesh::label_sequence>& faces      = serialMesh->heightStratum(0);
    400:         const Obj<typename Mesh::numbering_type>& fNumbering = serialMesh->getFactory()->getLocalNumbering(serialMesh, serialMesh->depth());

    402:         in.numberofcorners   = 3;
    403:         in.numberoftriangles = faces->size();
    404:         in.trianglearealist  = (double *) maxVolumes;
    405:         if (in.numberoftriangles > 0) {
    406:           const typename Mesh::label_sequence::iterator fEnd = faces->end();

    408:           PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRXX(ierr);
    409:           if (serialMesh->depth() == 1) {
    410:             for(typename Mesh::label_sequence::iterator f_iter = faces->begin(); f_iter != fEnd; ++f_iter) {
    411:               const Obj<typename Mesh::sieve_type::traits::coneSequence>&     cone = serialSieve->cone(*f_iter);
    412:               const typename Mesh::sieve_type::traits::coneSequence::iterator cEnd = cone->end();
    413:               const int                                                       idx  = fNumbering->getIndex(*f_iter);
    414:               int                                                             v    = 0;

    416:               for(typename Mesh::sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cEnd; ++c_iter) {
    417:                 in.trianglelist[idx*in.numberofcorners + v++] = vNumbering->getIndex(*c_iter);
    418:               }
    419:             }
    420:           } else if (serialMesh->depth() == 2) {
    421:             for(typename Mesh::label_sequence::iterator f_iter = faces->begin(); f_iter != fEnd; ++f_iter) {
    422:               typedef ALE::SieveAlg<Mesh> sieve_alg_type;
    423:               const Obj<typename sieve_alg_type::coneArray>&       cone = sieve_alg_type::nCone(serialMesh, *f_iter, 2);
    424:               const typename Mesh::sieve_type::coneArray::iterator cEnd = cone->end();
    425:               const int                                            idx  = fNumbering->getIndex(*f_iter);
    426:               int                                                  v    = 0;

    428:               for(typename Mesh::sieve_type::coneArray::iterator c_iter = cone->begin(); c_iter != cEnd; ++c_iter) {
    429:                 in.trianglelist[idx*in.numberofcorners + v++] = vNumbering->getIndex(*c_iter);
    430:               }
    431:             }
    432:           } else {
    433:             throw ALE::Exception("Invalid sieve: Cannot gives sieves of arbitrary depth to Triangle");
    434:           }
    435:         }
    436:         if (serialMesh->depth() == 2) {
    437:           const Obj<typename Mesh::label_sequence>&           edges    = serialMesh->depthStratum(1);
    438: #define NEW_LABEL
    439: #ifdef NEW_LABEL
    440:           for(typename Mesh::label_sequence::iterator e_iter = edges->begin(); e_iter != edges->end(); ++e_iter) {
    441:             if (serialMesh->getValue(markers, *e_iter)) {
    442:               in.numberofsegments++;
    443:             }
    444:           }
    445:           //std::cout << "Number of segments: " << in.numberofsegments << std::endl;
    446:           if (in.numberofsegments > 0) {
    447:             int s = 0;

    449:             PetscMalloc(in.numberofsegments * 2 * sizeof(int), &in.segmentlist);CHKERRXX(ierr);
    450:             PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRXX(ierr);
    451:             for(typename Mesh::label_sequence::iterator e_iter = edges->begin(); e_iter != edges->end(); ++e_iter) {
    452:               const int edgeMarker = serialMesh->getValue(markers, *e_iter);

    454:               if (edgeMarker) {
    455:                 const Obj<typename Mesh::sieve_type::traits::coneSequence>& cone = serialSieve->cone(*e_iter);
    456:                 int                                                p    = 0;

    458:                 for(typename Mesh::sieve_type::traits::coneSequence::iterator v_iter = cone->begin(); v_iter != cone->end(); ++v_iter) {
    459:                   in.segmentlist[s*2 + (p++)] = vNumbering->getIndex(*v_iter);
    460:                 }
    461:                 in.segmentmarkerlist[s++] = edgeMarker;
    462:               }
    463:             }
    464:           }
    465: #else
    466:           const Obj<typename Mesh::label_type::baseSequence>& boundary = markers->base();

    468:           in.numberofsegments = 0;
    469:           for(typename Mesh::label_type::baseSequence::iterator b_iter = boundary->begin(); b_iter != boundary->end(); ++b_iter) {
    470:             for(typename Mesh::label_sequence::iterator e_iter = edges->begin(); e_iter != edges->end(); ++e_iter) {
    471:               if (*b_iter == *e_iter) {
    472:                 in.numberofsegments++;
    473:               }
    474:             }
    475:           }
    476:           if (in.numberofsegments > 0) {
    477:             int s = 0;

    479:             PetscMalloc(in.numberofsegments * 2 * sizeof(int), &in.segmentlist);CHKERRXX(ierr);
    480:             PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRXX(ierr);
    481:             for(typename Mesh::label_type::baseSequence::iterator b_iter = boundary->begin(); b_iter != boundary->end(); ++b_iter) {
    482:               for(typename Mesh::label_sequence::iterator e_iter = edges->begin(); e_iter != edges->end(); ++e_iter) {
    483:                 if (*b_iter == *e_iter) {
    484:                   const Obj<typename Mesh::sieve_type::traits::coneSequence>& cone = serialSieve->cone(*e_iter);
    485:                   int                                                p    = 0;

    487:                   for(typename Mesh::sieve_type::traits::coneSequence::iterator v_iter = cone->begin(); v_iter != cone->end(); ++v_iter) {
    488:                     in.segmentlist[s*2 + (p++)] = vNumbering->getIndex(*v_iter);
    489:                   }
    490:                   in.segmentmarkerlist[s++] = serialMesh->getValue(markers, *e_iter);
    491:                 }
    492:               }
    493:             }
    494:           }
    495: #endif
    496:         }

    498:         in.numberofholes = 0;
    499:         if (in.numberofholes > 0) {
    500:           PetscMalloc(in.numberofholes * dim * sizeof(int), &in.holelist);CHKERRXX(ierr);
    501:         }
    502:         if (serialMesh->commRank() == 0) {
    503:           std::string args("pqezQra");

    505:           triangulate((char *) args.c_str(), &in, &out, NULL);
    506:         }
    507:         if (in.pointlist)         {PetscFree(in.pointlist);CHKERRXX(ierr);}
    508:         if (in.pointmarkerlist)   {PetscFree(in.pointmarkerlist);CHKERRXX(ierr);}
    509:         if (in.segmentlist)       {PetscFree(in.segmentlist);CHKERRXX(ierr);}
    510:         if (in.segmentmarkerlist) {PetscFree(in.segmentmarkerlist);CHKERRXX(ierr);}
    511:         if (in.trianglelist)      {PetscFree(in.trianglelist);CHKERRXX(ierr);}
    512:         const Obj<typename Mesh::sieve_type> newSieve = new typename Mesh::sieve_type(serialMesh->comm(), serialMesh->debug());
    513:         int     numCorners  = 3;
    514:         int     numCells    = out.numberoftriangles;
    515:         int    *cells       = out.trianglelist;
    516:         int     numVertices = out.numberofpoints;
    517:         double *coords      = out.pointlist;

    519:         ALE::SieveBuilder<Mesh>::buildTopology(newSieve, dim, numCells, cells, numVertices, interpolate, numCorners, -1, refMesh->getArrowSection("orientation"));
    520:         refMesh->setSieve(newSieve);
    521:         refMesh->stratify();
    522:         ALE::SieveBuilder<Mesh>::buildCoordinates(refMesh, dim, coords);
    523:         const Obj<typename Mesh::label_type>& newMarkers = refMesh->createLabel("marker");

    525:         if (refMesh->commRank() == 0) {
    526:           for(int v = 0; v < out.numberofpoints; v++) {
    527:             if (out.pointmarkerlist[v]) {
    528:               refMesh->setValue(newMarkers, v+out.numberoftriangles, out.pointmarkerlist[v]);
    529:             }
    530:           }
    531:           if (interpolate) {
    532:             for(int e = 0; e < out.numberofedges; e++) {
    533:               if (out.edgemarkerlist[e]) {
    534:                 const typename Mesh::point_type vertexA(out.edgelist[e*2+0]+out.numberoftriangles);
    535:                 const typename Mesh::point_type vertexB(out.edgelist[e*2+1]+out.numberoftriangles);
    536:                 const Obj<typename Mesh::sieve_type::supportSet> edge = newSieve->nJoin(vertexA, vertexB, 1);

    538:                 refMesh->setValue(newMarkers, *(edge->begin()), out.edgemarkerlist[e]);
    539:               }
    540:             }
    541:           }
    542:         }

    544:         Generator<Mesh>::finiOutput(&out);
    545:         if ((refMesh->commSize() > 1) && (!forceSerial)) {
    546:           return ALE::Distribution<Mesh>::distributeMesh(refMesh);
    547:         }
    548:         return refMesh;
    549:       };
    550:       static Obj<Mesh> refineMesh(const Obj<Mesh>& mesh, const Obj<typename Mesh::real_section_type>& maxVolumes, const bool interpolate = false) {
    551:         Obj<Mesh>                          serialMesh       = ALE::Distribution<Mesh>::unifyMesh(mesh);
    552:         const Obj<typename Mesh::real_section_type> serialMaxVolumes = ALE::Distribution<Mesh>::distributeSection(maxVolumes, serialMesh, serialMesh->getDistSendOverlap(), serialMesh->getDistRecvOverlap());

    554:         return refineMesh(serialMesh, serialMaxVolumes->restrictSpace(), interpolate);
    555:       };
    556:       static Obj<Mesh> refineMesh(const Obj<Mesh>& mesh, const double maxVolume, const bool interpolate = false, const bool forceSerial = false) {
    557:         Obj<Mesh> serialMesh;
    558:         if ((mesh->commSize() > 1) && (!forceSerial)) {
    559:           serialMesh = ALE::Distribution<Mesh>::unifyMesh(mesh);
    560:         } else {
    561:           serialMesh = mesh;
    562:         }
    563:         const int numFaces         = serialMesh->heightStratum(0)->size();
    564:         double   *serialMaxVolumes = new double[numFaces];

    566:         for(int f = 0; f < numFaces; f++) {
    567:           serialMaxVolumes[f] = maxVolume;
    568:         }
    569:         const Obj<Mesh> refMesh = refineMesh(serialMesh, serialMaxVolumes, interpolate, forceSerial);
    570:         delete [] serialMaxVolumes;
    571:         return refMesh;
    572:       };
    573:       static Obj<Mesh> refineMeshV(const Obj<Mesh>& mesh, const double maxVolumes[], const bool interpolate = false, const bool forceSerial = false, const bool renumber = false) {
    574:         typedef ALE::Mesh<PetscInt,PetscScalar> FlexMesh;
    575:         typedef typename Mesh::real_section_type::value_type real;
    576:         typedef typename Mesh::point_type point_type;
    577:         const int                             dim     = mesh->getDimension();
    578:         const Obj<Mesh>                       refMesh = new Mesh(mesh->comm(), dim, mesh->debug());
    579:         const Obj<typename Mesh::sieve_type>& sieve   = mesh->getSieve();
    580:         struct triangulateio in;
    581:         struct triangulateio out;
    582:         PetscErrorCode       ierr;

    584:         Generator<Mesh>::initInput(&in);
    585:         Generator<Mesh>::initOutput(&out);
    586:         const Obj<typename Mesh::label_sequence>&    vertices    = mesh->depthStratum(0);
    587:         const Obj<typename Mesh::label_type>&        markers     = mesh->getLabel("marker");
    588:         const Obj<typename Mesh::real_section_type>& coordinates = mesh->getRealSection("coordinates");
    589:         const Obj<typename Mesh::numbering_type>&    vNumbering  = mesh->getFactory()->getLocalNumbering(mesh, 0);

    591:         in.numberofpoints = vertices->size();
    592:         if (in.numberofpoints > 0) {
    593:           const typename Mesh::label_sequence::iterator vEnd = vertices->end();

    595:           PetscMalloc(in.numberofpoints * dim * sizeof(double), &in.pointlist);CHKERRXX(ierr);
    596:           PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRXX(ierr);
    597:           for(typename Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vEnd; ++v_iter) {
    598:             const typename Mesh::real_section_type::value_type *array = coordinates->restrictPoint(*v_iter);
    599:             const int                                           idx   = vNumbering->getIndex(*v_iter);

    601:             for(int d = 0; d < dim; d++) {
    602:               in.pointlist[idx*dim + d] = array[d];
    603:             }
    604:             in.pointmarkerlist[idx] = mesh->getValue(markers, *v_iter);
    605:           }
    606:         }
    607:         const Obj<typename Mesh::label_sequence>& faces      = mesh->heightStratum(0);
    608:         const Obj<typename Mesh::numbering_type>& fNumbering = mesh->getFactory()->getLocalNumbering(mesh, mesh->depth());

    610:         in.numberofcorners   = 3;
    611:         in.numberoftriangles = faces->size();
    612:         in.trianglearealist  = (double *) maxVolumes;
    613:         if (in.numberoftriangles > 0) {
    614:           PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRXX(ierr);
    615:           if (mesh->depth() == 1) {
    616:             ALE::ISieveVisitor::PointRetriever<typename Mesh::sieve_type> pV(3);
    617:             const typename Mesh::label_sequence::iterator fEnd = faces->end();

    619:             for(typename Mesh::label_sequence::iterator f_iter = faces->begin(); f_iter != fEnd; ++f_iter) {
    620:               sieve->cone(*f_iter, pV);
    621:               const int         idx  = fNumbering->getIndex(*f_iter);
    622:               const size_t      n    = pV.getSize();
    623:               const point_type *cone = pV.getPoints();

    625:               assert(n == 3);
    626:               for(int v = 0; v < 3; ++v) {
    627:                 in.trianglelist[idx*in.numberofcorners + v] = vNumbering->getIndex(cone[v]);
    628:               }
    629:               pV.clear();
    630:             }
    631:           } else if (mesh->depth() == 2) {
    632:             // Need extra space due to early error checking
    633:             ALE::ISieveVisitor::NConeRetriever<typename Mesh::sieve_type> ncV(*sieve, 4);
    634:             const typename Mesh::label_sequence::iterator fEnd = faces->end();

    636:             for(typename Mesh::label_sequence::iterator f_iter = faces->begin(); f_iter != fEnd; ++f_iter) {
    637:               ALE::ISieveTraversal<typename Mesh::sieve_type>::orientedClosure(*sieve, *f_iter, ncV);
    638:               const int         idx  = fNumbering->getIndex(*f_iter);
    639:               const size_t      n    = ncV.getSize();
    640:               const point_type *cone = ncV.getPoints();

    642:               assert(n == 3);
    643:               for(int v = 0; v < 3; ++v) {
    644:                 in.trianglelist[idx*in.numberofcorners + v] = vNumbering->getIndex(cone[v]);
    645:               }
    646:               ncV.clear();
    647:             }
    648:           } else {
    649:             throw ALE::Exception("Invalid sieve: Cannot gives sieves of arbitrary depth to Triangle");
    650:           }
    651:         }
    652:         if (mesh->depth() == 2) {
    653:           const Obj<typename Mesh::label_sequence>& edges = mesh->depthStratum(1);
    654:           for(typename Mesh::label_sequence::iterator e_iter = edges->begin(); e_iter != edges->end(); ++e_iter) {
    655:             if (mesh->getValue(markers, *e_iter)) {
    656:               in.numberofsegments++;
    657:             }
    658:           }
    659:           //std::cout << "Number of segments: " << in.numberofsegments << std::endl;
    660:           if (in.numberofsegments > 0) {
    661:             ALE::ISieveVisitor::PointRetriever<typename Mesh::sieve_type> pV(2);
    662:             int s = 0;

    664:             PetscMalloc(in.numberofsegments * 2 * sizeof(int), &in.segmentlist);CHKERRXX(ierr);
    665:             PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRXX(ierr);
    666:             for(typename Mesh::label_sequence::iterator e_iter = edges->begin(); e_iter != edges->end(); ++e_iter) {
    667:               const int edgeMarker = mesh->getValue(markers, *e_iter);

    669:               if (edgeMarker) {
    670:                 sieve->cone(*e_iter, pV);
    671:                 const size_t      n    = pV.getSize();
    672:                 const point_type *cone = pV.getPoints();

    674:                 assert(n == 2);
    675:                 for(int v = 0; v < 2; ++v) {
    676:                   in.segmentlist[s*2 + v] = vNumbering->getIndex(cone[v]);
    677:                 }
    678:                 in.segmentmarkerlist[s++] = edgeMarker;
    679:                 pV.clear();
    680:               }
    681:             }
    682:           }
    683:         }
    684:         const typename Mesh::holes_type& holes = mesh->getHoles();

    686:         in.numberofholes = holes.size();
    687:         if (in.numberofholes > 0) {
    688:           PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRXX(ierr);
    689:           for(int h = 0; h < in.numberofholes; ++h) {
    690:             for(int d = 0; d < dim; ++d) {
    691:               in.holelist[h*dim+d] = holes[h][d];
    692:             }
    693:           }
    694:         }
    695:         if (mesh->commRank() == 0) {
    696:           std::string args("pqezQra");

    698:           triangulate((char *) args.c_str(), &in, &out, NULL);
    699:         }
    700:         if (in.pointlist)         {PetscFree(in.pointlist);CHKERRXX(ierr);}
    701:         if (in.pointmarkerlist)   {PetscFree(in.pointmarkerlist);CHKERRXX(ierr);}
    702:         if (in.segmentlist)       {PetscFree(in.segmentlist);CHKERRXX(ierr);}
    703:         if (in.segmentmarkerlist) {PetscFree(in.segmentmarkerlist);CHKERRXX(ierr);}
    704:         if (in.trianglelist)      {PetscFree(in.trianglelist);CHKERRXX(ierr);}
    705:         const Obj<typename Mesh::sieve_type> newSieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
    706:         const Obj<FlexMesh>                  m        = new FlexMesh(mesh->comm(), dim, mesh->debug());
    707:         const Obj<FlexMesh::sieve_type>      newS     = new FlexMesh::sieve_type(m->comm(), m->debug());
    708:         int     numCorners  = 3;
    709:         int     numCells    = out.numberoftriangles;
    710:         int    *cells       = out.trianglelist;
    711:         int     numVertices = out.numberofpoints;
    712:         double *coords      = out.pointlist;
    713:         real   *coordsR;

    715:         ALE::SieveBuilder<FlexMesh>::buildTopology(newS, dim, numCells, cells, numVertices, interpolate, numCorners, -1, m->getArrowSection("orientation"));
    716:         m->setSieve(newS);
    717:         m->stratify();
    718:         refMesh->setSieve(newSieve);
    719:         std::map<typename Mesh::point_type,typename Mesh::point_type> renumbering;
    720:         ALE::ISieveConverter::convertSieve(*newS, *newSieve, renumbering, renumber);
    721:         refMesh->stratify();
    722:         ALE::ISieveConverter::convertOrientation(*newS, *newSieve, renumbering, m->getArrowSection("orientation").ptr());
    723:         {
    724:           if (sizeof(double) == sizeof(real)) {
    725:             coordsR = (real *) coords;
    726:           } else {
    727:             coordsR = new real[numVertices*dim];
    728:             for(int i = 0; i < numVertices*dim; ++i) coordsR[i] = coords[i];
    729:           }
    730:         }
    731:         ALE::SieveBuilder<Mesh>::buildCoordinates(refMesh, dim, coordsR);
    732:         {
    733:           if (sizeof(double) != sizeof(real)) {
    734:             delete [] coordsR;
    735:           }
    736:         }
    737:         const Obj<typename Mesh::label_type>& newMarkers = refMesh->createLabel("marker");

    739:         if (refMesh->commRank() == 0) {
    740:           for(int v = 0; v < out.numberofpoints; v++) {
    741:             if (out.pointmarkerlist[v]) {
    742:               if (renumber) {
    743:                 refMesh->setValue(newMarkers, renumbering[v+out.numberoftriangles], out.pointmarkerlist[v]);
    744:               } else {
    745:                 refMesh->setValue(newMarkers, v+out.numberoftriangles, out.pointmarkerlist[v]);
    746:               }
    747:             }
    748:           }
    749:           if (interpolate) {
    750:             for(int e = 0; e < out.numberofedges; e++) {
    751:               if (out.edgemarkerlist[e]) {
    752:                 const typename Mesh::point_type vertexA(out.edgelist[e*2+0]+out.numberoftriangles);
    753:                 const typename Mesh::point_type vertexB(out.edgelist[e*2+1]+out.numberoftriangles);
    754:                 const Obj<typename Mesh::sieve_type::supportSet> edge = newS->nJoin(vertexA, vertexB, 1);

    756:                 refMesh->setValue(newMarkers, *(edge->begin()), out.edgemarkerlist[e]);
    757:               }
    758:             }
    759:           }
    760:         }
    761:         refMesh->copyHoles(mesh);
    762:         Generator<Mesh>::finiOutput(&out);
    763: #if 0
    764:         if ((refMesh->commSize() > 1) && (!forceSerial)) {
    765:           return ALE::Distribution<Mesh>::distributeMesh(refMesh);
    766:         }
    767: #endif
    768:         return refMesh;
    769:       };
    770:       static Obj<Mesh> refineMeshV(const Obj<Mesh>& mesh, const Obj<typename Mesh::real_section_type>& maxVolumes, const bool interpolate = false, const bool renumber = false) {
    771:         throw ALE::Exception("Not yet implemented");
    772:       };
    773:       static Obj<Mesh> refineMeshV(const Obj<Mesh>& mesh, const double maxVolume, const bool interpolate = false, const bool forceSerial = false, const bool renumber = false) {
    774: #if 0
    775:         Obj<Mesh> serialMesh;
    776:         if (mesh->commSize() > 1) {
    777:           serialMesh = ALE::Distribution<Mesh>::unifyMesh(mesh);
    778:         } else {
    779:           serialMesh = mesh;
    780:         }
    781: #endif
    782:         const int numCells         = mesh->heightStratum(0)->size();
    783:         double   *serialMaxVolumes = new double[numCells];

    785:         for(int c = 0; c < numCells; c++) {
    786:           serialMaxVolumes[c] = maxVolume;
    787:         }
    788:         const Obj<Mesh> refMesh = refineMeshV(mesh, serialMaxVolumes, interpolate, forceSerial, renumber);
    789:         delete [] serialMaxVolumes;
    790:         return refMesh;
    791:       };
    792:       static Obj<Mesh> refineMeshLocal(const Obj<Mesh>& mesh, const double maxVolumes[], const bool interpolate = false) {
    793:         const int                    dim     = mesh->getDimension();
    794:         const Obj<Mesh>              refMesh = new Mesh(mesh->comm(), dim, mesh->debug());
    795:         const Obj<typename Mesh::sieve_type>& sieve   = mesh->getSieve();
    796:         struct triangulateio in;
    797:         struct triangulateio out;
    798:         PetscErrorCode       ierr;

    800:         Generator<Mesh>::initInput(&in);
    801:         Generator<Mesh>::initOutput(&out);
    802:         const Obj<typename Mesh::label_sequence>&    vertices    = mesh->depthStratum(0);
    803:         const Obj<typename Mesh::label_type>&        markers     = mesh->getLabel("marker");
    804:         const Obj<typename Mesh::real_section_type>& coordinates = mesh->getRealSection("coordinates");
    805:         const Obj<typename Mesh::numbering_type>&    vNumbering  = mesh->getFactory()->getLocalNumbering(mesh, 0);

    807:         in.numberofpoints = vertices->size();
    808:         if (in.numberofpoints > 0) {
    809:           PetscMalloc(in.numberofpoints * dim * sizeof(double), &in.pointlist);CHKERRXX(ierr);
    810:           PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRXX(ierr);
    811:           for(typename Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
    812:             const typename Mesh::real_section_type::value_type *array = coordinates->restrictPoint(*v_iter);
    813:             const int                                  idx   = vNumbering->getIndex(*v_iter);

    815:             for(int d = 0; d < dim; d++) {
    816:               in.pointlist[idx*dim + d] = array[d];
    817:             }
    818:             in.pointmarkerlist[idx] = mesh->getValue(markers, *v_iter);
    819:           }
    820:         }
    821:         const Obj<typename Mesh::label_sequence>& faces      = mesh->heightStratum(0);
    822:         const Obj<typename Mesh::numbering_type>& fNumbering = mesh->getFactory()->getLocalNumbering(mesh, mesh->depth());

    824:         in.numberofcorners   = 3;
    825:         in.numberoftriangles = faces->size();
    826:         in.trianglearealist  = (double *) maxVolumes;
    827:         if (in.numberoftriangles > 0) {
    828:           PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRXX(ierr);
    829:           if (mesh->depth() == 1) {
    830:             for(typename Mesh::label_sequence::iterator f_iter = faces->begin(); f_iter != faces->end(); ++f_iter) {
    831:               const Obj<typename Mesh::sieve_type::traits::coneSequence>& cone = sieve->cone(*f_iter);
    832:               const int                                          idx  = fNumbering->getIndex(*f_iter);
    833:               int                                                v    = 0;

    835:               for(typename Mesh::sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter) {
    836:                 in.trianglelist[idx*in.numberofcorners + v++] = vNumbering->getIndex(*c_iter);
    837:               }
    838:             }
    839:           } else if (mesh->depth() == 2) {
    840:             for(typename Mesh::label_sequence::iterator f_iter = faces->begin(); f_iter != faces->end(); ++f_iter) {
    841:               typedef ALE::SieveAlg<Mesh> sieve_alg_type;
    842:               const Obj<typename sieve_alg_type::coneArray>& cone = sieve_alg_type::nCone(mesh, *f_iter, 2);
    843:               const int                             idx  = fNumbering->getIndex(*f_iter);
    844:               int                                   v    = 0;

    846:               for(typename Mesh::sieve_type::coneArray::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter) {
    847:                 in.trianglelist[idx*in.numberofcorners + v++] = vNumbering->getIndex(*c_iter);
    848:               }
    849:             }
    850:           } else {
    851:             throw ALE::Exception("Invalid sieve: Cannot gives sieves of arbitrary depth to Triangle");
    852:           }
    853:         }
    854:         if (mesh->depth() == 2) {
    855:           const Obj<typename Mesh::label_sequence>& edges = mesh->depthStratum(1);
    856:           for(typename Mesh::label_sequence::iterator e_iter = edges->begin(); e_iter != edges->end(); ++e_iter) {
    857:             if (mesh->getValue(markers, *e_iter)) {
    858:               in.numberofsegments++;
    859:             }
    860:           }
    861:           //std::cout << "Number of segments: " << in.numberofsegments << std::endl;
    862:           if (in.numberofsegments > 0) {
    863:             int s = 0;

    865:             PetscMalloc(in.numberofsegments * 2 * sizeof(int), &in.segmentlist);CHKERRXX(ierr);
    866:             PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRXX(ierr);
    867:             for(typename Mesh::label_sequence::iterator e_iter = edges->begin(); e_iter != edges->end(); ++e_iter) {
    868:               const int edgeMarker = mesh->getValue(markers, *e_iter);

    870:               if (edgeMarker) {
    871:                 const Obj<typename Mesh::sieve_type::traits::coneSequence>& cone = sieve->cone(*e_iter);
    872:                 int                                                p    = 0;

    874:                 for(typename Mesh::sieve_type::traits::coneSequence::iterator v_iter = cone->begin(); v_iter != cone->end(); ++v_iter) {
    875:                   in.segmentlist[s*2 + (p++)] = vNumbering->getIndex(*v_iter);
    876:                 }
    877:                 in.segmentmarkerlist[s++] = edgeMarker;
    878:               }
    879:             }
    880:           }
    881:         }

    883:         in.numberofholes = 0;
    884:         if (in.numberofholes > 0) {
    885:           PetscMalloc(in.numberofholes * dim * sizeof(int), &in.holelist);CHKERRXX(ierr);
    886:         }
    887:         std::string args("pqezQra");

    889:         triangulate((char *) args.c_str(), &in, &out, NULL);
    890:         if (in.pointlist)         {PetscFree(in.pointlist);CHKERRXX(ierr);}
    891:         if (in.pointmarkerlist)   {PetscFree(in.pointmarkerlist);CHKERRXX(ierr);}
    892:         if (in.segmentlist)       {PetscFree(in.segmentlist);CHKERRXX(ierr);}
    893:         if (in.segmentmarkerlist) {PetscFree(in.segmentmarkerlist);CHKERRXX(ierr);}
    894:         if (in.trianglelist)      {PetscFree(in.trianglelist);CHKERRXX(ierr);}
    895:         const Obj<typename Mesh::sieve_type> newSieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
    896:         int     numCorners  = 3;
    897:         int     numCells    = out.numberoftriangles;
    898:         int    *cells       = out.trianglelist;
    899:         int     numVertices = out.numberofpoints;
    900:         double *coords      = out.pointlist;

    902:         ALE::SieveBuilder<Mesh>::buildTopologyMultiple(newSieve, dim, numCells, cells, numVertices, interpolate, numCorners, -1, refMesh->getArrowSection("orientation"));
    903:         refMesh->setSieve(newSieve);
    904:         refMesh->stratify();
    905:         ALE::SieveBuilder<Mesh>::buildCoordinatesMultiple(refMesh, dim, coords);
    906:         const Obj<typename Mesh::label_type>& newMarkers = refMesh->createLabel("marker");

    908:         for(int v = 0; v < out.numberofpoints; v++) {
    909:           if (out.pointmarkerlist[v]) {
    910:             refMesh->setValue(newMarkers, v+out.numberoftriangles, out.pointmarkerlist[v]);
    911:           }
    912:         }
    913:         if (interpolate) {
    914:           for(int e = 0; e < out.numberofedges; e++) {
    915:             if (out.edgemarkerlist[e]) {
    916:               const typename Mesh::point_type vertexA(out.edgelist[e*2+0]+out.numberoftriangles);
    917:               const typename Mesh::point_type vertexB(out.edgelist[e*2+1]+out.numberoftriangles);
    918:               const Obj<typename Mesh::sieve_type::supportSet> edge = newSieve->nJoin(vertexA, vertexB, 1);

    920:               refMesh->setValue(newMarkers, *(edge->begin()), out.edgemarkerlist[e]);
    921:             }
    922:           }
    923:         }
    924:         Generator<Mesh>::finiOutput(&out);
    925:         return refMesh;
    926:       };
    927:       static Obj<Mesh> refineMeshLocal(const Obj<Mesh>& mesh, const double maxVolume, const bool interpolate = false) {
    928:         const int numLocalFaces   = mesh->heightStratum(0)->size();
    929:         double   *localMaxVolumes = new double[numLocalFaces];

    931:         for(int f = 0; f < numLocalFaces; f++) {
    932:           localMaxVolumes[f] = maxVolume;
    933:         }
    934:         const Obj<Mesh> refMesh = refineMeshLocal(mesh, localMaxVolumes, interpolate);
    935:         const Obj<typename Mesh::sieve_type> refSieve = refMesh->getSieve();
    936:         delete [] localMaxVolumes;
    937: #if 0
    938:         typedef typename ALE::New::Completion<Mesh, typename Mesh::sieve_type::point_type> sieveCompletion;
    939:         // This is where we enforce consistency over the overlap
    940:         //   We need somehow to update the overlap to account for the new stuff
    941:         //
    942:         //   1) Since we are refining only, the vertices are invariant
    943:         //   2) We need to make another label for the interprocess boundaries so
    944:         //      that Triangle will respect them
    945:         //   3) We then throw all that label into the new overlap
    946:         //
    947:         // Alternative: Figure out explicitly which segments were refined, and then
    948:         //   communicated the refinement over the old overlap. Use this info to locally
    949:         //   construct the new overlap and flip to get a decent mesh
    950:         sieveCompletion::scatterCones(refSieve, refSieve, reMesh->getDistSendOverlap(), refMesh->getDistRecvOverlap(), refMesh);
    951: #endif
    952:         return refMesh;
    953:       };
    954:     };
    955:   };
    956: #endif
    957: #ifdef PETSC_HAVE_TETGEN
    958:   namespace TetGen {
    959:     template<typename Mesh>
    960:     class Generator {
    961:     public:
    962:       static Obj<Mesh> generateMesh(const Obj<Mesh>& boundary, const bool interpolate = false, const bool constrained = false) {
    963:         typedef ALE::SieveAlg<Mesh> sieve_alg_type;
    964:         const int         dim   = 3;
    965:         Obj<Mesh>         mesh  = new Mesh(boundary->comm(), dim, boundary->debug());
    966:         const PetscMPIInt rank  = mesh->commRank();
    967:         bool              createConvexHull = false;
    968:         ::tetgenio        in;
    969:         ::tetgenio        out;

    971:         const Obj<typename Mesh::label_sequence>&    vertices    = boundary->depthStratum(0);
    972:         const Obj<typename Mesh::numbering_type>&    vNumbering  = boundary->getFactory()->getLocalNumbering(boundary, 0);
    973:         const Obj<typename Mesh::real_section_type>& coordinates = boundary->getRealSection("coordinates");
    974:         const Obj<typename Mesh::label_type>&        markers     = boundary->getLabel("marker");

    977:         in.numberofpoints = vertices->size();
    978:         if (in.numberofpoints > 0) {
    979:           in.pointlist       = new double[in.numberofpoints*dim];
    980:           in.pointmarkerlist = new int[in.numberofpoints];
    981:           for(typename Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
    982:             const typename Mesh::real_section_type::value_type *array = coordinates->restrictPoint(*v_iter);
    983:             const int                                  idx   = vNumbering->getIndex(*v_iter);

    985:             for(int d = 0; d < dim; d++) {
    986:               in.pointlist[idx*dim + d] = array[d];
    987:             }
    988:             in.pointmarkerlist[idx] = boundary->getValue(markers, *v_iter);
    989:           }
    990:         }

    992:         if (boundary->depth() != 0) {  //our boundary mesh COULD be just a pointset; in which case depth = height = 0;
    993:           const Obj<typename Mesh::label_sequence>& facets     = boundary->depthStratum(boundary->depth());
    994:           //PetscPrintf(boundary->comm(), "%d facets on the boundary\n", facets->size());
    995:           const Obj<typename Mesh::numbering_type>& fNumbering = boundary->getFactory()->getLocalNumbering(boundary, boundary->depth());

    997:           in.numberoffacets = facets->size();
    998:           if (in.numberoffacets > 0) {
    999:             in.facetlist       = new tetgenio::facet[in.numberoffacets];
    1000:             in.facetmarkerlist = new int[in.numberoffacets];
    1001:             for(typename Mesh::label_sequence::iterator f_iter = facets->begin(); f_iter != facets->end(); ++f_iter) {
    1002:               const Obj<typename sieve_alg_type::coneArray>& cone = sieve_alg_type::nCone(boundary, *f_iter, boundary->depth());
    1003:               const int                             idx  = fNumbering->getIndex(*f_iter);

    1005:               in.facetlist[idx].numberofpolygons = 1;
    1006:               in.facetlist[idx].polygonlist      = new tetgenio::polygon[in.facetlist[idx].numberofpolygons];
    1007:               in.facetlist[idx].numberofholes    = 0;
    1008:               in.facetlist[idx].holelist         = NULL;

    1010:               tetgenio::polygon *poly = in.facetlist[idx].polygonlist;
    1011:               int                c    = 0;

    1013:               poly->numberofvertices = cone->size();
    1014:               poly->vertexlist       = new int[poly->numberofvertices];
    1015:               for(typename sieve_alg_type::coneArray::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter) {
    1016:                 const int vIdx = vNumbering->getIndex(*c_iter);

    1018:                 poly->vertexlist[c++] = vIdx;
    1019:               }
    1020:               in.facetmarkerlist[idx] = boundary->getValue(markers, *f_iter);
    1021:             }
    1022:           }
    1023:         }else {
    1024:           createConvexHull = true;
    1025:         }

    1027:         in.numberofholes = 0;
    1028:         if (rank == 0) {
    1029:           // Normal operation
    1030:           std::string args("pqezQ");
    1031:           //constrained operation
    1032:           if (constrained) {
    1033:             args = "pezQ";
    1034:             if (createConvexHull) {
    1035:               args = "ezQ";
    1036:               //PetscPrintf(boundary->comm(), "createConvexHull\n");
    1037:             }
    1038:           }
    1039:           // Just make tetrahedrons
    1040: //           std::string args("efzV");
    1041:           // Adds a center point
    1042: //           std::string args("pqezQi");
    1043: //           in.numberofaddpoints = 1;
    1044: //           in.addpointlist      = new double[in.numberofaddpoints*dim];
    1045: //           in.addpointlist[0]   = 0.5;
    1046: //           in.addpointlist[1]   = 0.5;
    1047: //           in.addpointlist[2]   = 0.5;

    1049:           //if (createConvexHull) args += "c";  NOT SURE, but this was basically unused before, and the convex hull should be filled in if "p" isn't included.
    1050:           ::tetrahedralize((char *) args.c_str(), &in, &out);
    1051:         }
    1052:         const Obj<typename Mesh::sieve_type> newSieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
    1053:         int     numCorners  = 4;
    1054:         int     numCells    = out.numberoftetrahedra;
    1055:         int    *cells       = out.tetrahedronlist;
    1056:         int     numVertices = out.numberofpoints;
    1057:         double *coords      = out.pointlist;

    1059:         if (!interpolate) {
    1060:           for(int c = 0; c < numCells; ++c) {
    1061:             int tmp = cells[c*4+0];
    1062:             cells[c*4+0] = cells[c*4+1];
    1063:             cells[c*4+1] = tmp;
    1064:           }
    1065:         }
    1066:         ALE::SieveBuilder<Mesh>::buildTopology(newSieve, dim, numCells, cells, numVertices, interpolate, numCorners, -1, mesh->getArrowSection("orientation"));
    1067:         mesh->setSieve(newSieve);
    1068:         mesh->stratify();
    1069:         ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, dim, coords);
    1070:         const Obj<typename Mesh::label_type>& newMarkers = mesh->createLabel("marker");

    1072:         for(int v = 0; v < out.numberofpoints; v++) {
    1073:           if (out.pointmarkerlist[v]) {
    1074:             mesh->setValue(newMarkers, v+out.numberoftetrahedra, out.pointmarkerlist[v]);
    1075:           }
    1076:         }
    1077:         if (interpolate) {
    1078:           if (out.edgemarkerlist) {
    1079:             for(int e = 0; e < out.numberofedges; e++) {
    1080:               if (out.edgemarkerlist[e]) {
    1081:                 typename Mesh::point_type endpointA(out.edgelist[e*2+0]+out.numberoftetrahedra);
    1082:                 typename Mesh::point_type endpointB(out.edgelist[e*2+1]+out.numberoftetrahedra);
    1083:                 Obj<typename Mesh::sieve_type::supportSet> edge = newSieve->nJoin(endpointA, endpointB, 1);

    1085:                 mesh->setValue(newMarkers, *edge->begin(), out.edgemarkerlist[e]);
    1086:               }
    1087:             }
    1088:           }
    1089:           if (out.trifacemarkerlist) {
    1090:             // Work around TetGen bug for raw tetrahedralization
    1091:             //   The boundary faces are 0,1,4,5,8,9,11,12,13,15,16,17
    1092: //             for(int f = 0; f < out.numberoftrifaces; f++) {
    1093: //               if (out.trifacemarkerlist[f]) {
    1094: //                 out.trifacemarkerlist[f] = 0;
    1095: //               } else {
    1096: //                 out.trifacemarkerlist[f] = 1;
    1097: //               }
    1098: //             }
    1099:             for(int f = 0; f < out.numberoftrifaces; f++) {
    1100:               if (out.trifacemarkerlist[f]) {
    1101:                 typename Mesh::point_type cornerA(out.trifacelist[f*3+0]+out.numberoftetrahedra);
    1102:                 typename Mesh::point_type cornerB(out.trifacelist[f*3+1]+out.numberoftetrahedra);
    1103:                 typename Mesh::point_type cornerC(out.trifacelist[f*3+2]+out.numberoftetrahedra);
    1104:                 Obj<typename Mesh::sieve_type::supportSet> corners = typename Mesh::sieve_type::supportSet();
    1105:                 Obj<typename Mesh::sieve_type::supportSet> edges   = typename Mesh::sieve_type::supportSet();
    1106:                 corners->clear();corners->insert(cornerA);corners->insert(cornerB);
    1107:                 edges->insert(*newSieve->nJoin1(corners)->begin());
    1108:                 corners->clear();corners->insert(cornerB);corners->insert(cornerC);
    1109:                 edges->insert(*newSieve->nJoin1(corners)->begin());
    1110:                 corners->clear();corners->insert(cornerC);corners->insert(cornerA);
    1111:                 edges->insert(*newSieve->nJoin1(corners)->begin());
    1112:                 const typename Mesh::point_type          face       = *newSieve->nJoin1(edges)->begin();
    1113:                 const int                       faceMarker = out.trifacemarkerlist[f];
    1114:                 const Obj<typename Mesh::coneArray>      closure    = sieve_alg_type::closure(mesh, face);
    1115:                 const typename Mesh::coneArray::iterator end        = closure->end();

    1117:                 for(typename Mesh::coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
    1118:                   mesh->setValue(newMarkers, *cl_iter, faceMarker);
    1119:                 }
    1120:               }
    1121:             }
    1122:           }
    1123:         }
    1124:         return mesh;
    1125:       };
    1128:       static Obj<Mesh> generateMeshV(const Obj<Mesh>& boundary, const bool interpolate = false, const bool constrained = false, const bool renumber = false) {
    1129:         typedef ALE::Mesh<PetscInt,PetscScalar> FlexMesh;
    1130:         typedef typename Mesh::real_section_type::value_type real;
    1131:         const int                             dim   = 3;
    1132:         Obj<Mesh>                             mesh  = new Mesh(boundary->comm(), dim, boundary->debug());
    1133:         const Obj<typename Mesh::sieve_type>& sieve = boundary->getSieve();
    1134:         const PetscMPIInt                     rank  = mesh->commRank();
    1135:         bool                                  createConvexHull = false;
    1136:         PetscErrorCode                        ierr;
    1137:         ::tetgenio in;
    1138:         ::tetgenio out;

    1140:         const Obj<typename Mesh::label_sequence>&    vertices    = boundary->depthStratum(0);
    1141:         const Obj<typename Mesh::label_type>&        markers     = boundary->getLabel("marker");
    1142:         const Obj<typename Mesh::real_section_type>& coordinates = boundary->getRealSection("coordinates");
    1143:         const Obj<typename Mesh::numbering_type>&    vNumbering  = boundary->getFactory()->getLocalNumbering(boundary, 0);

    1145:         in.numberofpoints = vertices->size();
    1146:         if (in.numberofpoints > 0) {
    1147:           const typename Mesh::label_sequence::iterator vEnd = vertices->end();

    1149:           in.pointlist       = new double[in.numberofpoints*dim];
    1150:           in.pointmarkerlist = new int[in.numberofpoints];
    1151:           for(typename Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vEnd; ++v_iter) {
    1152:             const typename Mesh::real_section_type::value_type *array = coordinates->restrictPoint(*v_iter);
    1153:             const int                                           idx   = vNumbering->getIndex(*v_iter);

    1155:             for(int d = 0; d < dim; ++d) {
    1156:               in.pointlist[idx*dim + d] = array[d];
    1157:             }
    1158:             in.pointmarkerlist[idx] = boundary->getValue(markers, *v_iter);
    1159:           }
    1160:         }

    1162:         // Our boundary mesh COULD be just a pointset; in which case depth = height = 0;
    1163:         if (boundary->depth() != 0) {
    1164:           const Obj<typename Mesh::label_sequence>& facets     = boundary->depthStratum(boundary->depth());
    1165:           const Obj<typename Mesh::numbering_type>& fNumbering = boundary->getFactory()->getLocalNumbering(boundary, boundary->depth());

    1167:           in.numberoffacets = facets->size();
    1168:           if (in.numberoffacets > 0) {
    1169:             ALE::ISieveVisitor::NConeRetriever<typename Mesh::sieve_type> ncV(*sieve, 5);
    1170:             const typename Mesh::label_sequence::iterator fEnd = facets->end();

    1172:             in.facetlist       = new tetgenio::facet[in.numberoffacets];
    1173:             in.facetmarkerlist = new int[in.numberoffacets];
    1174:             for(typename Mesh::label_sequence::iterator f_iter = facets->begin(); f_iter != fEnd; ++f_iter) {
    1175:               ALE::ISieveTraversal<typename Mesh::sieve_type>::orientedClosure(*sieve, *f_iter, ncV);
    1176:               const int idx  = fNumbering->getIndex(*f_iter);

    1178:               in.facetlist[idx].numberofpolygons = 1;
    1179:               in.facetlist[idx].polygonlist      = new tetgenio::polygon[in.facetlist[idx].numberofpolygons];
    1180:               in.facetlist[idx].numberofholes    = 0;
    1181:               in.facetlist[idx].holelist         = NULL;

    1183:               tetgenio::polygon               *poly = in.facetlist[idx].polygonlist;
    1184:               const size_t                     n    = ncV.getSize();
    1185:               const typename Mesh::point_type *cone = ncV.getPoints();

    1187:               poly->numberofvertices = n;
    1188:               poly->vertexlist       = new int[poly->numberofvertices];
    1189:               for(size_t c = 0; c < n; ++c) {
    1190:                 poly->vertexlist[c] = vNumbering->getIndex(cone[c]);
    1191:               }
    1192:               in.facetmarkerlist[idx] = boundary->getValue(markers, *f_iter);
    1193:               ncV.clear();
    1194:             }
    1195:           }
    1196:         } else {
    1197:           createConvexHull = true;
    1198:         }
    1199:         const typename Mesh::holes_type& holes = mesh->getHoles();

    1201:         in.numberofholes = holes.size();
    1202:         if (in.numberofholes > 0) {
    1203:           PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRXX(ierr);
    1204:           for(int h = 0; h < in.numberofholes; ++h) {
    1205:             for(int d = 0; d < dim; ++d) {
    1206:               in.holelist[h*dim+d] = holes[h][d];
    1207:             }
    1208:           }
    1209:         }
    1210:         if (rank == 0) {
    1211:           // Normal operation
    1212:           std::string args("pqezQ");
    1213:           // Constrained operation
    1214:           if (constrained) {
    1215:             args = "pezQ";
    1216:             if (createConvexHull) {
    1217:               args = "ezQ";
    1218:             }
    1219:           }
    1220:           // Just make tetrahedrons
    1221: //           std::string args("efzV");
    1222:           // Adds a center point
    1223: //           std::string args("pqezQi");
    1224: //           in.numberofaddpoints = 1;
    1225: //           in.addpointlist      = new double[in.numberofaddpoints*dim];
    1226: //           in.addpointlist[0]   = 0.5;
    1227: //           in.addpointlist[1]   = 0.5;
    1228: //           in.addpointlist[2]   = 0.5;
    1229:           ::tetrahedralize((char *) args.c_str(), &in, &out);
    1230:         }
    1231:         const Obj<typename Mesh::sieve_type> newSieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
    1232:         const Obj<FlexMesh>                  m        = new FlexMesh(mesh->comm(), dim, mesh->debug());
    1233:         const Obj<FlexMesh::sieve_type>      newS     = new FlexMesh::sieve_type(m->comm(), m->debug());
    1234:         int     numCorners  = 4;
    1235:         int     numCells    = out.numberoftetrahedra;
    1236:         int    *cells       = out.tetrahedronlist;
    1237:         int     numVertices = out.numberofpoints;
    1238:         double *coords      = out.pointlist;
    1239:         real   *coordsR;

    1241:         if (!interpolate) {
    1242:           // TetGen reports tetrahedra with the opposite orientation from what we expect
    1243:           for(int c = 0; c < numCells; ++c) {
    1244:             int tmp = cells[c*4+0];
    1245:             cells[c*4+0] = cells[c*4+1];
    1246:             cells[c*4+1] = tmp;
    1247:           }
    1248:         }
    1249:         ALE::SieveBuilder<FlexMesh>::buildTopology(newS, dim, numCells, cells, numVertices, interpolate, numCorners, -1, m->getArrowSection("orientation"));
    1250:         m->setSieve(newS);
    1251:         m->stratify();
    1252:         mesh->setSieve(newSieve);
    1253:         std::map<typename Mesh::point_type,typename Mesh::point_type> renumbering;
    1254:         ALE::ISieveConverter::convertSieve(*newS, *newSieve, renumbering, renumber);
    1255:         mesh->stratify();
    1256:         ALE::ISieveConverter::convertOrientation(*newS, *newSieve, renumbering, m->getArrowSection("orientation").ptr());
    1257:         {
    1258:           if (sizeof(double) == sizeof(real)) {
    1259:             coordsR = (real *) coords;
    1260:           } else {
    1261:             coordsR = new real[numVertices*dim];
    1262:             for(int i = 0; i < numVertices*dim; ++i) coordsR[i] = coords[i];
    1263:           }
    1264:         }
    1265:         ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, dim, coordsR);
    1266:         {
    1267:           if (sizeof(double) != sizeof(real)) {
    1268:             delete [] coordsR;
    1269:           }
    1270:         }
    1271:         const Obj<typename Mesh::label_type>& newMarkers = mesh->createLabel("marker");

    1273:         for(int v = 0; v < out.numberofpoints; v++) {
    1274:           if (out.pointmarkerlist[v]) {
    1275:             if (renumber) {
    1276:               mesh->setValue(newMarkers, renumbering[v+out.numberoftetrahedra], out.pointmarkerlist[v]);
    1277:             } else {
    1278:               mesh->setValue(newMarkers, v+out.numberoftetrahedra, out.pointmarkerlist[v]);
    1279:             }
    1280:           }
    1281:         }
    1282:         if (interpolate) {
    1283:           // This does not work anymore (edgemarkerlist is always empty). I tried -ee and it gave bogus results
    1284:           if (out.edgemarkerlist) {
    1285:             for(int e = 0; e < out.numberofedges; e++) {
    1286:               if (out.edgemarkerlist[e]) {
    1287:                 typename Mesh::point_type endpointA(out.edgelist[e*2+0]+out.numberoftetrahedra);
    1288:                 typename Mesh::point_type endpointB(out.edgelist[e*2+1]+out.numberoftetrahedra);
    1289:                 Obj<typename Mesh::sieve_type::supportSet> edge = newS->nJoin(endpointA, endpointB, 1);

    1291:                 if (renumber) {
    1292:                   mesh->setValue(newMarkers, renumbering[*edge->begin()], out.edgemarkerlist[e]);
    1293:                 } else {
    1294:                   mesh->setValue(newMarkers, *edge->begin(), out.edgemarkerlist[e]);
    1295:                 }
    1296:               }
    1297:             }
    1298:           }
    1299:           if (out.trifacemarkerlist) {
    1300:             // Work around TetGen bug for raw tetrahedralization
    1301:             //   The boundary faces are 0,1,4,5,8,9,11,12,13,15,16,17
    1302: //             for(int f = 0; f < out.numberoftrifaces; f++) {
    1303: //               if (out.trifacemarkerlist[f]) {
    1304: //                 out.trifacemarkerlist[f] = 0;
    1305: //               } else {
    1306: //                 out.trifacemarkerlist[f] = 1;
    1307: //               }
    1308: //             }
    1309:             for(int f = 0; f < out.numberoftrifaces; f++) {
    1310:               if (out.trifacemarkerlist[f]) {
    1311:                 typename Mesh::point_type cornerA = out.trifacelist[f*3+0]+out.numberoftetrahedra;
    1312:                 typename Mesh::point_type cornerB = out.trifacelist[f*3+1]+out.numberoftetrahedra;
    1313:                 typename Mesh::point_type cornerC = out.trifacelist[f*3+2]+out.numberoftetrahedra;
    1314:                 Obj<typename Mesh::sieve_type::supportSet> corners = typename Mesh::sieve_type::supportSet();
    1315:                 Obj<typename Mesh::sieve_type::supportSet> edges   = typename Mesh::sieve_type::supportSet();
    1316:                 corners->clear();corners->insert(cornerA);corners->insert(cornerB);
    1317:                 typename Mesh::point_type edgeA = *newS->nJoin1(corners)->begin();
    1318:                 corners->clear();corners->insert(cornerB);corners->insert(cornerC);
    1319:                 typename Mesh::point_type edgeB = *newS->nJoin1(corners)->begin();
    1320:                 corners->clear();corners->insert(cornerC);corners->insert(cornerA);
    1321:                 typename Mesh::point_type edgeC = *newS->nJoin1(corners)->begin();
    1322:                 edges->insert(edgeA); edges->insert(edgeB); edges->insert(edgeC);
    1323:                 ALE::ISieveVisitor::PointRetriever<typename Mesh::sieve_type> pV(30);
    1324:                 typename Mesh::point_type face       = *newS->nJoin1(edges)->begin();
    1325:                 const int                 faceMarker = out.trifacemarkerlist[f];

    1327:                 if (renumber) {face = renumbering[face];}
    1328:                 ALE::ISieveTraversal<typename Mesh::sieve_type>::orientedClosure(*newSieve, face, pV);
    1329:                 const size_t                     n    = pV.getSize();
    1330:                 const typename Mesh::point_type *cone = pV.getPoints();

    1332:                 for(size_t c = 0; c < n; ++c) {
    1333:                   mesh->setValue(newMarkers, cone[c], faceMarker);
    1334:                 }
    1335:                 pV.clear();
    1336:               }
    1337:             }
    1338:           }
    1339:         }
    1340:         mesh->copyHoles(boundary);
    1341:         return mesh;
    1342:       };
    1343:     };
    1344:     template<typename Mesh>
    1345:     class Refiner {
    1346:     public:
    1347:       static Obj<Mesh> refineMesh(const Obj<Mesh>& serialMesh, const double maxVolumes[], const bool interpolate = false) {
    1348:         typedef ALE::SieveAlg<Mesh> sieve_alg_type;
    1349:         const int       dim     = serialMesh->getDimension();
    1350:         const int       depth   = serialMesh->depth();
    1351:         const Obj<Mesh> refMesh = new Mesh(serialMesh->comm(), dim, serialMesh->debug());
    1352:         ::tetgenio      in;
    1353:         ::tetgenio      out;

    1355:         const Obj<typename Mesh::label_sequence>&    vertices    = serialMesh->depthStratum(0);
    1356:         const Obj<typename Mesh::label_type>&        markers     = serialMesh->getLabel("marker");
    1357:         const Obj<typename Mesh::real_section_type>& coordinates = serialMesh->getRealSection("coordinates");
    1358:         const Obj<typename Mesh::numbering_type>&    vNumbering  = serialMesh->getFactory()->getLocalNumbering(serialMesh, 0);

    1360:         in.numberofpoints = vertices->size();
    1361:         if (in.numberofpoints > 0) {
    1362:           in.pointlist       = new double[in.numberofpoints*dim];
    1363:           in.pointmarkerlist = new int[in.numberofpoints];
    1364:           for(typename Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
    1365:             const typename Mesh::real_section_type::value_type *array = coordinates->restrictPoint(*v_iter);
    1366:             const int                                  idx   = vNumbering->getIndex(*v_iter);

    1368:             for(int d = 0; d < dim; d++) {
    1369:               in.pointlist[idx*dim + d] = array[d];
    1370:             }
    1371:             in.pointmarkerlist[idx] = serialMesh->getValue(markers, *v_iter);
    1372:           }
    1373:         }
    1374:         const Obj<typename Mesh::label_sequence>& cells      = serialMesh->heightStratum(0);
    1375:         const Obj<typename Mesh::numbering_type>& cNumbering = serialMesh->getFactory()->getLocalNumbering(serialMesh, depth);

    1377:         in.numberofcorners       = 4;
    1378:         in.numberoftetrahedra    = cells->size();
    1379:         in.tetrahedronvolumelist = (double *) maxVolumes;
    1380:         if (in.numberoftetrahedra > 0) {
    1381:           in.tetrahedronlist     = new int[in.numberoftetrahedra*in.numberofcorners];
    1382:           for(typename Mesh::label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
    1383:             typedef ALE::SieveAlg<Mesh> sieve_alg_type;
    1384:             const Obj<typename sieve_alg_type::coneArray>& cone = sieve_alg_type::nCone(serialMesh, *c_iter, depth);
    1385:             const int                             idx  = cNumbering->getIndex(*c_iter);
    1386:             int                                   v    = 0;

    1388:             for(typename Mesh::sieve_type::coneArray::iterator v_iter = cone->begin(); v_iter != cone->end(); ++v_iter) {
    1389:               in.tetrahedronlist[idx*in.numberofcorners + v++] = vNumbering->getIndex(*v_iter);
    1390:             }
    1391:           }
    1392:         }
    1393:         if (serialMesh->depth() == 3) {
    1394:           const Obj<typename Mesh::label_sequence>& boundary = serialMesh->getLabelStratum("marker", 1);

    1396:           in.numberoftrifaces = 0;
    1397:           for(typename Mesh::label_sequence::iterator b_iter = boundary->begin(); b_iter != boundary->end(); ++b_iter) {
    1398:             if (serialMesh->height(*b_iter) == 1) {
    1399:               in.numberoftrifaces++;
    1400:             }
    1401:           }
    1402:           if (in.numberoftrifaces > 0) {
    1403:             int f = 0;

    1405:             in.trifacelist       = new int[in.numberoftrifaces*3];
    1406:             in.trifacemarkerlist = new int[in.numberoftrifaces];
    1407:             for(typename Mesh::label_sequence::iterator b_iter = boundary->begin(); b_iter != boundary->end(); ++b_iter) {
    1408:               if (serialMesh->height(*b_iter) == 1) {
    1409:                 const Obj<typename Mesh::coneArray>& cone = sieve_alg_type::nCone(serialMesh, *b_iter, 2);
    1410:                 int                         p    = 0;

    1412:                 for(typename Mesh::coneArray::iterator v_iter = cone->begin(); v_iter != cone->end(); ++v_iter) {
    1413:                   in.trifacelist[f*3 + (p++)] = vNumbering->getIndex(*v_iter);
    1414:                 }
    1415:                 in.trifacemarkerlist[f++] = serialMesh->getValue(markers, *b_iter);
    1416:               }
    1417:             }
    1418:           }
    1419:         }

    1421:         in.numberofholes = 0;
    1422:         if (serialMesh->commRank() == 0) {
    1423:           std::string args("qezQra");

    1425:           ::tetrahedralize((char *) args.c_str(), &in, &out);
    1426:         }
    1427:         in.tetrahedronvolumelist = NULL;
    1428:         const Obj<typename Mesh::sieve_type> newSieve = new typename Mesh::sieve_type(refMesh->comm(), refMesh->debug());
    1429:         int     numCorners  = 4;
    1430:         int     numCells    = out.numberoftetrahedra;
    1431:         int    *newCells       = out.tetrahedronlist;
    1432:         int     numVertices = out.numberofpoints;
    1433:         double *coords      = out.pointlist;

    1435:         if (!interpolate) {
    1436:           for(int c = 0; c < numCells; ++c) {
    1437:             int tmp = newCells[c*4+0];
    1438:             newCells[c*4+0] = newCells[c*4+1];
    1439:             newCells[c*4+1] = tmp;
    1440:           }
    1441:         }
    1442:         ALE::SieveBuilder<Mesh>::buildTopology(newSieve, dim, numCells, newCells, numVertices, interpolate, numCorners, -1, refMesh->getArrowSection("orientation"));
    1443:         refMesh->setSieve(newSieve);
    1444:         refMesh->stratify();
    1445:         ALE::SieveBuilder<Mesh>::buildCoordinates(refMesh, dim, coords);
    1446:         const Obj<typename Mesh::label_type>& newMarkers = refMesh->createLabel("marker");

    1449:         for(int v = 0; v < out.numberofpoints; v++) {
    1450:           if (out.pointmarkerlist[v]) {
    1451:             refMesh->setValue(newMarkers, v+out.numberoftetrahedra, out.pointmarkerlist[v]);
    1452:           }
    1453:         }
    1454:         if (interpolate) {
    1455:           if (out.edgemarkerlist) {
    1456:             for(int e = 0; e < out.numberofedges; e++) {
    1457:               if (out.edgemarkerlist[e]) {
    1458:                 typename Mesh::point_type endpointA(out.edgelist[e*2+0]+out.numberoftetrahedra);
    1459:                 typename Mesh::point_type endpointB(out.edgelist[e*2+1]+out.numberoftetrahedra);
    1460:                 Obj<typename Mesh::sieve_type::supportSet> edge = newSieve->nJoin(endpointA, endpointB, 1);

    1462:                 refMesh->setValue(newMarkers, *edge->begin(), out.edgemarkerlist[e]);
    1463:               }
    1464:             }
    1465:           }
    1466:           if (out.trifacemarkerlist) {
    1467:             for(int f = 0; f < out.numberoftrifaces; f++) {
    1468:               if (out.trifacemarkerlist[f]) {
    1469:                 typename Mesh::point_type cornerA(out.trifacelist[f*3+0]+out.numberoftetrahedra);
    1470:                 typename Mesh::point_type cornerB(out.trifacelist[f*3+1]+out.numberoftetrahedra);
    1471:                 typename Mesh::point_type cornerC(out.trifacelist[f*3+2]+out.numberoftetrahedra);
    1472:                 Obj<typename Mesh::sieve_type::supportSet> corners = typename Mesh::sieve_type::supportSet();
    1473:                 Obj<typename Mesh::sieve_type::supportSet> edges   = typename Mesh::sieve_type::supportSet();
    1474:                 corners->clear();corners->insert(cornerA);corners->insert(cornerB);
    1475:                 edges->insert(*newSieve->nJoin1(corners)->begin());
    1476:                 corners->clear();corners->insert(cornerB);corners->insert(cornerC);
    1477:                 edges->insert(*newSieve->nJoin1(corners)->begin());
    1478:                 corners->clear();corners->insert(cornerC);corners->insert(cornerA);
    1479:                 edges->insert(*newSieve->nJoin1(corners)->begin());
    1480:                 const typename Mesh::point_type          face       = *newSieve->nJoin1(edges)->begin();
    1481:                 const int                       faceMarker = out.trifacemarkerlist[f];
    1482:                 const Obj<typename Mesh::coneArray>      closure    = sieve_alg_type::closure(refMesh, face);
    1483:                 const typename Mesh::coneArray::iterator end        = closure->end();

    1485:                 for(typename Mesh::coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
    1486:                   refMesh->setValue(newMarkers, *cl_iter, faceMarker);
    1487:                 }
    1488:               }
    1489:             }
    1490:           }
    1491:         }
    1492:         if (refMesh->commSize() > 1) {
    1493:           return ALE::Distribution<Mesh>::distributeMesh(refMesh);
    1494:         }
    1495:         return refMesh;
    1496:       };
    1497:       static Obj<Mesh> refineMesh(const Obj<Mesh>& mesh, const Obj<typename Mesh::real_section_type>& maxVolumes, const bool interpolate = false) {
    1498:         Obj<Mesh>                          serialMesh       = ALE::Distribution<Mesh>::unifyMesh(mesh);
    1499:         const Obj<typename Mesh::real_section_type> serialMaxVolumes = ALE::Distribution<Mesh>::distributeSection(maxVolumes, serialMesh, serialMesh->getDistSendOverlap(), serialMesh->getDistRecvOverlap());

    1501:         return refineMesh(serialMesh, serialMaxVolumes->restrictSpace(), interpolate);
    1502:       };
    1503:       static Obj<Mesh> refineMesh(const Obj<Mesh>& mesh, const double maxVolume, const bool interpolate = false) {
    1504:         Obj<Mesh> serialMesh;
    1505:         if (mesh->commSize() > 1) {
    1506:           serialMesh = ALE::Distribution<Mesh>::unifyMesh(mesh);
    1507:         } else {
    1508:           serialMesh = mesh;
    1509:         }
    1510:         const int numCells         = serialMesh->heightStratum(0)->size();
    1511:         double   *serialMaxVolumes = new double[numCells];

    1513:         for(int c = 0; c < numCells; c++) {
    1514:           serialMaxVolumes[c] = maxVolume;
    1515:         }
    1516:         const Obj<Mesh> refMesh = refineMesh(serialMesh, serialMaxVolumes, interpolate);
    1517:         delete [] serialMaxVolumes;
    1518:         return refMesh;
    1519:       };
    1520:       static Obj<Mesh> refineMeshV(const Obj<Mesh>& mesh, const double maxVolumes[], const bool interpolate = false, const bool forceSerial = false, const bool renumber = false) {
    1521:         typedef ALE::Mesh<PetscInt,PetscScalar> FlexMesh;
    1522:         typedef typename Mesh::real_section_type::value_type real;
    1523:         typedef typename Mesh::point_type point_type;
    1524:         const int                             dim     = mesh->getDimension();
    1525:         const int                             depth   = mesh->depth();
    1526:         const Obj<Mesh>                       refMesh = new Mesh(mesh->comm(), dim, mesh->debug());
    1527:         const Obj<typename Mesh::sieve_type>& sieve   = mesh->getSieve();
    1528:         PetscErrorCode                        ierr;
    1529:         ::tetgenio in;
    1530:         ::tetgenio out;

    1532:         const Obj<typename Mesh::label_sequence>&    vertices    = mesh->depthStratum(0);
    1533:         const Obj<typename Mesh::label_type>&        markers     = mesh->getLabel("marker");
    1534:         const Obj<typename Mesh::real_section_type>& coordinates = mesh->getRealSection("coordinates");
    1535:         const Obj<typename Mesh::numbering_type>&    vNumbering  = mesh->getFactory()->getLocalNumbering(mesh, 0);

    1537:         in.numberofpoints = vertices->size();
    1538:         if (in.numberofpoints > 0) {
    1539:           const typename Mesh::label_sequence::iterator vEnd = vertices->end();

    1541:           in.pointlist       = new double[in.numberofpoints*dim];
    1542:           in.pointmarkerlist = new int[in.numberofpoints];
    1543:           for(typename Mesh::label_sequence::iterator v_iter = vertices->begin(); v_iter != vEnd; ++v_iter) {
    1544:             const typename Mesh::real_section_type::value_type *array = coordinates->restrictPoint(*v_iter);
    1545:             const int                                           idx   = vNumbering->getIndex(*v_iter);

    1547:             for(int d = 0; d < dim; d++) {
    1548:               in.pointlist[idx*dim + d] = array[d];
    1549:             }
    1550:             in.pointmarkerlist[idx] = mesh->getValue(markers, *v_iter);
    1551:           }
    1552:         }
    1553:         const Obj<typename Mesh::label_sequence>& cells      = mesh->heightStratum(0);
    1554:         const Obj<typename Mesh::numbering_type>& cNumbering = mesh->getFactory()->getLocalNumbering(mesh, depth);

    1556:         in.numberofcorners       = 4;
    1557:         in.numberoftetrahedra    = cells->size();
    1558:         in.tetrahedronvolumelist = (double *) maxVolumes;
    1559:         if (in.numberoftetrahedra > 0) {
    1560:           in.tetrahedronlist     = new int[in.numberoftetrahedra*in.numberofcorners];
    1561:           if (mesh->depth() == 1) {
    1562:             ALE::ISieveVisitor::PointRetriever<typename Mesh::sieve_type> pV(4);
    1563:             const typename Mesh::label_sequence::iterator cEnd = cells->end();

    1565:             for(typename Mesh::label_sequence::iterator c_iter = cells->begin(); c_iter != cEnd; ++c_iter) {
    1566:               sieve->cone(*c_iter, pV);
    1567:               const int         idx  = cNumbering->getIndex(*c_iter);
    1568:               const size_t      n    = pV.getSize();
    1569:               const point_type *cone = pV.getPoints();

    1571:               assert(n == 4);
    1572:               for(int v = 0; v < 4; ++v) {
    1573:                 in.tetrahedronlist[idx*in.numberofcorners + v] = vNumbering->getIndex(cone[v]);
    1574:               }
    1575:               pV.clear();
    1576:             }
    1577:           } else if (mesh->depth() == 3) {
    1578:             // Need extra space due to early error checking
    1579:             ALE::ISieveVisitor::NConeRetriever<typename Mesh::sieve_type> ncV(*sieve, 5);
    1580:             const typename Mesh::label_sequence::iterator cEnd = cells->end();

    1582:             for(typename Mesh::label_sequence::iterator c_iter = cells->begin(); c_iter != cEnd; ++c_iter) {
    1583:               ALE::ISieveTraversal<typename Mesh::sieve_type>::orientedClosure(*sieve, *c_iter, ncV);
    1584:               const int         idx  = cNumbering->getIndex(*c_iter);
    1585:               const size_t      n    = ncV.getSize();
    1586:               const point_type *cone = ncV.getPoints();

    1588:               assert(n == 4);
    1589:               for(int v = 0; v < 4; ++v) {
    1590:                 in.tetrahedronlist[idx*in.numberofcorners + v] = vNumbering->getIndex(cone[v]);
    1591:               }
    1592:               ncV.clear();
    1593:             }
    1594:           } else {
    1595:             throw ALE::Exception("Invalid sieve: Cannot gives sieves of arbitrary depth to TetGen");
    1596:           }
    1597:         }
    1598:         if (depth == 3) {
    1599:           const Obj<typename Mesh::label_sequence>&     boundary = mesh->getLabelStratum("marker", 1);
    1600:           const typename Mesh::label_sequence::iterator bEnd     = boundary->end();

    1602:           in.numberoftrifaces = 0;
    1603:           for(typename Mesh::label_sequence::iterator b_iter = boundary->begin(); b_iter != bEnd; ++b_iter) {
    1604:             if (mesh->height(*b_iter) == 1) {
    1605:               in.numberoftrifaces++;
    1606:             }
    1607:           }
    1608:           if (in.numberoftrifaces > 0) {
    1609:             ALE::ISieveVisitor::NConeRetriever<typename Mesh::sieve_type> ncV(*sieve, 5);
    1610:             int f = 0;

    1612:             in.trifacelist       = new int[in.numberoftrifaces*3];
    1613:             in.trifacemarkerlist = new int[in.numberoftrifaces];
    1614:             for(typename Mesh::label_sequence::iterator b_iter = boundary->begin(); b_iter != bEnd; ++b_iter) {
    1615:               if (mesh->height(*b_iter) == 1) {
    1616:                 ALE::ISieveTraversal<typename Mesh::sieve_type>::orientedClosure(*sieve, *b_iter, ncV);
    1617:                 const size_t      n    = ncV.getSize();
    1618:                 const point_type *cone = ncV.getPoints();

    1620:                 for(size_t p = 0; p < n; ++p) {
    1621:                   in.trifacelist[f*3 + p] = vNumbering->getIndex(cone[p]);
    1622:                 }
    1623:                 in.trifacemarkerlist[f++] = mesh->getValue(markers, *b_iter);
    1624:                 ncV.clear();
    1625:               }
    1626:             }
    1627:           }
    1628:         }
    1629:         const typename Mesh::holes_type& holes = mesh->getHoles();

    1631:         in.numberofholes = holes.size();
    1632:         if (in.numberofholes > 0) {
    1633:           PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRXX(ierr);
    1634:           for(int h = 0; h < in.numberofholes; ++h) {
    1635:             for(int d = 0; d < dim; ++d) {
    1636:               in.holelist[h*dim+d] = holes[h][d];
    1637:             }
    1638:           }
    1639:         }
    1640:         if (mesh->commRank() == 0) {
    1641:           std::string args("qezQra");

    1643:           ::tetrahedralize((char *) args.c_str(), &in, &out);
    1644:         }
    1645:         in.tetrahedronvolumelist = NULL;
    1646:         const Obj<typename Mesh::sieve_type> newSieve = new typename Mesh::sieve_type(refMesh->comm(), refMesh->debug());
    1647:         const Obj<FlexMesh>                  m        = new FlexMesh(mesh->comm(), dim, mesh->debug());
    1648:         const Obj<FlexMesh::sieve_type>      newS     = new FlexMesh::sieve_type(m->comm(), m->debug());
    1649:         int     numCorners  = 4;
    1650:         int     numCells    = out.numberoftetrahedra;
    1651:         int    *newCells    = out.tetrahedronlist;
    1652:         int     numVertices = out.numberofpoints;
    1653:         double *coords      = out.pointlist;
    1654:         real   *coordsR;

    1656:         if (!interpolate) {
    1657:           for(int c = 0; c < numCells; ++c) {
    1658:             int tmp = newCells[c*4+0];
    1659:             newCells[c*4+0] = newCells[c*4+1];
    1660:             newCells[c*4+1] = tmp;
    1661:           }
    1662:         }
    1663:         ALE::SieveBuilder<FlexMesh>::buildTopology(newS, dim, numCells, newCells, numVertices, interpolate, numCorners, -1, m->getArrowSection("orientation"));
    1664:         m->setSieve(newS);
    1665:         m->stratify();
    1666:         refMesh->setSieve(newSieve);
    1667:         std::map<typename Mesh::point_type,typename Mesh::point_type> renumbering;
    1668:         ALE::ISieveConverter::convertSieve(*newS, *newSieve, renumbering, renumber);
    1669:         refMesh->stratify();
    1670:         ALE::ISieveConverter::convertOrientation(*newS, *newSieve, renumbering, m->getArrowSection("orientation").ptr());
    1671:         {
    1672:           if (sizeof(double) == sizeof(real)) {
    1673:             coordsR = (real *) coords;
    1674:           } else {
    1675:             coordsR = new real[numVertices*dim];
    1676:             for(int i = 0; i < numVertices*dim; ++i) coordsR[i] = coords[i];
    1677:           }
    1678:         }
    1679:         ALE::SieveBuilder<Mesh>::buildCoordinates(refMesh, dim, coordsR);
    1680:         {
    1681:           if (sizeof(double) != sizeof(real)) {
    1682:             delete [] coordsR;
    1683:           }
    1684:         }
    1685:         const Obj<typename Mesh::label_type>& newMarkers = refMesh->createLabel("marker");

    1687:         for(int v = 0; v < out.numberofpoints; v++) {
    1688:           if (out.pointmarkerlist[v]) {
    1689:             if (renumber) {
    1690:               refMesh->setValue(newMarkers, renumbering[v+out.numberoftetrahedra], out.pointmarkerlist[v]);
    1691:             } else {
    1692:               refMesh->setValue(newMarkers, v+out.numberoftetrahedra, out.pointmarkerlist[v]);
    1693:             }
    1694:           }
    1695:         }
    1696:         if (interpolate) {
    1697:           // This does not work anymore (edgemarkerlist is always empty). I tried -ee and it gave bogus results
    1698:           if (out.edgemarkerlist) {
    1699:             for(int e = 0; e < out.numberofedges; e++) {
    1700:               if (out.edgemarkerlist[e]) {
    1701:                 typename Mesh::point_type endpointA(out.edgelist[e*2+0]+out.numberoftetrahedra);
    1702:                 typename Mesh::point_type endpointB(out.edgelist[e*2+1]+out.numberoftetrahedra);
    1703:                 Obj<typename Mesh::sieve_type::supportSet> edge = newS->nJoin(endpointA, endpointB, 1);

    1705:                 if (renumber) {
    1706:                   refMesh->setValue(newMarkers, renumbering[*edge->begin()], out.edgemarkerlist[e]);
    1707:                 } else {
    1708:                   refMesh->setValue(newMarkers, *edge->begin(), out.edgemarkerlist[e]);
    1709:                 }
    1710:               }
    1711:             }
    1712:           }
    1713:           if (out.trifacemarkerlist) {
    1714:             for(int f = 0; f < out.numberoftrifaces; f++) {
    1715:               if (out.trifacemarkerlist[f]) {
    1716:                 typename Mesh::point_type cornerA(out.trifacelist[f*3+0]+out.numberoftetrahedra);
    1717:                 typename Mesh::point_type cornerB(out.trifacelist[f*3+1]+out.numberoftetrahedra);
    1718:                 typename Mesh::point_type cornerC(out.trifacelist[f*3+2]+out.numberoftetrahedra);
    1719:                 Obj<typename Mesh::sieve_type::supportSet> corners = typename Mesh::sieve_type::supportSet();
    1720:                 Obj<typename Mesh::sieve_type::supportSet> edges   = typename Mesh::sieve_type::supportSet();
    1721:                 corners->clear();corners->insert(cornerA);corners->insert(cornerB);
    1722:                 edges->insert(*newS->nJoin1(corners)->begin());
    1723:                 corners->clear();corners->insert(cornerB);corners->insert(cornerC);
    1724:                 edges->insert(*newS->nJoin1(corners)->begin());
    1725:                 corners->clear();corners->insert(cornerC);corners->insert(cornerA);
    1726:                 edges->insert(*newS->nJoin1(corners)->begin());
    1727:                 ALE::ISieveVisitor::PointRetriever<typename Mesh::sieve_type> pV(30);
    1728:                 typename Mesh::point_type face       = *newS->nJoin1(edges)->begin();
    1729:                 const int                 faceMarker = out.trifacemarkerlist[f];

    1731:                 if (renumber) {face = renumbering[face];}
    1732:                 ALE::ISieveTraversal<typename Mesh::sieve_type>::orientedClosure(*newSieve, face, pV);
    1733:                 const size_t                     n    = pV.getSize();
    1734:                 const typename Mesh::point_type *cone = pV.getPoints();

    1736:                 for(size_t c = 0; c < n; ++c) {
    1737:                   refMesh->setValue(newMarkers, cone[c], faceMarker);
    1738:                 }
    1739:                 pV.clear();
    1740:               }
    1741:             }
    1742:           }
    1743:         }
    1744:         return refMesh;
    1745:       };
    1746:       static Obj<Mesh> refineMeshV(const Obj<Mesh>& mesh, const Obj<typename Mesh::real_section_type>& maxVolumes, const bool interpolate = false, const bool forceSerial = false, const bool renumber = false) {
    1747:         throw ALE::Exception("Not yet implemented");
    1748:       };
    1749:       static Obj<Mesh> refineMeshV(const Obj<Mesh>& mesh, const double maxVolume, const bool interpolate = false, const bool forceSerial = false, const bool renumber = false) {
    1750:         const int numCells         = mesh->heightStratum(0)->size();
    1751:         double   *serialMaxVolumes = new double[numCells];

    1753:         for(int c = 0; c < numCells; c++) {
    1754:           serialMaxVolumes[c] = maxVolume;
    1755:         }
    1756:         const Obj<Mesh> refMesh = refineMeshV(mesh, serialMaxVolumes, interpolate, forceSerial, renumber);
    1757:         delete [] serialMaxVolumes;
    1758:         return refMesh;
    1759:       };
    1760:     };
    1761:   };
    1762: #endif
    1763:   template<typename Mesh>
    1764:   class Generator {
    1765:   public:
    1766:     static Obj<Mesh> generateMesh(const Obj<Mesh>& boundary, const bool interpolate = false, const bool constrained = false) {
    1767:       int dim = boundary->getDimension();

    1769:       if (dim == 1) {
    1770: #ifdef PETSC_HAVE_TRIANGLE
    1771:         return ALE::Triangle::Generator<Mesh>::generateMesh(boundary, interpolate, constrained);
    1772: #else
    1773:         throw ALE::Exception("Mesh generation currently requires Triangle to be installed. Use --download-triangle during configure.");
    1774: #endif
    1775:       } else if (dim == 2) {
    1776: #ifdef PETSC_HAVE_TETGEN
    1777:         return ALE::TetGen::Generator<Mesh>::generateMesh(boundary, interpolate, constrained);
    1778: #else
    1779:         throw ALE::Exception("Mesh generation currently requires TetGen to be installed. Use --download-tetgen during configure.");
    1780: #endif
    1781:       }
    1782:       return NULL;
    1783:     };
    1784:     static Obj<Mesh> generateMeshV(const Obj<Mesh>& boundary, const bool interpolate = false, const bool constrained = false, const bool renumber = false) {
    1785:       int dim = boundary->getDimension();

    1787:       if (dim == 1) {
    1788: #ifdef PETSC_HAVE_TRIANGLE
    1789:         return ALE::Triangle::Generator<Mesh>::generateMeshV(boundary, interpolate, constrained, renumber);
    1790: #else
    1791:         throw ALE::Exception("Mesh generation currently requires Triangle to be installed. Use --download-triangle during configure.");
    1792: #endif
    1793:       } else if (dim == 2) {
    1794: #ifdef PETSC_HAVE_TETGEN
    1795:         return ALE::TetGen::Generator<Mesh>::generateMeshV(boundary, interpolate, constrained, renumber);
    1796: #else
    1797:         throw ALE::Exception("Mesh generation currently requires TetGen to be installed. Use --download-tetgen during configure.");
    1798: #endif
    1799:       }
    1800:       return NULL;
    1801:     };
    1802:     static Obj<Mesh> refineMesh(const Obj<Mesh>& mesh, const Obj<typename Mesh::real_section_type>& maxVolumes, const bool interpolate = false) {
    1803:       int dim = mesh->getDimension();

    1805:       if (dim == 2) {
    1806: #ifdef PETSC_HAVE_TRIANGLE
    1807:         return ALE::Triangle::Refiner<Mesh>::refineMesh(mesh, maxVolumes, interpolate);
    1808: #else
    1809:         throw ALE::Exception("Mesh refinement currently requires Triangle to be installed. Use --download-triangle during configure.");
    1810: #endif
    1811:       } else if (dim == 3) {
    1812: #ifdef PETSC_HAVE_TETGEN
    1813:         return ALE::TetGen::Refiner<Mesh>::refineMesh(mesh, maxVolumes, interpolate);
    1814: #else
    1815:         throw ALE::Exception("Mesh refinement currently requires TetGen to be installed. Use --download-tetgen during configure.");
    1816: #endif
    1817:       }
    1818:       return NULL;
    1819:     };
    1820:     static Obj<Mesh> refineMesh(const Obj<Mesh>& mesh, const double maxVolume, const bool interpolate = false, const bool forceSerial = false) {
    1821:       int dim = mesh->getDimension();

    1823:       if (dim == 2) {
    1824: #ifdef PETSC_HAVE_TRIANGLE
    1825:         return ALE::Triangle::Refiner<Mesh>::refineMesh(mesh, maxVolume, interpolate, forceSerial);
    1826: #else
    1827:         throw ALE::Exception("Mesh refinement currently requires Triangle to be installed. Use --download-triangle during configure.");
    1828: #endif
    1829:       } else if (dim == 3) {
    1830: #ifdef PETSC_HAVE_TETGEN
    1831:         return ALE::TetGen::Refiner<Mesh>::refineMesh(mesh, maxVolume, interpolate);
    1832: #else
    1833:         throw ALE::Exception("Mesh refinement currently requires TetGen to be installed. Use --download-tetgen during configure.");
    1834: #endif
    1835:       }
    1836:       return NULL;
    1837:     };
    1838:     static Obj<Mesh> refineMeshV(const Obj<Mesh>& mesh, const Obj<typename Mesh::real_section_type>& maxVolumes, const bool interpolate = false, const bool renumber = false) {
    1839:       int dim = mesh->getDimension();

    1841:       if (dim == 2) {
    1842: #ifdef PETSC_HAVE_TRIANGLE
    1843:         return ALE::Triangle::Refiner<Mesh>::refineMeshV(mesh, maxVolumes, interpolate, renumber);
    1844: #else
    1845:         throw ALE::Exception("Mesh refinement currently requires Triangle to be installed. Use --download-triangle during configure.");
    1846: #endif
    1847:       } else if (dim == 3) {
    1848: #ifdef PETSC_HAVE_TETGEN
    1849:         return ALE::TetGen::Refiner<Mesh>::refineMeshV(mesh, maxVolumes, interpolate, renumber);
    1850: #else
    1851:         throw ALE::Exception("Mesh refinement currently requires TetGen to be installed. Use --download-tetgen during configure.");
    1852: #endif
    1853:       }
    1854:       return NULL;
    1855:     };
    1856:     static Obj<Mesh> refineMeshV(const Obj<Mesh>& mesh, const double maxVolume, const bool interpolate = false, const bool forceSerial = false, const bool renumber = false) {
    1857:       int dim = mesh->getDimension();

    1859:       if (dim == 2) {
    1860: #ifdef PETSC_HAVE_TRIANGLE
    1861:         return ALE::Triangle::Refiner<Mesh>::refineMeshV(mesh, maxVolume, interpolate, forceSerial, renumber);
    1862: #else
    1863:         throw ALE::Exception("Mesh refinement currently requires Triangle to be installed. Use --download-triangle during configure.");
    1864: #endif
    1865:       } else if (dim == 3) {
    1866: #ifdef PETSC_HAVE_TETGEN
    1867:         return ALE::TetGen::Refiner<Mesh>::refineMeshV(mesh, maxVolume, interpolate, forceSerial, renumber);
    1868: #else
    1869:         throw ALE::Exception("Mesh refinement currently requires TetGen to be installed. Use --download-tetgen during configure.");
    1870: #endif
    1871:       }
    1872:       return NULL;
    1873:     };
    1874:     static Obj<Mesh> refineMeshLocal(const Obj<Mesh>& mesh, const double maxVolume, const bool interpolate = false) {
    1875:       int dim = mesh->getDimension();

    1877:       if (dim == 2) {
    1878: #ifdef PETSC_HAVE_TRIANGLE
    1879:         return ALE::Triangle::Refiner<Mesh>::refineMeshLocal(mesh, maxVolume, interpolate);
    1880: #else
    1881:         throw ALE::Exception("Mesh refinement currently requires Triangle to be installed. Use --download-triangle during configure.");
    1882: #endif
    1883:       } else if (dim == 3) {
    1884: #ifdef PETSC_HAVE_TETGEN
    1885:         return ALE::TetGen::Refiner<Mesh>::refineMesh(mesh, maxVolume, interpolate);
    1886: #else
    1887:         throw ALE::Exception("Mesh refinement currently requires TetGen to be installed. Use --download-tetgen during configure.");
    1888: #endif
    1889:       }
    1890:       return NULL;
    1891:     };
    1892:   };
    1893: }

    1895: #endif