xref: /petsc/src/dm/impls/plex/tests/ex46.c (revision ddd1d0956a6d7eae09277409cde098be056bea5b)
1a12d352dSMatthew G. Knepley static char help[] = "Tests 1D nested mesh refinement.\n\n";
2a12d352dSMatthew G. Knepley 
3a12d352dSMatthew G. Knepley #include <petscdmplex.h>
4a12d352dSMatthew G. Knepley #include <petscds.h>
5a12d352dSMatthew G. Knepley 
6a12d352dSMatthew G. Knepley typedef struct {
7a12d352dSMatthew G. Knepley   PetscInt             Nr;       /* Number of refinements */
8*ddd1d095SMatthew G. Knepley   PetscSimplePointFunc funcs[2]; /* Functions to test */
9a12d352dSMatthew G. Knepley } AppCtx;
10a12d352dSMatthew G. Knepley 
11a12d352dSMatthew G. Knepley static PetscErrorCode constant(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
12a12d352dSMatthew G. Knepley {
13a12d352dSMatthew G. Knepley   u[0] = 1.;
14a12d352dSMatthew G. Knepley   return 0;
15a12d352dSMatthew G. Knepley }
16a12d352dSMatthew G. Knepley 
17a12d352dSMatthew G. Knepley static PetscErrorCode linear(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
18a12d352dSMatthew G. Knepley {
19a12d352dSMatthew G. Knepley   u[0] = 2.*x[0] + 1.;
20a12d352dSMatthew G. Knepley   return 0;
21a12d352dSMatthew G. Knepley }
22a12d352dSMatthew G. Knepley 
23a12d352dSMatthew G. Knepley static PetscErrorCode quadratic(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
24a12d352dSMatthew G. Knepley {
25a12d352dSMatthew G. Knepley   u[0] = 3.*x[0]*x[0] + 2.*x[0] + 1.;
26a12d352dSMatthew G. Knepley   return 0;
27a12d352dSMatthew G. Knepley }
28a12d352dSMatthew G. Knepley 
29a12d352dSMatthew G. Knepley static PetscErrorCode cubic(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
30a12d352dSMatthew G. Knepley {
31a12d352dSMatthew G. Knepley   u[0] = 4.*x[0]*x[0]*x[0] + 3.*x[0]*x[0] + 2.*x[0] + 1.;
32a12d352dSMatthew G. Knepley   return 0;
33a12d352dSMatthew G. Knepley }
34a12d352dSMatthew G. Knepley 
35a12d352dSMatthew G. Knepley static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
36a12d352dSMatthew G. Knepley {
37a12d352dSMatthew G. Knepley   PetscFunctionBeginUser;
38a12d352dSMatthew G. Knepley   options->Nr = 1;
39d0609cedSBarry Smith   PetscOptionsBegin(comm, "", "1D Refinement Options", "DMPLEX");
409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-num_refine", "Refine cycles", "ex46.c", options->Nr, &options->Nr, NULL));
41d0609cedSBarry Smith   PetscOptionsEnd();
42a12d352dSMatthew G. Knepley   PetscFunctionReturn(0);
43a12d352dSMatthew G. Knepley }
44a12d352dSMatthew G. Knepley 
45a12d352dSMatthew G. Knepley static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm)
46a12d352dSMatthew G. Knepley {
47a12d352dSMatthew G. Knepley   PetscFunctionBeginUser;
489566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
499566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
509566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(*dm));
519566063dSJacob Faibussowitsch   PetscCall(DMSetApplicationContext(*dm, user));
529566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view"));
53a12d352dSMatthew G. Knepley   PetscFunctionReturn(0);
54a12d352dSMatthew G. Knepley }
55a12d352dSMatthew G. Knepley 
56a12d352dSMatthew G. Knepley static PetscErrorCode SetupDiscretization(DM dm, AppCtx *user)
57a12d352dSMatthew G. Knepley {
58a12d352dSMatthew G. Knepley   DM             cdm = dm;
59a12d352dSMatthew G. Knepley   PetscFE        fe;
60a12d352dSMatthew G. Knepley   PetscSpace     sp;
61a12d352dSMatthew G. Knepley   PetscInt       dim, deg;
62a12d352dSMatthew G. Knepley 
63a12d352dSMatthew G. Knepley   PetscFunctionBeginUser;
649566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
659566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, PETSC_FALSE, NULL, -1, &fe));
669566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) fe, "scalar"));
679566063dSJacob Faibussowitsch   PetscCall(DMSetField(dm, 0, NULL, (PetscObject) fe));
68*ddd1d095SMatthew G. Knepley   PetscCall(DMSetField(dm, 1, NULL, (PetscObject) fe));
699566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(dm));
70a12d352dSMatthew G. Knepley   while (cdm) {
719566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dm,cdm));
729566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(cdm, &cdm));
73a12d352dSMatthew G. Knepley   }
749566063dSJacob Faibussowitsch   PetscCall(PetscFEGetBasisSpace(fe, &sp));
759566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetDegree(sp, &deg, NULL));
76a12d352dSMatthew G. Knepley   switch (deg) {
77a12d352dSMatthew G. Knepley   case 0: user->funcs[0] = constant;break;
78a12d352dSMatthew G. Knepley   case 1: user->funcs[0] = linear;break;
79a12d352dSMatthew G. Knepley   case 2: user->funcs[0] = quadratic;break;
80a12d352dSMatthew G. Knepley   case 3: user->funcs[0] = cubic;break;
8163a3b9bcSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Could not determine function to test for degree %" PetscInt_FMT, deg);
82a12d352dSMatthew G. Knepley   }
83*ddd1d095SMatthew G. Knepley   user->funcs[1] = user->funcs[0];
849566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
85a12d352dSMatthew G. Knepley   PetscFunctionReturn(0);
86a12d352dSMatthew G. Knepley }
87a12d352dSMatthew G. Knepley 
88a12d352dSMatthew G. Knepley static PetscErrorCode CheckError(DM dm, Vec u, PetscSimplePointFunc funcs[])
89a12d352dSMatthew G. Knepley {
90a12d352dSMatthew G. Knepley   PetscReal      error, tol = PETSC_SMALL;
91a12d352dSMatthew G. Knepley   MPI_Comm       comm;
92a12d352dSMatthew G. Knepley 
93a12d352dSMatthew G. Knepley   PetscFunctionBeginUser;
949566063dSJacob Faibussowitsch   PetscCall(DMComputeL2Diff(dm, 0.0, funcs, NULL, u, &error));
959566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
969566063dSJacob Faibussowitsch   if (error > tol) PetscCall(PetscPrintf(comm, "Function tests FAIL at tolerance %g error %g\n", (double)tol,(double) error));
979566063dSJacob Faibussowitsch   else             PetscCall(PetscPrintf(comm, "Function tests pass at tolerance %g\n", (double)tol));
98a12d352dSMatthew G. Knepley   PetscFunctionReturn(0);
99a12d352dSMatthew G. Knepley }
100a12d352dSMatthew G. Knepley 
101a12d352dSMatthew G. Knepley int main(int argc, char **argv)
102a12d352dSMatthew G. Knepley {
103a12d352dSMatthew G. Knepley   DM             dm;
104a12d352dSMatthew G. Knepley   Vec            u;
105a12d352dSMatthew G. Knepley   AppCtx         user;
106a12d352dSMatthew G. Knepley   PetscInt       cStart, cEnd, c, r;
107a12d352dSMatthew G. Knepley 
1089566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
1099566063dSJacob Faibussowitsch   PetscCall(ProcessOptions(PETSC_COMM_WORLD, &user));
1109566063dSJacob Faibussowitsch   PetscCall(CreateMesh(PETSC_COMM_WORLD, &user, &dm));
1119566063dSJacob Faibussowitsch   PetscCall(SetupDiscretization(dm, &user));
1129566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(dm, &u));
1139566063dSJacob Faibussowitsch   PetscCall(DMProjectFunction(dm, 0.0, user.funcs, NULL, INSERT_ALL_VALUES, u));
1149566063dSJacob Faibussowitsch   PetscCall(CheckError(dm, u, user.funcs));
115a12d352dSMatthew G. Knepley   for (r = 0; r < user.Nr; ++r) {
116a12d352dSMatthew G. Knepley     DM      adm;
117a12d352dSMatthew G. Knepley     DMLabel adapt;
118a12d352dSMatthew G. Knepley     Vec     au;
119a12d352dSMatthew G. Knepley     Mat     Interp;
120a12d352dSMatthew G. Knepley 
1219566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, "adapt", &adapt));
1229566063dSJacob Faibussowitsch     PetscCall(DMLabelSetDefaultValue(adapt, DM_ADAPT_COARSEN));
1239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
124a12d352dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1259566063dSJacob Faibussowitsch       if (c % 2) PetscCall(DMLabelSetValue(adapt, c, DM_ADAPT_REFINE));
126a12d352dSMatthew G. Knepley     }
1279566063dSJacob Faibussowitsch     PetscCall(DMAdaptLabel(dm, adapt, &adm));
1289566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&adapt));
1299566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) adm, "Adapted Mesh"));
1309566063dSJacob Faibussowitsch     PetscCall(DMViewFromOptions(adm, NULL, "-dm_view"));
131a12d352dSMatthew G. Knepley 
1329566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(dm, adm, &Interp, NULL));
1339566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(adm, &au));
1349566063dSJacob Faibussowitsch     PetscCall(MatInterpolate(Interp, u, au));
1359566063dSJacob Faibussowitsch     PetscCall(CheckError(adm, au, user.funcs));
1369566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Interp));
1379566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dm, &u));
1389566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dm));
139a12d352dSMatthew G. Knepley     dm   = adm;
140a12d352dSMatthew G. Knepley     u    = au;
141a12d352dSMatthew G. Knepley   }
1429566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(dm, &u));
1439566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm));
1449566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
145b122ec5aSJacob Faibussowitsch   return 0;
146a12d352dSMatthew G. Knepley }
147a12d352dSMatthew G. Knepley 
148a12d352dSMatthew G. Knepley /*TEST
149a12d352dSMatthew G. Knepley 
150a12d352dSMatthew G. Knepley   test:
151a12d352dSMatthew G. Knepley     suffix: 0
152a12d352dSMatthew G. Knepley     args: -num_refine 4 -petscspace_degree 3 \
153a12d352dSMatthew G. Knepley           -dm_plex_dim 1 -dm_plex_box_faces 5 -dm_plex_transform_type refine_1d -dm_plex_hash_location -dm_view
154a12d352dSMatthew G. Knepley 
155a12d352dSMatthew G. Knepley TEST*/
156