xref: /petsc/src/dm/impls/plex/tests/ex22.c (revision b122ec5aa1bd4469eb4e0673542fb7de3f411254)
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;
135f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm,&dimR));
145f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDim(dm,&dimC));
15c4762a1bSJed Brown 
165f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm,dimR * numPoints,MPIU_REAL,&preimage));
175f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm,dimC * numPoints,MPIU_REAL,&mapped));
185f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm,dimR * numPoints,MPIU_REAL,&inverted));
19c4762a1bSJed Brown 
20c4762a1bSJed Brown   for (i = 0; i < dimR * numPoints; i++) {
215f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
345f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexReferenceToCoordinates(dm,cell,numPoints,preimage,mapped));
355f80ce2aSJacob Faibussowitsch   CHKERRQ(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) {
445f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"Bad inversion for cell %D with error %g (tol %g): (",cell,(double)max,(double)tol));
45c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
465f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"%+f",(double) preimage[i * dimR + j]));
47c4762a1bSJed Brown         if (j < dimR - 1) {
485f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscPrintf(PETSC_COMM_SELF,","));
49c4762a1bSJed Brown         }
50c4762a1bSJed Brown       }
515f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscPrintf(PETSC_COMM_SELF,") --> ("));
52c4762a1bSJed Brown       for (j = 0; j < dimC; j++) {
535f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"%+f",(double) mapped[i * dimC + j]));
54c4762a1bSJed Brown         if (j < dimC - 1) {
555f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscPrintf(PETSC_COMM_SELF,","));
56c4762a1bSJed Brown         }
57c4762a1bSJed Brown       }
585f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscPrintf(PETSC_COMM_SELF,") --> ("));
59c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
605f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"%+f",(double) inverted[i * dimR + j]));
61c4762a1bSJed Brown         if (j < dimR - 1) {
625f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscPrintf(PETSC_COMM_SELF,","));
63c4762a1bSJed Brown         }
64c4762a1bSJed Brown       }
655f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscPrintf(PETSC_COMM_SELF,")\n"));
66c4762a1bSJed Brown     } else {
67c4762a1bSJed Brown       char   strBuf[BUFSIZ] = {'\0'};
68c4762a1bSJed Brown       size_t offset = 0, count;
69c4762a1bSJed Brown 
705f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,"Good inversion for cell %D: (",&count,cell));
71c4762a1bSJed Brown       offset += count;
72c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
735f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,"%+f",&count,(double) preimage[i * dimR + j]));
74c4762a1bSJed Brown         offset += count;
75c4762a1bSJed Brown         if (j < dimR - 1) {
765f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,",",&count));
77c4762a1bSJed Brown           offset += count;
78c4762a1bSJed Brown         }
79c4762a1bSJed Brown       }
805f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,") --> (",&count));
81c4762a1bSJed Brown       offset += count;
82c4762a1bSJed Brown       for (j = 0; j < dimC; j++) {
835f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,"%+f",&count,(double) mapped[i * dimC + j]));
84c4762a1bSJed Brown         offset += count;
85c4762a1bSJed Brown         if (j < dimC - 1) {
865f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,",",&count));
87c4762a1bSJed Brown           offset += count;
88c4762a1bSJed Brown         }
89c4762a1bSJed Brown       }
905f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,") --> (",&count));
91c4762a1bSJed Brown       offset += count;
92c4762a1bSJed Brown       for (j = 0; j < dimR; j++) {
935f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,"%+f",&count,(double) inverted[i * dimR + j]));
94c4762a1bSJed Brown         offset += count;
95c4762a1bSJed Brown         if (j < dimR - 1) {
965f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,",",&count));
97c4762a1bSJed Brown           offset += count;
98c4762a1bSJed Brown         }
99c4762a1bSJed Brown       }
1005f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSNPrintfCount(strBuf + offset,BUFSIZ-offset,")\n",&count));
1015f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscInfo(dm,"%s",strBuf));
102c4762a1bSJed Brown     }
103c4762a1bSJed Brown   }
104c4762a1bSJed Brown 
1055f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm,dimR * numPoints,MPIU_REAL,&inverted));
1065f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm,dimC * numPoints,MPIU_REAL,&mapped));
1075f80ce2aSJacob Faibussowitsch   CHKERRQ(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   PetscErrorCode ierr;
125c4762a1bSJed Brown 
126*b122ec5aSJacob Faibussowitsch   CHKERRQ(PetscInitialize(&argc,&argv,NULL,help));
1275f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomCreate(PETSC_COMM_SELF,&randCtx));
1285f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomSetInterval(randCtx,-1.,1.));
1295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomSetFromOptions(randCtx));
130c4762a1bSJed Brown   ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"ex21",NULL);CHKERRQ(ierr);
1315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsReal("-vertex_perturbation","scale of random vertex distortion",NULL,perturb,&perturb,NULL));
1325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-num_test_points","number of points to test",NULL,numTests,&numTests,NULL,0));
133c4762a1bSJed Brown   ierr = PetscOptionsEnd();CHKERRQ(ierr);
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 
1445f80ce2aSJacob Faibussowitsch           CHKERRQ(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 
1535f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscFECreateDefault(PetscObjectComm((PetscObject) dm),dim,dim,isSimplex ? PETSC_TRUE : PETSC_FALSE,isSimplex ? NULL : "tensor_" ,PETSC_DEFAULT,&fe));
1545f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscFEGetBasisSpace(fe,&sp));
1555f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSpaceGetDegree(sp,&order,NULL));
1565f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetField(dm,0,NULL,(PetscObject)fe));
1575f80ce2aSJacob Faibussowitsch             CHKERRQ(DMCreateDS(dm));
1585f80ce2aSJacob Faibussowitsch             CHKERRQ(DMCreateLocalVector(dm,&localCoords));
1595f80ce2aSJacob Faibussowitsch             CHKERRQ(DMProjectFunctionLocal(dm,0,funcs,ctxs,INSERT_VALUES,localCoords));
1605f80ce2aSJacob Faibussowitsch             CHKERRQ(VecSetDM(localCoords,NULL)); /* This is necessary to prevent a reference loop */
1615f80ce2aSJacob Faibussowitsch             CHKERRQ(DMClone(dm,&dmCoord));
1625f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetField(dmCoord,0,NULL,(PetscObject)fe));
1635f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscFEDestroy(&fe));
1645f80ce2aSJacob Faibussowitsch             CHKERRQ(DMCreateDS(dmCoord));
1655f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetCoordinateDM(dm,dmCoord));
1665f80ce2aSJacob Faibussowitsch             CHKERRQ(DMDestroy(&dmCoord));
1675f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetCoordinatesLocal(dm,localCoords));
1685f80ce2aSJacob Faibussowitsch             CHKERRQ(VecDestroy(&localCoords));
169c4762a1bSJed Brown           }
1705f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscInfo(dm,"Testing %s%D %DD mesh embedded in %DD\n",isSimplex ? "P" : "Q" , order, dim, dimC));
1715f80ce2aSJacob Faibussowitsch           CHKERRQ(DMGetCoordinatesLocal(dm,&coords));
1725f80ce2aSJacob Faibussowitsch           CHKERRQ(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 
1805f80ce2aSJacob Faibussowitsch             CHKERRQ(DMGetCoordinateSection(dm,&sec));
1815f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)sec),&newSec));
1825f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionSetNumFields(newSec,1));
1835f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionGetChart(sec,&pStart,&pEnd));
1845f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionSetChart(newSec,pStart,pEnd));
185c4762a1bSJed Brown             for (p = pStart; p < pEnd; p++) {
186c4762a1bSJed Brown               PetscInt nDof;
187c4762a1bSJed Brown 
1885f80ce2aSJacob Faibussowitsch               CHKERRQ(PetscSectionGetDof(sec,p,&nDof));
1892c71b3e2SJacob Faibussowitsch               PetscCheckFalse(nDof % dim,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Coordinate section point %D has %D dofs != 0 mod %D",p,nDof,dim);
1905f80ce2aSJacob Faibussowitsch               CHKERRQ(PetscSectionSetDof(newSec,p,(nDof/dim)*dimC));
1915f80ce2aSJacob Faibussowitsch               CHKERRQ(PetscSectionSetFieldDof(newSec,p,0,(nDof/dim)*dimC));
192c4762a1bSJed Brown             }
1935f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionSetUp(newSec));
1945f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionGetStorageSize(newSec,&newN));
1955f80ce2aSJacob Faibussowitsch             CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,newN,&newVec));
1965f80ce2aSJacob Faibussowitsch             CHKERRQ(VecGetArray(newVec,&newCoordArray));
1975f80ce2aSJacob Faibussowitsch             CHKERRQ(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             }
2085f80ce2aSJacob Faibussowitsch             CHKERRQ(VecRestoreArray(coords,&coordArray));
2095f80ce2aSJacob Faibussowitsch             CHKERRQ(VecRestoreArray(newVec,&newCoordArray));
2105f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetCoordinateDim(dm,dimC));
2115f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetCoordinateSection(dm,dimC,newSec));
2125f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetCoordinatesLocal(dm,newVec));
2135f80ce2aSJacob Faibussowitsch             CHKERRQ(VecDestroy(&newVec));
2145f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionDestroy(&newSec));
2155f80ce2aSJacob Faibussowitsch             CHKERRQ(DMGetCoordinatesLocal(dm,&coords));
2165f80ce2aSJacob Faibussowitsch             CHKERRQ(DMGetCoordinateDM(dm,&coordDM));
217c4762a1bSJed Brown             if (isFE) {
218c4762a1bSJed Brown               PetscFE fe;
219c4762a1bSJed Brown 
2205f80ce2aSJacob Faibussowitsch               CHKERRQ(PetscFECreateDefault(PetscObjectComm((PetscObject) dm),dim,dimC,isSimplex ? PETSC_TRUE : PETSC_FALSE,isSimplex ? NULL : "tensor_",PETSC_DEFAULT,&fe));
2215f80ce2aSJacob Faibussowitsch               CHKERRQ(DMSetField(coordDM,0,NULL,(PetscObject)fe));
2225f80ce2aSJacob Faibussowitsch               CHKERRQ(PetscFEDestroy(&fe));
2235f80ce2aSJacob Faibussowitsch               CHKERRQ(DMCreateDS(coordDM));
224c4762a1bSJed Brown             }
2255f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetCoordinateDim(coordDM,dimC));
2265f80ce2aSJacob Faibussowitsch             CHKERRQ(VecGetLocalSize(coords,&n));
227c4762a1bSJed Brown           }
2285f80ce2aSJacob Faibussowitsch           CHKERRQ(VecGetArray(coords,&coordArray));
229c4762a1bSJed Brown           for (i = 0; i < n; i++) {
2305f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscRandomGetValueReal(randCtx,&noise));
231c4762a1bSJed Brown             coordArray[i] += noise * perturb;
232c4762a1bSJed Brown           }
2335f80ce2aSJacob Faibussowitsch           CHKERRQ(VecRestoreArray(coords,&coordArray));
2345f80ce2aSJacob Faibussowitsch           CHKERRQ(DMSetCoordinatesLocal(dm, coords));
2355f80ce2aSJacob Faibussowitsch           CHKERRQ(testIdentity(dm, isSimplex ? PETSC_TRUE : PETSC_FALSE, 0, randCtx, numTests, tol));
2365f80ce2aSJacob Faibussowitsch           CHKERRQ(DMDestroy(&dm));
237c4762a1bSJed Brown         }
238c4762a1bSJed Brown       }
239c4762a1bSJed Brown     }
240c4762a1bSJed Brown   }
2415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomDestroy(&randCtx));
242*b122ec5aSJacob Faibussowitsch   CHKERRQ(PetscFinalize());
243*b122ec5aSJacob 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