xref: /petsc/src/dm/dt/tests/ex10.c (revision d092c84b752daaa800a5a26c90ada1294ab10274)
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