xref: /petsc/src/dm/impls/plex/tutorials/ex10.c (revision b122ec5aa1bd4469eb4e0673542fb7de3f411254)
1adcf2cb4SMatthew G. Knepley static char help[] = "TDycore Mesh Examples\n\n";
2adcf2cb4SMatthew G. Knepley 
3adcf2cb4SMatthew G. Knepley #include <petscdmplex.h>
4adcf2cb4SMatthew G. Knepley 
5adcf2cb4SMatthew G. Knepley typedef struct {
6adcf2cb4SMatthew G. Knepley   PetscBool adapt; /* Flag for adaptation of the surface mesh */
7adcf2cb4SMatthew G. Knepley } AppCtx;
8adcf2cb4SMatthew G. Knepley 
9adcf2cb4SMatthew G. Knepley static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
10adcf2cb4SMatthew G. Knepley {
11adcf2cb4SMatthew G. Knepley   PetscErrorCode ierr;
12adcf2cb4SMatthew G. Knepley 
13adcf2cb4SMatthew G. Knepley   PetscFunctionBeginUser;
14adcf2cb4SMatthew G. Knepley   options->adapt = PETSC_FALSE;
15adcf2cb4SMatthew G. Knepley 
16adcf2cb4SMatthew G. Knepley   ierr = PetscOptionsBegin(comm, "", "Meshing Interpolation Test Options", "DMPLEX");CHKERRQ(ierr);
175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-adapt", "Flag for adaptation of the surface mesh", "ex10.c", options->adapt, &options->adapt, NULL));
181e1ea65dSPierre Jolivet   ierr = PetscOptionsEnd();CHKERRQ(ierr);
19adcf2cb4SMatthew G. Knepley   PetscFunctionReturn(0);
20adcf2cb4SMatthew G. Knepley }
21adcf2cb4SMatthew G. Knepley 
22adcf2cb4SMatthew G. Knepley static PetscErrorCode CreateDomainLabel(DM dm)
23adcf2cb4SMatthew G. Knepley {
24adcf2cb4SMatthew G. Knepley   DMLabel        label;
25adcf2cb4SMatthew G. Knepley   PetscInt       cStart, cEnd, c;
26adcf2cb4SMatthew G. Knepley 
27adcf2cb4SMatthew G. Knepley   PetscFunctionBeginUser;
285f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(dm, "Cell Sets"));
295f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLabel(dm, "Cell Sets", &label));
305f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
31adcf2cb4SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
32adcf2cb4SMatthew G. Knepley     PetscReal centroid[3], volume, x, y;
33adcf2cb4SMatthew G. Knepley 
345f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexComputeCellGeometryFVM(dm, c, &volume, centroid, NULL));
35adcf2cb4SMatthew G. Knepley     x = centroid[0]; y = centroid[1];
36adcf2cb4SMatthew G. Knepley     /* Headwaters are (0.0,0.25)--(0.1,0.75) */
375f80ce2aSJacob Faibussowitsch     if ((x >= 0.0 && x <  0.1) && (y >= 0.25 && y <= 0.75)) {CHKERRQ(DMLabelSetValue(label, c, 1));continue;}
38adcf2cb4SMatthew G. Knepley     /* River channel is (0.1,0.45)--(1.0,0.55) */
395f80ce2aSJacob Faibussowitsch     if ((x >= 0.1 && x <= 1.0) && (y >= 0.45 && y <= 0.55)) {CHKERRQ(DMLabelSetValue(label, c, 2));continue;}
40adcf2cb4SMatthew G. Knepley   }
41adcf2cb4SMatthew G. Knepley   PetscFunctionReturn(0);
42adcf2cb4SMatthew G. Knepley }
43adcf2cb4SMatthew G. Knepley 
44adcf2cb4SMatthew G. Knepley static PetscErrorCode AdaptMesh(DM *dm, AppCtx *ctx)
45adcf2cb4SMatthew G. Knepley {
46adcf2cb4SMatthew G. Knepley   DM              dmCur = *dm;
47adcf2cb4SMatthew G. Knepley   DMLabel         label;
48adcf2cb4SMatthew G. Knepley   IS              valueIS, vIS;
49adcf2cb4SMatthew G. Knepley   PetscBool       hasLabel;
50adcf2cb4SMatthew G. Knepley   const PetscInt *values;
51adcf2cb4SMatthew G. Knepley   PetscReal      *volConst; /* Volume constraints for each label value */
52adcf2cb4SMatthew G. Knepley   PetscReal       ratio;
53adcf2cb4SMatthew G. Knepley   PetscInt        dim, Nv, v, cStart, cEnd, c;
54adcf2cb4SMatthew G. Knepley   PetscBool       adapt = PETSC_TRUE;
55adcf2cb4SMatthew G. Knepley 
56adcf2cb4SMatthew G. Knepley   PetscFunctionBeginUser;
57adcf2cb4SMatthew G. Knepley   if (!ctx->adapt) PetscFunctionReturn(0);
585f80ce2aSJacob Faibussowitsch   CHKERRQ(DMHasLabel(*dm, "Cell Sets", &hasLabel));
595f80ce2aSJacob Faibussowitsch   if (!hasLabel) CHKERRQ(CreateDomainLabel(*dm));
605f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(*dm, &dim));
61adcf2cb4SMatthew G. Knepley   ratio = PetscPowRealInt(0.5, dim);
62adcf2cb4SMatthew G. Knepley   /* Get volume constraints */
635f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLabel(*dm, "Cell Sets", &label));
645f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetValueIS(label, &vIS));
655f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDuplicate(vIS, &valueIS));
665f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&vIS));
67adcf2cb4SMatthew G. Knepley   /* Sorting ruins the label */
685f80ce2aSJacob Faibussowitsch   CHKERRQ(ISSort(valueIS));
695f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetLocalSize(valueIS, &Nv));
705f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(valueIS, &values));
715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(Nv, &volConst));
72adcf2cb4SMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
73adcf2cb4SMatthew G. Knepley     char opt[128];
74adcf2cb4SMatthew G. Knepley 
75adcf2cb4SMatthew G. Knepley     volConst[v] = PETSC_MAX_REAL;
765f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(opt, 128, "-volume_constraint_%d", (int) values[v]));
775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsGetReal(NULL, NULL, opt, &volConst[v], NULL));
78adcf2cb4SMatthew G. Knepley   }
795f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(valueIS, &values));
805f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&valueIS));
81adcf2cb4SMatthew G. Knepley   /* Adapt mesh iteratively */
82adcf2cb4SMatthew G. Knepley   while (adapt) {
83adcf2cb4SMatthew G. Knepley     DM       dmAdapt;
84adcf2cb4SMatthew G. Knepley     DMLabel  adaptLabel;
85adcf2cb4SMatthew G. Knepley     PetscInt nAdaptLoc[2], nAdapt[2];
86adcf2cb4SMatthew G. Knepley 
87adcf2cb4SMatthew G. Knepley     adapt = PETSC_FALSE;
88adcf2cb4SMatthew G. Knepley     nAdaptLoc[0] = nAdaptLoc[1] = 0;
89adcf2cb4SMatthew G. Knepley     nAdapt[0]    = nAdapt[1]    = 0;
90adcf2cb4SMatthew G. Knepley     /* Adaptation is not preserving the domain label */
915f80ce2aSJacob Faibussowitsch     CHKERRQ(DMHasLabel(dmCur, "Cell Sets", &hasLabel));
925f80ce2aSJacob Faibussowitsch     if (!hasLabel) CHKERRQ(CreateDomainLabel(dmCur));
935f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLabel(dmCur, "Cell Sets", &label));
945f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetValueIS(label, &vIS));
955f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDuplicate(vIS, &valueIS));
965f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&vIS));
97adcf2cb4SMatthew G. Knepley     /* Sorting directly the label's value IS would corrupt the label so we duplicate the IS first */
985f80ce2aSJacob Faibussowitsch     CHKERRQ(ISSort(valueIS));
995f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(valueIS, &Nv));
1005f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(valueIS, &values));
101adcf2cb4SMatthew G. Knepley     /* Construct adaptation label */
1025f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, "adapt", &adaptLabel));
1035f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetHeightStratum(dmCur, 0, &cStart, &cEnd));
104adcf2cb4SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
105adcf2cb4SMatthew G. Knepley       PetscReal volume, centroid[3];
106adcf2cb4SMatthew G. Knepley       PetscInt  value, vidx;
107adcf2cb4SMatthew G. Knepley 
1085f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexComputeCellGeometryFVM(dmCur, c, &volume, centroid, NULL));
1095f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetValue(label, c, &value));
110adcf2cb4SMatthew G. Knepley       if (value < 0) continue;
1115f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFindInt(value, Nv, values, &vidx));
1122c71b3e2SJacob Faibussowitsch       PetscCheckFalse(vidx < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Value %D for cell %D does not exist in label", value, c);
1135f80ce2aSJacob Faibussowitsch       if (volume > volConst[vidx])        {CHKERRQ(DMLabelSetValue(adaptLabel, c, DM_ADAPT_REFINE));  ++nAdaptLoc[0];}
1145f80ce2aSJacob Faibussowitsch       if (volume < volConst[vidx]*ratio) {CHKERRQ(DMLabelSetValue(adaptLabel, c, DM_ADAPT_COARSEN)); ++nAdaptLoc[1];}
115adcf2cb4SMatthew G. Knepley     }
1165f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(valueIS, &values));
1175f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&valueIS));
1185f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Allreduce(&nAdaptLoc, &nAdapt, 2, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dmCur)));
119adcf2cb4SMatthew G. Knepley     if (nAdapt[0]) {
1205f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscInfo(dmCur, "Adapted mesh, marking %D cells for refinement, and %D cells for coarsening\n", nAdapt[0], nAdapt[1]));
1215f80ce2aSJacob Faibussowitsch       CHKERRQ(DMAdaptLabel(dmCur, adaptLabel, &dmAdapt));
1225f80ce2aSJacob Faibussowitsch       CHKERRQ(DMDestroy(&dmCur));
1235f80ce2aSJacob Faibussowitsch       CHKERRQ(DMViewFromOptions(dmAdapt, NULL, "-adapt_dm_view"));
124adcf2cb4SMatthew G. Knepley       dmCur = dmAdapt;
125adcf2cb4SMatthew G. Knepley       adapt = PETSC_TRUE;
126adcf2cb4SMatthew G. Knepley     }
1275f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelDestroy(&adaptLabel));
128adcf2cb4SMatthew G. Knepley   }
1295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(volConst));
130adcf2cb4SMatthew G. Knepley   *dm = dmCur;
131adcf2cb4SMatthew G. Knepley   PetscFunctionReturn(0);
132adcf2cb4SMatthew G. Knepley }
133adcf2cb4SMatthew G. Knepley 
134adcf2cb4SMatthew G. Knepley static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm)
135adcf2cb4SMatthew G. Knepley {
136adcf2cb4SMatthew G. Knepley   PetscInt       dim;
137adcf2cb4SMatthew G. Knepley 
138adcf2cb4SMatthew G. Knepley   PetscFunctionBeginUser;
139adcf2cb4SMatthew G. Knepley   /* Create top surface */
1405f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
1415f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
1425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) *dm, "init_"));
1435f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetFromOptions(*dm));
1445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) *dm, NULL));
145adcf2cb4SMatthew G. Knepley   /* Adapt surface */
1465f80ce2aSJacob Faibussowitsch   CHKERRQ(AdaptMesh(dm, user));
147adcf2cb4SMatthew G. Knepley   /* Extrude surface to get volume mesh */
1485f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(*dm, &dim));
1495f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLocalizeCoordinates(*dm));
1505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *dm, "Mesh"));
1515f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetFromOptions(*dm));
1525f80ce2aSJacob Faibussowitsch   CHKERRQ(DMViewFromOptions(*dm, NULL, "-dm_view"));
153adcf2cb4SMatthew G. Knepley   PetscFunctionReturn(0);
154adcf2cb4SMatthew G. Knepley }
155adcf2cb4SMatthew G. Knepley 
156adcf2cb4SMatthew G. Knepley int main(int argc, char **argv)
157adcf2cb4SMatthew G. Knepley {
158adcf2cb4SMatthew G. Knepley   DM             dm;
159adcf2cb4SMatthew G. Knepley   AppCtx         user;
160adcf2cb4SMatthew G. Knepley 
161*b122ec5aSJacob Faibussowitsch   CHKERRQ(PetscInitialize(&argc, &argv, NULL, help));
1625f80ce2aSJacob Faibussowitsch   CHKERRQ(ProcessOptions(PETSC_COMM_WORLD, &user));
1635f80ce2aSJacob Faibussowitsch   CHKERRQ(CreateMesh(PETSC_COMM_WORLD, &user, &dm));
1645f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&dm));
165*b122ec5aSJacob Faibussowitsch   CHKERRQ(PetscFinalize());
166*b122ec5aSJacob Faibussowitsch   return 0;
167adcf2cb4SMatthew G. Knepley }
168adcf2cb4SMatthew G. Knepley 
169adcf2cb4SMatthew G. Knepley /*TEST
170adcf2cb4SMatthew G. Knepley 
171adcf2cb4SMatthew G. Knepley   test:
172adcf2cb4SMatthew G. Knepley     suffix: 0
173adcf2cb4SMatthew G. Knepley     requires: triangle
174d410b0cfSMatthew G. Knepley     args: -init_dm_plex_dim 2 -init_dm_plex_box_faces 1,1 -dm_extrude 1 -dm_view
175adcf2cb4SMatthew G. Knepley 
176adcf2cb4SMatthew G. Knepley   test: # Regularly refine the surface before extrusion
177adcf2cb4SMatthew G. Knepley     suffix: 1
178adcf2cb4SMatthew G. Knepley     requires: triangle
179d410b0cfSMatthew G. Knepley     args: -init_dm_plex_dim 2 -init_dm_refine 2 -dm_extrude 1 -dm_view
180adcf2cb4SMatthew G. Knepley 
181adcf2cb4SMatthew G. Knepley   test: # Parallel run
182adcf2cb4SMatthew G. Knepley     suffix: 2
183adcf2cb4SMatthew G. Knepley     requires: triangle
184adcf2cb4SMatthew G. Knepley     nsize: 5
185e600fa54SMatthew G. Knepley     args: -init_dm_plex_dim 2 -init_dm_refine 3 -petscpartitioner_type simple -dm_extrude 3 -dm_view
186adcf2cb4SMatthew G. Knepley 
187adcf2cb4SMatthew G. Knepley   test: # adaptively refine the surface before extrusion
188adcf2cb4SMatthew G. Knepley     suffix: 3
189adcf2cb4SMatthew G. Knepley     requires: triangle
190d410b0cfSMatthew G. Knepley     args: -init_dm_plex_dim 2 -init_dm_plex_box_faces 5,5 -adapt -volume_constraint_1 0.01 -volume_constraint_2 0.000625 -dm_extrude 10
191adcf2cb4SMatthew G. Knepley 
192adcf2cb4SMatthew G. Knepley TEST*/
193