Actual source code: ex1.c
petsc-3.14.6 2021-03-30
1: static char help[] = "Demonstration of creating and viewing DMFields objects.\n\n";
3: #include <petscdmfield.h>
4: #include <petscdmplex.h>
5: #include <petscdmda.h>
7: static PetscErrorCode ViewResults(PetscViewer viewer, PetscInt N, PetscInt dim, PetscScalar *B, PetscScalar *D, PetscScalar *H, PetscReal *rB, PetscReal *rD, PetscReal *rH)
8: {
12: PetscViewerASCIIPrintf(viewer,"B:\n");
13: PetscScalarView(N,B,viewer);
14: PetscViewerASCIIPrintf(viewer,"D:\n");
15: PetscScalarView(N*dim,D,viewer);
16: PetscViewerASCIIPrintf(viewer,"H:\n");
17: PetscScalarView(N*dim*dim,H,viewer);
19: PetscViewerASCIIPrintf(viewer,"rB:\n");
20: PetscRealView(N,rB,viewer);
21: PetscViewerASCIIPrintf(viewer,"rD:\n");
22: PetscRealView(N*dim,rD,viewer);
23: PetscViewerASCIIPrintf(viewer,"rH:\n");
24: PetscRealView(N*dim*dim,rH,viewer);
25: return(0);
26: }
28: static PetscErrorCode TestEvaluate(DMField field, PetscInt n, PetscRandom rand)
29: {
30: DM dm;
31: PetscInt dim, i, nc;
32: PetscScalar *B, *D, *H;
33: PetscReal *rB, *rD, *rH;
34: Vec points;
35: PetscScalar *array;
36: PetscViewer viewer;
37: MPI_Comm comm;
41: comm = PetscObjectComm((PetscObject)field);
42: DMFieldGetNumComponents(field,&nc);
43: DMFieldGetDM(field,&dm);
44: DMGetDimension(dm,&dim);
45: VecCreateMPI(PetscObjectComm((PetscObject)field),n * dim,PETSC_DETERMINE,&points);
46: VecSetBlockSize(points,dim);
47: VecGetArray(points,&array);
48: for (i = 0; i < n * dim; i++) {PetscRandomGetValue(rand,&array[i]);}
49: VecRestoreArray(points,&array);
50: PetscMalloc6(n*nc,&B,n*nc,&rB,n*nc*dim,&D,n*nc*dim,&rD,n*nc*dim*dim,&H,n*nc*dim*dim,&rH);
51: DMFieldEvaluate(field,points,PETSC_SCALAR,B,D,H);
52: DMFieldEvaluate(field,points,PETSC_REAL,rB,rD,rH);
53: viewer = PETSC_VIEWER_STDOUT_(comm);
55: PetscObjectSetName((PetscObject)points,"Test Points");
56: VecView(points,viewer);
57: ViewResults(viewer,n*nc,dim,B,D,H,rB,rD,rH);
59: PetscFree6(B,rB,D,rD,H,rH);
60: VecDestroy(&points);
61: return(0);
62: }
64: static PetscErrorCode TestEvaluateFE(DMField field, PetscInt n, PetscInt cStart, PetscInt cEnd, PetscQuadrature quad, PetscRandom rand)
65: {
66: DM dm;
67: PetscInt dim, i, nc, nq;
68: PetscInt N;
69: PetscScalar *B, *D, *H;
70: PetscReal *rB, *rD, *rH;
71: PetscInt *cells;
72: IS cellIS;
73: PetscViewer viewer;
74: MPI_Comm comm;
78: comm = PetscObjectComm((PetscObject)field);
79: DMFieldGetNumComponents(field,&nc);
80: DMFieldGetDM(field,&dm);
81: DMGetDimension(dm,&dim);
82: PetscRandomSetInterval(rand,(PetscScalar) cStart, (PetscScalar) cEnd);
83: PetscMalloc1(n,&cells);
84: for (i = 0; i < n; i++) {
85: PetscReal rc;
87: PetscRandomGetValueReal(rand,&rc);
88: cells[i] = PetscFloorReal(rc);
89: }
90: ISCreateGeneral(comm,n,cells,PETSC_OWN_POINTER,&cellIS);
91: PetscObjectSetName((PetscObject)cellIS,"FE Test Cells");
92: PetscQuadratureGetData(quad,NULL,NULL,&nq,NULL,NULL);
93: N = n * nq * nc;
94: PetscMalloc6(N,&B,N,&rB,N*dim,&D,N*dim,&rD,N*dim*dim,&H,N*dim*dim,&rH);
95: DMFieldEvaluateFE(field,cellIS,quad,PETSC_SCALAR,B,D,H);
96: DMFieldEvaluateFE(field,cellIS,quad,PETSC_REAL,rB,rD,rH);
97: viewer = PETSC_VIEWER_STDOUT_(comm);
99: PetscObjectSetName((PetscObject)quad,"Test quadrature");
100: PetscQuadratureView(quad,viewer);
101: ISView(cellIS,viewer);
102: ViewResults(viewer,N,dim,B,D,H,rB,rD,rH);
104: PetscFree6(B,rB,D,rD,H,rH);
105: ISDestroy(&cellIS);
106: return(0);
107: }
109: static PetscErrorCode TestEvaluateFV(DMField field, PetscInt n, PetscInt cStart, PetscInt cEnd, PetscRandom rand)
110: {
111: DM dm;
112: PetscInt dim, i, nc;
113: PetscInt N;
114: PetscScalar *B, *D, *H;
115: PetscReal *rB, *rD, *rH;
116: PetscInt *cells;
117: IS cellIS;
118: PetscViewer viewer;
119: MPI_Comm comm;
123: comm = PetscObjectComm((PetscObject)field);
124: DMFieldGetNumComponents(field,&nc);
125: DMFieldGetDM(field,&dm);
126: DMGetDimension(dm,&dim);
127: PetscRandomSetInterval(rand,(PetscScalar) cStart, (PetscScalar) cEnd);
128: PetscMalloc1(n,&cells);
129: for (i = 0; i < n; i++) {
130: PetscReal rc;
132: PetscRandomGetValueReal(rand,&rc);
133: cells[i] = PetscFloorReal(rc);
134: }
135: ISCreateGeneral(comm,n,cells,PETSC_OWN_POINTER,&cellIS);
136: PetscObjectSetName((PetscObject)cellIS,"FV Test Cells");
137: N = n * nc;
138: PetscMalloc6(N,&B,N,&rB,N*dim,&D,N*dim,&rD,N*dim*dim,&H,N*dim*dim,&rH);
139: DMFieldEvaluateFV(field,cellIS,PETSC_SCALAR,B,D,H);
140: DMFieldEvaluateFV(field,cellIS,PETSC_REAL,rB,rD,rH);
141: viewer = PETSC_VIEWER_STDOUT_(comm);
143: ISView(cellIS,viewer);
144: ViewResults(viewer,N,dim,B,D,H,rB,rD,rH);
146: PetscFree6(B,rB,D,rD,H,rH);
147: ISDestroy(&cellIS);
148: return(0);
149: }
151: static PetscErrorCode radiusSquared(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx)
152: {
153: PetscInt i;
154: PetscReal r2 = 0.;
157: for (i = 0; i < dim; i++) {r2 += PetscSqr(x[i]);}
158: for (i = 0; i < Nf; i++) {
159: u[i] = (i + 1) * r2;
160: }
161: return(0);
162: }
164: static PetscErrorCode TestShellEvaluate(DMField field, Vec points, PetscDataType type, void *B, void *D, void *H)
165: {
166: Vec ctxVec = NULL;
167: const PetscScalar *mult;
168: PetscInt dim;
169: const PetscScalar *x;
170: PetscInt Nc, n, i, j, k, l;
171: PetscErrorCode ierr;
174: DMFieldGetNumComponents(field, &Nc);
175: DMFieldShellGetContext(field, (void *) &ctxVec);
176: VecGetBlockSize(points, &dim);
177: VecGetLocalSize(points, &n);
178: n /= Nc;
179: VecGetArrayRead(ctxVec, &mult);
180: VecGetArrayRead(points, &x);
181: for (i = 0; i < n; i++) {
182: PetscReal r2 = 0.;
184: for (j = 0; j < dim; j++) {r2 += PetscSqr(PetscRealPart(x[i * dim + j]));}
185: for (j = 0; j < Nc; j++) {
186: PetscReal m = PetscRealPart(mult[j]);
187: if (B) {
188: if (type == PETSC_SCALAR) {
189: ((PetscScalar *)B)[i * Nc + j] = m * r2;
190: } else {
191: ((PetscReal *)B)[i * Nc + j] = m * r2;
192: }
193: }
194: if (D) {
195: if (type == PETSC_SCALAR) {
196: for (k = 0; k < dim; k++) ((PetscScalar *)D)[(i * Nc + j) * dim + k] = 2. * m * x[i * dim + k];
197: } else {
198: for (k = 0; k < dim; k++) ((PetscReal *)D)[(i * Nc + j) * dim + k] = 2. * m * PetscRealPart(x[i * dim + k]);
199: }
200: }
201: if (H) {
202: if (type == PETSC_SCALAR) {
203: for (k = 0; k < dim; k++) for (l = 0; l < dim; l++) ((PetscScalar *)H)[((i * Nc + j) * dim + k) * dim + l] = (k == l) ? 2. * m : 0.;
204: } else {
205: for (k = 0; k < dim; k++) for (l = 0; l < dim; l++) ((PetscReal *)H)[((i * Nc + j) * dim + k) * dim + l] = (k == l) ? 2. * m : 0.;
206: }
207: }
208: }
209: }
210: VecRestoreArrayRead(points, &x);
211: VecRestoreArrayRead(ctxVec, &mult);
212: return(0);
213: }
215: static PetscErrorCode TestShellDestroy(DMField field)
216: {
217: Vec ctxVec = NULL;
218: PetscErrorCode ierr;
221: DMFieldShellGetContext(field, (void *) &ctxVec);
222: VecDestroy(&ctxVec);
223: return(0);
224: }
226: int main(int argc, char **argv)
227: {
228: DM dm = NULL;
229: MPI_Comm comm;
230: char type[256] = DMPLEX;
231: PetscBool isda, isplex;
232: PetscInt dim = 2;
233: DMField field = NULL;
234: PetscInt nc = 1;
235: PetscInt cStart = -1, cEnd = -1;
236: PetscRandom rand;
237: PetscQuadrature quad = NULL;
238: PetscInt pointsPerEdge = 2;
239: PetscInt numPoint = 0, numFE = 0, numFV = 0;
240: PetscBool testShell = PETSC_FALSE;
241: PetscErrorCode ierr;
243: PetscInitialize(&argc, &argv, NULL, help);if (ierr) return ierr;
244: comm = PETSC_COMM_WORLD;
245: PetscOptionsBegin(comm, "", "DMField Tutorial Options", "DM");
246: PetscOptionsFList("-dm_type","DM implementation on which to define field","ex1.c",DMList,type,type,256,NULL);
247: PetscOptionsRangeInt("-dim","DM intrinsic dimension", "ex1.c", dim, &dim, NULL,1,3);
248: PetscOptionsBoundedInt("-num_components","Number of components in field", "ex1.c", nc, &nc, NULL,1);
249: PetscOptionsBoundedInt("-num_quad_points","Number of quadrature points per dimension", "ex1.c", pointsPerEdge, &pointsPerEdge, NULL,1);
250: PetscOptionsBoundedInt("-num_point_tests", "Number of test points for DMFieldEvaluate()", "ex1.c", numPoint, &numPoint, NULL,0);
251: PetscOptionsBoundedInt("-num_fe_tests", "Number of test cells for DMFieldEvaluateFE()", "ex1.c", numFE, &numFE, NULL,0);
252: PetscOptionsBoundedInt("-num_fv_tests", "Number of test cells for DMFieldEvaluateFV()", "ex1.c", numFV, &numFV, NULL,0);
253: PetscOptionsBool("-test_shell", "Test the DMFIELDSHELL implementation of DMField", "ex1.c", testShell, &testShell, NULL);
254: PetscOptionsEnd();
256: if (dim > 3) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"This examples works for dim <= 3, not %D",dim);
257: PetscStrncmp(type,DMPLEX,256,&isplex);
258: PetscStrncmp(type,DMDA,256,&isda);
260: PetscRandomCreate(PETSC_COMM_SELF,&rand);
261: PetscRandomSetFromOptions(rand);
262: if (isplex) {
263: PetscBool simplex = PETSC_TRUE;
264: PetscInt overlap = 0;
265: Vec fieldvec;
266: PetscBool interpolate = PETSC_TRUE;
267: PetscInt inttypes[3];
268: DMBoundaryType types[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
269: PetscInt cells[3] = {3,3,3};
270: PetscBool flags[3] = {PETSC_FALSE, PETSC_FALSE, PETSC_FALSE};
271: PetscInt n = 3, i;
272: PetscFE fe;
274: PetscOptionsBegin(comm, "", "DMField DMPlex Options", "DM");
275: PetscOptionsBool("-simplex","Create a simplicial DMPlex","ex1.c",simplex,&simplex,NULL);
276: PetscOptionsBoundedInt("-overlap","DMPlex parallel overlap","ex1.c",overlap,&overlap,NULL,0);
277: PetscOptionsBool("-interpolate","Interpolate the DMPlex","ex1.c",interpolate,&interpolate,NULL);
278: PetscOptionsEList("-boundary_x","type of boundary in x direction","ex1.c",DMBoundaryTypes,5,DMBoundaryTypes[types[0]],&inttypes[0],&flags[0]);
279: PetscOptionsEList("-boundary_y","type of boundary in y direction","ex1.c",DMBoundaryTypes,5,DMBoundaryTypes[types[1]],&inttypes[1],&flags[1]);
280: PetscOptionsEList("-boundary_z","type of boundary in z direction","ex1.c",DMBoundaryTypes,5,DMBoundaryTypes[types[2]],&inttypes[2],&flags[2]);
281: PetscOptionsIntArray("-cells","Cells per dimension","ex1.c",cells,&n,NULL);
282: PetscOptionsEnd();
283: for (i = 0; i < 3; i++) {
284: if (flags[i]) {types[i] = (DMBoundaryType) inttypes[i];}
285: }
286: DMPlexCreateBoxMesh(comm,dim,simplex,cells,NULL,NULL,types,interpolate,&dm);
287: if (simplex) {
288: PetscDTStroudConicalQuadrature(dim, 1, pointsPerEdge, -1.0, 1.0, &quad);
289: } else {
290: PetscDTGaussTensorQuadrature(dim, 1, pointsPerEdge, -1.0, 1.0, &quad);
291: }
292: {
293: PetscPartitioner part;
294: DM dmDist;
296: DMPlexGetPartitioner(dm,&part);
297: PetscPartitionerSetType(part,PETSCPARTITIONERSIMPLE);
298: DMPlexDistribute(dm,overlap,NULL,&dmDist);
299: if (dmDist) {
300: DMDestroy(&dm);
301: dm = dmDist;
302: }
303: }
304: DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);
305: if (testShell) {
306: Vec ctxVec;
307: PetscInt i;
308: PetscScalar *array;
310: VecCreateSeq(PETSC_COMM_SELF, nc, &ctxVec);
311: VecSetUp(ctxVec);
312: VecGetArray(ctxVec,&array);
313: for (i = 0; i < nc; i++) array[i] = i + 1.;
314: VecRestoreArray(ctxVec,&array);
315: DMFieldCreateShell(dm, nc, DMFIELD_VERTEX, (void *) ctxVec, &field);
316: DMFieldShellSetEvaluate(field, TestShellEvaluate);
317: DMFieldShellSetDestroy(field, TestShellDestroy);
318: } else {
319: PetscFECreateDefault(comm,dim,nc,simplex,NULL,PETSC_DEFAULT,&fe);
320: PetscFESetName(fe,"MyPetscFE");
321: DMSetField(dm,0,NULL,(PetscObject)fe);
322: DMCreateDS(dm);
323: PetscFEDestroy(&fe);
324: DMCreateLocalVector(dm,&fieldvec);
325: {
326: PetscErrorCode (*func[1]) (PetscInt,PetscReal,const PetscReal [],PetscInt, PetscScalar *,void *);
327: void *ctxs[1];
329: func[0] = radiusSquared;
330: ctxs[0] = NULL;
332: DMProjectFunctionLocal(dm,0.0,func,ctxs,INSERT_ALL_VALUES,fieldvec);
333: }
334: DMFieldCreateDS(dm,0,fieldvec,&field);
335: VecDestroy(&fieldvec);
336: }
337: } else if (isda) {
338: PetscInt i;
339: PetscScalar *cv;
341: switch (dim) {
342: case 1:
343: DMDACreate1d(comm, DM_BOUNDARY_NONE, 3, 1, 1, NULL, &dm);
344: break;
345: case 2:
346: DMDACreate2d(comm, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_BOX, 3, 3, PETSC_DETERMINE, PETSC_DETERMINE, 1, 1, NULL, NULL, &dm);
347: break;
348: default:
349: DMDACreate3d(comm, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_BOX, 3, 3, 3, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_DETERMINE, 1, 1, NULL, NULL, NULL, &dm);
350: break;
351: }
352: DMSetUp(dm);
353: DMDAGetHeightStratum(dm,0,&cStart,&cEnd);
354: PetscMalloc1(nc * (1 << dim),&cv);
355: for (i = 0; i < nc * (1 << dim); i++) {
356: PetscReal rv;
358: PetscRandomGetValueReal(rand,&rv);
359: cv[i] = rv;
360: }
361: DMFieldCreateDA(dm,nc,cv,&field);
362: PetscFree(cv);
363: PetscDTGaussTensorQuadrature(dim, 1, pointsPerEdge, -1.0, 1.0, &quad);
364: } else SETERRQ1(comm,PETSC_ERR_SUP,"This test does not run for DM type %s",type);
366: PetscObjectSetName((PetscObject)dm,"mesh");
367: DMViewFromOptions(dm,NULL,"-dm_view");
368: DMDestroy(&dm);
369: PetscObjectSetName((PetscObject)field,"field");
370: PetscObjectViewFromOptions((PetscObject)field,NULL,"-dmfield_view");
371: if (numPoint) {TestEvaluate(field,numPoint,rand);}
372: if (numFE) {TestEvaluateFE(field,numFE,cStart,cEnd,quad,rand);}
373: if (numFV) {TestEvaluateFV(field,numFV,cStart,cEnd,rand);}
374: PetscQuadratureDestroy(&quad);
375: DMFieldDestroy(&field);
376: PetscRandomDestroy(&rand);
377: PetscFinalize();
378: return ierr;
379: }
381: /*TEST
383: test:
384: suffix: da
385: requires: !complex
386: args: -dm_type da -dim 2 -num_components 2 -num_point_tests 2 -num_fe_tests 2 -num_fv_tests 2 -dmfield_view
388: test:
389: suffix: da_1
390: requires: !complex
391: args: -dm_type da -dim 1 -num_fe_tests 2
393: test:
394: suffix: da_2
395: requires: !complex
396: args: -dm_type da -dim 2 -num_fe_tests 2
398: test:
399: suffix: da_3
400: requires: !complex
401: args: -dm_type da -dim 3 -num_fe_tests 2
403: test:
404: suffix: ds
405: requires: !complex triangle
406: args: -dm_type plex -dim 2 -num_components 2 -num_point_tests 2 -num_fe_tests 2 -num_fv_tests 2 -dmfield_view -petscspace_degree 2 -num_quad_points 1
408: test:
409: suffix: ds_simplex_0
410: requires: !complex triangle
411: args: -dm_type plex -dim 2 -num_fe_tests 2 -petscspace_degree 0
413: test:
414: suffix: ds_simplex_1
415: requires: !complex triangle
416: args: -dm_type plex -dim 2 -num_fe_tests 2 -petscspace_degree 1
418: test:
419: suffix: ds_simplex_2
420: requires: !complex triangle
421: args: -dm_type plex -dim 2 -num_fe_tests 2 -petscspace_degree 2
423: test:
424: suffix: ds_tensor_2_0
425: requires: !complex
426: args: -dm_type plex -dim 2 -num_fe_tests 2 -petscspace_poly_tensor 1 -petscspace_degree 0 -simplex 0
428: test:
429: suffix: ds_tensor_2_1
430: requires: !complex
431: args: -dm_type plex -dim 2 -num_fe_tests 2 -petscspace_poly_tensor 1 -petscspace_degree 1 -simplex 0
433: test:
434: suffix: ds_tensor_2_2
435: requires: !complex
436: args: -dm_type plex -dim 2 -num_fe_tests 2 -petscspace_poly_tensor 1 -petscspace_degree 2 -simplex 0
438: test:
439: suffix: ds_tensor_3_0
440: requires: !complex
441: args: -dm_type plex -dim 3 -num_fe_tests 2 -petscspace_poly_tensor 1 -petscspace_degree 0 -simplex 0
443: test:
444: suffix: ds_tensor_3_1
445: requires: !complex
446: args: -dm_type plex -dim 3 -num_fe_tests 2 -petscspace_poly_tensor 1 -petscspace_degree 1 -simplex 0
448: test:
449: suffix: ds_tensor_3_2
450: requires: !complex
451: args: -dm_type plex -dim 3 -num_fe_tests 2 -petscspace_poly_tensor 1 -petscspace_degree 2 -simplex 0
453: test:
454: suffix: shell
455: requires: !complex triangle
456: args: -dm_type plex -dim 2 -num_components 2 -num_point_tests 2 -num_fe_tests 2 -num_fv_tests 2 -dmfield_view -num_quad_points 1 -test_shell
458: TEST*/