Actual source code: ex105.c
1: static char help[] = "Tests DMPlexTransformCreateSplitCellLabel().\n\n";
3: #include <petscdmplex.h>
4: #include <petscdmplextransform.h>
6: // Flags a single cell for refinement, which is what an error estimator would do
7: static PetscErrorCode CreateAdaptLabel(DM dm, DMLabel *adaptLabel)
8: {
9: PetscInt cStart, cEnd;
11: PetscFunctionBeginUser;
12: PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
13: PetscCall(DMLabelCreate(PETSC_COMM_SELF, "adapt", adaptLabel));
14: PetscCall(DMLabelSetDefaultValue(*adaptLabel, DM_ADAPT_KEEP));
15: if (cEnd > cStart) PetscCall(DMLabelSetValue(*adaptLabel, cStart, DM_ADAPT_REFINE));
16: PetscFunctionReturn(PETSC_SUCCESS);
17: }
19: int main(int argc, char **argv)
20: {
21: DM dm, rdm;
22: DMPlexTransform tr;
23: DMLabel adaptLabel, splitLabel;
24: PetscInt cStart, cEnd, rcStart, rcEnd, numSplit;
26: PetscFunctionBeginUser;
27: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
28: PetscCall(DMCreate(PETSC_COMM_WORLD, &dm));
29: PetscCall(DMSetType(dm, DMPLEX));
30: PetscCall(DMSetFromOptions(dm));
31: // Without this the refined mesh does not keep the transformation that produced it
32: PetscCall(DMPlexSetSaveTransform(dm, PETSC_TRUE));
33: PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
35: PetscCall(CreateAdaptLabel(dm, &adaptLabel));
36: PetscCall(DMAdaptLabel(dm, adaptLabel, &rdm));
37: PetscCheck(rdm, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Adaptation did not produce a mesh");
38: PetscCall(DMPlexGetHeightStratum(rdm, 0, &rcStart, &rcEnd));
39: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Coarse cells: %" PetscInt_FMT " Refined cells: %" PetscInt_FMT "\n", cEnd - cStart, rcEnd - rcStart));
41: PetscCall(DMPlexGetTransform(rdm, &tr));
42: PetscCheck(tr, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Refined mesh did not keep its transform");
43: PetscCall(DMPlexTransformCreateSplitCellLabel(tr, rdm, &splitLabel));
44: PetscCall(DMLabelGetStratumSize(splitLabel, 1, &numSplit));
45: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Cells from a split parent: %" PetscInt_FMT "\n", numSplit));
46: // Every cell of a genuinely refined parent is marked, and cells passed through unchanged are not
47: PetscCheck(numSplit > 0, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "No cell came from a split parent, but the mesh grew");
48: PetscCheck(numSplit <= rcEnd - rcStart, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Marked %" PetscInt_FMT " cells, but the mesh only has %" PetscInt_FMT, numSplit, rcEnd - rcStart);
50: // The closure of the split cells is the set of entities whose star contains one, which is what PCPATCH wants
51: PetscCall(DMPlexLabelComplete(rdm, splitLabel));
52: PetscCall(DMLabelView(splitLabel, PETSC_VIEWER_STDOUT_WORLD));
54: PetscCall(DMLabelDestroy(&splitLabel));
55: PetscCall(DMLabelDestroy(&adaptLabel));
56: PetscCall(DMDestroy(&rdm));
57: PetscCall(DMDestroy(&dm));
58: PetscCall(PetscFinalize());
59: return 0;
60: }
62: /*TEST
64: # A doublet is two tetrahedra, so SBR splits the flagged cell and its neighbor to stay conforming
65: test:
66: suffix: sbr
67: args: -dm_adaptor cellrefiner -dm_plex_shape doublet -dm_plex_dim 3 -dm_plex_simplex 1 -dm_plex_transform_type refine_sbr
69: test:
70: suffix: regular
71: args: -dm_adaptor cellrefiner -dm_plex_simplex 0 -dm_plex_box_faces 2,2 -dm_plex_transform_type refine_regular
73: TEST*/