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