19371c9d4SSatish Balay static char help[] = "Tests implementation of PetscSpace_Sum by solving the Poisson equations using a PetscSpace_Poly and a PetscSpace_Sum and checking that \
2d092c84bSBrandon Whitchurch solutions agree up to machine precision.\n\n";
3d092c84bSBrandon Whitchurch
4d092c84bSBrandon Whitchurch #include <petscdmplex.h>
5d092c84bSBrandon Whitchurch #include <petscds.h>
6d092c84bSBrandon Whitchurch #include <petscfe.h>
7d092c84bSBrandon Whitchurch #include <petscsnes.h>
8d092c84bSBrandon Whitchurch /* We are solving the system of equations:
9d092c84bSBrandon Whitchurch * \vec{u} = -\grad{p}
10d092c84bSBrandon Whitchurch * \div{u} = f
11d092c84bSBrandon Whitchurch */
12d092c84bSBrandon Whitchurch
13d092c84bSBrandon Whitchurch /* Exact solutions for linear velocity
14d092c84bSBrandon Whitchurch \vec{u} = \vec{x};
15d092c84bSBrandon Whitchurch p = -0.5*(\vec{x} \cdot \vec{x});
16d092c84bSBrandon Whitchurch */
linear_u(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)17*2a8381b2SBarry Smith static PetscErrorCode linear_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
18d71ae5a4SJacob Faibussowitsch {
19d092c84bSBrandon Whitchurch PetscInt c;
20d092c84bSBrandon Whitchurch
21d092c84bSBrandon Whitchurch for (c = 0; c < Nc; ++c) u[c] = x[c];
223ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
23d092c84bSBrandon Whitchurch }
24d092c84bSBrandon Whitchurch
linear_p(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)25*2a8381b2SBarry Smith static PetscErrorCode linear_p(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
26d71ae5a4SJacob Faibussowitsch {
27d092c84bSBrandon Whitchurch PetscInt d;
28d092c84bSBrandon Whitchurch
29d092c84bSBrandon Whitchurch u[0] = 0.;
30d092c84bSBrandon Whitchurch for (d = 0; d < dim; ++d) u[0] += -0.5 * x[d] * x[d];
313ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
32d092c84bSBrandon Whitchurch }
33d092c84bSBrandon Whitchurch
linear_divu(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)34*2a8381b2SBarry Smith static PetscErrorCode linear_divu(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
35d71ae5a4SJacob Faibussowitsch {
36d092c84bSBrandon Whitchurch u[0] = dim;
373ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
38d092c84bSBrandon Whitchurch }
39d092c84bSBrandon Whitchurch
40d092c84bSBrandon Whitchurch /* fx_v are the residual functions for the equation \vec{u} = \grad{p}. f0_v is the term <v,u>.*/
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[])41d71ae5a4SJacob Faibussowitsch 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[])
42d71ae5a4SJacob Faibussowitsch {
43d092c84bSBrandon Whitchurch PetscInt i;
44d092c84bSBrandon Whitchurch
45d092c84bSBrandon Whitchurch for (i = 0; i < dim; ++i) f0[i] = u[uOff[0] + i];
46d092c84bSBrandon Whitchurch }
47d092c84bSBrandon Whitchurch
48d092c84bSBrandon Whitchurch /* f1_v is the term <v,-\grad{p}> but we integrate by parts to get <\grad{v}, -p*I> */
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[])49d71ae5a4SJacob Faibussowitsch 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[])
50d71ae5a4SJacob Faibussowitsch {
51d092c84bSBrandon Whitchurch PetscInt c;
52d092c84bSBrandon Whitchurch
53d092c84bSBrandon Whitchurch for (c = 0; c < dim; ++c) {
54d092c84bSBrandon Whitchurch PetscInt d;
55d092c84bSBrandon Whitchurch
56d092c84bSBrandon Whitchurch for (d = 0; d < dim; ++d) f1[c * dim + d] = (c == d) ? -u[uOff[1]] : 0;
57d092c84bSBrandon Whitchurch }
58d092c84bSBrandon Whitchurch }
59d092c84bSBrandon Whitchurch
60d092c84bSBrandon Whitchurch /* Residual function for enforcing \div{u} = f. */
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[])61d71ae5a4SJacob Faibussowitsch 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[])
62d71ae5a4SJacob Faibussowitsch {
63d092c84bSBrandon Whitchurch PetscScalar rhs, divu = 0;
64d092c84bSBrandon Whitchurch PetscInt i;
65d092c84bSBrandon Whitchurch
662da392ccSBarry Smith (void)linear_divu(dim, t, x, dim, &rhs, NULL);
67d092c84bSBrandon Whitchurch for (i = 0; i < dim; ++i) divu += u_x[uOff_x[0] + i * dim + i];
68d092c84bSBrandon Whitchurch f0[0] = divu - rhs;
69d092c84bSBrandon Whitchurch }
70d092c84bSBrandon Whitchurch
71d092c84bSBrandon Whitchurch /* Boundary residual. Dirichlet boundary for u means u_bdy=p*n */
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[])72d71ae5a4SJacob Faibussowitsch 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[])
73d71ae5a4SJacob Faibussowitsch {
74d092c84bSBrandon Whitchurch PetscScalar pressure;
75d092c84bSBrandon Whitchurch PetscInt d;
76d092c84bSBrandon Whitchurch
77d092c84bSBrandon Whitchurch (void)linear_p(dim, t, x, dim, &pressure, NULL);
78d092c84bSBrandon Whitchurch for (d = 0; d < dim; ++d) f0[d] = pressure * n[d];
79d092c84bSBrandon Whitchurch }
80d092c84bSBrandon Whitchurch
81d092c84bSBrandon Whitchurch /* gx_yz are the jacobian functions obtained by taking the derivative of the y residual w.r.t z*/
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[])82d71ae5a4SJacob Faibussowitsch 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[])
83d71ae5a4SJacob Faibussowitsch {
84d092c84bSBrandon Whitchurch PetscInt c;
85d092c84bSBrandon Whitchurch
86d092c84bSBrandon Whitchurch for (c = 0; c < dim; ++c) g0[c * dim + c] = 1.0;
87d092c84bSBrandon Whitchurch }
88d092c84bSBrandon Whitchurch
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[])89d71ae5a4SJacob Faibussowitsch 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[])
90d71ae5a4SJacob Faibussowitsch {
91d092c84bSBrandon Whitchurch PetscInt c;
92d092c84bSBrandon Whitchurch
93d092c84bSBrandon Whitchurch for (c = 0; c < dim; ++c) g1[c * dim + c] = 1.0;
94d092c84bSBrandon Whitchurch }
95d092c84bSBrandon Whitchurch
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[])96d71ae5a4SJacob Faibussowitsch 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[])
97d71ae5a4SJacob Faibussowitsch {
98d092c84bSBrandon Whitchurch PetscInt c;
99d092c84bSBrandon Whitchurch
100d092c84bSBrandon Whitchurch for (c = 0; c < dim; ++c) g2[c * dim + c] = -1.0;
101d092c84bSBrandon Whitchurch }
102d092c84bSBrandon Whitchurch
1039371c9d4SSatish Balay typedef struct {
10430602db0SMatthew G. Knepley PetscInt dummy;
105*2a8381b2SBarry Smith } AppCtx;
106d092c84bSBrandon Whitchurch
CreateMesh(MPI_Comm comm,AppCtx * ctx,DM * mesh)107*2a8381b2SBarry Smith static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *ctx, DM *mesh)
108d71ae5a4SJacob Faibussowitsch {
109d092c84bSBrandon Whitchurch PetscFunctionBegin;
1109566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh));
1119566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX));
1129566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(*mesh));
113*2a8381b2SBarry Smith PetscCall(DMSetApplicationContext(*mesh, ctx));
1149566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(*mesh, NULL, "-dm_view"));
1153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
116d092c84bSBrandon Whitchurch }
117d092c84bSBrandon Whitchurch
118d092c84bSBrandon Whitchurch /* Setup the system of equations that we wish to solve */
SetupProblem(DM dm,AppCtx * ctx)119*2a8381b2SBarry Smith static PetscErrorCode SetupProblem(DM dm, AppCtx *ctx)
120d71ae5a4SJacob Faibussowitsch {
12145480ffeSMatthew G. Knepley PetscDS ds;
12245480ffeSMatthew G. Knepley DMLabel label;
12345480ffeSMatthew G. Knepley PetscWeakForm wf;
124d092c84bSBrandon Whitchurch const PetscInt id = 1;
12545480ffeSMatthew G. Knepley PetscInt bd;
126d092c84bSBrandon Whitchurch
127d092c84bSBrandon Whitchurch PetscFunctionBegin;
1289566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds));
129d092c84bSBrandon Whitchurch /* All of these are independent of the user's choice of solution */
1309566063dSJacob Faibussowitsch PetscCall(PetscDSSetResidual(ds, 0, f0_v, f1_v));
1319566063dSJacob Faibussowitsch PetscCall(PetscDSSetResidual(ds, 1, f0_q_linear, NULL));
1329566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_vu, NULL, NULL, NULL));
1339566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 1, NULL, NULL, g2_vp, NULL));
1349566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 1, 0, NULL, g1_qu, NULL, NULL));
135d092c84bSBrandon Whitchurch
1369566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &label));
137*2a8381b2SBarry Smith PetscCall(PetscDSAddBoundary(ds, DM_BC_NATURAL, "Boundary Integral", label, 1, &id, 0, 0, NULL, (PetscFortranCallbackFn *)NULL, NULL, ctx, &bd));
1389566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(ds, bd, &wf, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL));
1399566063dSJacob Faibussowitsch PetscCall(PetscWeakFormSetIndexBdResidual(wf, label, 1, 0, 0, 0, f0_bd_u_linear, 0, NULL));
14045480ffeSMatthew G. Knepley
1419566063dSJacob Faibussowitsch PetscCall(PetscDSSetExactSolution(ds, 0, linear_u, NULL));
1428fb5bd83SMatthew G. Knepley PetscCall(PetscDSSetExactSolution(ds, 1, linear_p, NULL));
1433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
144d092c84bSBrandon Whitchurch }
145d092c84bSBrandon Whitchurch
146d092c84bSBrandon Whitchurch /* Create the finite element spaces we will use for this system */
SetupDiscretization(DM mesh,DM mesh_sum,PetscErrorCode (* setup)(DM,AppCtx *),AppCtx * ctx)147*2a8381b2SBarry Smith static PetscErrorCode SetupDiscretization(DM mesh, DM mesh_sum, PetscErrorCode (*setup)(DM, AppCtx *), AppCtx *ctx)
148d71ae5a4SJacob Faibussowitsch {
149d092c84bSBrandon Whitchurch DM cdm = mesh, cdm_sum = mesh_sum;
15012fc5b22SMatthew G. Knepley PetscDS ds;
151d092c84bSBrandon Whitchurch PetscFE u, divu, u_sum, divu_sum;
15230602db0SMatthew G. Knepley PetscInt dim;
15330602db0SMatthew G. Knepley PetscBool simplex;
154d092c84bSBrandon Whitchurch
155d092c84bSBrandon Whitchurch PetscFunctionBegin;
1569566063dSJacob Faibussowitsch PetscCall(DMGetDimension(mesh, &dim));
1579566063dSJacob Faibussowitsch PetscCall(DMPlexIsSimplex(mesh, &simplex));
15812fc5b22SMatthew G. Knepley
15912fc5b22SMatthew G. Knepley {
16012fc5b22SMatthew G. Knepley PetscBool force;
16112fc5b22SMatthew G. Knepley // Turn off automatic quadrature selection as a test
16212fc5b22SMatthew G. Knepley PetscCall(DMGetDS(mesh_sum, &ds));
16312fc5b22SMatthew G. Knepley PetscCall(PetscDSGetForceQuad(ds, &force));
16412fc5b22SMatthew G. Knepley if (force) PetscCall(PetscDSSetForceQuad(ds, PETSC_FALSE));
16512fc5b22SMatthew G. Knepley }
16612fc5b22SMatthew G. Knepley
167d092c84bSBrandon Whitchurch /* Create FE objects and give them names so that options can be set from
168d092c84bSBrandon Whitchurch * command line. Each field gets 2 instances (i.e. velocity and velocity_sum)created twice so that we can compare between approaches. */
1699566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)mesh), dim, dim, simplex, "velocity_", -1, &u));
1709566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)u, "velocity"));
1719566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)mesh_sum), dim, dim, simplex, "velocity_sum_", -1, &u_sum));
1729566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)u_sum, "velocity_sum"));
1739566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)mesh), dim, 1, simplex, "divu_", -1, &divu));
1749566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)divu, "divu"));
1759566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)mesh_sum), dim, 1, simplex, "divu_sum_", -1, &divu_sum));
1769566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)divu_sum, "divu_sum"));
177d092c84bSBrandon Whitchurch
1789566063dSJacob Faibussowitsch PetscCall(PetscFECopyQuadrature(u, divu));
1799566063dSJacob Faibussowitsch PetscCall(PetscFECopyQuadrature(u_sum, divu_sum));
180d092c84bSBrandon Whitchurch
181d092c84bSBrandon Whitchurch /* Associate the FE objects with the mesh and setup the system */
1829566063dSJacob Faibussowitsch PetscCall(DMSetField(mesh, 0, NULL, (PetscObject)u));
1839566063dSJacob Faibussowitsch PetscCall(DMSetField(mesh, 1, NULL, (PetscObject)divu));
1849566063dSJacob Faibussowitsch PetscCall(DMCreateDS(mesh));
185*2a8381b2SBarry Smith PetscCall((*setup)(mesh, ctx));
186d092c84bSBrandon Whitchurch
1879566063dSJacob Faibussowitsch PetscCall(DMSetField(mesh_sum, 0, NULL, (PetscObject)u_sum));
1889566063dSJacob Faibussowitsch PetscCall(DMSetField(mesh_sum, 1, NULL, (PetscObject)divu_sum));
1899566063dSJacob Faibussowitsch PetscCall(DMCreateDS(mesh_sum));
190*2a8381b2SBarry Smith PetscCall((*setup)(mesh_sum, ctx));
191d092c84bSBrandon Whitchurch
192d092c84bSBrandon Whitchurch while (cdm) {
1939566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(mesh, cdm));
1949566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(cdm, &cdm));
195d092c84bSBrandon Whitchurch }
196d092c84bSBrandon Whitchurch
197d092c84bSBrandon Whitchurch while (cdm_sum) {
1989566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(mesh_sum, cdm_sum));
1999566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(cdm_sum, &cdm_sum));
200d092c84bSBrandon Whitchurch }
201d092c84bSBrandon Whitchurch
202d092c84bSBrandon Whitchurch /* The Mesh now owns the fields, so we can destroy the FEs created in this
203d092c84bSBrandon Whitchurch * function */
2049566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&u));
2059566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&divu));
2069566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&u_sum));
2079566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&divu_sum));
2089566063dSJacob Faibussowitsch PetscCall(DMDestroy(&cdm));
2099566063dSJacob Faibussowitsch PetscCall(DMDestroy(&cdm_sum));
2103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
211d092c84bSBrandon Whitchurch }
212d092c84bSBrandon Whitchurch
main(int argc,char ** argv)213d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
214d71ae5a4SJacob Faibussowitsch {
215*2a8381b2SBarry Smith AppCtx ctx;
216d092c84bSBrandon Whitchurch DM dm, dm_sum;
217d092c84bSBrandon Whitchurch SNES snes, snes_sum;
218d092c84bSBrandon Whitchurch Vec u, u_sum;
219d092c84bSBrandon Whitchurch PetscReal errNorm;
220d092c84bSBrandon Whitchurch const PetscReal errTol = PETSC_SMALL;
221d092c84bSBrandon Whitchurch
222327415f7SBarry Smith PetscFunctionBeginUser;
223c8025a54SPierre Jolivet PetscCall(PetscInitialize(&argc, &argv, NULL, help));
224d092c84bSBrandon Whitchurch
225d092c84bSBrandon Whitchurch /* Set up a snes for the standard approach, one space with 2 components */
2269566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes));
227*2a8381b2SBarry Smith PetscCall(CreateMesh(PETSC_COMM_WORLD, &ctx, &dm));
2289566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, dm));
229d092c84bSBrandon Whitchurch
230d092c84bSBrandon Whitchurch /* Set up a snes for the sum space approach, where each subspace of the sum space represents one component */
2319566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes_sum));
232*2a8381b2SBarry Smith PetscCall(CreateMesh(PETSC_COMM_WORLD, &ctx, &dm_sum));
2339566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_sum, dm_sum));
234*2a8381b2SBarry Smith PetscCall(SetupDiscretization(dm, dm_sum, SetupProblem, &ctx));
235d092c84bSBrandon Whitchurch
236d092c84bSBrandon Whitchurch /* Set up and solve the system using standard approach. */
2379566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &u));
2389566063dSJacob Faibussowitsch PetscCall(VecSet(u, 0.0));
2399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)u, "solution"));
240*2a8381b2SBarry Smith PetscCall(DMPlexSetSNESLocalFEM(dm, PETSC_FALSE, &ctx));
2419566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes));
2429566063dSJacob Faibussowitsch PetscCall(DMSNESCheckFromOptions(snes, u));
2439566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes, NULL, u));
2449566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u));
2459566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(u, NULL, "-solution_view"));
246d092c84bSBrandon Whitchurch
247d092c84bSBrandon Whitchurch /* Set up and solve the sum space system */
2489566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm_sum, &u_sum));
2499566063dSJacob Faibussowitsch PetscCall(VecSet(u_sum, 0.0));
2509566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)u_sum, "solution_sum"));
251*2a8381b2SBarry Smith PetscCall(DMPlexSetSNESLocalFEM(dm_sum, PETSC_FALSE, &ctx));
2529566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_sum));
2539566063dSJacob Faibussowitsch PetscCall(DMSNESCheckFromOptions(snes_sum, u_sum));
2549566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_sum, NULL, u_sum));
2559566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes_sum, &u_sum));
2569566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(u_sum, NULL, "-solution_sum_view"));
257d092c84bSBrandon Whitchurch
258d092c84bSBrandon Whitchurch /* Check if standard solution and sum space solution match to machine precision */
2599566063dSJacob Faibussowitsch PetscCall(VecAXPY(u_sum, -1, u));
2609566063dSJacob Faibussowitsch PetscCall(VecNorm(u_sum, NORM_2, &errNorm));
261d0609cedSBarry Smith PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Sum space provides the same solution as a regular space: %s", (errNorm < errTol) ? "true" : "false"));
262d092c84bSBrandon Whitchurch
263d092c84bSBrandon Whitchurch /* Cleanup */
2649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&u_sum));
2659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&u));
2669566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_sum));
2679566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes));
2689566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm_sum));
2699566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm));
2709566063dSJacob Faibussowitsch PetscCall(PetscFinalize());
271b122ec5aSJacob Faibussowitsch return 0;
272d092c84bSBrandon Whitchurch }
273d092c84bSBrandon Whitchurch
274d092c84bSBrandon Whitchurch /*TEST
275d092c84bSBrandon Whitchurch test:
276d092c84bSBrandon Whitchurch suffix: 2d_lagrange
277d092c84bSBrandon Whitchurch requires: triangle
27830602db0SMatthew G. Knepley args: -velocity_petscspace_degree 1 \
279d092c84bSBrandon Whitchurch -velocity_petscspace_type poly \
280d092c84bSBrandon Whitchurch -velocity_petscspace_components 2\
281d092c84bSBrandon Whitchurch -velocity_petscdualspace_type lagrange \
282d092c84bSBrandon Whitchurch -divu_petscspace_degree 0 \
283d092c84bSBrandon Whitchurch -divu_petscspace_type poly \
284d092c84bSBrandon Whitchurch -divu_petscdualspace_lagrange_continuity false \
285d092c84bSBrandon Whitchurch -velocity_sum_petscfe_default_quadrature_order 1 \
286d092c84bSBrandon Whitchurch -velocity_sum_petscspace_degree 1 \
287d092c84bSBrandon Whitchurch -velocity_sum_petscspace_type sum \
288d092c84bSBrandon Whitchurch -velocity_sum_petscspace_variables 2 \
289d092c84bSBrandon Whitchurch -velocity_sum_petscspace_components 2 \
290d092c84bSBrandon Whitchurch -velocity_sum_petscspace_sum_spaces 2 \
291d092c84bSBrandon Whitchurch -velocity_sum_petscspace_sum_concatenate true \
292d092c84bSBrandon Whitchurch -velocity_sum_petscdualspace_type lagrange \
293417c287bSToby Isaac -velocity_sum_sumcomp_0_petscspace_type poly \
294417c287bSToby Isaac -velocity_sum_sumcomp_0_petscspace_degree 1 \
295417c287bSToby Isaac -velocity_sum_sumcomp_0_petscspace_variables 2 \
296417c287bSToby Isaac -velocity_sum_sumcomp_0_petscspace_components 1 \
297417c287bSToby Isaac -velocity_sum_sumcomp_1_petscspace_type poly \
298417c287bSToby Isaac -velocity_sum_sumcomp_1_petscspace_degree 1 \
299417c287bSToby Isaac -velocity_sum_sumcomp_1_petscspace_variables 2 \
300417c287bSToby Isaac -velocity_sum_sumcomp_1_petscspace_components 1 \
301d092c84bSBrandon Whitchurch -divu_sum_petscspace_degree 0 \
302d092c84bSBrandon Whitchurch -divu_sum_petscspace_type sum \
303d092c84bSBrandon Whitchurch -divu_sum_petscspace_variables 2 \
304d092c84bSBrandon Whitchurch -divu_sum_petscspace_components 1 \
305d092c84bSBrandon Whitchurch -divu_sum_petscspace_sum_spaces 1 \
306d092c84bSBrandon Whitchurch -divu_sum_petscspace_sum_concatenate true \
307d092c84bSBrandon Whitchurch -divu_sum_petscdualspace_lagrange_continuity false \
308417c287bSToby Isaac -divu_sum_sumcomp_0_petscspace_type poly \
309417c287bSToby Isaac -divu_sum_sumcomp_0_petscspace_degree 0 \
310417c287bSToby Isaac -divu_sum_sumcomp_0_petscspace_variables 2 \
311417c287bSToby Isaac -divu_sum_sumcomp_0_petscspace_components 1 \
312d092c84bSBrandon Whitchurch -dm_refine 0 \
313d092c84bSBrandon Whitchurch -snes_error_if_not_converged \
314d092c84bSBrandon Whitchurch -ksp_rtol 1e-10 \
315d092c84bSBrandon Whitchurch -ksp_error_if_not_converged \
316d092c84bSBrandon Whitchurch -pc_type fieldsplit\
317d092c84bSBrandon Whitchurch -pc_fieldsplit_type schur\
318d092c84bSBrandon Whitchurch -divu_sum_petscdualspace_lagrange_continuity false \
319d092c84bSBrandon Whitchurch -pc_fieldsplit_schur_precondition full
320d092c84bSBrandon Whitchurch TEST*/
321