xref: /petsc/src/dm/impls/plex/tests/ex99.c (revision a69119a591a03a9d906b29c0a4e9802e4d7c9795)
1 static char help[] = "Tests DMPlex Gmsh reader.\n\n";
2 
3 #include <petscdmplex.h>
4 
5 #if !defined(PETSC_GMSH_EXE)
6 #define PETSC_GMSH_EXE "gmsh"
7 #endif
8 
9 #include <petscds.h>
10 
11 static void one(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar value[]) {
12   value[0] = (PetscReal)1;
13 }
14 
15 static PetscErrorCode CreateFE(DM dm) {
16   DM             cdm;
17   PetscSpace     P;
18   PetscDualSpace Q;
19   DM             K;
20   PetscFE        fe;
21   DMPolytopeType ptype;
22 
23   PetscInt  dim, k;
24   PetscBool isSimplex;
25 
26   PetscDS ds;
27 
28   PetscFunctionBeginUser;
29   PetscCall(DMGetCoordinateDM(dm, &cdm));
30   PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe));
31   PetscCall(PetscFEGetBasisSpace(fe, &P));
32   PetscCall(PetscFEGetDualSpace(fe, &Q));
33   PetscCall(PetscDualSpaceGetDM(Q, &K));
34   PetscCall(DMGetDimension(K, &dim));
35   PetscCall(PetscSpaceGetDegree(P, &k, NULL));
36   PetscCall(DMPlexGetCellType(K, 0, &ptype));
37   switch (ptype) {
38   case DM_POLYTOPE_QUADRILATERAL:
39   case DM_POLYTOPE_HEXAHEDRON: isSimplex = PETSC_FALSE; break;
40   default: isSimplex = PETSC_TRUE; break;
41   }
42 
43   PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, 1, isSimplex, k, PETSC_DETERMINE, &fe));
44   PetscCall(PetscFESetName(fe, "scalar"));
45   PetscCall(DMAddField(dm, NULL, (PetscObject)fe));
46   PetscCall(PetscFEDestroy(&fe));
47   PetscCall(DMCreateDS(dm));
48 
49   PetscCall(DMGetDS(dm, &ds));
50   PetscCall(PetscDSSetObjective(ds, 0, one));
51   PetscFunctionReturn(0);
52 }
53 
54 static PetscErrorCode CheckIntegral(DM dm, PetscReal integral, PetscReal tol) {
55   Vec         u;
56   PetscReal   rval;
57   PetscScalar result;
58 
59   PetscFunctionBeginUser;
60   PetscCall(DMGetGlobalVector(dm, &u));
61   PetscCall(DMPlexComputeIntegralFEM(dm, u, &result, NULL));
62   PetscCall(DMRestoreGlobalVector(dm, &u));
63   rval = PetscRealPart(result);
64   if (integral > 0 && PetscAbsReal(integral - rval) > tol) {
65     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "Calculated value %g != %g actual value (error %g > %g tol)\n", (double)rval, (double)integral, (double)PetscAbsReal(integral - rval), (double)tol));
66   }
67   PetscFunctionReturn(0);
68 }
69 
70 int main(int argc, char **argv) {
71   DM                dm;
72   const char *const mshlist[] = {"seg", "tri", "qua", "tet", "wed", "hex", "vtx", "B2tri", "B2qua", "B3tet", "B3hex"};
73   const char *const fmtlist[] = {"msh22", "msh40", "msh41"};
74   PetscInt          msh       = 5;
75   PetscInt          fmt       = 2;
76   PetscBool         bin       = PETSC_TRUE;
77   PetscInt          dim       = 3;
78   PetscInt          order     = 2;
79 
80   const char cmdtemplate[]            = "%s -format %s %s -%d -order %d %s -o %s";
81   char       gmsh[PETSC_MAX_PATH_LEN] = PETSC_GMSH_EXE;
82   char       tag[PETSC_MAX_PATH_LEN], path[PETSC_MAX_PATH_LEN];
83   char       geo[PETSC_MAX_PATH_LEN], geodir[PETSC_MAX_PATH_LEN] = ".";
84   char       out[PETSC_MAX_PATH_LEN], outdir[PETSC_MAX_PATH_LEN] = ".";
85   char       cmd[PETSC_MAX_PATH_LEN * 4];
86   PetscBool  set, flg;
87   FILE      *fp;
88 
89   PetscFunctionBeginUser;
90   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
91 
92   PetscCall(PetscStrncpy(geodir, "${PETSC_DIR}/share/petsc/datafiles/meshes", sizeof(geodir)));
93   PetscCall(PetscOptionsGetenv(PETSC_COMM_SELF, "GMSH", path, sizeof(path), &set));
94   if (set) PetscCall(PetscStrncpy(gmsh, path, sizeof(gmsh)));
95   PetscCall(PetscOptionsGetString(NULL, NULL, "-gmsh", gmsh, sizeof(gmsh), NULL));
96   PetscCall(PetscOptionsGetString(NULL, NULL, "-dir", geodir, sizeof(geodir), NULL));
97   PetscCall(PetscOptionsGetString(NULL, NULL, "-out", outdir, sizeof(outdir), NULL));
98   PetscCall(PetscOptionsGetEList(NULL, NULL, "-msh", mshlist, PETSC_STATIC_ARRAY_LENGTH(mshlist), &msh, NULL));
99   PetscCall(PetscOptionsGetEList(NULL, NULL, "-fmt", fmtlist, PETSC_STATIC_ARRAY_LENGTH(fmtlist), &fmt, NULL));
100   PetscCall(PetscOptionsGetBool(NULL, NULL, "-bin", &bin, NULL));
101   PetscCall(PetscOptionsGetInt(NULL, NULL, "-dim", &dim, NULL));
102   PetscCall(PetscOptionsGetInt(NULL, NULL, "-order", &order, NULL));
103   if (fmt == 1) bin = PETSC_FALSE; /* Recent Gmsh releases cannot generate msh40+binary format*/
104 
105   { /* This test requires Gmsh >= 4.2.0 */
106     char space[PETSC_MAX_PATH_LEN];
107     int  inum = 0, major = 0, minor = 0, micro = 0;
108     PetscCall(PetscSNPrintf(cmd, sizeof(cmd), "%s -info", gmsh));
109     PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, cmd, "r", &fp));
110     if (fp) inum = fscanf(fp, "Version %s %d.%d.%d", space, &major, &minor, &micro);
111     PetscCall(PetscPClose(PETSC_COMM_SELF, fp));
112     if (inum != 4 || major < 4 || (major == 4 && minor < 2)) {
113       PetscCall(PetscPrintf(PETSC_COMM_SELF, "Gmsh>=4.2.0 not available\n"));
114       goto finish;
115     }
116   }
117 
118   PetscCall(PetscSNPrintf(tag, sizeof(tag), "%s-%d-%d-%s%s", mshlist[msh], (int)dim, (int)order, fmtlist[fmt], bin ? "-bin" : ""));
119   PetscCall(PetscSNPrintf(geo, sizeof(geo), "%s/gmsh-%s.geo", geodir, mshlist[msh]));
120   PetscCall(PetscSNPrintf(out, sizeof(out), "%s/mesh-%s.msh", outdir, tag));
121   PetscCall(PetscStrreplace(PETSC_COMM_SELF, geo, path, sizeof(path)));
122   PetscCall(PetscFixFilename(path, geo));
123   PetscCall(PetscStrreplace(PETSC_COMM_SELF, out, path, sizeof(path)));
124   PetscCall(PetscFixFilename(path, out));
125   PetscCall(PetscTestFile(geo, 'r', &flg));
126   PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_USER_INPUT, "File not found: %s", geo);
127 
128   PetscCall(PetscSNPrintf(cmd, sizeof(cmd), cmdtemplate, gmsh, fmtlist[fmt], bin ? "-bin" : "", (int)dim, (int)order, geo, out));
129   PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, cmd, "r", &fp));
130   PetscCall(PetscPClose(PETSC_COMM_SELF, fp));
131 
132   PetscCall(DMPlexCreateFromFile(PETSC_COMM_SELF, out, "ex99_plex", PETSC_TRUE, &dm));
133   PetscCall(PetscSNPrintf(tag, sizeof(tag), "mesh-%s", mshlist[msh]));
134   PetscCall(PetscObjectSetName((PetscObject)dm, tag));
135   PetscCall(DMSetFromOptions(dm));
136   PetscCall(DMViewFromOptions(dm, NULL, "-dm_view"));
137   {
138     PetscBool check;
139     PetscReal integral = 0, tol = (PetscReal)1.0e-4;
140     PetscCall(PetscOptionsGetReal(NULL, NULL, "-integral", &integral, &check));
141     PetscCall(PetscOptionsGetReal(NULL, NULL, "-tol", &tol, NULL));
142     if (check) {
143       PetscCall(CreateFE(dm));
144       PetscCall(CheckIntegral(dm, integral, tol));
145     }
146   }
147   PetscCall(DMDestroy(&dm));
148 
149 finish:
150   PetscCall(PetscFinalize());
151   return 0;
152 }
153 
154 /*TEST
155 
156   build:
157     requires: defined(PETSC_HAVE_POPEN)
158 
159   test:
160     requires: defined(PETSC_GMSH_EXE)
161     args: -dir ${wPETSC_DIR}/share/petsc/datafiles/meshes
162     args: -msh {{vtx}separate_output}
163     args: -order 1
164     args: -fmt {{msh22 msh40 msh41}} -bin {{0 1}}
165     args: -dm_view ::ascii_info_detail
166     args: -dm_plex_check_all
167     args: -dm_plex_gmsh_highorder false
168     args: -dm_plex_boundary_label marker
169     args: -dm_plex_gmsh_spacedim 3
170 
171   test:
172     requires: defined(PETSC_GMSH_EXE)
173     args: -dir ${wPETSC_DIR}/share/petsc/datafiles/meshes
174     args: -msh {{seg tri qua tet wed hex}separate_output}
175     args: -order {{1 2 3 7}}
176     args: -fmt {{msh22 msh40 msh41}} -bin {{0 1}}
177     args: -dm_view ::ascii_info_detail
178     args: -dm_plex_check_all
179     args: -dm_plex_gmsh_highorder false
180     args: -dm_plex_boundary_label marker
181 
182   testset:
183     suffix: B2 # 2D ball
184     requires: defined(PETSC_GMSH_EXE)
185     args: -dir ${wPETSC_DIR}/share/petsc/datafiles/meshes
186     args: -msh {{B2tri B2qua}}
187     args: -dim 2 -integral 3.141592653589793 # pi
188     args: -order {{2 3 4 5 6 7 8 9}} -tol 0.05
189 
190   testset:
191     suffix: B2_bnd # 2D ball boundary
192     requires: defined(PETSC_GMSH_EXE)
193     args: -dir ${wPETSC_DIR}/share/petsc/datafiles/meshes
194     args: -dm_plex_gmsh_spacedim 2
195     args: -msh {{B2tri B2qua}}
196     args: -dim 1 -integral 6.283185307179586 # 2*pi
197     args: -order {{2 3 4 5 6 7 8 9}} -tol 0.05
198 
199   testset:
200     suffix: B3 # 3D ball
201     requires: defined(PETSC_GMSH_EXE)
202     args: -dir ${wPETSC_DIR}/share/petsc/datafiles/meshes
203     args: -msh {{B3tet B3hex}}
204     args: -dim 3 -integral 4.1887902047863905 # 4/3*pi
205     args: -order {{2 3 4 5}} -tol 0.20
206 
207   testset:
208     suffix: B3_bnd # 3D ball boundary
209     requires: defined(PETSC_GMSH_EXE)
210     args: -dir ${wPETSC_DIR}/share/petsc/datafiles/meshes
211     args: -dm_plex_gmsh_spacedim 3
212     args: -msh {{B3tet B3hex}}
213     args: -dim 2 -integral 12.566370614359172 # 4*pi
214     args: -order {{2 3 4 5 6 7 8 9}} -tol 0.25
215 
216   testset:
217     suffix: B_lin # linear discretizations
218     requires: defined(PETSC_GMSH_EXE)
219     args: -dir ${wPETSC_DIR}/share/petsc/datafiles/meshes
220     args: -dm_plex_gmsh_highorder true
221     args: -dm_plex_gmsh_project true
222     args: -dm_plex_gmsh_project_petscspace_degree {{1 2 3}separate_output}
223     args: -dm_plex_gmsh_fe_view
224     args: -dm_plex_gmsh_project_fe_view
225     args: -order 1 -tol 1e-4
226     test:
227       suffix: dim-1
228       args: -dm_plex_gmsh_spacedim 2
229       args: -msh {{B2tri B2qua}separate_output}
230       args: -dim 1 -integral 5.656854249492381 # 4*sqrt(2)
231     test:
232       suffix: dim-2
233       args: -dm_plex_gmsh_spacedim 2
234       args: -msh {{B2tri B2qua}separate_output}
235       args: -dim 2 -integral 2.000000000000000 # 2
236     test:
237       suffix: dim-2_msh-B3tet
238       args: -dm_plex_gmsh_spacedim 3
239       args: -msh B3tet -dim 2 -integral 9.914478
240     test:
241       suffix: dim-2_msh-B3hex
242       args: -dm_plex_gmsh_spacedim 3
243       args: -msh B3hex -dim 2 -integral 8.000000
244     test:
245       suffix: dim-3_msh-B3tet
246       args: -dm_plex_gmsh_spacedim 3
247       args: -msh B3tet -dim 3 -integral 2.666649
248     test:
249       suffix: dim-3_msh-B3hex
250       args: -dm_plex_gmsh_spacedim 3
251       args: -msh B3hex -dim 3 -integral 1.539600
252 
253 TEST*/
254