1c4762a1bSJed Brown static char help[] = "Tests affine subspaces.\n\n"; 2c4762a1bSJed Brown 3c4762a1bSJed Brown #include <petscfe.h> 4c4762a1bSJed Brown #include <petscdmplex.h> 5c4762a1bSJed Brown #include <petscdmshell.h> 6c4762a1bSJed Brown 7c4762a1bSJed Brown int main(int argc, char **argv) 8c4762a1bSJed Brown { 9c4762a1bSJed Brown DM dm; 10c4762a1bSJed Brown PetscFE fe; 11c4762a1bSJed Brown PetscSpace space; 12c4762a1bSJed Brown PetscDualSpace dualspace, dualsubspace; 13c4762a1bSJed Brown PetscInt dim = 2, Nc = 3, cStart, cEnd; 14c4762a1bSJed Brown PetscBool simplex = PETSC_TRUE; 15c4762a1bSJed Brown MPI_Comm comm; 16c4762a1bSJed Brown PetscErrorCode ierr; 17c4762a1bSJed Brown 18c4762a1bSJed Brown ierr = PetscInitialize(&argc,&argv,NULL,help);if (ierr) return ierr; 19c4762a1bSJed Brown comm = PETSC_COMM_WORLD; 20c4762a1bSJed Brown ierr = PetscOptionsBegin(comm,"","Options for subspace test","none");CHKERRQ(ierr); 21*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsRangeInt("-dim", "The spatial dimension","ex5.c",dim,&dim,NULL,1,3)); 22*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-simplex", "Test simplex element","ex5.c",simplex,&simplex,NULL)); 23*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-num_comp", "Number of components in space","ex5.c",Nc,&Nc,NULL,1)); 241e1ea65dSPierre Jolivet ierr = PetscOptionsEnd();CHKERRQ(ierr); 25*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMShellCreate(comm,&dm)); 26*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateDefault(comm,dim,Nc,simplex,NULL,PETSC_DEFAULT,&fe)); 27*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dm)); 28*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFESetName(fe, "solution")); 29*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEGetBasisSpace(fe,&space)); 30*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceGetNumComponents(space,&Nc)); 31*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEGetDualSpace(fe,&dualspace)); 32*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetHeightSubspace(dualspace,1,&dualsubspace)); 33*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDM(dualspace,&dm)); 34*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm,0,&cStart,&cEnd)); 35c4762a1bSJed Brown if (cEnd > cStart) { 36c4762a1bSJed Brown PetscInt coneSize; 37c4762a1bSJed Brown 38*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm,cStart,&coneSize)); 39c4762a1bSJed Brown if (coneSize) { 40c4762a1bSJed Brown PetscFE traceFE; 41c4762a1bSJed Brown const PetscInt *cone; 42c4762a1bSJed Brown PetscInt point, nSub, nFull; 43c4762a1bSJed Brown PetscReal xi0[3] = {-1., -1., -1.}; 44c4762a1bSJed Brown PetscScalar *outSub, *outFull; 45c4762a1bSJed Brown PetscReal *testSub, *testFull; 46c4762a1bSJed Brown PetscTabulation Tsub, Tfull; 47c4762a1bSJed Brown PetscReal J[9], detJ; 48c4762a1bSJed Brown PetscInt i, j; 49c4762a1bSJed Brown PetscSection sectionFull; 50c4762a1bSJed Brown Vec vecFull; 51c4762a1bSJed Brown PetscScalar *arrayFull, *arraySub; 52c4762a1bSJed Brown PetscReal err; 53c4762a1bSJed Brown PetscRandom rand; 54c4762a1bSJed Brown 55*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm,cStart,&cone)); 56c4762a1bSJed Brown point = cone[0]; 57*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreatePointTrace(fe,point,&traceFE)); 58*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFESetUp(traceFE)); 59*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEViewFromOptions(traceFE,NULL,"-trace_fe_view")); 60*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc4(dim - 1,&testSub,dim,&testFull,Nc,&outSub,Nc,&outFull)); 61*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomCreate(PETSC_COMM_SELF,&rand)); 62*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomSetFromOptions(rand)); 63*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomSetInterval(rand,-1.,1.)); 64c4762a1bSJed Brown /* create a random point in the trace domain */ 65c4762a1bSJed Brown for (i = 0; i < dim - 1; i++) { 66*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomGetValueReal(rand,&testSub[i])); 67c4762a1bSJed Brown } 68*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(dm,point,NULL,testFull,J,NULL,&detJ)); 69c4762a1bSJed Brown /* project it into the full domain */ 70c4762a1bSJed Brown for (i = 0; i < dim; i++) { 71c4762a1bSJed Brown for (j = 0; j < dim - 1; j++) testFull[i] += J[i * dim + j] * (testSub[j] - xi0[j]); 72c4762a1bSJed Brown } 73c4762a1bSJed Brown /* create a random vector in the full domain */ 74*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEGetDimension(fe,&nFull)); 75*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,nFull,&vecFull)); 76*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(vecFull,&arrayFull)); 77c4762a1bSJed Brown for (i = 0; i < nFull; i++) { 78*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomGetValue(rand,&arrayFull[i])); 79c4762a1bSJed Brown } 80*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(vecFull,&arrayFull)); 81c4762a1bSJed Brown /* create a vector on the trace domain */ 82*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEGetDimension(traceFE,&nSub)); 83c4762a1bSJed Brown /* get the subset of the original finite element space that is supported on the trace space */ 84*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetSection(dualspace,§ionFull)); 85*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(sectionFull)); 86c4762a1bSJed Brown /* get the trace degrees of freedom */ 87*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nSub,&arraySub)); 88*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(dm,sectionFull,vecFull,point,&nSub,&arraySub)); 89c4762a1bSJed Brown /* get the tabulations */ 90*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateTabulation(traceFE,1,1,testSub,0,&Tsub)); 91*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateTabulation(fe,1,1,testFull,0,&Tfull)); 92c4762a1bSJed Brown for (i = 0; i < Nc; i++) { 93c4762a1bSJed Brown outSub[i] = 0.0; 94c4762a1bSJed Brown for (j = 0; j < nSub; j++) { 95c4762a1bSJed Brown outSub[i] += Tsub->T[0][j * Nc + i] * arraySub[j]; 96c4762a1bSJed Brown } 97c4762a1bSJed Brown } 98*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(vecFull,&arrayFull)); 99c4762a1bSJed Brown err = 0.0; 100c4762a1bSJed Brown for (i = 0; i < Nc; i++) { 101c4762a1bSJed Brown PetscScalar diff; 102c4762a1bSJed Brown 103c4762a1bSJed Brown outFull[i] = 0.0; 104c4762a1bSJed Brown for (j = 0; j < nFull; j++) { 105c4762a1bSJed Brown outFull[i] += Tfull->T[0][j * Nc + i] * arrayFull[j]; 106c4762a1bSJed Brown } 107c4762a1bSJed Brown diff = outFull[i] - outSub[i]; 108c4762a1bSJed Brown err += PetscRealPart(PetscConj(diff) * diff); 109c4762a1bSJed Brown } 110c4762a1bSJed Brown err = PetscSqrtReal(err); 111c4762a1bSJed Brown if (err > PETSC_SMALL) { 11298921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Trace FE error %g",err); 113c4762a1bSJed Brown } 114*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(vecFull,&arrayFull)); 115*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTabulationDestroy(&Tfull)); 116*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTabulationDestroy(&Tsub)); 117c4762a1bSJed Brown /* clean up */ 118*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(arraySub)); 119*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&vecFull)); 120*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomDestroy(&rand)); 121*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree4(testSub,testFull,outSub,outFull)); 122*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEDestroy(&traceFE)); 123c4762a1bSJed Brown } 124c4762a1bSJed Brown } 125*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEDestroy(&fe)); 126c4762a1bSJed Brown ierr = PetscFinalize(); 127c4762a1bSJed Brown return ierr; 128c4762a1bSJed Brown } 129c4762a1bSJed Brown 130c4762a1bSJed Brown /*TEST 131c4762a1bSJed Brown test: 132c4762a1bSJed Brown suffix: 0 133c4762a1bSJed Brown args: -petscspace_degree 1 -trace_fe_view 134c4762a1bSJed Brown TEST*/ 135