xref: /petsc/src/dm/impls/plex/tests/ex22.c (revision 327415f76d85372a4417cf1aaa14db707d4d6c04)
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 
7c4762a1bSJed Brown static PetscErrorCode testIdentity(DM dm, PetscBool dmIsSimplicial, PetscInt cell, PetscRandom randCtx, PetscInt numPoints, PetscReal tol)
8c4762a1bSJed Brown {
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 
20c4762a1bSJed Brown   for (i = 0; i < dimR * numPoints; i++) {
219566063dSJacob Faibussowitsch     PetscCall(PetscRandomGetValueReal(randCtx, &preimage[i]));
22c4762a1bSJed Brown   }
23c4762a1bSJed Brown   if (dmIsSimplicial && dimR > 1) {
24c4762a1bSJed Brown     for (i = 0; i < numPoints; i++) {
25c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
26c4762a1bSJed Brown         PetscReal x = preimage[i * dimR + j];
27c4762a1bSJed Brown         PetscReal y = preimage[i * dimR + ((j + 1) % dimR)];
28c4762a1bSJed Brown 
29c4762a1bSJed Brown         preimage[i * dimR + ((j + 1) % dimR)] = -1. + (y + 1.) * 0.5 * (1. - x);
30c4762a1bSJed Brown       }
31c4762a1bSJed Brown     }
32c4762a1bSJed Brown   }
33c4762a1bSJed Brown 
349566063dSJacob Faibussowitsch   PetscCall(DMPlexReferenceToCoordinates(dm,cell,numPoints,preimage,mapped));
359566063dSJacob Faibussowitsch   PetscCall(DMPlexCoordinatesToReference(dm,cell,numPoints,mapped,inverted));
36c4762a1bSJed Brown 
37c4762a1bSJed Brown   for (i = 0; i < numPoints; i++) {
38c4762a1bSJed Brown     PetscReal max = 0.;
39c4762a1bSJed Brown 
40c4762a1bSJed Brown     for (j = 0; j < dimR; j++) {
41c4762a1bSJed Brown       max = PetscMax(max,PetscAbsReal(preimage[i * dimR + j] - inverted[i * dimR + j]));
42c4762a1bSJed Brown     }
43c4762a1bSJed Brown     if (max > tol) {
4463a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF,"Bad inversion for cell %" PetscInt_FMT " with error %g (tol %g): (",cell,(double)max,(double)tol));
45c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
469566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF,"%+f",(double) preimage[i * dimR + j]));
47c4762a1bSJed Brown         if (j < dimR - 1) {
489566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF,","));
49c4762a1bSJed Brown         }
50c4762a1bSJed Brown       }
519566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF,") --> ("));
52c4762a1bSJed Brown       for (j = 0; j < dimC; j++) {
539566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF,"%+f",(double) mapped[i * dimC + j]));
54c4762a1bSJed Brown         if (j < dimC - 1) {
559566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF,","));
56c4762a1bSJed Brown         }
57c4762a1bSJed Brown       }
589566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF,") --> ("));
59c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
609566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF,"%+f",(double) inverted[i * dimR + j]));
61c4762a1bSJed Brown         if (j < dimR - 1) {
629566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF,","));
63c4762a1bSJed Brown         }
64c4762a1bSJed Brown       }
659566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF,")\n"));
66c4762a1bSJed Brown     } else {
67c4762a1bSJed Brown       char   strBuf[BUFSIZ] = {'\0'};
68c4762a1bSJed Brown       size_t offset = 0, count;
69c4762a1bSJed Brown 
7063a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,"Good inversion for cell %" PetscInt_FMT ": (",&count,cell));
71c4762a1bSJed Brown       offset += count;
72c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
739566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,"%+f",&count,(double) preimage[i * dimR + j]));
74c4762a1bSJed Brown         offset += count;
75c4762a1bSJed Brown         if (j < dimR - 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 < dimC; j++) {
839566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,"%+f",&count,(double) mapped[i * dimC + j]));
84c4762a1bSJed Brown         offset += count;
85c4762a1bSJed Brown         if (j < dimC - 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,") --> (",&count));
91c4762a1bSJed Brown       offset += count;
92c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
939566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,"%+f",&count,(double) inverted[i * dimR + j]));
94c4762a1bSJed Brown         offset += count;
95c4762a1bSJed Brown         if (j < dimR - 1) {
969566063dSJacob Faibussowitsch           PetscCall(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,",",&count));
97c4762a1bSJed Brown           offset += count;
98c4762a1bSJed Brown         }
99c4762a1bSJed Brown       }
1009566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,")\n",&count));
1019566063dSJacob Faibussowitsch       PetscCall(PetscInfo(dm,"%s",strBuf));
102c4762a1bSJed Brown     }
103c4762a1bSJed Brown   }
104c4762a1bSJed Brown 
1059566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm,dimR * numPoints,MPIU_REAL,&inverted));
1069566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm,dimC * numPoints,MPIU_REAL,&mapped));
1079566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm,dimR * numPoints,MPIU_REAL,&preimage));
108c4762a1bSJed Brown   PetscFunctionReturn(0);
109c4762a1bSJed Brown }
110c4762a1bSJed Brown 
111c4762a1bSJed Brown static PetscErrorCode identityEmbedding(PetscInt dim, PetscReal time, const PetscReal *x, PetscInt Nf, PetscScalar *u, void *ctx)
112c4762a1bSJed Brown {
113c4762a1bSJed Brown   PetscInt i;
114c4762a1bSJed Brown 
115c4762a1bSJed Brown   for (i = 0; i < dim; i++) {u[i] = x[i];};
116c4762a1bSJed Brown   return 0;
117c4762a1bSJed Brown }
118c4762a1bSJed Brown 
119c4762a1bSJed Brown int main(int argc, char **argv)
120c4762a1bSJed Brown {
121c4762a1bSJed Brown   PetscRandom    randCtx;
122c4762a1bSJed Brown   PetscInt       dim, dimC, isSimplex, isFE, numTests = 10;
123c4762a1bSJed Brown   PetscReal      perturb = 0.1, tol = 10. * PETSC_SMALL;
124c4762a1bSJed Brown 
125*327415f7SBarry Smith   PetscFunctionBeginUser;
1269566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc,&argv,NULL,help));
1279566063dSJacob Faibussowitsch   PetscCall(PetscRandomCreate(PETSC_COMM_SELF,&randCtx));
1289566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetInterval(randCtx,-1.,1.));
1299566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetFromOptions(randCtx));
130d0609cedSBarry Smith   PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"ex21",NULL);
1319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-vertex_perturbation","scale of random vertex distortion",NULL,perturb,&perturb,NULL));
1329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-num_test_points","number of points to test",NULL,numTests,&numTests,NULL,0));
133d0609cedSBarry Smith   PetscOptionsEnd();
134c4762a1bSJed Brown   for (dim = 1; dim <= 3; dim++) {
135c4762a1bSJed Brown     for (dimC = dim; dimC <= PetscMin(3,dim + 1); dimC++) {
136c4762a1bSJed Brown       for (isSimplex = 0; isSimplex < 2; isSimplex++) {
137c4762a1bSJed Brown         for (isFE = 0; isFE < 2; isFE++) {
138c4762a1bSJed Brown           DM           dm;
139c4762a1bSJed Brown           Vec          coords;
140c4762a1bSJed Brown           PetscScalar *coordArray;
141c4762a1bSJed Brown           PetscReal    noise;
142c4762a1bSJed Brown           PetscInt     i, n, order = 1;
143c4762a1bSJed Brown 
1449566063dSJacob Faibussowitsch           PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex ? PETSC_TRUE : PETSC_FALSE), &dm));
145c4762a1bSJed Brown           if (isFE) {
146c4762a1bSJed Brown             DM             dmCoord;
147c4762a1bSJed Brown             PetscSpace     sp;
148c4762a1bSJed Brown             PetscFE        fe;
149c4762a1bSJed Brown             Vec            localCoords;
150c4762a1bSJed Brown             PetscErrorCode (*funcs[1])(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *) = {identityEmbedding};
151c4762a1bSJed Brown             void           *ctxs[1] = {NULL};
152c4762a1bSJed Brown 
1539566063dSJacob Faibussowitsch             PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject) dm),dim,dim,isSimplex ? PETSC_TRUE : PETSC_FALSE,isSimplex ? NULL : "tensor_" ,PETSC_DEFAULT,&fe));
1549566063dSJacob Faibussowitsch             PetscCall(PetscFEGetBasisSpace(fe,&sp));
1559566063dSJacob Faibussowitsch             PetscCall(PetscSpaceGetDegree(sp,&order,NULL));
1569566063dSJacob Faibussowitsch             PetscCall(DMSetField(dm,0,NULL,(PetscObject)fe));
1579566063dSJacob Faibussowitsch             PetscCall(DMCreateDS(dm));
1589566063dSJacob Faibussowitsch             PetscCall(DMCreateLocalVector(dm,&localCoords));
1599566063dSJacob Faibussowitsch             PetscCall(DMProjectFunctionLocal(dm,0,funcs,ctxs,INSERT_VALUES,localCoords));
1609566063dSJacob Faibussowitsch             PetscCall(VecSetDM(localCoords,NULL)); /* This is necessary to prevent a reference loop */
1619566063dSJacob Faibussowitsch             PetscCall(DMClone(dm,&dmCoord));
1629566063dSJacob Faibussowitsch             PetscCall(DMSetField(dmCoord,0,NULL,(PetscObject)fe));
1639566063dSJacob Faibussowitsch             PetscCall(PetscFEDestroy(&fe));
1649566063dSJacob Faibussowitsch             PetscCall(DMCreateDS(dmCoord));
1659566063dSJacob Faibussowitsch             PetscCall(DMSetCoordinateDM(dm,dmCoord));
1669566063dSJacob Faibussowitsch             PetscCall(DMDestroy(&dmCoord));
1679566063dSJacob Faibussowitsch             PetscCall(DMSetCoordinatesLocal(dm,localCoords));
1689566063dSJacob Faibussowitsch             PetscCall(VecDestroy(&localCoords));
169c4762a1bSJed Brown           }
17063a3b9bcSJacob Faibussowitsch           PetscCall(PetscInfo(dm,"Testing %s%" PetscInt_FMT " %" PetscInt_FMT "D mesh embedded in %" PetscInt_FMT "D\n",isSimplex ? "P" : "Q" , order, dim, dimC));
1719566063dSJacob Faibussowitsch           PetscCall(DMGetCoordinatesLocal(dm,&coords));
1729566063dSJacob Faibussowitsch           PetscCall(VecGetLocalSize(coords,&n));
173c4762a1bSJed Brown           if (dimC > dim) { /* reembed in higher dimension */
174c4762a1bSJed Brown             PetscSection sec, newSec;
175c4762a1bSJed Brown             PetscInt     pStart, pEnd, p, i, newN;
176c4762a1bSJed Brown             Vec          newVec;
177c4762a1bSJed Brown             DM           coordDM;
178c4762a1bSJed Brown             PetscScalar  *newCoordArray;
179c4762a1bSJed Brown 
1809566063dSJacob Faibussowitsch             PetscCall(DMGetCoordinateSection(dm,&sec));
1819566063dSJacob Faibussowitsch             PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)sec),&newSec));
1829566063dSJacob Faibussowitsch             PetscCall(PetscSectionSetNumFields(newSec,1));
1839566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetChart(sec,&pStart,&pEnd));
1849566063dSJacob Faibussowitsch             PetscCall(PetscSectionSetChart(newSec,pStart,pEnd));
185c4762a1bSJed Brown             for (p = pStart; p < pEnd; p++) {
186c4762a1bSJed Brown               PetscInt nDof;
187c4762a1bSJed Brown 
1889566063dSJacob Faibussowitsch               PetscCall(PetscSectionGetDof(sec,p,&nDof));
18963a3b9bcSJacob 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);
1909566063dSJacob Faibussowitsch               PetscCall(PetscSectionSetDof(newSec,p,(nDof/dim)*dimC));
1919566063dSJacob Faibussowitsch               PetscCall(PetscSectionSetFieldDof(newSec,p,0,(nDof/dim)*dimC));
192c4762a1bSJed Brown             }
1939566063dSJacob Faibussowitsch             PetscCall(PetscSectionSetUp(newSec));
1949566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetStorageSize(newSec,&newN));
1959566063dSJacob Faibussowitsch             PetscCall(VecCreateSeq(PETSC_COMM_SELF,newN,&newVec));
1969566063dSJacob Faibussowitsch             PetscCall(VecGetArray(newVec,&newCoordArray));
1979566063dSJacob Faibussowitsch             PetscCall(VecGetArray(coords,&coordArray));
198c4762a1bSJed Brown             for (i = 0; i < n / dim; i++) {
199c4762a1bSJed Brown               PetscInt j;
200c4762a1bSJed Brown 
201c4762a1bSJed Brown               for (j = 0; j < dim; j++) {
202c4762a1bSJed Brown                 newCoordArray[i * dimC + j] = coordArray[i * dim + j];
203c4762a1bSJed Brown               }
204c4762a1bSJed Brown               for (; j < dimC; j++) {
205c4762a1bSJed Brown                 newCoordArray[i * dimC + j] = 0.;
206c4762a1bSJed Brown               }
207c4762a1bSJed Brown             }
2089566063dSJacob Faibussowitsch             PetscCall(VecRestoreArray(coords,&coordArray));
2099566063dSJacob Faibussowitsch             PetscCall(VecRestoreArray(newVec,&newCoordArray));
2109566063dSJacob Faibussowitsch             PetscCall(DMSetCoordinateDim(dm,dimC));
2119566063dSJacob Faibussowitsch             PetscCall(DMSetCoordinateSection(dm,dimC,newSec));
2129566063dSJacob Faibussowitsch             PetscCall(DMSetCoordinatesLocal(dm,newVec));
2139566063dSJacob Faibussowitsch             PetscCall(VecDestroy(&newVec));
2149566063dSJacob Faibussowitsch             PetscCall(PetscSectionDestroy(&newSec));
2159566063dSJacob Faibussowitsch             PetscCall(DMGetCoordinatesLocal(dm,&coords));
2169566063dSJacob Faibussowitsch             PetscCall(DMGetCoordinateDM(dm,&coordDM));
217c4762a1bSJed Brown             if (isFE) {
218c4762a1bSJed Brown               PetscFE fe;
219c4762a1bSJed Brown 
2209566063dSJacob Faibussowitsch               PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject) dm),dim,dimC,isSimplex ? PETSC_TRUE : PETSC_FALSE,isSimplex ? NULL : "tensor_",PETSC_DEFAULT,&fe));
2219566063dSJacob Faibussowitsch               PetscCall(DMSetField(coordDM,0,NULL,(PetscObject)fe));
2229566063dSJacob Faibussowitsch               PetscCall(PetscFEDestroy(&fe));
2239566063dSJacob Faibussowitsch               PetscCall(DMCreateDS(coordDM));
224c4762a1bSJed Brown             }
2259566063dSJacob Faibussowitsch             PetscCall(DMSetCoordinateDim(coordDM,dimC));
2269566063dSJacob Faibussowitsch             PetscCall(VecGetLocalSize(coords,&n));
227c4762a1bSJed Brown           }
2289566063dSJacob Faibussowitsch           PetscCall(VecGetArray(coords,&coordArray));
229c4762a1bSJed Brown           for (i = 0; i < n; i++) {
2309566063dSJacob Faibussowitsch             PetscCall(PetscRandomGetValueReal(randCtx,&noise));
231c4762a1bSJed Brown             coordArray[i] += noise * perturb;
232c4762a1bSJed Brown           }
2339566063dSJacob Faibussowitsch           PetscCall(VecRestoreArray(coords,&coordArray));
2349566063dSJacob Faibussowitsch           PetscCall(DMSetCoordinatesLocal(dm, coords));
2359566063dSJacob Faibussowitsch           PetscCall(testIdentity(dm, isSimplex ? PETSC_TRUE : PETSC_FALSE, 0, randCtx, numTests, tol));
2369566063dSJacob Faibussowitsch           PetscCall(DMDestroy(&dm));
237c4762a1bSJed Brown         }
238c4762a1bSJed Brown       }
239c4762a1bSJed Brown     }
240c4762a1bSJed Brown   }
2419566063dSJacob Faibussowitsch   PetscCall(PetscRandomDestroy(&randCtx));
2429566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
243b122ec5aSJacob Faibussowitsch   return 0;
244c4762a1bSJed Brown }
245c4762a1bSJed Brown 
246c4762a1bSJed Brown /*TEST
247c4762a1bSJed Brown 
248c4762a1bSJed Brown   test:
249c4762a1bSJed Brown     suffix: 0
250c4762a1bSJed Brown     args: -petscspace_degree 2 -tensor_petscspace_degree 2
251c4762a1bSJed Brown 
252c4762a1bSJed Brown TEST*/
253