Date: 2013-07-02T14:45:38+00:00

Actual source code: plexcreate.c
petsc-3.4.2 2013-07-02

      1: #define PETSCDM_DLL
      2: #include <petsc-private/dmpleximpl.h>    /*I   "petscdmplex.h"   I*/
      3: #include <petscdmda.h>
      4: #include <petscsf.h>

      8: PetscErrorCode  DMSetFromOptions_Plex(DM dm)
      9: {
     10:   DM_Plex        *mesh = (DM_Plex*) dm->data;

     15:   PetscOptionsHead("DMPlex Options");
     16:   /* Handle DMPlex refinement */
     17:   /* Handle associated vectors */
     18:   /* Handle viewing */
     19:   PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMView", PETSC_FALSE, &mesh->printSetValues, NULL);
     20:   PetscOptionsInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMView", 0, &mesh->printFEM, NULL);
     21:   PetscOptionsTail();
     22:   return(0);
     23: }

     27: /*
     28:  Simple square boundary:

     30:  18--5-17--4--16
     31:   |     |     |
     32:   6    10     3
     33:   |     |     |
     34:  19-11-20--9--15
     35:   |     |     |
     36:   7     8     2
     37:   |     |     |
     38:  12--0-13--1--14
     39: */
     40: PetscErrorCode DMPlexCreateSquareBoundary(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
     41: {
     42:   PetscInt       numVertices    = (edges[0]+1)*(edges[1]+1);
     43:   PetscInt       numEdges       = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
     44:   PetscInt       markerTop      = 1;
     45:   PetscInt       markerBottom   = 1;
     46:   PetscInt       markerRight    = 1;
     47:   PetscInt       markerLeft     = 1;
     48:   PetscBool      markerSeparate = PETSC_FALSE;
     49:   Vec            coordinates;
     50:   PetscSection   coordSection;
     51:   PetscScalar    *coords;
     52:   PetscInt       coordSize;
     53:   PetscMPIInt    rank;
     54:   PetscInt       v, vx, vy;

     58:   PetscOptionsGetBool(((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL);
     59:   if (markerSeparate) {
     60:     markerTop    = 1;
     61:     markerBottom = 0;
     62:     markerRight  = 0;
     63:     markerLeft   = 0;
     64:   }
     65:   MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);
     66:   if (!rank) {
     67:     PetscInt e, ex, ey;

     69:     DMPlexSetChart(dm, 0, numEdges+numVertices);
     70:     for (e = 0; e < numEdges; ++e) {
     71:       DMPlexSetConeSize(dm, e, 2);
     72:     }
     73:     DMSetUp(dm); /* Allocate space for cones */
     74:     for (vx = 0; vx <= edges[0]; vx++) {
     75:       for (ey = 0; ey < edges[1]; ey++) {
     76:         PetscInt edge   = vx*edges[1] + ey + edges[0]*(edges[1]+1);
     77:         PetscInt vertex = ey*(edges[0]+1) + vx + numEdges;
     78:         PetscInt cone[2];

     80:         cone[0] = vertex; cone[1] = vertex+edges[0]+1;
     81:         DMPlexSetCone(dm, edge, cone);
     82:         if (vx == edges[0]) {
     83:           DMPlexSetLabelValue(dm, "marker", edge,    markerRight);
     84:           DMPlexSetLabelValue(dm, "marker", cone[0], markerRight);
     85:           if (ey == edges[1]-1) {
     86:             DMPlexSetLabelValue(dm, "marker", cone[1], markerRight);
     87:           }
     88:         } else if (vx == 0) {
     89:           DMPlexSetLabelValue(dm, "marker", edge,    markerLeft);
     90:           DMPlexSetLabelValue(dm, "marker", cone[0], markerLeft);
     91:           if (ey == edges[1]-1) {
     92:             DMPlexSetLabelValue(dm, "marker", cone[1], markerLeft);
     93:           }
     94:         }
     95:       }
     96:     }
     97:     for (vy = 0; vy <= edges[1]; vy++) {
     98:       for (ex = 0; ex < edges[0]; ex++) {
     99:         PetscInt edge   = vy*edges[0]     + ex;
    100:         PetscInt vertex = vy*(edges[0]+1) + ex + numEdges;
    101:         PetscInt cone[2];

    103:         cone[0] = vertex; cone[1] = vertex+1;
    104:         DMPlexSetCone(dm, edge, cone);
    105:         if (vy == edges[1]) {
    106:           DMPlexSetLabelValue(dm, "marker", edge,    markerTop);
    107:           DMPlexSetLabelValue(dm, "marker", cone[0], markerTop);
    108:           if (ex == edges[0]-1) {
    109:             DMPlexSetLabelValue(dm, "marker", cone[1], markerTop);
    110:           }
    111:         } else if (vy == 0) {
    112:           DMPlexSetLabelValue(dm, "marker", edge,    markerBottom);
    113:           DMPlexSetLabelValue(dm, "marker", cone[0], markerBottom);
    114:           if (ex == edges[0]-1) {
    115:             DMPlexSetLabelValue(dm, "marker", cone[1], markerBottom);
    116:           }
    117:         }
    118:       }
    119:     }
    120:   }
    121:   DMPlexSymmetrize(dm);
    122:   DMPlexStratify(dm);
    123:   /* Build coordinates */
    124:   DMPlexGetCoordinateSection(dm, &coordSection);
    125:   PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices);
    126:   for (v = numEdges; v < numEdges+numVertices; ++v) {
    127:     PetscSectionSetDof(coordSection, v, 2);
    128:   }
    129:   PetscSectionSetUp(coordSection);
    130:   PetscSectionGetStorageSize(coordSection, &coordSize);
    131:   VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);
    132:   VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);
    133:   VecSetFromOptions(coordinates);
    134:   VecGetArray(coordinates, &coords);
    135:   for (vy = 0; vy <= edges[1]; ++vy) {
    136:     for (vx = 0; vx <= edges[0]; ++vx) {
    137:       coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
    138:       coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
    139:     }
    140:   }
    141:   VecRestoreArray(coordinates, &coords);
    142:   DMSetCoordinatesLocal(dm, coordinates);
    143:   VecDestroy(&coordinates);
    144:   return(0);
    145: }

    149: /*
    150:  Simple cubic boundary:

    152:      2-------3
    153:     /|      /|
    154:    6-------7 |
    155:    | |     | |
    156:    | 0-----|-1
    157:    |/      |/
    158:    4-------5
    159: */
    160: PetscErrorCode DMPlexCreateCubeBoundary(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[])
    161: {
    162:   PetscInt       numVertices = (faces[0]+1)*(faces[1]+1)*(faces[2]+1);
    163:   PetscInt       numFaces    = 6;
    164:   Vec            coordinates;
    165:   PetscSection   coordSection;
    166:   PetscScalar    *coords;
    167:   PetscInt       coordSize;
    168:   PetscMPIInt    rank;
    169:   PetscInt       v, vx, vy, vz;

    173:   if ((faces[0] < 1) || (faces[1] < 1) || (faces[2] < 1)) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Must have at least 1 face per side");
    174:   if ((faces[0] > 1) || (faces[1] > 1) || (faces[2] > 1)) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Currently can't handle more than 1 face per side");
    175:   PetscMalloc(numVertices*2 * sizeof(PetscReal), &coords);
    176:   MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);
    177:   if (!rank) {
    178:     PetscInt f;

    180:     DMPlexSetChart(dm, 0, numFaces+numVertices);
    181:     for (f = 0; f < numFaces; ++f) {
    182:       DMPlexSetConeSize(dm, f, 4);
    183:     }
    184:     DMSetUp(dm); /* Allocate space for cones */
    185:     for (v = 0; v < numFaces+numVertices; ++v) {
    186:       DMPlexSetLabelValue(dm, "marker", v, 1);
    187:     }
    188:     { /* Side 0 (Front) */
    189:       PetscInt cone[4];
    190:       cone[0] = numFaces+4; cone[1] = numFaces+5; cone[2] = numFaces+7; cone[3] = numFaces+6;
    191:       DMPlexSetCone(dm, 0, cone);
    192:     }
    193:     { /* Side 1 (Back) */
    194:       PetscInt cone[4];
    195:       cone[0] = numFaces+1; cone[1] = numFaces+0; cone[2] = numFaces+2; cone[3] = numFaces+3;
    196:       DMPlexSetCone(dm, 1, cone);
    197:     }
    198:     { /* Side 2 (Bottom) */
    199:       PetscInt cone[4];
    200:       cone[0] = numFaces+0; cone[1] = numFaces+1; cone[2] = numFaces+5; cone[3] = numFaces+4;
    201:       DMPlexSetCone(dm, 2, cone);
    202:     }
    203:     { /* Side 3 (Top) */
    204:       PetscInt cone[4];
    205:       cone[0] = numFaces+6; cone[1] = numFaces+7; cone[2] = numFaces+3; cone[3] = numFaces+2;
    206:       DMPlexSetCone(dm, 3, cone);
    207:     }
    208:     { /* Side 4 (Left) */
    209:       PetscInt cone[4];
    210:       cone[0] = numFaces+0; cone[1] = numFaces+4; cone[2] = numFaces+6; cone[3] = numFaces+2;
    211:       DMPlexSetCone(dm, 4, cone);
    212:     }
    213:     { /* Side 5 (Right) */
    214:       PetscInt cone[4];
    215:       cone[0] = numFaces+5; cone[1] = numFaces+1; cone[2] = numFaces+3; cone[3] = numFaces+7;
    216:       DMPlexSetCone(dm, 5, cone);
    217:     }
    218:   }
    219:   DMPlexSymmetrize(dm);
    220:   DMPlexStratify(dm);
    221:   /* Build coordinates */
    222:   DMPlexGetCoordinateSection(dm, &coordSection);
    223:   PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices);
    224:   for (v = numFaces; v < numFaces+numVertices; ++v) {
    225:     PetscSectionSetDof(coordSection, v, 3);
    226:   }
    227:   PetscSectionSetUp(coordSection);
    228:   PetscSectionGetStorageSize(coordSection, &coordSize);
    229:   VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);
    230:   PetscObjectSetName((PetscObject) coordinates, "coordinates");
    231:   VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);
    232:   VecSetFromOptions(coordinates);
    233:   VecGetArray(coordinates, &coords);
    234:   for (vz = 0; vz <= faces[2]; ++vz) {
    235:     for (vy = 0; vy <= faces[1]; ++vy) {
    236:       for (vx = 0; vx <= faces[0]; ++vx) {
    237:         coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
    238:         coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
    239:         coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
    240:       }
    241:     }
    242:   }
    243:   VecRestoreArray(coordinates, &coords);
    244:   DMSetCoordinatesLocal(dm, coordinates);
    245:   VecDestroy(&coordinates);
    246:   return(0);
    247: }

    251: /*
    252:  Simple square mesh:

    254:  22--8-23--9--24
    255:   |     |     |
    256:  13  2 14  3  15
    257:   |     |     |
    258:  19--6-20--7--21
    259:   |     |     |
    260:  10  0 11  1 12
    261:   |     |     |
    262:  16--4-17--5--18
    263: */
    264: PetscErrorCode DMPlexCreateSquareMesh(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
    265: {
    266:   PetscInt       markerTop      = 1;
    267:   PetscInt       markerBottom   = 1;
    268:   PetscInt       markerRight    = 1;
    269:   PetscInt       markerLeft     = 1;
    270:   PetscBool      markerSeparate = PETSC_FALSE;
    271:   PetscMPIInt    rank;

    275:   MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);
    276:   PetscOptionsGetBool(((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL);
    277:   if (markerSeparate) {
    278:     markerTop    = 3;
    279:     markerBottom = 1;
    280:     markerRight  = 2;
    281:     markerLeft   = 4;
    282:   }
    283:   {
    284:     const PetscInt numXEdges    = !rank ? edges[0]   : 0;
    285:     const PetscInt numYEdges    = !rank ? edges[1]   : 0;
    286:     const PetscInt numXVertices = !rank ? edges[0]+1 : 0;
    287:     const PetscInt numYVertices = !rank ? edges[1]+1 : 0;
    288:     const PetscInt numTotXEdges = numXEdges*numYVertices;
    289:     const PetscInt numTotYEdges = numYEdges*numXVertices;
    290:     const PetscInt numVertices  = numXVertices*numYVertices;
    291:     const PetscInt numEdges     = numTotXEdges + numTotYEdges;
    292:     const PetscInt numFaces     = numXEdges*numYEdges;
    293:     const PetscInt firstVertex  = numFaces;
    294:     const PetscInt firstXEdge   = numFaces + numVertices;
    295:     const PetscInt firstYEdge   = numFaces + numVertices + numTotXEdges;
    296:     Vec            coordinates;
    297:     PetscSection   coordSection;
    298:     PetscScalar    *coords;
    299:     PetscInt       coordSize;
    300:     PetscInt       v, vx, vy;
    301:     PetscInt       f, fx, fy, e, ex, ey;

    303:     DMPlexSetChart(dm, 0, numFaces+numEdges+numVertices);
    304:     for (f = 0; f < numFaces; ++f) {
    305:       DMPlexSetConeSize(dm, f, 4);
    306:     }
    307:     for (e = firstXEdge; e < firstXEdge+numEdges; ++e) {
    308:       DMPlexSetConeSize(dm, e, 2);
    309:     }
    310:     DMSetUp(dm); /* Allocate space for cones */
    311:     /* Build faces */
    312:     for (fy = 0; fy < numYEdges; fy++) {
    313:       for (fx = 0; fx < numXEdges; fx++) {
    314:         const PetscInt face    = fy*numXEdges + fx;
    315:         const PetscInt edgeL   = firstYEdge + fx*numYEdges + fy;
    316:         const PetscInt edgeB   = firstXEdge + fy*numXEdges + fx;
    317:         const PetscInt ornt[4] = {0,     0,               -2,              -2};
    318:         PetscInt       cone[4];

    320:         cone[0] = edgeB; cone[1] = edgeL+numYEdges; cone[2] = edgeB+numXEdges; cone[3] = edgeL;
    321:         DMPlexSetCone(dm, face, cone);
    322:         DMPlexSetConeOrientation(dm, face, ornt);
    323:       }
    324:     }
    325:     /* Build Y edges*/
    326:     for (vx = 0; vx < numXVertices; vx++) {
    327:       for (ey = 0; ey < numYEdges; ey++) {
    328:         const PetscInt edge   = firstYEdge  + vx*numYEdges + ey;
    329:         const PetscInt vertex = firstVertex + ey*numXVertices + vx;
    330:         PetscInt       cone[2];

    332:         cone[0] = vertex; cone[1] = vertex+numXVertices;
    333:         DMPlexSetCone(dm, edge, cone);
    334:         if (vx == numXVertices-1) {
    335:           DMPlexSetLabelValue(dm, "marker", edge,    markerRight);
    336:           DMPlexSetLabelValue(dm, "marker", cone[0], markerRight);
    337:           if (ey == numYEdges-1) {
    338:             DMPlexSetLabelValue(dm, "marker", cone[1], markerRight);
    339:           }
    340:         } else if (vx == 0) {
    341:           DMPlexSetLabelValue(dm, "marker", edge,    markerLeft);
    342:           DMPlexSetLabelValue(dm, "marker", cone[0], markerLeft);
    343:           if (ey == numYEdges-1) {
    344:             DMPlexSetLabelValue(dm, "marker", cone[1], markerLeft);
    345:           }
    346:         }
    347:       }
    348:     }
    349:     /* Build X edges*/
    350:     for (vy = 0; vy < numYVertices; vy++) {
    351:       for (ex = 0; ex < numXEdges; ex++) {
    352:         const PetscInt edge   = firstXEdge  + vy*numXEdges + ex;
    353:         const PetscInt vertex = firstVertex + vy*numXVertices + ex;
    354:         PetscInt       cone[2];

    356:         cone[0] = vertex; cone[1] = vertex+1;
    357:         DMPlexSetCone(dm, edge, cone);
    358:         if (vy == numYVertices-1) {
    359:           DMPlexSetLabelValue(dm, "marker", edge,    markerTop);
    360:           DMPlexSetLabelValue(dm, "marker", cone[0], markerTop);
    361:           if (ex == numXEdges-1) {
    362:             DMPlexSetLabelValue(dm, "marker", cone[1], markerTop);
    363:           }
    364:         } else if (vy == 0) {
    365:           DMPlexSetLabelValue(dm, "marker", edge,    markerBottom);
    366:           DMPlexSetLabelValue(dm, "marker", cone[0], markerBottom);
    367:           if (ex == numXEdges-1) {
    368:             DMPlexSetLabelValue(dm, "marker", cone[1], markerBottom);
    369:           }
    370:         }
    371:       }
    372:     }
    373:     DMPlexSymmetrize(dm);
    374:     DMPlexStratify(dm);
    375:     /* Build coordinates */
    376:     DMPlexGetCoordinateSection(dm, &coordSection);
    377:     PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVertices);
    378:     for (v = firstVertex; v < firstVertex+numVertices; ++v) {
    379:       PetscSectionSetDof(coordSection, v, 2);
    380:     }
    381:     PetscSectionSetUp(coordSection);
    382:     PetscSectionGetStorageSize(coordSection, &coordSize);
    383:     VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);
    384:     VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);
    385:     VecSetFromOptions(coordinates);
    386:     VecGetArray(coordinates, &coords);
    387:     for (vy = 0; vy < numYVertices; ++vy) {
    388:       for (vx = 0; vx < numXVertices; ++vx) {
    389:         coords[(vy*numXVertices+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/numXEdges)*vx;
    390:         coords[(vy*numXVertices+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/numYEdges)*vy;
    391:       }
    392:     }
    393:     VecRestoreArray(coordinates, &coords);
    394:     DMSetCoordinatesLocal(dm, coordinates);
    395:     VecDestroy(&coordinates);
    396:   }
    397:   return(0);
    398: }

    402: /*@
    403:   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box).

    405:   Collective on MPI_Comm

    407:   Input Parameters:
    408: + comm - The communicator for the DM object
    409: . dim - The spatial dimension
    410: - interpolate - Flag to create intermediate mesh pieces (edges, faces)

    412:   Output Parameter:
    413: . dm  - The DM object

    415:   Level: beginner

    417: .keywords: DM, create
    418: .seealso: DMSetType(), DMCreate()
    419: @*/
    420: PetscErrorCode DMPlexCreateBoxMesh(MPI_Comm comm, PetscInt dim, PetscBool interpolate, DM *dm)
    421: {
    422:   DM             boundary;

    427:   DMCreate(comm, &boundary);
    429:   DMSetType(boundary, DMPLEX);
    430:   DMPlexSetDimension(boundary, dim-1);
    431:   switch (dim) {
    432:   case 2:
    433:   {
    434:     PetscReal lower[2] = {0.0, 0.0};
    435:     PetscReal upper[2] = {1.0, 1.0};
    436:     PetscInt  edges[2] = {2, 2};

    438:     DMPlexCreateSquareBoundary(boundary, lower, upper, edges);
    439:     break;
    440:   }
    441:   case 3:
    442:   {
    443:     PetscReal lower[3] = {0.0, 0.0, 0.0};
    444:     PetscReal upper[3] = {1.0, 1.0, 1.0};
    445:     PetscInt  faces[3] = {1, 1, 1};

    447:     DMPlexCreateCubeBoundary(boundary, lower, upper, faces);
    448:     break;
    449:   }
    450:   default:
    451:     SETERRQ1(comm, PETSC_ERR_SUP, "Dimension not supported: %d", dim);
    452:   }
    453:   DMPlexGenerate(boundary, NULL, interpolate, dm);
    454:   DMDestroy(&boundary);
    455:   return(0);
    456: }

    460: PetscErrorCode DMPlexCreateHexBoxMesh(MPI_Comm comm, PetscInt dim, const PetscInt cells[], DM *dm)
    461: {

    466:   DMCreate(comm, dm);
    468:   DMSetType(*dm, DMPLEX);
    469:   DMPlexSetDimension(*dm, dim);
    470:   switch (dim) {
    471:   case 2:
    472:   {
    473:     PetscReal lower[2] = {0.0, 0.0};
    474:     PetscReal upper[2] = {1.0, 1.0};

    476:     DMPlexCreateSquareMesh(*dm, lower, upper, cells);
    477:     break;
    478:   }
    479: #if 0
    480:   case 3:
    481:   {
    482:     PetscReal lower[3] = {0.0, 0.0, 0.0};
    483:     PetscReal upper[3] = {1.0, 1.0, 1.0};

    485:     DMPlexCreateCubeMesh(boundary, lower, upper, cells);
    486:     break;
    487:   }
    488: #endif
    489:   default:
    490:     SETERRQ1(comm, PETSC_ERR_SUP, "Dimension not supported: %d", dim);
    491:   }
    492:   return(0);
    493: }

    495: /* External function declarations here */
    496: extern PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling);
    497: extern PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J);
    498: extern PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm);
    499: extern PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined);
    500: extern PetscErrorCode DMSetUp_Plex(DM dm);
    501: extern PetscErrorCode DMDestroy_Plex(DM dm);
    502: extern PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer);
    503: extern PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm);
    504: extern PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS);

    508: static PetscErrorCode DMCreateGlobalVector_Plex(DM dm,Vec *vec)
    509: {

    513:   DMCreateGlobalVector_Section_Private(dm,vec);
    514:   /* VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM); */
    515:   VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex);
    516:   return(0);
    517: }

    521: static PetscErrorCode DMCreateLocalVector_Plex(DM dm,Vec *vec)
    522: {

    526:   DMCreateLocalVector_Section_Private(dm,vec);
    527:   VecSetOperation(*vec, VECOP_VIEW, (void(*)(void)) VecView_Plex_Local);
    528:   return(0);
    529: }

    534: PetscErrorCode DMInitialize_Plex(DM dm)
    535: {

    539:   PetscStrallocpy(VECSTANDARD, (char**)&dm->vectype);

    541:   dm->ops->view                            = DMView_Plex;
    542:   dm->ops->setfromoptions                  = DMSetFromOptions_Plex;
    543:   dm->ops->setup                           = DMSetUp_Plex;
    544:   dm->ops->createglobalvector              = DMCreateGlobalVector_Plex;
    545:   dm->ops->createlocalvector               = DMCreateLocalVector_Plex;
    546:   dm->ops->getlocaltoglobalmapping         = NULL;
    547:   dm->ops->getlocaltoglobalmappingblock    = NULL;
    548:   dm->ops->createfieldis                   = NULL;
    549:   dm->ops->createcoordinatedm              = DMCreateCoordinateDM_Plex;
    550:   dm->ops->getcoloring                     = 0;
    551:   dm->ops->creatematrix                    = DMCreateMatrix_Plex;
    552:   dm->ops->createinterpolation             = 0;
    553:   dm->ops->getaggregates                   = 0;
    554:   dm->ops->getinjection                    = 0;
    555:   dm->ops->refine                          = DMRefine_Plex;
    556:   dm->ops->coarsen                         = 0;
    557:   dm->ops->refinehierarchy                 = 0;
    558:   dm->ops->coarsenhierarchy                = 0;
    559:   dm->ops->globaltolocalbegin              = NULL;
    560:   dm->ops->globaltolocalend                = NULL;
    561:   dm->ops->localtoglobalbegin              = NULL;
    562:   dm->ops->localtoglobalend                = NULL;
    563:   dm->ops->destroy                         = DMDestroy_Plex;
    564:   dm->ops->createsubdm                     = DMCreateSubDM_Plex;
    565:   dm->ops->locatepoints                    = DMLocatePoints_Plex;
    566:   return(0);
    567: }

    569: /*MC
    570:   DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram.
    571:                     In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is
    572:                     specified by a PetscSection object. Ownership in the global representation is determined by
    573:                     ownership of the underlying DMPlex points. This is specified by another PetscSection object.

    575:   Level: intermediate

    577: .seealso: DMType, DMPlexCreate(), DMCreate(), DMSetType()
    578: M*/

    582: PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
    583: {
    584:   DM_Plex        *mesh;
    585:   PetscInt       unit, d;

    590:   PetscNewLog(dm, DM_Plex, &mesh);
    591:   dm->data = mesh;

    593:   mesh->refct             = 1;
    594:   mesh->dim               = 0;
    595:   PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection);
    596:   mesh->maxConeSize       = 0;
    597:   mesh->cones             = NULL;
    598:   mesh->coneOrientations  = NULL;
    599:   PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection);
    600:   mesh->maxSupportSize    = 0;
    601:   mesh->supports          = NULL;
    602:   mesh->refinementUniform = PETSC_TRUE;
    603:   mesh->refinementLimit   = -1.0;

    605:   mesh->facesTmp = NULL;

    607:   mesh->subpointMap = NULL;

    609:   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;

    611:   mesh->labels              = NULL;
    612:   mesh->globalVertexNumbers = NULL;
    613:   mesh->globalCellNumbers   = NULL;
    614:   for (d = 0; d < 8; ++d) mesh->hybridPointMax[d] = PETSC_DETERMINE;
    615:   mesh->vtkCellHeight     = 0;
    616:   mesh->preallocCenterDim = -1;

    618:   mesh->integrateResidualFEM       = NULL;
    619:   mesh->integrateJacobianActionFEM = NULL;
    620:   mesh->integrateJacobianFEM       = NULL;

    622:   mesh->printSetValues = PETSC_FALSE;
    623:   mesh->printFEM       = 0;

    625:   DMInitialize_Plex(dm);
    626:   return(0);
    627: }

    631: /*@
    632:   DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.

    634:   Collective on MPI_Comm

    636:   Input Parameter:
    637: . comm - The communicator for the DMPlex object

    639:   Output Parameter:
    640: . mesh  - The DMPlex object

    642:   Level: beginner

    644: .keywords: DMPlex, create
    645: @*/
    646: PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
    647: {

    652:   DMCreate(comm, mesh);
    653:   DMSetType(*mesh, DMPLEX);
    654:   return(0);
    655: }

    659: /*@
    660:   DMPlexClone - Creates a DMPlex object with the same mesh as the original.

    662:   Collective on MPI_Comm

    664:   Input Parameter:
    665: . dm - The original DMPlex object

    667:   Output Parameter:
    668: . newdm  - The new DMPlex object

    670:   Level: beginner

    672: .keywords: DMPlex, create
    673: @*/
    674: PetscErrorCode DMPlexClone(DM dm, DM *newdm)
    675: {
    676:   DM_Plex        *mesh;
    677:   Vec             coords;
    678:   void           *ctx;

    684:   DMCreate(PetscObjectComm((PetscObject)dm), newdm);
    685:   PetscSFDestroy(&(*newdm)->sf);
    686:   PetscObjectReference((PetscObject) dm->sf);
    687:   (*newdm)->sf = dm->sf;
    688:   mesh         = (DM_Plex*) dm->data;
    689:   mesh->refct++;
    690:   (*newdm)->data = mesh;
    691:   PetscObjectChangeTypeName((PetscObject) *newdm, DMPLEX);
    692:   DMInitialize_Plex(*newdm);
    693:   DMGetApplicationContext(dm, &ctx);
    694:   DMSetApplicationContext(*newdm, ctx);
    695:   DMGetCoordinatesLocal(dm, &coords);
    696:   if (coords) {
    697:     DMSetCoordinatesLocal(*newdm, coords);
    698:   } else {
    699:     DMGetCoordinates(dm, &coords);
    700:     if (coords) {DMSetCoordinates(*newdm, coords);}
    701:   }
    702:   return(0);
    703: }

    707: /*
    708:   This takes as input the common mesh generator output, a list of the vertices for each cell
    709: */
    710: PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[])
    711: {
    712:   PetscInt      *cone, c, p;

    716:   DMPlexSetChart(dm, 0, numCells+numVertices);
    717:   for (c = 0; c < numCells; ++c) {
    718:     DMPlexSetConeSize(dm, c, numCorners);
    719:   }
    720:   DMSetUp(dm);
    721:   DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);
    722:   for (c = 0; c < numCells; ++c) {
    723:     for (p = 0; p < numCorners; ++p) {
    724:       cone[p] = cells[c*numCorners+p]+numCells;
    725:     }
    726:     DMPlexSetCone(dm, c, cone);
    727:   }
    728:   DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);
    729:   DMPlexSymmetrize(dm);
    730:   DMPlexStratify(dm);
    731:   return(0);
    732: }

    736: /*
    737:   This takes as input the coordinates for each vertex
    738: */
    739: PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[])
    740: {
    741:   PetscSection   coordSection;
    742:   Vec            coordinates;
    743:   PetscScalar   *coords;
    744:   PetscInt       coordSize, v, d;

    748:   DMPlexGetCoordinateSection(dm, &coordSection);
    749:   PetscSectionSetNumFields(coordSection, 1);
    750:   PetscSectionSetFieldComponents(coordSection, 0, spaceDim);
    751:   PetscSectionSetChart(coordSection, numCells, numCells + numVertices);
    752:   for (v = numCells; v < numCells+numVertices; ++v) {
    753:     PetscSectionSetDof(coordSection, v, spaceDim);
    754:     PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);
    755:   }
    756:   PetscSectionSetUp(coordSection);
    757:   PetscSectionGetStorageSize(coordSection, &coordSize);
    758:   VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);
    759:   PetscObjectSetName((PetscObject) coordinates, "coordinates");
    760:   VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);
    761:   VecSetFromOptions(coordinates);
    762:   VecGetArray(coordinates, &coords);
    763:   for (v = 0; v < numVertices; ++v) {
    764:     for (d = 0; d < spaceDim; ++d) {
    765:       coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d];
    766:     }
    767:   }
    768:   VecRestoreArray(coordinates, &coords);
    769:   DMSetCoordinatesLocal(dm, coordinates);
    770:   VecDestroy(&coordinates);
    771:   return(0);
    772: }

    776: /*@C
    777:   DMPlexCreateFromCellList - This takes as input common mesh generator output, a list of the vertices for each cell, and produces a DM

    779:   Input Parameters:
    780: + comm - The communicator
    781: . dim - The topological dimension of the mesh
    782: . numCells - The number of cells
    783: . numVertices - The number of vertices
    784: . numCorners - The number of vertices for each cell
    785: . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
    786: . cells - An array of numCells*numCorners numbers, the vertices for each cell
    787: . spaceDim - The spatial dimension used for coordinates
    788: - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex

    790:   Output Parameter:
    791: . dm - The DM

    793:   Note: Two triangles sharing a face
    794: $
    795: $        2
    796: $      / | \
    797: $     /  |  \
    798: $    /   |   \
    799: $   0  0 | 1  3
    800: $    \   |   /
    801: $     \  |  /
    802: $      \ | /
    803: $        1
    804: would have input
    805: $  numCells = 2, numVertices = 4
    806: $  cells = [0 1 2  1 3 2]
    807: $
    808: which would result in the DMPlex
    809: $
    810: $        4
    811: $      / | \
    812: $     /  |  \
    813: $    /   |   \
    814: $   2  0 | 1  5
    815: $    \   |   /
    816: $     \  |  /
    817: $      \ | /
    818: $        3

    820:   Level: beginner

    822: .seealso: DMPlexCreate()
    823: @*/
    824: PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], PetscInt spaceDim, const double vertexCoords[], DM *dm)
    825: {

    829:   DMCreate(comm, dm);
    830:   DMSetType(*dm, DMPLEX);
    831:   DMPlexSetDimension(*dm, dim);
    832:   DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);
    833:   if (interpolate) {
    834:     DM idm;

    836:     DMPlexInterpolate(*dm, &idm);
    837:     DMDestroy(dm);
    838:     *dm  = idm;
    839:   }
    840:   DMPlexBuildCoordinates_Private(*dm, spaceDim, numCells, numVertices, vertexCoords);
    841:   return(0);
    842: }

    846: /*
    847:   This takes as input the raw Hasse Diagram data
    848: */
    849: PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
    850: {
    851:   Vec            coordinates;
    852:   PetscSection   coordSection;
    853:   PetscScalar    *coords;
    854:   PetscInt       coordSize, firstVertex = numPoints[depth], pStart = 0, pEnd = 0, p, v, dim, d, off;

    858:   DMPlexGetDimension(dm, &dim);
    859:   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
    860:   DMPlexSetChart(dm, pStart, pEnd);
    861:   for (p = pStart; p < pEnd; ++p) {
    862:     DMPlexSetConeSize(dm, p, coneSize[p-pStart]);
    863:   }
    864:   DMSetUp(dm); /* Allocate space for cones */
    865:   for (p = pStart, off = 0; p < pEnd; off += coneSize[p-pStart], ++p) {
    866:     DMPlexSetCone(dm, p, &cones[off]);
    867:     DMPlexSetConeOrientation(dm, p, &coneOrientations[off]);
    868:   }
    869:   DMPlexSymmetrize(dm);
    870:   DMPlexStratify(dm);
    871:   /* Build coordinates */
    872:   DMPlexGetCoordinateSection(dm, &coordSection);
    873:   PetscSectionSetNumFields(coordSection, 1);
    874:   PetscSectionSetFieldComponents(coordSection, 0, dim);
    875:   PetscSectionSetChart(coordSection, firstVertex, firstVertex+numPoints[0]);
    876:   for (v = firstVertex; v < firstVertex+numPoints[0]; ++v) {
    877:     PetscSectionSetDof(coordSection, v, dim);
    878:     PetscSectionSetFieldDof(coordSection, v, 0, dim);
    879:   }
    880:   PetscSectionSetUp(coordSection);
    881:   PetscSectionGetStorageSize(coordSection, &coordSize);
    882:   VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);
    883:   PetscObjectSetName((PetscObject) coordinates, "coordinates");
    884:   VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);
    885:   VecSetFromOptions(coordinates);
    886:   VecGetArray(coordinates, &coords);
    887:   for (v = 0; v < numPoints[0]; ++v) {
    888:     PetscInt off;

    890:     PetscSectionGetOffset(coordSection, v+firstVertex, &off);
    891:     for (d = 0; d < dim; ++d) {
    892:       coords[off+d] = vertexCoords[v*dim+d];
    893:     }
    894:   }
    895:   VecRestoreArray(coordinates, &coords);
    896:   DMSetCoordinatesLocal(dm, coordinates);
    897:   VecDestroy(&coordinates);
    898:   return(0);
    899: }