Actual source code: plexgenerate.c

      1: #include <petsc/private/dmpleximpl.h>

      3: /*@
      4:   DMPlexInvertCell - Flips cell orientations since `DMPLEX` stores some of them internally with outward normals.

      6:   Input Parameters:
      7: + cellType - The cell type
      8: - cone     - The incoming cone

     10:   Output Parameter:
     11: . cone - The inverted cone (in-place)

     13:   Level: developer

     15: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGenerate()`
     16: @*/
     17: PetscErrorCode DMPlexInvertCell(DMPolytopeType cellType, PetscInt cone[])
     18: {
     19: #define SWAPCONE(cone, i, j) \
     20:   do { \
     21:     PetscInt _cone_tmp; \
     22:     _cone_tmp = (cone)[i]; \
     23:     (cone)[i] = (cone)[j]; \
     24:     (cone)[j] = _cone_tmp; \
     25:   } while (0)

     27:   PetscFunctionBegin;
     28:   switch (cellType) {
     29:   case DM_POLYTOPE_POINT:
     30:     break;
     31:   case DM_POLYTOPE_SEGMENT:
     32:     break;
     33:   case DM_POLYTOPE_POINT_PRISM_TENSOR:
     34:     break;
     35:   case DM_POLYTOPE_TRIANGLE:
     36:     break;
     37:   case DM_POLYTOPE_QUADRILATERAL:
     38:     break;
     39:   case DM_POLYTOPE_SEG_PRISM_TENSOR:
     40:     SWAPCONE(cone, 2, 3);
     41:     break;
     42:   case DM_POLYTOPE_TETRAHEDRON:
     43:     SWAPCONE(cone, 0, 1);
     44:     break;
     45:   case DM_POLYTOPE_HEXAHEDRON:
     46:     SWAPCONE(cone, 1, 3);
     47:     break;
     48:   case DM_POLYTOPE_TRI_PRISM:
     49:     SWAPCONE(cone, 1, 2);
     50:     break;
     51:   case DM_POLYTOPE_TRI_PRISM_TENSOR:
     52:     break;
     53:   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
     54:     break;
     55:   case DM_POLYTOPE_PYRAMID:
     56:     SWAPCONE(cone, 1, 3);
     57:     break;
     58:   default:
     59:     break;
     60:   }
     61:   PetscFunctionReturn(PETSC_SUCCESS);
     62: #undef SWAPCONE
     63: }

     65: /*@
     66:   DMPlexReorderCell - Flips cell orientations since `DMPLEX` stores some of them internally with outward normals.

     68:   Input Parameters:
     69: + dm   - The `DMPLEX` object
     70: . cell - The cell
     71: - cone - The incoming cone

     73:   Output Parameter:
     74: . cone - The reordered cone (in-place)

     76:   Level: developer

     78: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGenerate()`
     79: @*/
     80: PetscErrorCode DMPlexReorderCell(DM dm, PetscInt cell, PetscInt cone[])
     81: {
     82:   DMPolytopeType cellType;

     84:   PetscFunctionBegin;
     85:   PetscCall(DMPlexGetCellType(dm, cell, &cellType));
     86:   PetscCall(DMPlexInvertCell(cellType, cone));
     87:   PetscFunctionReturn(PETSC_SUCCESS);
     88: }

     90: /*@C
     91:   DMPlexTriangleSetOptions - Set the options used for the Triangle mesh generator

     93:   Not Collective

     95:   Input Parameters:
     96: + dm   - The `DMPLEX` object
     97: - opts - The command line options

     99:   Level: developer

    101: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTetgenSetOptions()`, `DMPlexGenerate()`
    102: @*/
    103: PetscErrorCode DMPlexTriangleSetOptions(DM dm, const char *opts)
    104: {
    105:   DM_Plex *mesh = (DM_Plex *)dm->data;

    107:   PetscFunctionBegin;
    109:   PetscAssertPointer(opts, 2);
    110:   PetscCall(PetscFree(mesh->triangleOpts));
    111:   PetscCall(PetscStrallocpy(opts, &mesh->triangleOpts));
    112:   PetscFunctionReturn(PETSC_SUCCESS);
    113: }

    115: /*@C
    116:   DMPlexTetgenSetOptions - Set the options used for the Tetgen mesh generator

    118:   Not Collective

    120:   Input Parameters:
    121: + dm   - The `DMPLEX` object
    122: - opts - The command line options

    124:   Level: developer

    126: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTriangleSetOptions()`, `DMPlexGenerate()`
    127: @*/
    128: PetscErrorCode DMPlexTetgenSetOptions(DM dm, const char *opts)
    129: {
    130:   DM_Plex *mesh = (DM_Plex *)dm->data;

    132:   PetscFunctionBegin;
    134:   PetscAssertPointer(opts, 2);
    135:   PetscCall(PetscFree(mesh->tetgenOpts));
    136:   PetscCall(PetscStrallocpy(opts, &mesh->tetgenOpts));
    137:   PetscFunctionReturn(PETSC_SUCCESS);
    138: }

    140: /*@
    141:   DMPlexGenerate - Generates a mesh.

    143:   Not Collective

    145:   Input Parameters:
    146: + boundary    - The `DMPLEX` boundary object
    147: . name        - The mesh generation package name
    148: - interpolate - Flag to create intermediate mesh elements

    150:   Output Parameter:
    151: . mesh - The `DMPLEX` object

    153:   Options Database Keys:
    154: + -dm_plex_generate <name> - package to generate mesh, for example, triangle, ctetgen or tetgen
    155: - -dm_generator <name>     - package to generate mesh, for example, triangle, ctetgen or tetgen

    157:   Level: intermediate

    159: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMRefine()`
    160: @*/
    161: PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh)
    162: {
    163:   DMGeneratorFunctionList fl;
    164:   char                    genname[PETSC_MAX_PATH_LEN];
    165:   const char             *suggestions;
    166:   PetscInt                dim;
    167:   PetscBool               flg;

    169:   PetscFunctionBegin;
    172:   PetscCall(DMGetDimension(boundary, &dim));
    173:   PetscCall(PetscOptionsGetString(((PetscObject)boundary)->options, ((PetscObject)boundary)->prefix, "-dm_generator", genname, sizeof(genname), &flg));
    174:   if (flg) name = genname;
    175:   else {
    176:     PetscCall(PetscOptionsGetString(((PetscObject)boundary)->options, ((PetscObject)boundary)->prefix, "-dm_plex_generate", genname, sizeof(genname), &flg));
    177:     if (flg) name = genname;
    178:   }

    180:   fl = DMGenerateList;
    181:   if (name) {
    182:     while (fl) {
    183:       PetscCall(PetscStrcmp(fl->name, name, &flg));
    184:       if (flg) {
    185:         PetscCall((*fl->generate)(boundary, interpolate, mesh));
    186:         PetscFunctionReturn(PETSC_SUCCESS);
    187:       }
    188:       fl = fl->next;
    189:     }
    190:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Grid generator %s not registered; you may need to add --download-%s to your ./configure options", name, name);
    191:   } else {
    192:     while (fl) {
    193:       if (boundary->dim == fl->dim) {
    194:         PetscCall((*fl->generate)(boundary, interpolate, mesh));
    195:         PetscFunctionReturn(PETSC_SUCCESS);
    196:       }
    197:       fl = fl->next;
    198:     }
    199:     suggestions = "";
    200:     if (boundary->dim + 1 == 2) suggestions = " You may need to add --download-triangle to your ./configure options";
    201:     else if (boundary->dim + 1 == 3) suggestions = " You may need to add --download-ctetgen or --download-tetgen in your ./configure options";
    202:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No grid generator of dimension %" PetscInt_FMT " registered%s", boundary->dim + 1, suggestions);
    203:   }
    204: }