1*d092c84bSBrandon Whitchurch static char help[] = 2*d092c84bSBrandon Whitchurch "Tests implementation of PetscSpace_Sum by solving the Poisson equations using a PetscSpace_Poly and a PetscSpace_Sum and checking that \ 3*d092c84bSBrandon Whitchurch solutions agree up to machine precision.\n\n"; 4*d092c84bSBrandon Whitchurch 5*d092c84bSBrandon Whitchurch #include <petscdmplex.h> 6*d092c84bSBrandon Whitchurch #include <petscds.h> 7*d092c84bSBrandon Whitchurch #include <petscfe.h> 8*d092c84bSBrandon Whitchurch #include <petscsnes.h> 9*d092c84bSBrandon Whitchurch /* We are solving the system of equations: 10*d092c84bSBrandon Whitchurch * \vec{u} = -\grad{p} 11*d092c84bSBrandon Whitchurch * \div{u} = f 12*d092c84bSBrandon Whitchurch */ 13*d092c84bSBrandon Whitchurch 14*d092c84bSBrandon Whitchurch /* Exact solutions for linear velocity 15*d092c84bSBrandon Whitchurch \vec{u} = \vec{x}; 16*d092c84bSBrandon Whitchurch p = -0.5*(\vec{x} \cdot \vec{x}); 17*d092c84bSBrandon Whitchurch */ 18*d092c84bSBrandon Whitchurch static PetscErrorCode linear_u(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nc,PetscScalar *u,void *ctx) 19*d092c84bSBrandon Whitchurch { 20*d092c84bSBrandon Whitchurch PetscInt c; 21*d092c84bSBrandon Whitchurch 22*d092c84bSBrandon Whitchurch for (c = 0; c < Nc; ++c) u[c] = x[c]; 23*d092c84bSBrandon Whitchurch return 0; 24*d092c84bSBrandon Whitchurch } 25*d092c84bSBrandon Whitchurch 26*d092c84bSBrandon Whitchurch static PetscErrorCode linear_p(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nc,PetscScalar *u,void *ctx) 27*d092c84bSBrandon Whitchurch { 28*d092c84bSBrandon Whitchurch PetscInt d; 29*d092c84bSBrandon Whitchurch 30*d092c84bSBrandon Whitchurch u[0] = 0.; 31*d092c84bSBrandon Whitchurch for (d=0; d<dim; ++d) u[0] += -0.5*x[d]*x[d]; 32*d092c84bSBrandon Whitchurch return 0; 33*d092c84bSBrandon Whitchurch } 34*d092c84bSBrandon Whitchurch 35*d092c84bSBrandon Whitchurch static PetscErrorCode linear_divu(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nc,PetscScalar *u,void *ctx) 36*d092c84bSBrandon Whitchurch { 37*d092c84bSBrandon Whitchurch u[0] = dim; 38*d092c84bSBrandon Whitchurch return 0; 39*d092c84bSBrandon Whitchurch } 40*d092c84bSBrandon Whitchurch 41*d092c84bSBrandon Whitchurch /* fx_v are the residual functions for the equation \vec{u} = \grad{p}. f0_v is the term <v,u>.*/ 42*d092c84bSBrandon Whitchurch static void f0_v(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[]) 43*d092c84bSBrandon Whitchurch { 44*d092c84bSBrandon Whitchurch PetscInt i; 45*d092c84bSBrandon Whitchurch 46*d092c84bSBrandon Whitchurch for (i=0; i<dim; ++i) f0[i] = u[uOff[0] + i]; 47*d092c84bSBrandon Whitchurch } 48*d092c84bSBrandon Whitchurch 49*d092c84bSBrandon Whitchurch /* f1_v is the term <v,-\grad{p}> but we integrate by parts to get <\grad{v}, -p*I> */ 50*d092c84bSBrandon Whitchurch static void f1_v(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 f1[]) 51*d092c84bSBrandon Whitchurch { 52*d092c84bSBrandon Whitchurch PetscInt c; 53*d092c84bSBrandon Whitchurch 54*d092c84bSBrandon Whitchurch for (c=0; c<dim; ++c) { 55*d092c84bSBrandon Whitchurch PetscInt d; 56*d092c84bSBrandon Whitchurch 57*d092c84bSBrandon Whitchurch for (d=0; d<dim; ++d) f1[c*dim + d] = (c==d) ? -u[uOff[1]] : 0; 58*d092c84bSBrandon Whitchurch } 59*d092c84bSBrandon Whitchurch } 60*d092c84bSBrandon Whitchurch 61*d092c84bSBrandon Whitchurch /* Residual function for enforcing \div{u} = f. */ 62*d092c84bSBrandon Whitchurch static void f0_q_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[]) 63*d092c84bSBrandon Whitchurch { 64*d092c84bSBrandon Whitchurch PetscScalar rhs,divu=0; 65*d092c84bSBrandon Whitchurch PetscInt i; 66*d092c84bSBrandon Whitchurch 67*d092c84bSBrandon Whitchurch (void)linear_divu(dim,t,x,dim,&rhs,NULL);; 68*d092c84bSBrandon Whitchurch for (i=0; i< dim; ++i) divu += u_x[uOff_x[0]+i*dim+i]; 69*d092c84bSBrandon Whitchurch f0[0] = divu-rhs; 70*d092c84bSBrandon Whitchurch } 71*d092c84bSBrandon Whitchurch 72*d092c84bSBrandon Whitchurch /* Boundary residual. Dirichlet boundary for u means u_bdy=p*n */ 73*d092c84bSBrandon Whitchurch 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[]) 74*d092c84bSBrandon Whitchurch { 75*d092c84bSBrandon Whitchurch PetscScalar pressure; 76*d092c84bSBrandon Whitchurch PetscInt d; 77*d092c84bSBrandon Whitchurch 78*d092c84bSBrandon Whitchurch (void)linear_p(dim,t,x,dim,&pressure,NULL); 79*d092c84bSBrandon Whitchurch for (d=0; d<dim; ++d) f0[d] = pressure*n[d]; 80*d092c84bSBrandon Whitchurch } 81*d092c84bSBrandon Whitchurch 82*d092c84bSBrandon Whitchurch /* gx_yz are the jacobian functions obtained by taking the derivative of the y residual w.r.t z*/ 83*d092c84bSBrandon Whitchurch 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[]) 84*d092c84bSBrandon Whitchurch { 85*d092c84bSBrandon Whitchurch PetscInt c; 86*d092c84bSBrandon Whitchurch 87*d092c84bSBrandon Whitchurch for (c=0; c<dim; ++c) g0[c*dim + c] = 1.0; 88*d092c84bSBrandon Whitchurch } 89*d092c84bSBrandon Whitchurch 90*d092c84bSBrandon Whitchurch 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[]) 91*d092c84bSBrandon Whitchurch { 92*d092c84bSBrandon Whitchurch PetscInt c; 93*d092c84bSBrandon Whitchurch 94*d092c84bSBrandon Whitchurch for (c=0; c<dim; ++c) g1[c*dim + c] = 1.0; 95*d092c84bSBrandon Whitchurch } 96*d092c84bSBrandon Whitchurch 97*d092c84bSBrandon Whitchurch static void g2_vp(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 g2[]) 98*d092c84bSBrandon Whitchurch { 99*d092c84bSBrandon Whitchurch PetscInt c; 100*d092c84bSBrandon Whitchurch 101*d092c84bSBrandon Whitchurch for (c=0; c<dim; ++c) g2[c*dim + c] = -1.0; 102*d092c84bSBrandon Whitchurch } 103*d092c84bSBrandon Whitchurch 104*d092c84bSBrandon Whitchurch typedef struct 105*d092c84bSBrandon Whitchurch { 106*d092c84bSBrandon Whitchurch PetscBool simplex; 107*d092c84bSBrandon Whitchurch PetscInt dim; 108*d092c84bSBrandon Whitchurch } UserCtx; 109*d092c84bSBrandon Whitchurch 110*d092c84bSBrandon Whitchurch /* Process command line options and initialize the UserCtx struct */ 111*d092c84bSBrandon Whitchurch static PetscErrorCode ProcessOptions(MPI_Comm comm,UserCtx *user) 112*d092c84bSBrandon Whitchurch { 113*d092c84bSBrandon Whitchurch PetscErrorCode ierr; 114*d092c84bSBrandon Whitchurch 115*d092c84bSBrandon Whitchurch PetscFunctionBegin; 116*d092c84bSBrandon Whitchurch /* Default to 2D, triangle mesh.*/ 117*d092c84bSBrandon Whitchurch user->simplex = PETSC_TRUE; 118*d092c84bSBrandon Whitchurch user->dim = 2; 119*d092c84bSBrandon Whitchurch 120*d092c84bSBrandon Whitchurch ierr = PetscOptionsBegin(comm,"","PetscSpaceSum Tests","PetscSpace");CHKERRQ(ierr); 121*d092c84bSBrandon Whitchurch ierr = PetscOptionsBool("-simplex","Whether to use simplices (true) or tensor-product (false) cells in " "the mesh","ex8.c",user->simplex, 122*d092c84bSBrandon Whitchurch &user->simplex,NULL);CHKERRQ(ierr); 123*d092c84bSBrandon Whitchurch ierr = PetscOptionsInt("-dim","Number of solution dimensions","ex8.c",user->dim,&user->dim,NULL);CHKERRQ(ierr); 124*d092c84bSBrandon Whitchurch ierr = PetscOptionsEnd();CHKERRQ(ierr); 125*d092c84bSBrandon Whitchurch PetscFunctionReturn(0); 126*d092c84bSBrandon Whitchurch } 127*d092c84bSBrandon Whitchurch 128*d092c84bSBrandon Whitchurch static PetscErrorCode CreateMesh(MPI_Comm comm,UserCtx *user,DM *mesh) 129*d092c84bSBrandon Whitchurch { 130*d092c84bSBrandon Whitchurch PetscErrorCode ierr; 131*d092c84bSBrandon Whitchurch DMLabel label; 132*d092c84bSBrandon Whitchurch const char *name = "marker"; 133*d092c84bSBrandon Whitchurch DM dmDist = NULL; 134*d092c84bSBrandon Whitchurch PetscPartitioner part; 135*d092c84bSBrandon Whitchurch 136*d092c84bSBrandon Whitchurch PetscFunctionBegin; 137*d092c84bSBrandon Whitchurch /* Create box mesh from user parameters */ 138*d092c84bSBrandon Whitchurch ierr = DMPlexCreateBoxMesh(comm,user->dim,user->simplex,NULL,NULL,NULL,NULL,PETSC_TRUE,mesh);CHKERRQ(ierr); 139*d092c84bSBrandon Whitchurch 140*d092c84bSBrandon Whitchurch /* Make sure the mesh gets properly distributed if running in parallel */ 141*d092c84bSBrandon Whitchurch ierr = DMPlexGetPartitioner(*mesh,&part);CHKERRQ(ierr); 142*d092c84bSBrandon Whitchurch ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr); 143*d092c84bSBrandon Whitchurch ierr = DMPlexDistribute(*mesh,0,NULL,&dmDist);CHKERRQ(ierr); 144*d092c84bSBrandon Whitchurch if (dmDist) { 145*d092c84bSBrandon Whitchurch ierr = DMDestroy(mesh);CHKERRQ(ierr); 146*d092c84bSBrandon Whitchurch *mesh = dmDist; 147*d092c84bSBrandon Whitchurch } 148*d092c84bSBrandon Whitchurch 149*d092c84bSBrandon Whitchurch /* Mark the boundaries, we will need this later when setting up the system of 150*d092c84bSBrandon Whitchurch * equations */ 151*d092c84bSBrandon Whitchurch ierr = DMCreateLabel(*mesh,name);CHKERRQ(ierr); 152*d092c84bSBrandon Whitchurch ierr = DMGetLabel(*mesh,name,&label);CHKERRQ(ierr); 153*d092c84bSBrandon Whitchurch ierr = DMPlexMarkBoundaryFaces(*mesh,1,label);CHKERRQ(ierr); 154*d092c84bSBrandon Whitchurch ierr = DMPlexLabelComplete(*mesh,label);CHKERRQ(ierr); 155*d092c84bSBrandon Whitchurch ierr = DMLocalizeCoordinates(*mesh);CHKERRQ(ierr); 156*d092c84bSBrandon Whitchurch ierr = PetscObjectSetName((PetscObject) *mesh,"Mesh");CHKERRQ(ierr); 157*d092c84bSBrandon Whitchurch 158*d092c84bSBrandon Whitchurch /* Get any other mesh options from the command line */ 159*d092c84bSBrandon Whitchurch ierr = DMSetApplicationContext(*mesh,user);CHKERRQ(ierr); 160*d092c84bSBrandon Whitchurch ierr = DMSetFromOptions(*mesh);CHKERRQ(ierr); 161*d092c84bSBrandon Whitchurch ierr = DMViewFromOptions(*mesh,NULL,"-dm_view");CHKERRQ(ierr); 162*d092c84bSBrandon Whitchurch 163*d092c84bSBrandon Whitchurch ierr = DMDestroy(&dmDist);CHKERRQ(ierr); 164*d092c84bSBrandon Whitchurch PetscFunctionReturn(0); 165*d092c84bSBrandon Whitchurch } 166*d092c84bSBrandon Whitchurch 167*d092c84bSBrandon Whitchurch /* Setup the system of equations that we wish to solve */ 168*d092c84bSBrandon Whitchurch static PetscErrorCode SetupProblem(DM dm,UserCtx *user) 169*d092c84bSBrandon Whitchurch { 170*d092c84bSBrandon Whitchurch PetscDS prob; 171*d092c84bSBrandon Whitchurch PetscErrorCode ierr; 172*d092c84bSBrandon Whitchurch const PetscInt id=1; 173*d092c84bSBrandon Whitchurch 174*d092c84bSBrandon Whitchurch PetscFunctionBegin; 175*d092c84bSBrandon Whitchurch ierr = DMGetDS(dm,&prob);CHKERRQ(ierr); 176*d092c84bSBrandon Whitchurch /* All of these are independent of the user's choice of solution */ 177*d092c84bSBrandon Whitchurch ierr = PetscDSSetResidual(prob,0,f0_v,f1_v);CHKERRQ(ierr); 178*d092c84bSBrandon Whitchurch ierr = PetscDSSetResidual(prob,1,f0_q_linear,NULL);CHKERRQ(ierr); 179*d092c84bSBrandon Whitchurch ierr = PetscDSSetJacobian(prob,0,0,g0_vu,NULL,NULL,NULL);CHKERRQ(ierr); 180*d092c84bSBrandon Whitchurch ierr = PetscDSSetJacobian(prob,0,1,NULL,NULL,g2_vp,NULL);CHKERRQ(ierr); 181*d092c84bSBrandon Whitchurch ierr = PetscDSSetJacobian(prob,1,0,NULL,g1_qu,NULL,NULL);CHKERRQ(ierr); 182*d092c84bSBrandon Whitchurch 183*d092c84bSBrandon Whitchurch ierr = PetscDSAddBoundary(prob,DM_BC_NATURAL,"Boundary Integral","marker",0,0,NULL,(void (*)(void))NULL,1,&id,user);CHKERRQ(ierr); 184*d092c84bSBrandon Whitchurch ierr = PetscDSSetBdResidual(prob,0,f0_bd_u_linear,NULL);CHKERRQ(ierr); 185*d092c84bSBrandon Whitchurch ierr = PetscDSSetExactSolution(prob,0,linear_u,NULL);CHKERRQ(ierr); 186*d092c84bSBrandon Whitchurch ierr = PetscDSSetExactSolution(prob,1,linear_divu,NULL);CHKERRQ(ierr); 187*d092c84bSBrandon Whitchurch PetscFunctionReturn(0); 188*d092c84bSBrandon Whitchurch } 189*d092c84bSBrandon Whitchurch 190*d092c84bSBrandon Whitchurch /* Create the finite element spaces we will use for this system */ 191*d092c84bSBrandon Whitchurch static PetscErrorCode SetupDiscretization(DM mesh,DM mesh_sum,PetscErrorCode (*setup)(DM,UserCtx*),UserCtx *user) 192*d092c84bSBrandon Whitchurch { 193*d092c84bSBrandon Whitchurch DM cdm = mesh,cdm_sum = mesh_sum; 194*d092c84bSBrandon Whitchurch PetscFE u,divu,u_sum,divu_sum; 195*d092c84bSBrandon Whitchurch const PetscInt dim = user->dim; 196*d092c84bSBrandon Whitchurch PetscErrorCode ierr; 197*d092c84bSBrandon Whitchurch 198*d092c84bSBrandon Whitchurch PetscFunctionBegin; 199*d092c84bSBrandon Whitchurch /* Create FE objects and give them names so that options can be set from 200*d092c84bSBrandon Whitchurch * command line. Each field gets 2 instances (i.e. velocity and velocity_sum)created twice so that we can compare between approaches. */ 201*d092c84bSBrandon Whitchurch ierr = PetscFECreateDefault(PetscObjectComm((PetscObject)mesh),dim,dim,user->simplex,"velocity_",-1,&u);CHKERRQ(ierr); 202*d092c84bSBrandon Whitchurch ierr = PetscObjectSetName((PetscObject)u,"velocity");CHKERRQ(ierr); 203*d092c84bSBrandon Whitchurch ierr = PetscFECreateDefault(PetscObjectComm((PetscObject)mesh_sum),dim,dim,user->simplex,"velocity_sum_",-1,&u_sum);CHKERRQ(ierr); 204*d092c84bSBrandon Whitchurch ierr = PetscObjectSetName((PetscObject)u_sum,"velocity_sum");CHKERRQ(ierr); 205*d092c84bSBrandon Whitchurch ierr = PetscFECreateDefault(PetscObjectComm((PetscObject)mesh),dim,1,user->simplex,"divu_",-1,&divu);CHKERRQ(ierr); 206*d092c84bSBrandon Whitchurch ierr = PetscObjectSetName((PetscObject)divu,"divu");CHKERRQ(ierr); 207*d092c84bSBrandon Whitchurch ierr = PetscFECreateDefault(PetscObjectComm((PetscObject)mesh_sum),dim,1,user->simplex,"divu_sum_",-1,&divu_sum);CHKERRQ(ierr); 208*d092c84bSBrandon Whitchurch ierr = PetscObjectSetName((PetscObject)divu_sum,"divu_sum");CHKERRQ(ierr); 209*d092c84bSBrandon Whitchurch 210*d092c84bSBrandon Whitchurch ierr = PetscFECopyQuadrature(u,divu);CHKERRQ(ierr); 211*d092c84bSBrandon Whitchurch ierr = PetscFECopyQuadrature(u_sum,divu_sum);CHKERRQ(ierr); 212*d092c84bSBrandon Whitchurch 213*d092c84bSBrandon Whitchurch /* Associate the FE objects with the mesh and setup the system */ 214*d092c84bSBrandon Whitchurch ierr = DMSetField(mesh,0,NULL,(PetscObject)u);CHKERRQ(ierr); 215*d092c84bSBrandon Whitchurch ierr = DMSetField(mesh,1,NULL,(PetscObject)divu);CHKERRQ(ierr); 216*d092c84bSBrandon Whitchurch ierr = DMCreateDS(mesh);CHKERRQ(ierr); 217*d092c84bSBrandon Whitchurch ierr = (*setup)(mesh,user);CHKERRQ(ierr); 218*d092c84bSBrandon Whitchurch 219*d092c84bSBrandon Whitchurch ierr = DMSetField(mesh_sum,0,NULL,(PetscObject)u_sum);CHKERRQ(ierr); 220*d092c84bSBrandon Whitchurch ierr = DMSetField(mesh_sum,1,NULL,(PetscObject)divu_sum);CHKERRQ(ierr); 221*d092c84bSBrandon Whitchurch ierr = DMCreateDS(mesh_sum);CHKERRQ(ierr); 222*d092c84bSBrandon Whitchurch ierr = (*setup)(mesh_sum,user);CHKERRQ(ierr); 223*d092c84bSBrandon Whitchurch 224*d092c84bSBrandon Whitchurch while (cdm) { 225*d092c84bSBrandon Whitchurch ierr = DMCopyDisc(mesh,cdm);CHKERRQ(ierr); 226*d092c84bSBrandon Whitchurch ierr = DMGetCoarseDM(cdm,&cdm);CHKERRQ(ierr); 227*d092c84bSBrandon Whitchurch } 228*d092c84bSBrandon Whitchurch 229*d092c84bSBrandon Whitchurch while (cdm_sum) { 230*d092c84bSBrandon Whitchurch ierr = DMCopyDisc(mesh_sum,cdm_sum);CHKERRQ(ierr); 231*d092c84bSBrandon Whitchurch ierr = DMGetCoarseDM(cdm_sum,&cdm_sum);CHKERRQ(ierr); 232*d092c84bSBrandon Whitchurch } 233*d092c84bSBrandon Whitchurch 234*d092c84bSBrandon Whitchurch /* The Mesh now owns the fields, so we can destroy the FEs created in this 235*d092c84bSBrandon Whitchurch * function */ 236*d092c84bSBrandon Whitchurch ierr = PetscFEDestroy(&u);CHKERRQ(ierr); 237*d092c84bSBrandon Whitchurch ierr = PetscFEDestroy(&divu);CHKERRQ(ierr); 238*d092c84bSBrandon Whitchurch ierr = PetscFEDestroy(&u_sum);CHKERRQ(ierr); 239*d092c84bSBrandon Whitchurch ierr = PetscFEDestroy(&divu_sum);CHKERRQ(ierr); 240*d092c84bSBrandon Whitchurch ierr = DMDestroy(&cdm);CHKERRQ(ierr); 241*d092c84bSBrandon Whitchurch ierr = DMDestroy(&cdm_sum);CHKERRQ(ierr); 242*d092c84bSBrandon Whitchurch PetscFunctionReturn(0); 243*d092c84bSBrandon Whitchurch } 244*d092c84bSBrandon Whitchurch 245*d092c84bSBrandon Whitchurch int main(int argc,char **argv) 246*d092c84bSBrandon Whitchurch { 247*d092c84bSBrandon Whitchurch UserCtx user; 248*d092c84bSBrandon Whitchurch DM dm,dm_sum; 249*d092c84bSBrandon Whitchurch SNES snes,snes_sum; 250*d092c84bSBrandon Whitchurch Vec u,u_sum; 251*d092c84bSBrandon Whitchurch PetscReal errNorm; 252*d092c84bSBrandon Whitchurch const PetscReal errTol = PETSC_SMALL; 253*d092c84bSBrandon Whitchurch PetscErrorCode ierr; 254*d092c84bSBrandon Whitchurch 255*d092c84bSBrandon Whitchurch ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; 256*d092c84bSBrandon Whitchurch ierr = ProcessOptions(PETSC_COMM_WORLD,&user);CHKERRQ(ierr); 257*d092c84bSBrandon Whitchurch 258*d092c84bSBrandon Whitchurch /* Set up a snes for the standard approach, one space with 2 components */ 259*d092c84bSBrandon Whitchurch ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr); 260*d092c84bSBrandon Whitchurch ierr = CreateMesh(PETSC_COMM_WORLD,&user,&dm);CHKERRQ(ierr); 261*d092c84bSBrandon Whitchurch ierr = SNESSetDM(snes,dm);CHKERRQ(ierr); 262*d092c84bSBrandon Whitchurch 263*d092c84bSBrandon Whitchurch /* Set up a snes for the sum space approach, where each subspace of the sum space represents one component */ 264*d092c84bSBrandon Whitchurch ierr = SNESCreate(PETSC_COMM_WORLD,&snes_sum);CHKERRQ(ierr); 265*d092c84bSBrandon Whitchurch ierr = CreateMesh(PETSC_COMM_WORLD,&user,&dm_sum);CHKERRQ(ierr); 266*d092c84bSBrandon Whitchurch ierr = SNESSetDM(snes_sum,dm_sum);CHKERRQ(ierr); 267*d092c84bSBrandon Whitchurch ierr = SetupDiscretization(dm,dm_sum,SetupProblem,&user);CHKERRQ(ierr); 268*d092c84bSBrandon Whitchurch 269*d092c84bSBrandon Whitchurch /* Set up and solve the system using standard approach. */ 270*d092c84bSBrandon Whitchurch ierr = DMCreateGlobalVector(dm,&u);CHKERRQ(ierr); 271*d092c84bSBrandon Whitchurch ierr = VecSet(u,0.0);CHKERRQ(ierr); 272*d092c84bSBrandon Whitchurch ierr = PetscObjectSetName((PetscObject)u,"solution");CHKERRQ(ierr); 273*d092c84bSBrandon Whitchurch ierr = DMPlexSetSNESLocalFEM(dm,&user,&user,&user);CHKERRQ(ierr); 274*d092c84bSBrandon Whitchurch ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 275*d092c84bSBrandon Whitchurch ierr = DMSNESCheckFromOptions(snes,u,NULL,NULL);CHKERRQ(ierr); 276*d092c84bSBrandon Whitchurch ierr = SNESSolve(snes,NULL,u);CHKERRQ(ierr); 277*d092c84bSBrandon Whitchurch ierr = SNESGetSolution(snes,&u);CHKERRQ(ierr); 278*d092c84bSBrandon Whitchurch ierr = VecViewFromOptions(u,NULL,"-solution_view");CHKERRQ(ierr); 279*d092c84bSBrandon Whitchurch 280*d092c84bSBrandon Whitchurch /* Set up and solve the sum space system */ 281*d092c84bSBrandon Whitchurch ierr = DMCreateGlobalVector(dm_sum,&u_sum);CHKERRQ(ierr); 282*d092c84bSBrandon Whitchurch ierr = VecSet(u_sum,0.0);CHKERRQ(ierr); 283*d092c84bSBrandon Whitchurch ierr = PetscObjectSetName((PetscObject)u_sum,"solution_sum");CHKERRQ(ierr); 284*d092c84bSBrandon Whitchurch ierr = DMPlexSetSNESLocalFEM(dm_sum,&user,&user,&user);CHKERRQ(ierr); 285*d092c84bSBrandon Whitchurch ierr = SNESSetFromOptions(snes_sum);CHKERRQ(ierr); 286*d092c84bSBrandon Whitchurch ierr = DMSNESCheckFromOptions(snes_sum,u_sum,NULL,NULL);CHKERRQ(ierr); 287*d092c84bSBrandon Whitchurch ierr = SNESSolve(snes_sum,NULL,u_sum);CHKERRQ(ierr); 288*d092c84bSBrandon Whitchurch ierr = SNESGetSolution(snes_sum,&u_sum);CHKERRQ(ierr); 289*d092c84bSBrandon Whitchurch ierr = VecViewFromOptions(u_sum,NULL,"-solution_sum_view");CHKERRQ(ierr); 290*d092c84bSBrandon Whitchurch 291*d092c84bSBrandon Whitchurch /* Check if standard solution and sum space solution match to machine precision */ 292*d092c84bSBrandon Whitchurch ierr = VecAXPY(u_sum,-1,u);CHKERRQ(ierr); 293*d092c84bSBrandon Whitchurch ierr = VecNorm(u_sum,NORM_2,&errNorm);CHKERRQ(ierr); 294*d092c84bSBrandon Whitchurch ierr = PetscPrintf(PETSC_COMM_WORLD,"Sum space provides the same solution as a regular space: %s",(errNorm < errTol) ? "true" : "false");CHKERRQ( 295*d092c84bSBrandon Whitchurch ierr); 296*d092c84bSBrandon Whitchurch 297*d092c84bSBrandon Whitchurch /* Cleanup */ 298*d092c84bSBrandon Whitchurch ierr = VecDestroy(&u_sum);CHKERRQ(ierr); 299*d092c84bSBrandon Whitchurch ierr = VecDestroy(&u);CHKERRQ(ierr); 300*d092c84bSBrandon Whitchurch ierr = SNESDestroy(&snes_sum);CHKERRQ(ierr); 301*d092c84bSBrandon Whitchurch ierr = SNESDestroy(&snes);CHKERRQ(ierr); 302*d092c84bSBrandon Whitchurch ierr = DMDestroy(&dm_sum);CHKERRQ(ierr); 303*d092c84bSBrandon Whitchurch ierr = DMDestroy(&dm);CHKERRQ(ierr); 304*d092c84bSBrandon Whitchurch ierr = PetscFinalize(); 305*d092c84bSBrandon Whitchurch return ierr; 306*d092c84bSBrandon Whitchurch } 307*d092c84bSBrandon Whitchurch 308*d092c84bSBrandon Whitchurch /*TEST 309*d092c84bSBrandon Whitchurch test: 310*d092c84bSBrandon Whitchurch suffix: 2d_lagrange 311*d092c84bSBrandon Whitchurch requires: triangle 312*d092c84bSBrandon Whitchurch args: -dim 2 \ 313*d092c84bSBrandon Whitchurch -simplex true \ 314*d092c84bSBrandon Whitchurch -velocity_petscspace_degree 1 \ 315*d092c84bSBrandon Whitchurch -velocity_petscspace_type poly \ 316*d092c84bSBrandon Whitchurch -velocity_petscspace_components 2\ 317*d092c84bSBrandon Whitchurch -velocity_petscdualspace_type lagrange \ 318*d092c84bSBrandon Whitchurch -divu_petscspace_degree 0 \ 319*d092c84bSBrandon Whitchurch -divu_petscspace_type poly \ 320*d092c84bSBrandon Whitchurch -divu_petscdualspace_lagrange_continuity false \ 321*d092c84bSBrandon Whitchurch -velocity_sum_petscfe_default_quadrature_order 1 \ 322*d092c84bSBrandon Whitchurch -velocity_sum_petscspace_degree 1 \ 323*d092c84bSBrandon Whitchurch -velocity_sum_petscspace_type sum \ 324*d092c84bSBrandon Whitchurch -velocity_sum_petscspace_variables 2 \ 325*d092c84bSBrandon Whitchurch -velocity_sum_petscspace_components 2 \ 326*d092c84bSBrandon Whitchurch -velocity_sum_petscspace_sum_spaces 2 \ 327*d092c84bSBrandon Whitchurch -velocity_sum_petscspace_sum_concatenate true \ 328*d092c84bSBrandon Whitchurch -velocity_sum_petscdualspace_type lagrange \ 329*d092c84bSBrandon Whitchurch -velocity_sum_subspace0_petscspace_type poly \ 330*d092c84bSBrandon Whitchurch -velocity_sum_subspace0_petscspace_degree 1 \ 331*d092c84bSBrandon Whitchurch -velocity_sum_subspace0_petscspace_variables 2 \ 332*d092c84bSBrandon Whitchurch -velocity_sum_subspace0_petscspace_components 1 \ 333*d092c84bSBrandon Whitchurch -velocity_sum_subspace1_petscspace_type poly \ 334*d092c84bSBrandon Whitchurch -velocity_sum_subspace1_petscspace_degree 1 \ 335*d092c84bSBrandon Whitchurch -velocity_sum_subspace1_petscspace_variables 2 \ 336*d092c84bSBrandon Whitchurch -velocity_sum_subspace1_petscspace_components 1 \ 337*d092c84bSBrandon Whitchurch -divu_sum_petscspace_degree 0 \ 338*d092c84bSBrandon Whitchurch -divu_sum_petscspace_type sum \ 339*d092c84bSBrandon Whitchurch -divu_sum_petscspace_variables 2 \ 340*d092c84bSBrandon Whitchurch -divu_sum_petscspace_components 1 \ 341*d092c84bSBrandon Whitchurch -divu_sum_petscspace_sum_spaces 1 \ 342*d092c84bSBrandon Whitchurch -divu_sum_petscspace_sum_concatenate true \ 343*d092c84bSBrandon Whitchurch -divu_sum_petscdualspace_lagrange_continuity false \ 344*d092c84bSBrandon Whitchurch -divu_sum_subspace0_petscspace_type poly \ 345*d092c84bSBrandon Whitchurch -divu_sum_subspace0_petscspace_degree 0 \ 346*d092c84bSBrandon Whitchurch -divu_sum_subspace0_petscspace_variables 2 \ 347*d092c84bSBrandon Whitchurch -divu_sum_subspace0_petscspace_components 1 \ 348*d092c84bSBrandon Whitchurch -dm_refine 0 \ 349*d092c84bSBrandon Whitchurch -snes_error_if_not_converged \ 350*d092c84bSBrandon Whitchurch -ksp_rtol 1e-10 \ 351*d092c84bSBrandon Whitchurch -ksp_error_if_not_converged \ 352*d092c84bSBrandon Whitchurch -pc_type fieldsplit\ 353*d092c84bSBrandon Whitchurch -pc_fieldsplit_type schur\ 354*d092c84bSBrandon Whitchurch -divu_sum_petscdualspace_lagrange_continuity false \ 355*d092c84bSBrandon Whitchurch -pc_fieldsplit_schur_precondition full 356*d092c84bSBrandon Whitchurch TEST*/ 357