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