xref: /petsc/src/dm/impls/plex/tests/ex22.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
1c4762a1bSJed Brown 
2c4762a1bSJed Brown const char help[] = "Test DMPlexCoordinatesToReference().\n\n";
3c4762a1bSJed Brown 
4c4762a1bSJed Brown #include <petscdm.h>
5c4762a1bSJed Brown #include <petscdmplex.h>
6c4762a1bSJed Brown 
7d71ae5a4SJacob Faibussowitsch static PetscErrorCode testIdentity(DM dm, PetscBool dmIsSimplicial, PetscInt cell, PetscRandom randCtx, PetscInt numPoints, PetscReal tol)
8d71ae5a4SJacob Faibussowitsch {
9c4762a1bSJed Brown   PetscInt   i, j, dimC, dimR;
10c4762a1bSJed Brown   PetscReal *preimage, *mapped, *inverted;
11c4762a1bSJed Brown 
12c4762a1bSJed Brown   PetscFunctionBegin;
139566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dimR));
149566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimC));
15c4762a1bSJed Brown 
169566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, dimR * numPoints, MPIU_REAL, &preimage));
179566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, dimC * numPoints, MPIU_REAL, &mapped));
189566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, dimR * numPoints, MPIU_REAL, &inverted));
19c4762a1bSJed Brown 
2048a46eb9SPierre Jolivet   for (i = 0; i < dimR * numPoints; i++) PetscCall(PetscRandomGetValueReal(randCtx, &preimage[i]));
21c4762a1bSJed Brown   if (dmIsSimplicial && dimR > 1) {
22c4762a1bSJed Brown     for (i = 0; i < numPoints; i++) {
23c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
24c4762a1bSJed Brown         PetscReal x = preimage[i * dimR + j];
25c4762a1bSJed Brown         PetscReal y = preimage[i * dimR + ((j + 1) % dimR)];
26c4762a1bSJed Brown 
27c4762a1bSJed Brown         preimage[i * dimR + ((j + 1) % dimR)] = -1. + (y + 1.) * 0.5 * (1. - x);
28c4762a1bSJed Brown       }
29c4762a1bSJed Brown     }
30c4762a1bSJed Brown   }
31c4762a1bSJed Brown 
329566063dSJacob Faibussowitsch   PetscCall(DMPlexReferenceToCoordinates(dm, cell, numPoints, preimage, mapped));
339566063dSJacob Faibussowitsch   PetscCall(DMPlexCoordinatesToReference(dm, cell, numPoints, mapped, inverted));
34c4762a1bSJed Brown 
35c4762a1bSJed Brown   for (i = 0; i < numPoints; i++) {
36c4762a1bSJed Brown     PetscReal max = 0.;
37c4762a1bSJed Brown 
38ad540459SPierre Jolivet     for (j = 0; j < dimR; j++) max = PetscMax(max, PetscAbsReal(preimage[i * dimR + j] - inverted[i * dimR + j]));
39c4762a1bSJed Brown     if (max > tol) {
4063a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, "Bad inversion for cell %" PetscInt_FMT " with error %g (tol %g): (", cell, (double)max, (double)tol));
41c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
429566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "%+f", (double)preimage[i * dimR + j]));
4348a46eb9SPierre Jolivet         if (j < dimR - 1) PetscCall(PetscPrintf(PETSC_COMM_SELF, ","));
44c4762a1bSJed Brown       }
459566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, ") --> ("));
46c4762a1bSJed Brown       for (j = 0; j < dimC; j++) {
479566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "%+f", (double)mapped[i * dimC + j]));
4848a46eb9SPierre Jolivet         if (j < dimC - 1) PetscCall(PetscPrintf(PETSC_COMM_SELF, ","));
49c4762a1bSJed Brown       }
509566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, ") --> ("));
51c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
529566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "%+f", (double)inverted[i * dimR + j]));
5348a46eb9SPierre Jolivet         if (j < dimR - 1) PetscCall(PetscPrintf(PETSC_COMM_SELF, ","));
54c4762a1bSJed Brown       }
559566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, ")\n"));
56c4762a1bSJed Brown     } else {
57c4762a1bSJed Brown       char   strBuf[BUFSIZ] = {'\0'};
58c4762a1bSJed Brown       size_t offset         = 0, count;
59c4762a1bSJed Brown 
6063a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintfCount(strBuf + offset, BUFSIZ - offset, "Good inversion for cell %" PetscInt_FMT ": (", &count, cell));
61c4762a1bSJed Brown       offset += count;
62c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
639566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintfCount(strBuf + offset, BUFSIZ - offset, "%+f", &count, (double)preimage[i * dimR + j]));
64c4762a1bSJed Brown         offset += count;
65c4762a1bSJed Brown         if (j < dimR - 1) {
669566063dSJacob Faibussowitsch           PetscCall(PetscSNPrintfCount(strBuf + offset, BUFSIZ - offset, ",", &count));
67c4762a1bSJed Brown           offset += count;
68c4762a1bSJed Brown         }
69c4762a1bSJed Brown       }
709566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintfCount(strBuf + offset, BUFSIZ - offset, ") --> (", &count));
71c4762a1bSJed Brown       offset += count;
72c4762a1bSJed Brown       for (j = 0; j < dimC; j++) {
739566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintfCount(strBuf + offset, BUFSIZ - offset, "%+f", &count, (double)mapped[i * dimC + j]));
74c4762a1bSJed Brown         offset += count;
75c4762a1bSJed Brown         if (j < dimC - 1) {
769566063dSJacob Faibussowitsch           PetscCall(PetscSNPrintfCount(strBuf + offset, BUFSIZ - offset, ",", &count));
77c4762a1bSJed Brown           offset += count;
78c4762a1bSJed Brown         }
79c4762a1bSJed Brown       }
809566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintfCount(strBuf + offset, BUFSIZ - offset, ") --> (", &count));
81c4762a1bSJed Brown       offset += count;
82c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
839566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintfCount(strBuf + offset, BUFSIZ - offset, "%+f", &count, (double)inverted[i * dimR + j]));
84c4762a1bSJed Brown         offset += count;
85c4762a1bSJed Brown         if (j < dimR - 1) {
869566063dSJacob Faibussowitsch           PetscCall(PetscSNPrintfCount(strBuf + offset, BUFSIZ - offset, ",", &count));
87c4762a1bSJed Brown           offset += count;
88c4762a1bSJed Brown         }
89c4762a1bSJed Brown       }
909566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintfCount(strBuf + offset, BUFSIZ - offset, ")\n", &count));
919566063dSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "%s", strBuf));
92c4762a1bSJed Brown     }
93c4762a1bSJed Brown   }
94c4762a1bSJed Brown 
959566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, dimR * numPoints, MPIU_REAL, &inverted));
969566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, dimC * numPoints, MPIU_REAL, &mapped));
979566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, dimR * numPoints, MPIU_REAL, &preimage));
98*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99c4762a1bSJed Brown }
100c4762a1bSJed Brown 
101d71ae5a4SJacob Faibussowitsch static PetscErrorCode identityEmbedding(PetscInt dim, PetscReal time, const PetscReal *x, PetscInt Nf, PetscScalar *u, void *ctx)
102d71ae5a4SJacob Faibussowitsch {
103c4762a1bSJed Brown   PetscInt i;
104c4762a1bSJed Brown 
105ad540459SPierre Jolivet   for (i = 0; i < dim; i++) u[i] = x[i];
106*3ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
107c4762a1bSJed Brown }
108c4762a1bSJed Brown 
109d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
110d71ae5a4SJacob Faibussowitsch {
111c4762a1bSJed Brown   PetscRandom randCtx;
112c4762a1bSJed Brown   PetscInt    dim, dimC, isSimplex, isFE, numTests = 10;
113c4762a1bSJed Brown   PetscReal   perturb = 0.1, tol = 10. * PETSC_SMALL;
114c4762a1bSJed Brown 
115327415f7SBarry Smith   PetscFunctionBeginUser;
1169566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
1179566063dSJacob Faibussowitsch   PetscCall(PetscRandomCreate(PETSC_COMM_SELF, &randCtx));
1189566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetInterval(randCtx, -1., 1.));
1199566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetFromOptions(randCtx));
120d0609cedSBarry Smith   PetscOptionsBegin(PETSC_COMM_WORLD, NULL, "ex21", NULL);
1219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-vertex_perturbation", "scale of random vertex distortion", NULL, perturb, &perturb, NULL));
1229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-num_test_points", "number of points to test", NULL, numTests, &numTests, NULL, 0));
123d0609cedSBarry Smith   PetscOptionsEnd();
124c4762a1bSJed Brown   for (dim = 1; dim <= 3; dim++) {
125c4762a1bSJed Brown     for (dimC = dim; dimC <= PetscMin(3, dim + 1); dimC++) {
126c4762a1bSJed Brown       for (isSimplex = 0; isSimplex < 2; isSimplex++) {
127c4762a1bSJed Brown         for (isFE = 0; isFE < 2; isFE++) {
128c4762a1bSJed Brown           DM           dm;
129c4762a1bSJed Brown           Vec          coords;
130c4762a1bSJed Brown           PetscScalar *coordArray;
131c4762a1bSJed Brown           PetscReal    noise;
132c4762a1bSJed Brown           PetscInt     i, n, order = 1;
133c4762a1bSJed Brown 
1349566063dSJacob Faibussowitsch           PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex ? PETSC_TRUE : PETSC_FALSE), &dm));
135c4762a1bSJed Brown           if (isFE) {
136c4762a1bSJed Brown             DM         dmCoord;
137c4762a1bSJed Brown             PetscSpace sp;
138c4762a1bSJed Brown             PetscFE    fe;
139c4762a1bSJed Brown             Vec        localCoords;
140c4762a1bSJed Brown             PetscErrorCode (*funcs[1])(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *) = {identityEmbedding};
141c4762a1bSJed Brown             void *ctxs[1]                                                                                       = {NULL};
142c4762a1bSJed Brown 
1439566063dSJacob Faibussowitsch             PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)dm), dim, dim, isSimplex ? PETSC_TRUE : PETSC_FALSE, isSimplex ? NULL : "tensor_", PETSC_DEFAULT, &fe));
1449566063dSJacob Faibussowitsch             PetscCall(PetscFEGetBasisSpace(fe, &sp));
1459566063dSJacob Faibussowitsch             PetscCall(PetscSpaceGetDegree(sp, &order, NULL));
1469566063dSJacob Faibussowitsch             PetscCall(DMSetField(dm, 0, NULL, (PetscObject)fe));
1479566063dSJacob Faibussowitsch             PetscCall(DMCreateDS(dm));
1489566063dSJacob Faibussowitsch             PetscCall(DMCreateLocalVector(dm, &localCoords));
1499566063dSJacob Faibussowitsch             PetscCall(DMProjectFunctionLocal(dm, 0, funcs, ctxs, INSERT_VALUES, localCoords));
1509566063dSJacob Faibussowitsch             PetscCall(VecSetDM(localCoords, NULL)); /* This is necessary to prevent a reference loop */
1519566063dSJacob Faibussowitsch             PetscCall(DMClone(dm, &dmCoord));
1529566063dSJacob Faibussowitsch             PetscCall(DMSetField(dmCoord, 0, NULL, (PetscObject)fe));
1539566063dSJacob Faibussowitsch             PetscCall(PetscFEDestroy(&fe));
1549566063dSJacob Faibussowitsch             PetscCall(DMCreateDS(dmCoord));
1559566063dSJacob Faibussowitsch             PetscCall(DMSetCoordinateDM(dm, dmCoord));
1569566063dSJacob Faibussowitsch             PetscCall(DMDestroy(&dmCoord));
1579566063dSJacob Faibussowitsch             PetscCall(DMSetCoordinatesLocal(dm, localCoords));
1589566063dSJacob Faibussowitsch             PetscCall(VecDestroy(&localCoords));
159c4762a1bSJed Brown           }
16063a3b9bcSJacob Faibussowitsch           PetscCall(PetscInfo(dm, "Testing %s%" PetscInt_FMT " %" PetscInt_FMT "D mesh embedded in %" PetscInt_FMT "D\n", isSimplex ? "P" : "Q", order, dim, dimC));
1619566063dSJacob Faibussowitsch           PetscCall(DMGetCoordinatesLocal(dm, &coords));
1629566063dSJacob Faibussowitsch           PetscCall(VecGetLocalSize(coords, &n));
163c4762a1bSJed Brown           if (dimC > dim) { /* reembed in higher dimension */
164c4762a1bSJed Brown             PetscSection sec, newSec;
165c4762a1bSJed Brown             PetscInt     pStart, pEnd, p, i, newN;
166c4762a1bSJed Brown             Vec          newVec;
167c4762a1bSJed Brown             DM           coordDM;
168c4762a1bSJed Brown             PetscScalar *newCoordArray;
169c4762a1bSJed Brown 
1709566063dSJacob Faibussowitsch             PetscCall(DMGetCoordinateSection(dm, &sec));
1719566063dSJacob Faibussowitsch             PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)sec), &newSec));
1729566063dSJacob Faibussowitsch             PetscCall(PetscSectionSetNumFields(newSec, 1));
1739566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetChart(sec, &pStart, &pEnd));
1749566063dSJacob Faibussowitsch             PetscCall(PetscSectionSetChart(newSec, pStart, pEnd));
175c4762a1bSJed Brown             for (p = pStart; p < pEnd; p++) {
176c4762a1bSJed Brown               PetscInt nDof;
177c4762a1bSJed Brown 
1789566063dSJacob Faibussowitsch               PetscCall(PetscSectionGetDof(sec, p, &nDof));
17963a3b9bcSJacob Faibussowitsch               PetscCheck(nDof % dim == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Coordinate section point %" PetscInt_FMT " has %" PetscInt_FMT " dofs != 0 mod %" PetscInt_FMT, p, nDof, dim);
1809566063dSJacob Faibussowitsch               PetscCall(PetscSectionSetDof(newSec, p, (nDof / dim) * dimC));
1819566063dSJacob Faibussowitsch               PetscCall(PetscSectionSetFieldDof(newSec, p, 0, (nDof / dim) * dimC));
182c4762a1bSJed Brown             }
1839566063dSJacob Faibussowitsch             PetscCall(PetscSectionSetUp(newSec));
1849566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetStorageSize(newSec, &newN));
1859566063dSJacob Faibussowitsch             PetscCall(VecCreateSeq(PETSC_COMM_SELF, newN, &newVec));
1869566063dSJacob Faibussowitsch             PetscCall(VecGetArray(newVec, &newCoordArray));
1879566063dSJacob Faibussowitsch             PetscCall(VecGetArray(coords, &coordArray));
188c4762a1bSJed Brown             for (i = 0; i < n / dim; i++) {
189c4762a1bSJed Brown               PetscInt j;
190c4762a1bSJed Brown 
191ad540459SPierre Jolivet               for (j = 0; j < dim; j++) newCoordArray[i * dimC + j] = coordArray[i * dim + j];
192ad540459SPierre Jolivet               for (; j < dimC; j++) newCoordArray[i * dimC + j] = 0.;
193c4762a1bSJed Brown             }
1949566063dSJacob Faibussowitsch             PetscCall(VecRestoreArray(coords, &coordArray));
1959566063dSJacob Faibussowitsch             PetscCall(VecRestoreArray(newVec, &newCoordArray));
1969566063dSJacob Faibussowitsch             PetscCall(DMSetCoordinateDim(dm, dimC));
1979566063dSJacob Faibussowitsch             PetscCall(DMSetCoordinateSection(dm, dimC, newSec));
1989566063dSJacob Faibussowitsch             PetscCall(DMSetCoordinatesLocal(dm, newVec));
1999566063dSJacob Faibussowitsch             PetscCall(VecDestroy(&newVec));
2009566063dSJacob Faibussowitsch             PetscCall(PetscSectionDestroy(&newSec));
2019566063dSJacob Faibussowitsch             PetscCall(DMGetCoordinatesLocal(dm, &coords));
2029566063dSJacob Faibussowitsch             PetscCall(DMGetCoordinateDM(dm, &coordDM));
203c4762a1bSJed Brown             if (isFE) {
204c4762a1bSJed Brown               PetscFE fe;
205c4762a1bSJed Brown 
2069566063dSJacob Faibussowitsch               PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)dm), dim, dimC, isSimplex ? PETSC_TRUE : PETSC_FALSE, isSimplex ? NULL : "tensor_", PETSC_DEFAULT, &fe));
2079566063dSJacob Faibussowitsch               PetscCall(DMSetField(coordDM, 0, NULL, (PetscObject)fe));
2089566063dSJacob Faibussowitsch               PetscCall(PetscFEDestroy(&fe));
2099566063dSJacob Faibussowitsch               PetscCall(DMCreateDS(coordDM));
210c4762a1bSJed Brown             }
2119566063dSJacob Faibussowitsch             PetscCall(DMSetCoordinateDim(coordDM, dimC));
2129566063dSJacob Faibussowitsch             PetscCall(VecGetLocalSize(coords, &n));
213c4762a1bSJed Brown           }
2149566063dSJacob Faibussowitsch           PetscCall(VecGetArray(coords, &coordArray));
215c4762a1bSJed Brown           for (i = 0; i < n; i++) {
2169566063dSJacob Faibussowitsch             PetscCall(PetscRandomGetValueReal(randCtx, &noise));
217c4762a1bSJed Brown             coordArray[i] += noise * perturb;
218c4762a1bSJed Brown           }
2199566063dSJacob Faibussowitsch           PetscCall(VecRestoreArray(coords, &coordArray));
2209566063dSJacob Faibussowitsch           PetscCall(DMSetCoordinatesLocal(dm, coords));
2219566063dSJacob Faibussowitsch           PetscCall(testIdentity(dm, isSimplex ? PETSC_TRUE : PETSC_FALSE, 0, randCtx, numTests, tol));
2229566063dSJacob Faibussowitsch           PetscCall(DMDestroy(&dm));
223c4762a1bSJed Brown         }
224c4762a1bSJed Brown       }
225c4762a1bSJed Brown     }
226c4762a1bSJed Brown   }
2279566063dSJacob Faibussowitsch   PetscCall(PetscRandomDestroy(&randCtx));
2289566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
229b122ec5aSJacob Faibussowitsch   return 0;
230c4762a1bSJed Brown }
231c4762a1bSJed Brown 
232c4762a1bSJed Brown /*TEST
233c4762a1bSJed Brown 
234c4762a1bSJed Brown   test:
235c4762a1bSJed Brown     suffix: 0
236c4762a1bSJed Brown     args: -petscspace_degree 2 -tensor_petscspace_degree 2
237c4762a1bSJed Brown 
238c4762a1bSJed Brown TEST*/
239