130602db0SMatthew G. Knepley const char help[] = "A test of H-div conforming discretizations on different cell types.\n"; 2c4762a1bSJed Brown 3c4762a1bSJed Brown #include <petscdmplex.h> 4c4762a1bSJed Brown #include <petscds.h> 5c4762a1bSJed Brown #include <petscsnes.h> 6c4762a1bSJed Brown #include <petscconvest.h> 7c4762a1bSJed Brown #include <petscfe.h> 8c4762a1bSJed Brown #include <petsc/private/petscfeimpl.h> 9c4762a1bSJed Brown 10c4762a1bSJed Brown /* 110e3d61c9SBarry Smith We are using the system 120e3d61c9SBarry Smith 130e3d61c9SBarry Smith \vec{u} = \vec{\hat{u}} 140e3d61c9SBarry Smith p = \div{\vec{u}} in low degree approximation space 150e3d61c9SBarry Smith d = \div{\vec{u}} - p == 0 in higher degree approximation space 160e3d61c9SBarry Smith 170e3d61c9SBarry Smith That is, we are using the field d to compute the error between \div{\vec{u}} 180e3d61c9SBarry Smith computed in a space 1 degree higher than p and the value of p which is 190e3d61c9SBarry Smith \div{u} computed in the low degree space. If H-div 200e3d61c9SBarry Smith elements are implemented correctly then this should be identically zero since 210e3d61c9SBarry Smith the divergence of a function in H(div) should be exactly representable in L_2 220e3d61c9SBarry Smith by definition. 23c4762a1bSJed Brown */ 24c4762a1bSJed Brown static PetscErrorCode zero_func(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nc,PetscScalar *u,void *ctx) 25c4762a1bSJed Brown { 26c4762a1bSJed Brown PetscInt c; 27c4762a1bSJed Brown for (c = 0; c < Nc; ++c) u[c] = 0; 28c4762a1bSJed Brown return 0; 29c4762a1bSJed Brown } 30c4762a1bSJed Brown /* Linear Exact Functions 31c4762a1bSJed Brown \vec{u} = \vec{x}; 32c4762a1bSJed Brown p = dim; 33c4762a1bSJed Brown */ 34c4762a1bSJed Brown static PetscErrorCode linear_u(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nc,PetscScalar *u,void *ctx) 35c4762a1bSJed Brown { 36c4762a1bSJed Brown PetscInt c; 37c4762a1bSJed Brown for (c = 0; c < Nc; ++c) u[c] = x[c]; 38c4762a1bSJed Brown return 0; 39c4762a1bSJed Brown } 40c4762a1bSJed Brown static PetscErrorCode linear_p(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nc,PetscScalar *u,void *ctx) 41c4762a1bSJed Brown { 42c4762a1bSJed Brown u[0] = dim; 43c4762a1bSJed Brown return 0; 44c4762a1bSJed Brown } 45c4762a1bSJed Brown 46c4762a1bSJed Brown /* Sinusoidal Exact Functions 47c4762a1bSJed Brown * u_i = \sin{2*\pi*x_i} 48c4762a1bSJed Brown * p = \Sum_{i=1}^{dim} 2*\pi*cos{2*\pi*x_i} 49c4762a1bSJed Brown * */ 50c4762a1bSJed Brown 51c4762a1bSJed Brown static PetscErrorCode sinusoid_u(PetscInt dim,PetscReal time,const PetscReal 52c4762a1bSJed Brown x[],PetscInt Nc,PetscScalar *u,void *ctx) 53c4762a1bSJed Brown { 54c4762a1bSJed Brown PetscInt c; 55c4762a1bSJed Brown for (c = 0; c< Nc; ++c) u[c] = PetscSinReal(2*PETSC_PI*x[c]); 56c4762a1bSJed Brown return 0; 57c4762a1bSJed Brown } 58c4762a1bSJed Brown static PetscErrorCode sinusoid_p(PetscInt dim,PetscReal time,const PetscReal 59c4762a1bSJed Brown x[],PetscInt Nc,PetscScalar *u,void *ctx) 60c4762a1bSJed Brown { 61c4762a1bSJed Brown PetscInt d; 62c4762a1bSJed Brown u[0]=0; 63c4762a1bSJed Brown for (d=0; d<dim; ++d) u[0] += 2*PETSC_PI*PetscCosReal(2*PETSC_PI*x[d]); 64c4762a1bSJed Brown return 0; 65c4762a1bSJed Brown } 66c4762a1bSJed Brown 67c4762a1bSJed Brown /* Pointwise residual for u = u*. Need one of these for each possible u* */ 68c4762a1bSJed Brown static void f0_v_linear(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[]) 69c4762a1bSJed Brown { 70c4762a1bSJed Brown PetscInt i; 71c4762a1bSJed Brown PetscScalar *u_rhs; 72c4762a1bSJed Brown 73c4762a1bSJed Brown PetscCalloc1(dim,&u_rhs); 74c4762a1bSJed Brown (void) linear_u(dim,t,x,dim,u_rhs,NULL); 75c4762a1bSJed Brown for (i = 0; i < dim; ++i) f0[i] = u[uOff[0]+i]-u_rhs[i]; 76c4762a1bSJed Brown PetscFree(u_rhs); 77c4762a1bSJed Brown } 78c4762a1bSJed Brown 79c4762a1bSJed Brown static void f0_v_sinusoid(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[]) 80c4762a1bSJed Brown { 81c4762a1bSJed Brown PetscInt i; 82c4762a1bSJed Brown PetscScalar *u_rhs; 83c4762a1bSJed Brown 84c4762a1bSJed Brown PetscCalloc1(dim,&u_rhs); 85c4762a1bSJed Brown (void) sinusoid_u(dim,t,x,dim,u_rhs,NULL); 86c4762a1bSJed Brown for (i = 0; i < dim; ++i) f0[i] = u[uOff[0]+i]-u_rhs[i]; 87c4762a1bSJed Brown PetscFree(u_rhs); 88c4762a1bSJed Brown } 89c4762a1bSJed Brown 90c4762a1bSJed Brown /* Residual function for enforcing p = \div{u}. */ 91c4762a1bSJed Brown static void f0_q(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[]) 92c4762a1bSJed Brown { 93c4762a1bSJed Brown PetscInt i; 94c4762a1bSJed Brown PetscScalar divu; 95c4762a1bSJed Brown 96c4762a1bSJed Brown divu = 0.; 97c4762a1bSJed Brown for (i = 0; i< dim; ++i) divu += u_x[uOff_x[0]+i*dim+i]; 98c4762a1bSJed Brown f0[0] = u[uOff[1]] - divu; 99c4762a1bSJed Brown } 100c4762a1bSJed Brown 101c4762a1bSJed Brown /* Residual function for p_err = \div{u} - p. */ 102c4762a1bSJed Brown static void f0_w(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[]) 103c4762a1bSJed Brown { 104c4762a1bSJed Brown PetscInt i; 105c4762a1bSJed Brown PetscScalar divu; 106c4762a1bSJed Brown 107c4762a1bSJed Brown divu = 0.; 108c4762a1bSJed Brown for (i = 0; i < dim; ++i) divu += u_x[uOff_x[0] + i*dim +i]; 109c4762a1bSJed Brown f0[0] = u[uOff[2]] - u[uOff[1]] + divu; 110c4762a1bSJed Brown } 111c4762a1bSJed Brown 112c4762a1bSJed Brown /* Boundary residual for the embedding system. Need one for each form of 113c4762a1bSJed Brown * solution. These enforce u = \hat{u} at the boundary. */ 114c4762a1bSJed Brown static void f0_bd_u_sinusoid(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],const PetscReal n[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[]) 115c4762a1bSJed Brown { 116c4762a1bSJed Brown PetscInt d; 117c4762a1bSJed Brown PetscScalar *u_rhs; 118c4762a1bSJed Brown PetscCalloc1(dim,&u_rhs); 119c4762a1bSJed Brown (void) sinusoid_u(dim,t,x,dim,u_rhs,NULL); 120c4762a1bSJed Brown 121c4762a1bSJed Brown for (d=0; d<dim; ++d) f0[d] = u_rhs[d]; 122c4762a1bSJed Brown PetscFree(u_rhs); 123c4762a1bSJed Brown 124c4762a1bSJed Brown } 125c4762a1bSJed Brown 126c4762a1bSJed Brown static void f0_bd_u_linear(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],const PetscReal n[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[]) 127c4762a1bSJed Brown { 128c4762a1bSJed Brown PetscInt d; 129c4762a1bSJed Brown PetscScalar *u_rhs; 130c4762a1bSJed Brown PetscCalloc1(dim,&u_rhs); 131c4762a1bSJed Brown (void) linear_u(dim,t,x,dim,u_rhs,NULL); 132c4762a1bSJed Brown 133c4762a1bSJed Brown for (d=0; d<dim; ++d) f0[d] = u_rhs[d]; 134c4762a1bSJed Brown PetscFree(u_rhs); 135c4762a1bSJed Brown } 136c4762a1bSJed Brown /* Jacobian functions. For the following, v is the test function associated with 137c4762a1bSJed Brown * u, q the test function associated with p, and w the test function associated 138c4762a1bSJed Brown * with d. */ 139c4762a1bSJed Brown /* <v, u> */ 140c4762a1bSJed Brown static void g0_vu(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,PetscReal u_tShift,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar g0[]) 141c4762a1bSJed Brown { 142c4762a1bSJed Brown PetscInt c; 143c4762a1bSJed Brown for (c = 0; c < dim; ++c) g0[c * dim + c] = 1.0; 144c4762a1bSJed Brown } 145c4762a1bSJed Brown 146c4762a1bSJed Brown /* <q, p> */ 147c4762a1bSJed Brown static void g0_qp(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,PetscReal u_tShift,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar g0[]) 148c4762a1bSJed Brown { 149c4762a1bSJed Brown PetscInt d; 150c4762a1bSJed Brown for (d=0; d< dim; ++d) g0[d * dim + d] = 1.0; 151c4762a1bSJed Brown } 152c4762a1bSJed Brown 153c4762a1bSJed Brown /* -<q, \div{u}> For the embedded system. This is different from the method of 154c4762a1bSJed Brown * manufactured solution because instead of computing <q,\div{u}> - <q,f> we 155c4762a1bSJed Brown * need <q,p> - <q,\div{u}.*/ 156c4762a1bSJed Brown static void g1_qu(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,PetscReal u_tShift,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar g1[]) 157c4762a1bSJed Brown { 158c4762a1bSJed Brown PetscInt d; 159c4762a1bSJed Brown for (d = 0; d < dim; ++d) g1[d * dim + d] = -1.0; 160c4762a1bSJed Brown } 161c4762a1bSJed Brown 162c4762a1bSJed Brown /* <w, p> This is only used by the embedded system. Where we need to compute 163c4762a1bSJed Brown * <w,d> - <w,p> + <w, \div{u}>*/ 164c4762a1bSJed Brown static void g0_wp(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,PetscReal u_tShift,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar g0[]) 165c4762a1bSJed Brown { 166c4762a1bSJed Brown PetscInt d; 167c4762a1bSJed Brown for (d=0; d< dim; ++d) g0[d * dim + d] = -1.0; 168c4762a1bSJed Brown } 169c4762a1bSJed Brown 170c4762a1bSJed Brown /* <w, d> */ 171c4762a1bSJed Brown static void g0_wd(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,PetscReal u_tShift,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar g0[]) 172c4762a1bSJed Brown { 173c4762a1bSJed Brown PetscInt c; 174c4762a1bSJed Brown for (c = 0; c < dim; ++c) g0[c*dim+c] = 1.0; 175c4762a1bSJed Brown } 176c4762a1bSJed Brown 177c4762a1bSJed Brown /* <w, \div{u}> for the embedded system. */ 178c4762a1bSJed Brown static void g1_wu(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,PetscReal u_tShift,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar g1[]) 179c4762a1bSJed Brown { 180c4762a1bSJed Brown PetscInt d; 181c4762a1bSJed Brown for (d = 0; d < dim; ++d) g1[d * dim + d] = 1.0; 182c4762a1bSJed Brown } 183c4762a1bSJed Brown 184c4762a1bSJed Brown /* Enum and string array for selecting mesh perturbation options */ 185c4762a1bSJed Brown typedef enum { NONE = 0,PERTURB = 1,SKEW = 2,SKEW_PERTURB = 3 } Transform; 186c4762a1bSJed Brown const char* const TransformTypes[] = {"none","perturb","skew","skew_perturb","Perturbation","",NULL}; 187c4762a1bSJed Brown 188c4762a1bSJed Brown /* Enum and string array for selecting the form of the exact solution*/ 189c4762a1bSJed Brown typedef enum 190c4762a1bSJed Brown { LINEAR = 0,SINUSOIDAL = 1 } Solution; 191c4762a1bSJed Brown const char* const SolutionTypes[] = {"linear","sinusoidal","Solution","",NULL}; 192c4762a1bSJed Brown 193c4762a1bSJed Brown typedef struct 194c4762a1bSJed Brown { 195c4762a1bSJed Brown Transform mesh_transform; 196c4762a1bSJed Brown Solution sol_form; 197c4762a1bSJed Brown } UserCtx; 198c4762a1bSJed Brown 199c4762a1bSJed Brown /* Process command line options and initialize the UserCtx struct */ 200c4762a1bSJed Brown static PetscErrorCode ProcessOptions(MPI_Comm comm,UserCtx * user) 201c4762a1bSJed Brown { 202c4762a1bSJed Brown PetscErrorCode ierr; 203c4762a1bSJed Brown 204c4762a1bSJed Brown PetscFunctionBegin; 205c4762a1bSJed Brown /* Default to 2D, unperturbed triangle mesh and Linear solution.*/ 206c4762a1bSJed Brown user->mesh_transform = NONE; 207c4762a1bSJed Brown user->sol_form = LINEAR; 208c4762a1bSJed Brown 209c4762a1bSJed Brown ierr = PetscOptionsBegin(comm,"","H-div Test Options","DMPLEX");CHKERRQ(ierr); 2105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnum("-mesh_transform","Method used to perturb the mesh vertices. Options are skew, perturb, skew_perturb,or none","ex39.c",TransformTypes,(PetscEnum) user->mesh_transform,(PetscEnum*) &user->mesh_transform,NULL)); 2115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnum("-sol_form","Form of the exact solution. Options are Linear or Sinusoidal","ex39.c",SolutionTypes,(PetscEnum) user->sol_form,(PetscEnum*) &user->sol_form,NULL)); 212c4762a1bSJed Brown ierr = PetscOptionsEnd();CHKERRQ(ierr); 213c4762a1bSJed Brown PetscFunctionReturn(0); 214c4762a1bSJed Brown } 215c4762a1bSJed Brown 216c4762a1bSJed Brown /* Perturb the position of each mesh vertex by a small amount.*/ 217c4762a1bSJed Brown static PetscErrorCode PerturbMesh(DM *mesh,PetscScalar *coordVals,PetscInt npoints,PetscInt dim) 218c4762a1bSJed Brown { 219c4762a1bSJed Brown PetscInt i,j,k; 220d092c84bSBrandon Whitchurch PetscReal minCoords[3],maxCoords[3],maxPert[3],randVal,amp; 221c4762a1bSJed Brown PetscRandom ran; 222c4762a1bSJed Brown 223c4762a1bSJed Brown PetscFunctionBegin; 2245f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(*mesh,&dim)); 2255f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalBoundingBox(*mesh,minCoords,maxCoords)); 2265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomCreate(PETSC_COMM_WORLD,&ran)); 227c4762a1bSJed Brown 228c4762a1bSJed Brown /* Compute something approximately equal to half an edge length. This is the 229a5b23f4aSJose E. Roman * most we can perturb points and guarantee that there won't be any topology 230c4762a1bSJed Brown * issues. */ 231d092c84bSBrandon Whitchurch for (k = 0; k < dim; ++k) maxPert[k] = 0.025 * (maxCoords[k] - minCoords[k]) / (PetscPowReal(npoints,1. / dim) - 1); 232c4762a1bSJed Brown /* For each mesh vertex */ 233c4762a1bSJed Brown for (i = 0; i < npoints; ++i) { 234c4762a1bSJed Brown /* For each coordinate of the vertex */ 235c4762a1bSJed Brown for (j = 0; j < dim; ++j) { 236c4762a1bSJed Brown /* Generate a random amplitude in [-0.5*maxPert, 0.5*maxPert] */ 2375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomGetValueReal(ran,&randVal)); 238c4762a1bSJed Brown amp = maxPert[j] * (randVal - 0.5); 239c4762a1bSJed Brown /* Add the perturbation to the vertex*/ 240d092c84bSBrandon Whitchurch coordVals[dim * i + j] += amp; 241c4762a1bSJed Brown } 242c4762a1bSJed Brown } 243c4762a1bSJed Brown 244c4762a1bSJed Brown PetscRandomDestroy(&ran); 245c4762a1bSJed Brown PetscFunctionReturn(0); 246c4762a1bSJed Brown } 247c4762a1bSJed Brown 248c4762a1bSJed Brown /* Apply a global skew transformation to the mesh. */ 249c4762a1bSJed Brown static PetscErrorCode SkewMesh(DM * mesh,PetscScalar * coordVals,PetscInt npoints,PetscInt dim) 250c4762a1bSJed Brown { 251c4762a1bSJed Brown PetscInt i,j,k,l; 252c4762a1bSJed Brown PetscScalar * transMat; 253c4762a1bSJed Brown PetscScalar tmpcoord[3]; 254c4762a1bSJed Brown PetscRandom ran; 255c4762a1bSJed Brown PetscReal randVal; 256c4762a1bSJed Brown 257c4762a1bSJed Brown PetscFunctionBegin; 2585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(dim * dim,&transMat)); 2595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomCreate(PETSC_COMM_WORLD,&ran)); 260c4762a1bSJed Brown 261c4762a1bSJed Brown /* Make a matrix representing a skew transformation */ 262c4762a1bSJed Brown for (i = 0; i < dim; ++i) { 263c4762a1bSJed Brown for (j = 0; j < dim; ++j) { 2645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomGetValueReal(ran,&randVal)); 265d092c84bSBrandon Whitchurch if (i == j) transMat[i * dim + j] = 1.; 266c4762a1bSJed Brown else if (j < i) transMat[i * dim + j] = 2 * (j + i)*randVal; 267c4762a1bSJed Brown else transMat[i * dim + j] = 0; 268c4762a1bSJed Brown } 269c4762a1bSJed Brown } 270c4762a1bSJed Brown 271c4762a1bSJed Brown /* Multiply each coordinate vector by our tranformation.*/ 272c4762a1bSJed Brown for (i = 0; i < npoints; ++i) { 273c4762a1bSJed Brown for (j = 0; j < dim; ++j) { 274c4762a1bSJed Brown tmpcoord[j] = 0; 275c4762a1bSJed Brown for (k = 0; k < dim; ++k) tmpcoord[j] += coordVals[dim * i + k] * transMat[dim * k + j]; 276c4762a1bSJed Brown } 277c4762a1bSJed Brown for (l = 0; l < dim; ++l) coordVals[dim * i + l] = tmpcoord[l]; 278c4762a1bSJed Brown } 2795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(transMat)); 2805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomDestroy(&ran)); 281c4762a1bSJed Brown PetscFunctionReturn(0); 282c4762a1bSJed Brown } 283c4762a1bSJed Brown 284c4762a1bSJed Brown /* Accesses the mesh coordinate array and performs the transformation operations 285c4762a1bSJed Brown * specified by the user options */ 286c4762a1bSJed Brown static PetscErrorCode TransformMesh(UserCtx * user,DM * mesh) 287c4762a1bSJed Brown { 288c4762a1bSJed Brown PetscInt dim,npoints; 289c4762a1bSJed Brown PetscScalar * coordVals; 290c4762a1bSJed Brown Vec coords; 291c4762a1bSJed Brown 292c4762a1bSJed Brown PetscFunctionBegin; 2935f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinates(*mesh,&coords)); 2945f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coords,&coordVals)); 2955f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(coords,&npoints)); 2965f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(*mesh,&dim)); 297c4762a1bSJed Brown npoints = npoints / dim; 298c4762a1bSJed Brown 299c4762a1bSJed Brown switch (user->mesh_transform) { 300c4762a1bSJed Brown case PERTURB: 3015f80ce2aSJacob Faibussowitsch CHKERRQ(PerturbMesh(mesh,coordVals,npoints,dim)); 302c4762a1bSJed Brown break; 303c4762a1bSJed Brown case SKEW: 3045f80ce2aSJacob Faibussowitsch CHKERRQ(SkewMesh(mesh,coordVals,npoints,dim)); 305c4762a1bSJed Brown break; 306c4762a1bSJed Brown case SKEW_PERTURB: 3075f80ce2aSJacob Faibussowitsch CHKERRQ(SkewMesh(mesh,coordVals,npoints,dim)); 3085f80ce2aSJacob Faibussowitsch CHKERRQ(PerturbMesh(mesh,coordVals,npoints,dim)); 309c4762a1bSJed Brown break; 310c4762a1bSJed Brown default: 311c4762a1bSJed Brown PetscFunctionReturn(-1); 312c4762a1bSJed Brown } 3135f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coords,&coordVals)); 3145f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinates(*mesh,coords)); 315c4762a1bSJed Brown PetscFunctionReturn(0); 316c4762a1bSJed Brown } 317c4762a1bSJed Brown 318c4762a1bSJed Brown static PetscErrorCode CreateMesh(MPI_Comm comm,UserCtx * user,DM * mesh) 319c4762a1bSJed Brown { 320c4762a1bSJed Brown PetscFunctionBegin; 3215f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, mesh)); 3225f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*mesh, DMPLEX)); 3235f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions(*mesh)); 324c4762a1bSJed Brown 325c4762a1bSJed Brown /* Perform any mesh transformations if specified by user */ 326c4762a1bSJed Brown if (user->mesh_transform != NONE) { 3275f80ce2aSJacob Faibussowitsch CHKERRQ(TransformMesh(user,mesh)); 328c4762a1bSJed Brown } 329c4762a1bSJed Brown 330c4762a1bSJed Brown /* Get any other mesh options from the command line */ 3315f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetApplicationContext(*mesh,user)); 3325f80ce2aSJacob Faibussowitsch CHKERRQ(DMViewFromOptions(*mesh,NULL,"-dm_view")); 333c4762a1bSJed Brown PetscFunctionReturn(0); 334c4762a1bSJed Brown } 335c4762a1bSJed Brown 336c4762a1bSJed Brown /* Setup the system of equations that we wish to solve */ 337c4762a1bSJed Brown static PetscErrorCode SetupProblem(DM dm,UserCtx * user) 338c4762a1bSJed Brown { 339c4762a1bSJed Brown PetscDS prob; 34045480ffeSMatthew G. Knepley DMLabel label; 341c4762a1bSJed Brown const PetscInt id=1; 342c4762a1bSJed Brown 343c4762a1bSJed Brown PetscFunctionBegin; 3445f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(dm,&prob)); 345c4762a1bSJed Brown /* All of these are independent of the user's choice of solution */ 3465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetResidual(prob,1,f0_q,NULL)); 3475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetResidual(prob,2,f0_w,NULL)); 3485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetJacobian(prob,0,0,g0_vu,NULL,NULL,NULL)); 3495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetJacobian(prob,1,0,NULL,g1_qu,NULL,NULL)); 3505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetJacobian(prob,1,1,g0_qp,NULL,NULL,NULL)); 3515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetJacobian(prob,2,0,NULL,g1_wu,NULL,NULL)); 3525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetJacobian(prob,2,1,g0_wp,NULL,NULL,NULL)); 3535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetJacobian(prob,2,2,g0_wd,NULL,NULL,NULL)); 354c4762a1bSJed Brown 355c4762a1bSJed Brown /* Field 2 is the error between \div{u} and pressure in a higher dimensional 356c4762a1bSJed Brown * space. If all is right this should be machine zero. */ 3575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetExactSolution(prob,2,zero_func,NULL)); 358c4762a1bSJed Brown 359c4762a1bSJed Brown switch (user->sol_form) { 360c4762a1bSJed Brown case LINEAR: 3615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetResidual(prob,0,f0_v_linear,NULL)); 3625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetBdResidual(prob,0,f0_bd_u_linear,NULL)); 3635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetExactSolution(prob,0,linear_u,NULL)); 3645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetExactSolution(prob,1,linear_p,NULL)); 365c4762a1bSJed Brown break; 366c4762a1bSJed Brown case SINUSOIDAL: 3675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetResidual(prob,0,f0_v_sinusoid,NULL)); 3685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetBdResidual(prob,0,f0_bd_u_sinusoid,NULL)); 3695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetExactSolution(prob,0,sinusoid_u,NULL)); 3705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetExactSolution(prob,1,sinusoid_p,NULL)); 371c4762a1bSJed Brown break; 372c4762a1bSJed Brown default: 373c4762a1bSJed Brown PetscFunctionReturn(-1); 374c4762a1bSJed Brown } 375c4762a1bSJed Brown 3765f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm, "marker", &label)); 3775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSAddBoundary(prob,DM_BC_NATURAL,"Boundary Integral",label,1,&id,0,0,NULL,(void (*)(void))NULL,NULL,user,NULL)); 378c4762a1bSJed Brown PetscFunctionReturn(0); 379c4762a1bSJed Brown } 380c4762a1bSJed Brown 381c4762a1bSJed Brown /* Create the finite element spaces we will use for this system */ 382c4762a1bSJed Brown static PetscErrorCode SetupDiscretization(DM mesh,PetscErrorCode (*setup)(DM,UserCtx*),UserCtx *user) 383c4762a1bSJed Brown { 384c4762a1bSJed Brown DM cdm = mesh; 385c4762a1bSJed Brown PetscFE fevel,fepres,fedivErr; 38630602db0SMatthew G. Knepley PetscInt dim; 38730602db0SMatthew G. Knepley PetscBool simplex; 388c4762a1bSJed Brown PetscErrorCode ierr; 389c4762a1bSJed Brown 390c4762a1bSJed Brown PetscFunctionBegin; 3915f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(mesh, &dim)); 3925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexIsSimplex(mesh, &simplex)); 393c4762a1bSJed Brown /* Create FE objects and give them names so that options can be set from 394c4762a1bSJed Brown * command line */ 3955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateDefault(PetscObjectComm((PetscObject) mesh),dim,dim,simplex,"velocity_",-1,&fevel)); 3965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) fevel,"velocity")); 397c4762a1bSJed Brown 3985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateDefault(PetscObjectComm((PetscObject) mesh),dim,1,simplex,"pressure_",-1,&fepres)); 3995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) fepres,"pressure")); 400c4762a1bSJed Brown 401c4762a1bSJed Brown ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) 40230602db0SMatthew G. Knepley mesh),dim,1,simplex,"divErr_",-1,&fedivErr);CHKERRQ(ierr); 4035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) fedivErr,"divErr")); 404c4762a1bSJed Brown 4055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECopyQuadrature(fevel,fepres)); 4065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECopyQuadrature(fevel,fedivErr)); 407c4762a1bSJed Brown 408c4762a1bSJed Brown /* Associate the FE objects with the mesh and setup the system */ 4095f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(mesh,0,NULL,(PetscObject) fevel)); 4105f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(mesh,1,NULL,(PetscObject) fepres)); 4115f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(mesh,2,NULL,(PetscObject) fedivErr)); 4125f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateDS(mesh)); 4135f80ce2aSJacob Faibussowitsch CHKERRQ((*setup)(mesh,user)); 414c4762a1bSJed Brown 415c4762a1bSJed Brown while (cdm) { 4165f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDisc(mesh,cdm)); 4175f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoarseDM(cdm,&cdm)); 418c4762a1bSJed Brown } 419c4762a1bSJed Brown 420c4762a1bSJed Brown /* The Mesh now owns the fields, so we can destroy the FEs created in this 421c4762a1bSJed Brown * function */ 4225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEDestroy(&fevel)); 4235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEDestroy(&fepres)); 4245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEDestroy(&fedivErr)); 4255f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&cdm)); 426c4762a1bSJed Brown PetscFunctionReturn(0); 427c4762a1bSJed Brown } 428c4762a1bSJed Brown 429c4762a1bSJed Brown int main(int argc,char **argv) 430c4762a1bSJed Brown { 431c4762a1bSJed Brown PetscInt i; 432c4762a1bSJed Brown UserCtx user; 433c4762a1bSJed Brown DM mesh; 434c4762a1bSJed Brown SNES snes; 435c4762a1bSJed Brown Vec computed,divErr; 436c4762a1bSJed Brown PetscReal divErrNorm; 437c4762a1bSJed Brown IS * fieldIS; 438c4762a1bSJed Brown PetscBool exampleSuccess = PETSC_FALSE; 439d092c84bSBrandon Whitchurch const PetscReal errTol = 10. * PETSC_SMALL; 440c4762a1bSJed Brown 441c4762a1bSJed Brown char stdFormat[] = "L2 Norm of the Divergence Error is: %g\n H(div) elements working correctly: %s\n"; 442c4762a1bSJed Brown 443c4762a1bSJed Brown /* Initialize PETSc */ 444*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscInitialize(&argc,&argv,NULL,help)); 4455f80ce2aSJacob Faibussowitsch CHKERRQ(ProcessOptions(PETSC_COMM_WORLD,&user)); 446c4762a1bSJed Brown 447c4762a1bSJed Brown /* Set up the system, we need to create a solver and a mesh and then assign 448c4762a1bSJed Brown * the correct spaces into the mesh*/ 4495f80ce2aSJacob Faibussowitsch CHKERRQ(SNESCreate(PETSC_COMM_WORLD,&snes)); 4505f80ce2aSJacob Faibussowitsch CHKERRQ(CreateMesh(PETSC_COMM_WORLD,&user,&mesh)); 4515f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetDM(snes,mesh)); 4525f80ce2aSJacob Faibussowitsch CHKERRQ(SetupDiscretization(mesh,SetupProblem,&user)); 4535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetSNESLocalFEM(mesh,&user,&user,&user)); 4545f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetFromOptions(snes)); 455c4762a1bSJed Brown 456c4762a1bSJed Brown /* Grab field IS so that we can view the solution by field */ 4575f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateFieldIS(mesh,NULL,NULL,&fieldIS)); 458c4762a1bSJed Brown 459c4762a1bSJed Brown /* Create a vector to store the SNES solution, solve the system and grab the 460c4762a1bSJed Brown * solution from SNES */ 4615f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(mesh,&computed)); 4625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) computed,"computedSolution")); 4635f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(computed,0.0)); 4645f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSolve(snes,NULL,computed)); 4655f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetSolution(snes,&computed)); 4665f80ce2aSJacob Faibussowitsch CHKERRQ(VecViewFromOptions(computed,NULL,"-computedSolution_view")); 467c4762a1bSJed Brown 468c4762a1bSJed Brown /* Now we pull out the portion of the vector corresponding to the 3rd field 469c4762a1bSJed Brown * which is the error between \div{u} computed in a higher dimensional space 470c4762a1bSJed Brown * and p = \div{u} computed in a low dimension space. We report the L2 norm of 471c4762a1bSJed Brown * this vector which should be zero if the H(div) spaces are implemented 472c4762a1bSJed Brown * correctly. */ 4735f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSubVector(computed,fieldIS[2],&divErr)); 4745f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(divErr,NORM_2,&divErrNorm)); 4755f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreSubVector(computed,fieldIS[2],&divErr)); 476c4762a1bSJed Brown exampleSuccess = (PetscBool)(divErrNorm <= errTol); 477c4762a1bSJed Brown 4785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,stdFormat,divErrNorm,exampleSuccess ? "true" : "false")); 479c4762a1bSJed Brown 480c4762a1bSJed Brown /* Tear down */ 4815f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&divErr)); 4825f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&computed)); 483c4762a1bSJed Brown for (i = 0; i < 3; ++i) { 4845f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&fieldIS[i])); 485c4762a1bSJed Brown } 4865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(fieldIS)); 4875f80ce2aSJacob Faibussowitsch CHKERRQ(SNESDestroy(&snes)); 4885f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&mesh)); 489*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscFinalize()); 490*b122ec5aSJacob Faibussowitsch return 0; 491c4762a1bSJed Brown } 492c4762a1bSJed Brown 493c4762a1bSJed Brown /*TEST 494c4762a1bSJed Brown testset: 495c4762a1bSJed Brown suffix: 2d_bdm 496c4762a1bSJed Brown requires: triangle 49730602db0SMatthew G. Knepley args: -velocity_petscfe_default_quadrature_order 1 \ 498c4762a1bSJed Brown -velocity_petscspace_degree 1 \ 499c4762a1bSJed Brown -velocity_petscdualspace_type bdm \ 500c4762a1bSJed Brown -divErr_petscspace_degree 1 \ 501c4762a1bSJed Brown -divErr_petscdualspace_lagrange_continuity false \ 502c4762a1bSJed Brown -snes_error_if_not_converged \ 503c4762a1bSJed Brown -ksp_rtol 1e-10 \ 504c4762a1bSJed Brown -ksp_error_if_not_converged \ 505c4762a1bSJed Brown -pc_type fieldsplit\ 506c4762a1bSJed Brown -pc_fieldsplit_detect_saddle_point\ 507c4762a1bSJed Brown -pc_fieldsplit_type schur\ 508c4762a1bSJed Brown -pc_fieldsplit_schur_precondition full 509c4762a1bSJed Brown test: 510c4762a1bSJed Brown suffix: linear 511c4762a1bSJed Brown args: -sol_form linear -mesh_transform none 512c4762a1bSJed Brown test: 513c4762a1bSJed Brown suffix: sinusoidal 514c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform none 515c4762a1bSJed Brown test: 516c4762a1bSJed Brown suffix: sinusoidal_skew 517c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform skew 518c4762a1bSJed Brown test: 519c4762a1bSJed Brown suffix: sinusoidal_perturb 520c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform perturb 521c4762a1bSJed Brown test: 522c4762a1bSJed Brown suffix: sinusoidal_skew_perturb 523c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform skew_perturb 524c4762a1bSJed Brown 525c4762a1bSJed Brown testset: 526c4762a1bSJed Brown TODO: broken 527c4762a1bSJed Brown suffix: 2d_bdmq 52830602db0SMatthew G. Knepley args: -dm_plex_simplex false \ 529c4762a1bSJed Brown -velocity_petscspace_degree 1 \ 530c4762a1bSJed Brown -velocity_petscdualspace_type bdm \ 531d092c84bSBrandon Whitchurch -velocity_petscdualspace_lagrange_tensor 1 \ 532c4762a1bSJed Brown -divErr_petscspace_degree 1 \ 533c4762a1bSJed Brown -divErr_petscdualspace_lagrange_continuity false \ 534c4762a1bSJed Brown -snes_error_if_not_converged \ 535c4762a1bSJed Brown -ksp_rtol 1e-10 \ 536c4762a1bSJed Brown -ksp_error_if_not_converged \ 537c4762a1bSJed Brown -pc_type fieldsplit\ 538c4762a1bSJed Brown -pc_fieldsplit_detect_saddle_point\ 539c4762a1bSJed Brown -pc_fieldsplit_type schur\ 540c4762a1bSJed Brown -pc_fieldsplit_schur_precondition full 541c4762a1bSJed Brown test: 542c4762a1bSJed Brown suffix: linear 543c4762a1bSJed Brown args: -sol_form linear -mesh_transform none 544c4762a1bSJed Brown test: 545c4762a1bSJed Brown suffix: sinusoidal 546c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform none 547c4762a1bSJed Brown test: 548c4762a1bSJed Brown suffix: sinusoidal_skew 549c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform skew 550c4762a1bSJed Brown test: 551c4762a1bSJed Brown suffix: sinusoidal_perturb 552c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform perturb 553c4762a1bSJed Brown test: 554c4762a1bSJed Brown suffix: sinusoidal_skew_perturb 555c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform skew_perturb 556c4762a1bSJed Brown 557c4762a1bSJed Brown testset: 558c4762a1bSJed Brown suffix: 3d_bdm 559c4762a1bSJed Brown requires: ctetgen 56030602db0SMatthew G. Knepley args: -dm_plex_dim 3 \ 561c4762a1bSJed Brown -velocity_petscspace_degree 1 \ 562c4762a1bSJed Brown -velocity_petscdualspace_type bdm \ 563c4762a1bSJed Brown -divErr_petscspace_degree 1 \ 564c4762a1bSJed Brown -divErr_petscdualspace_lagrange_continuity false \ 565c4762a1bSJed Brown -snes_error_if_not_converged \ 566c4762a1bSJed Brown -ksp_rtol 1e-10 \ 567c4762a1bSJed Brown -ksp_error_if_not_converged \ 568c4762a1bSJed Brown -pc_type fieldsplit \ 569c4762a1bSJed Brown -pc_fieldsplit_detect_saddle_point \ 570c4762a1bSJed Brown -pc_fieldsplit_type schur \ 571c4762a1bSJed Brown -pc_fieldsplit_schur_precondition full 572c4762a1bSJed Brown test: 573c4762a1bSJed Brown suffix: linear 574c4762a1bSJed Brown args: -sol_form linear -mesh_transform none 575c4762a1bSJed Brown test: 576c4762a1bSJed Brown suffix: sinusoidal 577c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform none 578c4762a1bSJed Brown test: 579c4762a1bSJed Brown suffix: sinusoidal_skew 580c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform skew 581c4762a1bSJed Brown test: 582c4762a1bSJed Brown suffix: sinusoidal_perturb 583c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform perturb 584c4762a1bSJed Brown test: 585c4762a1bSJed Brown suffix: sinusoidal_skew_perturb 586c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform skew_perturb 587c4762a1bSJed Brown 588c4762a1bSJed Brown testset: 589c4762a1bSJed Brown TODO: broken 590c4762a1bSJed Brown suffix: 3d_bdmq 591c4762a1bSJed Brown requires: ctetgen 59230602db0SMatthew G. Knepley args: -dm_plex_dim 3 \ 59330602db0SMatthew G. Knepley -dm_plex_simplex false \ 594c4762a1bSJed Brown -velocity_petscspace_degree 1 \ 595c4762a1bSJed Brown -velocity_petscdualspace_type bdm \ 596d092c84bSBrandon Whitchurch -velocity_petscdualspace_lagrange_tensor 1 \ 597c4762a1bSJed Brown -divErr_petscspace_degree 1 \ 598c4762a1bSJed Brown -divErr_petscdualspace_lagrange_continuity false \ 599c4762a1bSJed Brown -snes_error_if_not_converged \ 600c4762a1bSJed Brown -ksp_rtol 1e-10 \ 601c4762a1bSJed Brown -ksp_error_if_not_converged \ 602c4762a1bSJed Brown -pc_type fieldsplit \ 603c4762a1bSJed Brown -pc_fieldsplit_detect_saddle_point \ 604c4762a1bSJed Brown -pc_fieldsplit_type schur \ 605c4762a1bSJed Brown -pc_fieldsplit_schur_precondition full 606c4762a1bSJed Brown test: 607c4762a1bSJed Brown suffix: linear 608c4762a1bSJed Brown args: -sol_form linear -mesh_transform none 609c4762a1bSJed Brown test: 610c4762a1bSJed Brown suffix: sinusoidal 611c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform none 612c4762a1bSJed Brown test: 613c4762a1bSJed Brown suffix: sinusoidal_skew 614c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform skew 615c4762a1bSJed Brown test: 616c4762a1bSJed Brown suffix: sinusoidal_perturb 617c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform perturb 618c4762a1bSJed Brown test: 619c4762a1bSJed Brown suffix: sinusoidal_skew_perturb 620c4762a1bSJed Brown args: -sol_form sinusoidal -mesh_transform skew_perturb 621d092c84bSBrandon Whitchurch 622d092c84bSBrandon Whitchurch test: 623d092c84bSBrandon Whitchurch suffix: quad_rt_0 62430602db0SMatthew G. Knepley args: -dm_plex_simplex false -mesh_transform skew \ 625d092c84bSBrandon Whitchurch -divErr_petscspace_degree 1 \ 626d092c84bSBrandon Whitchurch -divErr_petscdualspace_lagrange_continuity false \ 627d092c84bSBrandon Whitchurch -snes_error_if_not_converged \ 628d092c84bSBrandon Whitchurch -ksp_rtol 1e-10 \ 629d092c84bSBrandon Whitchurch -ksp_error_if_not_converged \ 630d092c84bSBrandon Whitchurch -pc_type fieldsplit\ 631d092c84bSBrandon Whitchurch -pc_fieldsplit_detect_saddle_point\ 632d092c84bSBrandon Whitchurch -pc_fieldsplit_type schur\ 633d092c84bSBrandon Whitchurch -pc_fieldsplit_schur_precondition full \ 634d092c84bSBrandon Whitchurch -velocity_petscfe_default_quadrature_order 1 \ 635d092c84bSBrandon Whitchurch -velocity_petscspace_type sum \ 636d092c84bSBrandon Whitchurch -velocity_petscspace_variables 2 \ 637d092c84bSBrandon Whitchurch -velocity_petscspace_components 2 \ 638d092c84bSBrandon Whitchurch -velocity_petscspace_sum_spaces 2 \ 639d092c84bSBrandon Whitchurch -velocity_petscspace_sum_concatenate true \ 640417c287bSToby Isaac -velocity_sumcomp_0_petscspace_variables 2 \ 641417c287bSToby Isaac -velocity_sumcomp_0_petscspace_type tensor \ 642417c287bSToby Isaac -velocity_sumcomp_0_petscspace_tensor_spaces 2 \ 643417c287bSToby Isaac -velocity_sumcomp_0_petscspace_tensor_uniform false \ 644417c287bSToby Isaac -velocity_sumcomp_0_tensorcomp_0_petscspace_degree 1 \ 645417c287bSToby Isaac -velocity_sumcomp_0_tensorcomp_1_petscspace_degree 0 \ 646417c287bSToby Isaac -velocity_sumcomp_1_petscspace_variables 2 \ 647417c287bSToby Isaac -velocity_sumcomp_1_petscspace_type tensor \ 648417c287bSToby Isaac -velocity_sumcomp_1_petscspace_tensor_spaces 2 \ 649417c287bSToby Isaac -velocity_sumcomp_1_petscspace_tensor_uniform false \ 650417c287bSToby Isaac -velocity_sumcomp_1_tensorcomp_0_petscspace_degree 0 \ 651417c287bSToby Isaac -velocity_sumcomp_1_tensorcomp_1_petscspace_degree 1 \ 652d092c84bSBrandon Whitchurch -velocity_petscdualspace_form_degree -1 \ 653d092c84bSBrandon Whitchurch -velocity_petscdualspace_order 1 \ 654d092c84bSBrandon Whitchurch -velocity_petscdualspace_lagrange_trimmed true 655c4762a1bSJed Brown TEST*/ 656