Actual source code: ex38.c
1: const char help[] = "Test DMPlexInsertBoundaryValues with DMPlexSetClosurePermutationTensor.\n";
3: #include <petscdmplex.h>
5: static PetscErrorCode bc_func(PetscInt dim, PetscReal time, const PetscReal coords[], PetscInt num_comp_u, PetscScalar *u, PetscCtx ctx)
6: {
7: PetscFunctionBeginUser;
8: for (PetscInt i = 0; i < num_comp_u; i++) u[i] = coords[i];
9: PetscFunctionReturn(PETSC_SUCCESS);
10: }
12: int main(int argc, char **argv)
13: {
14: DM dm;
15: PetscFE fe;
16: Vec U_loc;
17: PetscInt dim, order = 1;
18: PetscBool tensorCoords = PETSC_TRUE;
20: /* Initialize PETSc */
21: PetscFunctionBeginUser;
22: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
23: PetscCall(PetscOptionsGetBool(NULL, NULL, "-tensor_coords", &tensorCoords, NULL));
24: PetscCall(PetscOptionsGetInt(NULL, NULL, "-order", &order, NULL));
25: PetscCall(DMCreate(PETSC_COMM_WORLD, &dm));
26: PetscCall(DMSetType(dm, DMPLEX));
27: PetscCall(DMSetFromOptions(dm));
29: PetscCall(DMGetDimension(dm, &dim));
30: PetscCall(PetscFECreateLagrange(PETSC_COMM_WORLD, dim, dim, PETSC_FALSE, order, order, &fe));
31: PetscCall(DMAddField(dm, NULL, (PetscObject)fe));
32: PetscCall(PetscFEDestroy(&fe));
33: PetscCall(DMCreateDS(dm));
35: PetscCall(DMViewFromOptions(dm, NULL, "-dm_view"));
37: DMLabel label;
38: PetscInt marker_ids[] = {1};
39: PetscCall(DMGetLabel(dm, "marker", &label));
40: PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "mms", label, 1, marker_ids, 0, 0, NULL, (PetscVoidFn *)bc_func, NULL, NULL, NULL));
41: PetscCall(DMPlexSetClosurePermutationTensor(dm, PETSC_DETERMINE, NULL));
42: {
43: DM cdm;
44: PetscCall(DMGetCoordinateDM(dm, &cdm));
45: if (tensorCoords) PetscCall(DMPlexSetClosurePermutationTensor(cdm, PETSC_DETERMINE, NULL));
46: }
48: PetscCall(DMCreateLocalVector(dm, &U_loc));
49: {
50: /* The tensor permutation is stored per closure size, so a wrong degree leaves the cell closure silently unpermuted */
51: PetscSection section;
52: PetscScalar *vals = NULL;
53: PetscInt cStart, clSize;
54: IS perm;
56: PetscCall(DMGetLocalSection(dm, §ion));
57: PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
58: PetscCall(DMPlexVecGetClosure(dm, section, U_loc, cStart, &clSize, &vals));
59: PetscCall(DMPlexVecRestoreClosure(dm, section, U_loc, cStart, &clSize, &vals));
60: PetscCall(PetscSectionGetClosurePermutation(section, (PetscObject)dm, dim, clSize, &perm));
61: PetscCall(ISDestroy(&perm));
62: }
63: PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, U_loc, 1., NULL, NULL, NULL));
64: PetscCall(VecViewFromOptions(U_loc, NULL, "-u_loc_vec_view"));
65: PetscCall(VecDestroy(&U_loc));
66: PetscCall(DMDestroy(&dm));
67: PetscCall(PetscFinalize());
68: return 0;
69: }
71: /*TEST
72: test:
73: suffix: 2d
74: args: -dm_plex_simplex 0 -dm_plex_dim 2 -dm_plex_box_faces 3,3 -u_loc_vec_view
75: test:
76: suffix: 3d
77: args: -dm_plex_simplex 0 -dm_plex_dim 3 -dm_plex_box_faces 3,3,3 -u_loc_vec_view
78: test:
79: # The tensor degree is recovered from the dual space size with a floating-point cube root, which overshoots in
80: # single precision for order >= 4
81: suffix: 3d_q4
82: output_file: output/empty.out
83: args: -dm_plex_simplex 0 -dm_plex_dim 3 -dm_plex_box_faces 1,1,1 -order 4 -tensor_coords 0
84: TEST*/