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 PetscBool extrude; /* Flag for extrusion of the suraace mesh */ 8adcf2cb4SMatthew G. Knepley } AppCtx; 9adcf2cb4SMatthew G. Knepley 10adcf2cb4SMatthew G. Knepley static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options) 11adcf2cb4SMatthew G. Knepley { 12adcf2cb4SMatthew G. Knepley PetscErrorCode ierr; 13adcf2cb4SMatthew G. Knepley 14adcf2cb4SMatthew G. Knepley PetscFunctionBeginUser; 15adcf2cb4SMatthew G. Knepley options->adapt = PETSC_FALSE; 16adcf2cb4SMatthew G. Knepley options->extrude = PETSC_TRUE; 17adcf2cb4SMatthew G. Knepley 18adcf2cb4SMatthew G. Knepley ierr = PetscOptionsBegin(comm, "", "Meshing Interpolation Test Options", "DMPLEX");CHKERRQ(ierr); 19adcf2cb4SMatthew G. Knepley ierr = PetscOptionsBool("-adapt", "Flag for adaptation of the surface mesh", "ex10.c", options->adapt, &options->adapt, NULL);CHKERRQ(ierr); 20adcf2cb4SMatthew G. Knepley ierr = PetscOptionsBool("-extrude", "Flag for extrusion of the surface mesh", "ex10.c", options->extrude, &options->extrude, NULL);CHKERRQ(ierr); 21*1e1ea65dSPierre Jolivet ierr = PetscOptionsEnd();CHKERRQ(ierr); 22adcf2cb4SMatthew G. Knepley PetscFunctionReturn(0); 23adcf2cb4SMatthew G. Knepley } 24adcf2cb4SMatthew G. Knepley 25adcf2cb4SMatthew G. Knepley static PetscErrorCode CreateDomainLabel(DM dm) 26adcf2cb4SMatthew G. Knepley { 27adcf2cb4SMatthew G. Knepley DMLabel label; 28adcf2cb4SMatthew G. Knepley PetscInt cStart, cEnd, c; 29adcf2cb4SMatthew G. Knepley PetscErrorCode ierr; 30adcf2cb4SMatthew G. Knepley 31adcf2cb4SMatthew G. Knepley PetscFunctionBeginUser; 32adcf2cb4SMatthew G. Knepley ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr); 33adcf2cb4SMatthew G. Knepley ierr = DMGetLabel(dm, "Cell Sets", &label);CHKERRQ(ierr); 34adcf2cb4SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 35adcf2cb4SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 36adcf2cb4SMatthew G. Knepley PetscReal centroid[3], volume, x, y; 37adcf2cb4SMatthew G. Knepley 38adcf2cb4SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFVM(dm, c, &volume, centroid, NULL);CHKERRQ(ierr); 39adcf2cb4SMatthew G. Knepley x = centroid[0]; y = centroid[1]; 40adcf2cb4SMatthew G. Knepley /* Headwaters are (0.0,0.25)--(0.1,0.75) */ 41adcf2cb4SMatthew G. Knepley if ((x >= 0.0 && x < 0.1) && (y >= 0.25 && y <= 0.75)) {ierr = DMLabelSetValue(label, c, 1);CHKERRQ(ierr);continue;} 42adcf2cb4SMatthew G. Knepley /* River channel is (0.1,0.45)--(1.0,0.55) */ 43adcf2cb4SMatthew G. Knepley if ((x >= 0.1 && x <= 1.0) && (y >= 0.45 && y <= 0.55)) {ierr = DMLabelSetValue(label, c, 2);CHKERRQ(ierr);continue;} 44adcf2cb4SMatthew G. Knepley } 45adcf2cb4SMatthew G. Knepley PetscFunctionReturn(0); 46adcf2cb4SMatthew G. Knepley } 47adcf2cb4SMatthew G. Knepley 48adcf2cb4SMatthew G. Knepley static PetscErrorCode AdaptMesh(DM *dm, AppCtx *ctx) 49adcf2cb4SMatthew G. Knepley { 50adcf2cb4SMatthew G. Knepley DM dmCur = *dm; 51adcf2cb4SMatthew G. Knepley DMLabel label; 52adcf2cb4SMatthew G. Knepley IS valueIS, vIS; 53adcf2cb4SMatthew G. Knepley PetscBool hasLabel; 54adcf2cb4SMatthew G. Knepley const PetscInt *values; 55adcf2cb4SMatthew G. Knepley PetscReal *volConst; /* Volume constraints for each label value */ 56adcf2cb4SMatthew G. Knepley PetscReal ratio; 57adcf2cb4SMatthew G. Knepley PetscInt dim, Nv, v, cStart, cEnd, c; 58adcf2cb4SMatthew G. Knepley PetscBool adapt = PETSC_TRUE; 59adcf2cb4SMatthew G. Knepley PetscErrorCode ierr; 60adcf2cb4SMatthew G. Knepley 61adcf2cb4SMatthew G. Knepley PetscFunctionBeginUser; 62adcf2cb4SMatthew G. Knepley if (!ctx->adapt) PetscFunctionReturn(0); 63adcf2cb4SMatthew G. Knepley ierr = DMHasLabel(*dm, "Cell Sets", &hasLabel);CHKERRQ(ierr); 64adcf2cb4SMatthew G. Knepley if (!hasLabel) {ierr = CreateDomainLabel(*dm);CHKERRQ(ierr);} 65adcf2cb4SMatthew G. Knepley ierr = DMGetDimension(*dm, &dim);CHKERRQ(ierr); 66adcf2cb4SMatthew G. Knepley ratio = PetscPowRealInt(0.5, dim); 67adcf2cb4SMatthew G. Knepley /* Get volume constraints */ 68adcf2cb4SMatthew G. Knepley ierr = DMGetLabel(*dm, "Cell Sets", &label);CHKERRQ(ierr); 69adcf2cb4SMatthew G. Knepley ierr = DMLabelGetValueIS(label, &vIS);CHKERRQ(ierr); 70adcf2cb4SMatthew G. Knepley ierr = ISDuplicate(vIS, &valueIS);CHKERRQ(ierr); 71adcf2cb4SMatthew G. Knepley ierr = ISDestroy(&vIS);CHKERRQ(ierr); 72adcf2cb4SMatthew G. Knepley /* Sorting ruins the label */ 73adcf2cb4SMatthew G. Knepley ierr = ISSort(valueIS);CHKERRQ(ierr); 74adcf2cb4SMatthew G. Knepley ierr = ISGetLocalSize(valueIS, &Nv);CHKERRQ(ierr); 75adcf2cb4SMatthew G. Knepley ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 76adcf2cb4SMatthew G. Knepley ierr = PetscMalloc1(Nv, &volConst);CHKERRQ(ierr); 77adcf2cb4SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 78adcf2cb4SMatthew G. Knepley char opt[128]; 79adcf2cb4SMatthew G. Knepley 80adcf2cb4SMatthew G. Knepley volConst[v] = PETSC_MAX_REAL; 81adcf2cb4SMatthew G. Knepley ierr = PetscSNPrintf(opt, 128, "-volume_constraint_%d", (int) values[v]);CHKERRQ(ierr); 82adcf2cb4SMatthew G. Knepley ierr = PetscOptionsGetReal(NULL, NULL, opt, &volConst[v], NULL);CHKERRQ(ierr); 83adcf2cb4SMatthew G. Knepley } 84adcf2cb4SMatthew G. Knepley ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 85adcf2cb4SMatthew G. Knepley ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 86adcf2cb4SMatthew G. Knepley /* Adapt mesh iteratively */ 87adcf2cb4SMatthew G. Knepley while (adapt) { 88adcf2cb4SMatthew G. Knepley DM dmAdapt; 89adcf2cb4SMatthew G. Knepley DMLabel adaptLabel; 90adcf2cb4SMatthew G. Knepley PetscInt nAdaptLoc[2], nAdapt[2]; 91adcf2cb4SMatthew G. Knepley 92adcf2cb4SMatthew G. Knepley adapt = PETSC_FALSE; 93adcf2cb4SMatthew G. Knepley nAdaptLoc[0] = nAdaptLoc[1] = 0; 94adcf2cb4SMatthew G. Knepley nAdapt[0] = nAdapt[1] = 0; 95adcf2cb4SMatthew G. Knepley /* Adaptation is not preserving the domain label */ 96adcf2cb4SMatthew G. Knepley ierr = DMHasLabel(dmCur, "Cell Sets", &hasLabel);CHKERRQ(ierr); 97adcf2cb4SMatthew G. Knepley if (!hasLabel) {ierr = CreateDomainLabel(dmCur);CHKERRQ(ierr);} 98adcf2cb4SMatthew G. Knepley ierr = DMGetLabel(dmCur, "Cell Sets", &label);CHKERRQ(ierr); 99adcf2cb4SMatthew G. Knepley ierr = DMLabelGetValueIS(label, &vIS);CHKERRQ(ierr); 100adcf2cb4SMatthew G. Knepley ierr = ISDuplicate(vIS, &valueIS);CHKERRQ(ierr); 101adcf2cb4SMatthew G. Knepley ierr = ISDestroy(&vIS);CHKERRQ(ierr); 102adcf2cb4SMatthew G. Knepley /* Sorting directly the label's value IS would corrupt the label so we duplicate the IS first */ 103adcf2cb4SMatthew G. Knepley ierr = ISSort(valueIS);CHKERRQ(ierr); 104adcf2cb4SMatthew G. Knepley ierr = ISGetLocalSize(valueIS, &Nv);CHKERRQ(ierr); 105adcf2cb4SMatthew G. Knepley ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 106adcf2cb4SMatthew G. Knepley /* Construct adaptation label */ 107adcf2cb4SMatthew G. Knepley ierr = DMLabelCreate(PETSC_COMM_SELF, "adapt", &adaptLabel);CHKERRQ(ierr); 108adcf2cb4SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dmCur, 0, &cStart, &cEnd);CHKERRQ(ierr); 109adcf2cb4SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 110adcf2cb4SMatthew G. Knepley PetscReal volume, centroid[3]; 111adcf2cb4SMatthew G. Knepley PetscInt value, vidx; 112adcf2cb4SMatthew G. Knepley 113adcf2cb4SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFVM(dmCur, c, &volume, centroid, NULL);CHKERRQ(ierr); 114adcf2cb4SMatthew G. Knepley ierr = DMLabelGetValue(label, c, &value);CHKERRQ(ierr); 115adcf2cb4SMatthew G. Knepley if (value < 0) continue; 116adcf2cb4SMatthew G. Knepley ierr = PetscFindInt(value, Nv, values, &vidx);CHKERRQ(ierr); 117adcf2cb4SMatthew G. Knepley if (vidx < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Value %D for cell %D does not exist in label", value, c); 118adcf2cb4SMatthew G. Knepley if (volume > volConst[vidx]) {ierr = DMLabelSetValue(adaptLabel, c, DM_ADAPT_REFINE);CHKERRQ(ierr); ++nAdaptLoc[0];} 119adcf2cb4SMatthew G. Knepley if (volume < volConst[vidx]*ratio) {ierr = DMLabelSetValue(adaptLabel, c, DM_ADAPT_COARSEN);CHKERRQ(ierr); ++nAdaptLoc[1];} 120adcf2cb4SMatthew G. Knepley } 121adcf2cb4SMatthew G. Knepley ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 122adcf2cb4SMatthew G. Knepley ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 12355b25c41SPierre Jolivet ierr = MPI_Allreduce(&nAdaptLoc, &nAdapt, 2, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dmCur));CHKERRMPI(ierr); 124adcf2cb4SMatthew G. Knepley if (nAdapt[0]) { 125adcf2cb4SMatthew G. Knepley ierr = PetscInfo2(dmCur, "Adapted mesh, marking %D cells for refinement, and %D cells for coarsening\n", nAdapt[0], nAdapt[1]);CHKERRQ(ierr); 126adcf2cb4SMatthew G. Knepley ierr = DMAdaptLabel(dmCur, adaptLabel, &dmAdapt);CHKERRQ(ierr); 127*1e1ea65dSPierre Jolivet ierr = DMDestroy(&dmCur);CHKERRQ(ierr); 128adcf2cb4SMatthew G. Knepley ierr = DMViewFromOptions(dmAdapt, NULL, "-adapt_dm_view");CHKERRQ(ierr); 129adcf2cb4SMatthew G. Knepley dmCur = dmAdapt; 130adcf2cb4SMatthew G. Knepley adapt = PETSC_TRUE; 131adcf2cb4SMatthew G. Knepley } 132adcf2cb4SMatthew G. Knepley ierr = DMLabelDestroy(&adaptLabel);CHKERRQ(ierr); 133adcf2cb4SMatthew G. Knepley } 134adcf2cb4SMatthew G. Knepley ierr = PetscFree(volConst);CHKERRQ(ierr); 135adcf2cb4SMatthew G. Knepley *dm = dmCur; 136adcf2cb4SMatthew G. Knepley PetscFunctionReturn(0); 137adcf2cb4SMatthew G. Knepley } 138adcf2cb4SMatthew G. Knepley 139adcf2cb4SMatthew G. Knepley static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) 140adcf2cb4SMatthew G. Knepley { 141adcf2cb4SMatthew G. Knepley PetscInt dim; 142adcf2cb4SMatthew G. Knepley PetscErrorCode ierr; 143adcf2cb4SMatthew G. Knepley 144adcf2cb4SMatthew G. Knepley PetscFunctionBeginUser; 145adcf2cb4SMatthew G. Knepley /* Create top surface */ 14630602db0SMatthew G. Knepley ierr = DMCreate(comm, dm);CHKERRQ(ierr); 14730602db0SMatthew G. Knepley ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 14830602db0SMatthew G. Knepley ierr = PetscObjectSetOptionsPrefix((PetscObject) *dm, "init_");CHKERRQ(ierr); 14930602db0SMatthew G. Knepley ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); 150adcf2cb4SMatthew G. Knepley /* Adapt surface */ 151adcf2cb4SMatthew G. Knepley ierr = AdaptMesh(dm, user);CHKERRQ(ierr); 152adcf2cb4SMatthew G. Knepley /* Extrude surface to get volume mesh */ 153adcf2cb4SMatthew G. Knepley ierr = DMGetDimension(*dm, &dim);CHKERRQ(ierr); 154adcf2cb4SMatthew G. Knepley if (dim < 3 && user->extrude) { 155adcf2cb4SMatthew G. Knepley DM edm; 156adcf2cb4SMatthew G. Knepley 157adcf2cb4SMatthew G. Knepley ierr = PetscObjectSetOptionsPrefix((PetscObject) *dm, "srf_");CHKERRQ(ierr); 158adcf2cb4SMatthew G. Knepley ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); 159adcf2cb4SMatthew G. Knepley ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); 160adcf2cb4SMatthew G. Knepley ierr = PetscObjectSetOptionsPrefix((PetscObject) *dm, NULL);CHKERRQ(ierr); 161adcf2cb4SMatthew G. Knepley ierr = DMPlexExtrude(*dm, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_TRUE, NULL, PETSC_TRUE, &edm);CHKERRQ(ierr); 162adcf2cb4SMatthew G. Knepley ierr = DMDestroy(dm);CHKERRQ(ierr); 163adcf2cb4SMatthew G. Knepley *dm = edm; 164adcf2cb4SMatthew G. Knepley } 165adcf2cb4SMatthew G. Knepley ierr = DMLocalizeCoordinates(*dm);CHKERRQ(ierr); 166adcf2cb4SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) *dm, "Mesh");CHKERRQ(ierr); 167adcf2cb4SMatthew G. Knepley ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); 168adcf2cb4SMatthew G. Knepley ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); 169adcf2cb4SMatthew G. Knepley PetscFunctionReturn(0); 170adcf2cb4SMatthew G. Knepley } 171adcf2cb4SMatthew G. Knepley 172adcf2cb4SMatthew G. Knepley int main(int argc, char **argv) 173adcf2cb4SMatthew G. Knepley { 174adcf2cb4SMatthew G. Knepley DM dm; 175adcf2cb4SMatthew G. Knepley AppCtx user; 176adcf2cb4SMatthew G. Knepley PetscErrorCode ierr; 177adcf2cb4SMatthew G. Knepley 178adcf2cb4SMatthew G. Knepley ierr = PetscInitialize(&argc, &argv, NULL, help);if (ierr) return ierr; 179adcf2cb4SMatthew G. Knepley ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr); 180adcf2cb4SMatthew G. Knepley ierr = CreateMesh(PETSC_COMM_WORLD, &user, &dm);CHKERRQ(ierr); 181adcf2cb4SMatthew G. Knepley ierr = DMDestroy(&dm);CHKERRQ(ierr); 182adcf2cb4SMatthew G. Knepley ierr = PetscFinalize(); 183adcf2cb4SMatthew G. Knepley return ierr; 184adcf2cb4SMatthew G. Knepley } 185adcf2cb4SMatthew G. Knepley 186adcf2cb4SMatthew G. Knepley /*TEST 187adcf2cb4SMatthew G. Knepley 188adcf2cb4SMatthew G. Knepley test: 189adcf2cb4SMatthew G. Knepley suffix: 0 190adcf2cb4SMatthew G. Knepley requires: triangle 19130602db0SMatthew G. Knepley args: -init_dm_plex_dim 2 -init_dm_plex_box_faces 1,1 -dm_view 192adcf2cb4SMatthew G. Knepley 193adcf2cb4SMatthew G. Knepley test: # Regularly refine the surface before extrusion 194adcf2cb4SMatthew G. Knepley suffix: 1 195adcf2cb4SMatthew G. Knepley requires: triangle 19630602db0SMatthew G. Knepley args: -init_dm_plex_dim 2 -srf_dm_refine 2 -dm_view 197adcf2cb4SMatthew G. Knepley 198adcf2cb4SMatthew G. Knepley test: # Parallel run 199adcf2cb4SMatthew G. Knepley suffix: 2 200adcf2cb4SMatthew G. Knepley requires: triangle 201adcf2cb4SMatthew G. Knepley nsize: 5 20230602db0SMatthew G. Knepley args: -init_dm_plex_dim 2 -srf_dm_refine 3 -petscpartitioner_type simple -dm_distribute -dm_plex_extrude_layers 3 -dm_view 203adcf2cb4SMatthew G. Knepley 204adcf2cb4SMatthew G. Knepley test: # adaptively refine the surface before extrusion 205adcf2cb4SMatthew G. Knepley suffix: 3 206adcf2cb4SMatthew G. Knepley requires: triangle 20730602db0SMatthew 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_plex_extrude_layers 10 208adcf2cb4SMatthew G. Knepley 209adcf2cb4SMatthew G. Knepley TEST*/ 210