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

      1: #ifndef included_ALE_DMBuilder_hh
      2: #define included_ALE_DMBuilder_hh

      4: #ifndef  included_ALE_Mesh_hh
      5: #include <sieve/Mesh.hh>
      6: #endif

      8: #include <petscdmmesh.hh>

     10: namespace ALE {

     12:   class DMBuilder {
     13:   public:
     16:     static PetscErrorCode createBasketMesh(MPI_Comm comm, const int dim, const bool structured, const bool interpolate, const int debug, DM *dm) {
     17:       typedef PETSC_MESH_TYPE::real_section_type::value_type real;

     21:       if (structured) {
     22:         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "Structured grids cannot handle boundary meshes");
     23:       } else {
     24:         typedef ALE::Mesh<PetscInt,PetscScalar> FlexMesh;
     25:         typedef PETSC_MESH_TYPE::point_type point_type;
     26:         DM boundary;

     28:         DMCreate(comm, &boundary);
     29:         DMSetType(boundary, DMMESH);
     30:         Obj<PETSC_MESH_TYPE>             meshBd = new PETSC_MESH_TYPE(comm, dim-1, debug);
     31:         Obj<PETSC_MESH_TYPE::sieve_type> sieve  = new PETSC_MESH_TYPE::sieve_type(comm, debug);
     32:         std::map<point_type,point_type>  renumbering;
     33:         Obj<FlexMesh>                    mB;

     35:         meshBd->setSieve(sieve);
     36:         if (dim == 2) {
     37:           real lower[2] = {0.0, 0.0};
     38:           real upper[2] = {1.0, 1.0};
     39:           int  edges    = 2;

     41:           mB = ALE::MeshBuilder<FlexMesh>::createSquareBoundary(comm, lower, upper, edges, debug);
     42:         } else if (dim == 3) {
     43:           real lower[3] = {0.0, 0.0, 0.0};
     44:           real upper[3] = {1.0, 1.0, 1.0};
     45:           int  faces[3] = {3, 3, 3};

     47:           mB = ALE::MeshBuilder<FlexMesh>::createCubeBoundary(comm, lower, upper, faces, debug);
     48:         } else {
     49:           SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP, "Dimension not supported: %d", dim);
     50:         }
     51:         ALE::ISieveConverter::convertMesh(*mB, *meshBd, renumbering, false);
     52:         DMMeshSetMesh(boundary, meshBd);
     53:         *dm = boundary;
     54:       }
     55:       return(0);
     56:     };
     59:     static PetscErrorCode createBoxMesh(MPI_Comm comm, const int dim, const bool structured, const bool interpolate, const int debug, DM *dm) {
     60:       typedef PETSC_MESH_TYPE::real_section_type::value_type real;

     64:       if (structured) {
     65:         DM             da;
     66:         const PetscInt dof = 1;
     67:         const PetscInt pd  = PETSC_DECIDE;

     69:         if (dim == 2) {
     70:           DMDACreate2d(comm, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE, DMDA_STENCIL_BOX, -3, -3, pd, pd, dof, 1, NULL, NULL, &da);
     71:         } else if (dim == 3) {
     72:           DMDACreate3d(comm, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE, DMDA_STENCIL_BOX, -3, -3, -3, pd, pd, pd, dof, 1, NULL, NULL, NULL, &da);
     73:         } else {
     74:           SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP, "Dimension not supported: %d", dim);
     75:         }
     76:         DMDASetUniformCoordinates(da, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
     77:         *dm = da;
     78:       } else {
     79:         typedef ALE::Mesh<PetscInt,PetscScalar> FlexMesh;
     80:         typedef PETSC_MESH_TYPE::point_type point_type;
     81:         DM mesh;
     82:         DM boundary;

     84:         DMCreate(comm, &boundary);
     85:         DMSetType(boundary, DMMESH);
     86:         Obj<PETSC_MESH_TYPE>             meshBd = new PETSC_MESH_TYPE(comm, dim-1, debug);
     87:         Obj<PETSC_MESH_TYPE::sieve_type> sieve  = new PETSC_MESH_TYPE::sieve_type(comm, debug);
     88:         std::map<point_type,point_type>  renumbering;
     89:         Obj<FlexMesh>                    mB;

     91:         meshBd->setSieve(sieve);
     92:         if (dim == 2) {
     93:           real lower[2] = {0.0, 0.0};
     94:           real upper[2] = {1.0, 1.0};
     95:           int  edges[2] = {2, 2};

     97:           mB = ALE::MeshBuilder<FlexMesh>::createSquareBoundary(comm, lower, upper, edges, debug);
     98:         } else if (dim == 3) {
     99:           real lower[3] = {0.0, 0.0, 0.0};
    100:           real upper[3] = {1.0, 1.0, 1.0};
    101:           int  faces[3] = {3, 3, 3};

    103:           mB = ALE::MeshBuilder<FlexMesh>::createCubeBoundary(comm, lower, upper, faces, debug);
    104:         } else {
    105:           SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP, "Dimension not supported: %d", dim);
    106:         }
    107:         ALE::ISieveConverter::convertMesh(*mB, *meshBd, renumbering, false);
    108:         DMMeshSetMesh(boundary, meshBd);
    109:         DMMeshGenerate(boundary, (PetscBool) interpolate, &mesh);
    110:         DMDestroy(&boundary);
    111:         *dm = mesh;
    112:       }
    113:       return(0);
    114:     };
    117:     static PetscErrorCode createReentrantBoxMesh(MPI_Comm comm, const int dim, const bool interpolate, const int debug, DM *dm) {
    118:       typedef ALE::Mesh<PetscInt,PetscScalar> FlexMesh;
    119:       typedef PETSC_MESH_TYPE::point_type point_type;
    120:       typedef PETSC_MESH_TYPE::real_section_type::value_type real;
    121:       DM         mesh;
    122:       DM         boundary;

    126:       DMCreate(comm, &boundary);
    127:       DMSetType(boundary, DMMESH);
    128:       Obj<PETSC_MESH_TYPE>             meshBd = new PETSC_MESH_TYPE(comm, dim-1, debug);
    129:       Obj<PETSC_MESH_TYPE::sieve_type> sieve  = new PETSC_MESH_TYPE::sieve_type(comm, debug);
    130:       std::map<point_type,point_type>  renumbering;
    131:       Obj<FlexMesh>                    mB;

    133:       meshBd->setSieve(sieve);
    134:       if (dim == 2) {
    135:         real lower[2]  = {-1.0, -1.0};
    136:         real upper[2]  = {1.0, 1.0};
    137:         real offset[2] = {0.5, 0.5};

    139:         mB = ALE::MeshBuilder<FlexMesh>::createReentrantBoundary(comm, lower, upper, offset, debug);
    140:       } else if (dim == 3) {
    141:         real lower[3]  = {-1.0, -1.0, -1.0};
    142:         real upper[3]  = { 1.0,  1.0,  1.0};
    143:         real offset[3] = { 0.5,  0.5,  0.5};

    145:         mB = ALE::MeshBuilder<FlexMesh>::createFicheraCornerBoundary(comm, lower, upper, offset, debug);
    146:       } else {
    147:         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP, "Dimension not supported: %d", dim);
    148:       }
    149:       ALE::ISieveConverter::convertMesh(*mB, *meshBd, renumbering, false);
    150:       DMMeshSetMesh(boundary, meshBd);
    151:       DMMeshGenerate(boundary, (PetscBool) interpolate, &mesh);
    152:       DMDestroy(&boundary);
    153:       *dm = mesh;
    154:       return(0);
    155:     };
    158:     static PetscErrorCode createSphericalMesh(MPI_Comm comm, const int dim, const bool interpolate, const int debug, DM *dm) {
    159:       typedef ALE::Mesh<PetscInt,PetscScalar> FlexMesh;
    160:       typedef PETSC_MESH_TYPE::point_type point_type;
    161:       DM         mesh;
    162:       DM         boundary;

    166:       DMCreate(comm, &boundary);
    167:       DMSetType(boundary, DMMESH);
    168:       Obj<PETSC_MESH_TYPE>             meshBd = new PETSC_MESH_TYPE(comm, dim-1, debug);
    169:       Obj<PETSC_MESH_TYPE::sieve_type> sieve  = new PETSC_MESH_TYPE::sieve_type(comm, debug);
    170:       std::map<point_type,point_type>  renumbering;
    171:       Obj<FlexMesh>                    mB;

    173:       meshBd->setSieve(sieve);
    174:       if (dim == 2) {
    175:         mB = ALE::MeshBuilder<FlexMesh>::createCircularReentrantBoundary(comm, 100, 1.0, 1.0, debug);
    176:       } else {
    177:         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP, "Dimension not supported: %d", dim);
    178:       }
    179:       ALE::ISieveConverter::convertMesh(*mB, *meshBd, renumbering, false);
    180:       DMMeshSetMesh(boundary, meshBd);
    181:       DMMeshGenerate(boundary, (PetscBool) interpolate, &mesh);
    182:       DMDestroy(&boundary);
    183:       *dm = mesh;
    184:       return(0);
    185:     };
    188:     static PetscErrorCode createReentrantSphericalMesh(MPI_Comm comm, const int dim, const bool interpolate, const int debug, DM *dm) {
    189:       typedef ALE::Mesh<PetscInt,PetscScalar> FlexMesh;
    190:       typedef PETSC_MESH_TYPE::point_type point_type;
    191:       DM         mesh;
    192:       DM         boundary;

    196:       DMCreate(comm, &boundary);
    197:       DMSetType(boundary, DMMESH);
    198:       Obj<PETSC_MESH_TYPE>             meshBd = new PETSC_MESH_TYPE(comm, dim-1, debug);
    199:       Obj<PETSC_MESH_TYPE::sieve_type> sieve  = new PETSC_MESH_TYPE::sieve_type(comm, debug);
    200:       std::map<point_type,point_type>  renumbering;
    201:       Obj<FlexMesh>                    mB;

    203:       meshBd->setSieve(sieve);
    204:       if (dim == 2) {
    205:         mB = ALE::MeshBuilder<FlexMesh>::createCircularReentrantBoundary(comm, 100, 1.0, 0.9, debug);
    206:       } else {
    207:         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP, "Dimension not supported: %d", dim);
    208:       }
    209:       ALE::ISieveConverter::convertMesh(*mB, *meshBd, renumbering, false);
    210:       DMMeshSetMesh(boundary, meshBd);
    211:       DMMeshGenerate(boundary, (PetscBool) interpolate, &mesh);
    212:       DMDestroy(&boundary);
    213:       *dm = mesh;
    214:       return(0);
    215:     };
    218:     static PetscErrorCode MeshRefineSingularity(DM mesh, double * singularity, double factor, DM *refinedMesh) {
    219:       typedef PETSC_MESH_TYPE::real_section_type::value_type real;
    220:       ALE::Obj<PETSC_MESH_TYPE> oldMesh;
    221:       double              oldLimit;
    222:       PetscErrorCode      ierr;

    225:       DMMeshGetMesh(mesh, oldMesh);
    226:       DMCreate(oldMesh->comm(), refinedMesh);
    227:       DMSetType(*refinedMesh, DMMESH);
    228:       int dim = oldMesh->getDimension();
    229:       oldLimit = oldMesh->getMaxVolume();
    230:       //double oldLimInv = 1./oldLimit;
    231:       real curLimit, tmpLimit;
    232:       real minLimit = oldLimit/16384.;             //arbitrary;
    233:       const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& coordinates = oldMesh->getRealSection("coordinates");
    234:       const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& volume_limits = oldMesh->getRealSection("volume_limits");
    235:       volume_limits->setFiberDimension(oldMesh->heightStratum(0), 1);
    236:       oldMesh->allocate(volume_limits);
    237:       const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& cells = oldMesh->heightStratum(0);
    238:       PETSC_MESH_TYPE::label_sequence::iterator c_iter = cells->begin();
    239:       PETSC_MESH_TYPE::label_sequence::iterator c_iter_end = cells->end();
    240:       real centerCoords[dim];
    241:       while (c_iter != c_iter_end) {
    242:         const real * coords = oldMesh->restrictClosure(coordinates, *c_iter);
    243:         for (int i = 0; i < dim; i++) {
    244:           centerCoords[i] = 0;
    245:           for (int j = 0; j < dim+1; j++) {
    246:             centerCoords[i] += coords[j*dim+i];
    247:           }
    248:           centerCoords[i] = centerCoords[i]/(dim+1);
    249:         }
    250:         real dist = 0.;
    251:         for (int i = 0; i < dim; i++) {
    252:           dist += (centerCoords[i] - singularity[i])*(centerCoords[i] - singularity[i]);
    253:         }
    254:         if (dist > 0.) {
    255:           dist = sqrt(dist);
    256:           real mu = pow(dist, factor);
    257:           //PetscPrintf(oldMesh->comm(), "%f\n", mu);
    258:           tmpLimit = oldLimit*pow(mu, dim);
    259:           if (tmpLimit > minLimit) {
    260:             curLimit = tmpLimit;
    261:           } else curLimit = minLimit;
    262:         } else curLimit = minLimit;
    263:         //PetscPrintf(oldMesh->comm(), "%f, %f\n", dist, tmpLimit);
    264:         volume_limits->updatePoint(*c_iter, &curLimit);
    265:         c_iter++;
    266:       }
    267: #ifdef PETSC_OPT_SIEVE
    268:       ALE::Obj<PETSC_MESH_TYPE> newMesh = ALE::Generator<PETSC_MESH_TYPE>::refineMeshV(oldMesh, volume_limits, true);
    269: #else
    270:       ALE::Obj<PETSC_MESH_TYPE> newMesh = ALE::Generator<PETSC_MESH_TYPE>::refineMesh(oldMesh, volume_limits, true);
    271: #endif
    272:       DMMeshSetMesh(*refinedMesh, newMesh);
    273:       const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& s = newMesh->getRealSection("default");
    274:       const Obj<std::set<std::string> >& discs = oldMesh->getDiscretizations();

    276:       for(std::set<std::string>::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter) {
    277:         newMesh->setDiscretization(*f_iter, oldMesh->getDiscretization(*f_iter));
    278:       }
    279:       newMesh->setupField(s);
    280:       return(0);
    281:     };
    284:     static PetscErrorCode MeshRefineSingularity_Fichera(DM mesh, double * singularity, double factor, DM *refinedMesh) {
    285:       typedef PETSC_MESH_TYPE::real_section_type::value_type real;
    286:       ALE::Obj<PETSC_MESH_TYPE> oldMesh;
    287:       real                      oldLimit;
    288:       PetscErrorCode            ierr;

    291:       DMMeshGetMesh(mesh, oldMesh);
    292:       DMCreate(oldMesh->comm(), refinedMesh);
    293:       DMSetType(*refinedMesh, DMMESH);
    294:       int dim = oldMesh->getDimension();
    295:       oldLimit = oldMesh->getMaxVolume();
    296:       //double oldLimInv = 1./oldLimit;
    297:       real curLimit, tmpLimit;
    298:       real minLimit = oldLimit/16384.;             //arbitrary;
    299:       const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& coordinates = oldMesh->getRealSection("coordinates");
    300:       const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& volume_limits = oldMesh->getRealSection("volume_limits");
    301:       volume_limits->setFiberDimension(oldMesh->heightStratum(0), 1);
    302:       oldMesh->allocate(volume_limits);
    303:       const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& cells = oldMesh->heightStratum(0);
    304:       PETSC_MESH_TYPE::label_sequence::iterator c_iter = cells->begin();
    305:       PETSC_MESH_TYPE::label_sequence::iterator c_iter_end = cells->end();
    306:       real centerCoords[dim];
    307:       while (c_iter != c_iter_end) {
    308:         const real *coords = oldMesh->restrictClosure(coordinates, *c_iter);
    309:         for (int i = 0; i < dim; i++) {
    310:           centerCoords[i] = 0;
    311:           for (int j = 0; j < dim+1; j++) {
    312:             centerCoords[i] += coords[j*dim+i];
    313:           }
    314:           centerCoords[i] = centerCoords[i]/(dim+1);
    315:           //PetscPrintf(oldMesh->comm(), "%f, ", centerCoords[i]);
    316:         }
    317:         //PetscPrintf(oldMesh->comm(), "\n");
    318:         real dist = 0.;
    319:         real cornerdist = 0.;
    320:         //HERE'S THE DIFFERENCE: if centercoords is less than the singularity coordinate for each direction, include that direction in the distance
    321:         /*
    322:           for (int i = 0; i < dim; i++) {
    323:           if (centerCoords[i] <= singularity[i]) {
    324:           dist += (centerCoords[i] - singularity[i])*(centerCoords[i] - singularity[i]);
    325:           }
    326:           }
    327:         */
    328:         //determine: the per-dimension distance: cases
    329:         for (int i = 0; i < dim; i++) {
    330:           cornerdist = 0.;
    331:           if (centerCoords[i] > singularity[i]) {
    332:             for (int j = 0; j < dim; j++) {
    333:               if (j != i) cornerdist += (centerCoords[j] - singularity[j])*(centerCoords[j] - singularity[j]);
    334:             }
    335:             if (cornerdist < dist || dist == 0.) dist = cornerdist;
    336:           }
    337:         }
    338:         //patch up AROUND the corner by minimizing between the distance from the relevant axis and the singular vertex
    339:         real singdist = 0.;
    340:         for (int i = 0; i < dim; i++) {
    341:           singdist += (centerCoords[i] - singularity[i])*(centerCoords[i] - singularity[i]);
    342:         }
    343:         if (singdist < dist || dist == 0.) dist = singdist;
    344:         if (dist > 0.) {
    345:           dist = sqrt(dist);
    346:           real mu = pow(dist, factor);
    347:           //PetscPrintf(oldMesh->comm(), "%f, %f\n", mu, dist);
    348:           tmpLimit = oldLimit*pow(mu, dim);
    349:           if (tmpLimit > minLimit) {
    350:             curLimit = tmpLimit;
    351:           } else curLimit = minLimit;
    352:         } else curLimit = minLimit;
    353:         //PetscPrintf(oldMesh->comm(), "%f, %f\n", dist, tmpLimit);
    354:         volume_limits->updatePoint(*c_iter, &curLimit);
    355:         c_iter++;
    356:       }
    357: #ifdef PETSC_OPT_SIEVE
    358:       ALE::Obj<PETSC_MESH_TYPE> newMesh = ALE::Generator<PETSC_MESH_TYPE>::refineMeshV(oldMesh, volume_limits, true);
    359: #else
    360:       ALE::Obj<PETSC_MESH_TYPE> newMesh = ALE::Generator<PETSC_MESH_TYPE>::refineMesh(oldMesh, volume_limits, true);
    361: #endif
    362:       DMMeshSetMesh(*refinedMesh, newMesh);
    363:       const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& s = newMesh->getRealSection("default");
    364:       const Obj<std::set<std::string> >& discs = oldMesh->getDiscretizations();

    366:       for(std::set<std::string>::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter) {
    367:         newMesh->setDiscretization(*f_iter, oldMesh->getDiscretization(*f_iter));
    368:       }
    369:       newMesh->setupField(s);
    370:       //  PetscPrintf(newMesh->comm(), "refined\n");
    371:       return(0);
    372:     };
    373:   };
    374: }

    376: #endif