1c4762a1bSJed Brown static char help[] = "Poisson Problem in mixed form with 2d and 3d with finite elements.\n\ 2c4762a1bSJed Brown We solve the Poisson problem in a rectangular\n\ 3c4762a1bSJed Brown domain, using a parallel unstructured mesh (DMPLEX) to discretize it.\n\ 4c4762a1bSJed Brown This example supports automatic convergence estimation\n\ 5c4762a1bSJed Brown and Hdiv elements.\n\n\n"; 6c4762a1bSJed Brown 769b95281SMatthew G. Knepley /* 869b95281SMatthew G. Knepley 969b95281SMatthew G. Knepley The mixed form of Poisson's equation, e.g. https://firedrakeproject.org/demos/poisson_mixed.py.html, is given 1069b95281SMatthew G. Knepley in the strong form by 1169b95281SMatthew G. Knepley \begin{align} 1269b95281SMatthew G. Knepley \vb{q} - \nabla u &= 0 \\ 1369b95281SMatthew G. Knepley \nabla \cdot \vb{q} &= f 1469b95281SMatthew G. Knepley \end{align} 1569b95281SMatthew G. Knepley where $u$ is the potential, as in the original problem, but we also discretize the gradient of potential $\vb{q}$, 1669b95281SMatthew G. Knepley or flux, directly. The weak form is then 1769b95281SMatthew G. Knepley \begin{align} 1869b95281SMatthew G. Knepley <t, \vb{q}> + <\nabla \cdot t, u> - <t_n, u>_\Gamma &= 0 \\ 1969b95281SMatthew G. Knepley <v, \nabla \cdot \vb{q}> &= <v, f> 2069b95281SMatthew G. Knepley \end{align} 2169b95281SMatthew G. Knepley For the original Poisson problem, the Dirichlet boundary forces an essential boundary condition on the potential space, 2269b95281SMatthew G. Knepley and the Neumann boundary gives a natural boundary condition in the weak form. In the mixed formulation, the Neumann 2369b95281SMatthew G. Knepley boundary gives an essential boundary condition on the flux space, $\vb{q} \cdot \vu{n} = h$, and the Dirichlet condition 2469b95281SMatthew G. Knepley becomes a natural condition in the weak form, <t_n, g>_\Gamma. 2569b95281SMatthew G. Knepley */ 2669b95281SMatthew G. Knepley 27c4762a1bSJed Brown #include <petscdmplex.h> 28c4762a1bSJed Brown #include <petscsnes.h> 29c4762a1bSJed Brown #include <petscds.h> 30c4762a1bSJed Brown #include <petscconvest.h> 31c4762a1bSJed Brown 329371c9d4SSatish Balay typedef enum { 339371c9d4SSatish Balay SOL_LINEAR, 349371c9d4SSatish Balay SOL_QUADRATIC, 359371c9d4SSatish Balay SOL_QUARTIC, 369371c9d4SSatish Balay SOL_QUARTIC_NEUMANN, 379371c9d4SSatish Balay SOL_UNKNOWN, 389371c9d4SSatish Balay NUM_SOLTYPE 399371c9d4SSatish Balay } SolType; 4069b95281SMatthew G. Knepley const char *SolTypeNames[NUM_SOLTYPE + 3] = {"linear", "quadratic", "quartic", "quartic_neumann", "unknown", "SolType", "SOL_", NULL}; 41c4762a1bSJed Brown 42c4762a1bSJed Brown typedef struct { 43c4762a1bSJed Brown SolType solType; /* The type of exact solution */ 44c4762a1bSJed Brown } AppCtx; 45c4762a1bSJed Brown 46d71ae5a4SJacob Faibussowitsch static void f0_u(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[]) 47d71ae5a4SJacob Faibussowitsch { 4869b95281SMatthew G. Knepley PetscInt d; 4969b95281SMatthew G. Knepley for (d = 0; d < dim; ++d) f0[0] += u_x[uOff_x[0] + d * dim + d]; 5069b95281SMatthew G. Knepley } 5169b95281SMatthew G. Knepley 52c4762a1bSJed Brown /* 2D Dirichlet potential example 53c4762a1bSJed Brown 54c4762a1bSJed Brown u = x 55c4762a1bSJed Brown q = <1, 0> 56c4762a1bSJed Brown f = 0 57c4762a1bSJed Brown 58c4762a1bSJed Brown We will need a boundary integral of u over \Gamma. 59c4762a1bSJed Brown */ 60d71ae5a4SJacob Faibussowitsch static PetscErrorCode linear_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 61d71ae5a4SJacob Faibussowitsch { 62c4762a1bSJed Brown u[0] = x[0]; 63*3ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 64c4762a1bSJed Brown } 65d71ae5a4SJacob Faibussowitsch static PetscErrorCode linear_q(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 66d71ae5a4SJacob Faibussowitsch { 67c4762a1bSJed Brown PetscInt c; 68c4762a1bSJed Brown for (c = 0; c < Nc; ++c) u[c] = c ? 0.0 : 1.0; 69*3ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 70c4762a1bSJed Brown } 71c4762a1bSJed Brown 72d71ae5a4SJacob Faibussowitsch static void f0_linear_u(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[]) 73d71ae5a4SJacob Faibussowitsch { 7469b95281SMatthew G. Knepley f0[0] = 0.0; 7569b95281SMatthew G. Knepley f0_u(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, a_t, a_x, t, x, numConstants, constants, f0); 7669b95281SMatthew G. Knepley } 77d71ae5a4SJacob Faibussowitsch static void f0_bd_linear_q(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 78d71ae5a4SJacob Faibussowitsch { 7969b95281SMatthew G. Knepley PetscScalar potential; 8069b95281SMatthew G. Knepley PetscInt d; 8169b95281SMatthew G. Knepley 82*3ba16761SJacob Faibussowitsch PetscCallAbort(PETSC_COMM_SELF, linear_u(dim, t, x, dim, &potential, NULL)); 8369b95281SMatthew G. Knepley for (d = 0; d < dim; ++d) f0[d] = -potential * n[d]; 8469b95281SMatthew G. Knepley } 8569b95281SMatthew G. Knepley 86c4762a1bSJed Brown /* 2D Dirichlet potential example 87c4762a1bSJed Brown 88c4762a1bSJed Brown u = x^2 + y^2 89c4762a1bSJed Brown q = <2x, 2y> 90c4762a1bSJed Brown f = 4 91c4762a1bSJed Brown 92c4762a1bSJed Brown We will need a boundary integral of u over \Gamma. 93c4762a1bSJed Brown */ 94d71ae5a4SJacob Faibussowitsch static PetscErrorCode quadratic_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 95d71ae5a4SJacob Faibussowitsch { 96c4762a1bSJed Brown PetscInt d; 97c4762a1bSJed Brown 98c4762a1bSJed Brown u[0] = 0.0; 99c4762a1bSJed Brown for (d = 0; d < dim; ++d) u[0] += x[d] * x[d]; 100*3ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 101c4762a1bSJed Brown } 102d71ae5a4SJacob Faibussowitsch static PetscErrorCode quadratic_q(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 103d71ae5a4SJacob Faibussowitsch { 104c4762a1bSJed Brown PetscInt c; 105c4762a1bSJed Brown for (c = 0; c < Nc; ++c) u[c] = 2.0 * x[c]; 106*3ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 107c4762a1bSJed Brown } 108c4762a1bSJed Brown 109d71ae5a4SJacob Faibussowitsch static void f0_quadratic_u(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[]) 110d71ae5a4SJacob Faibussowitsch { 11169b95281SMatthew G. Knepley f0[0] = -4.0; 11269b95281SMatthew G. Knepley f0_u(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, a_t, a_x, t, x, numConstants, constants, f0); 11369b95281SMatthew G. Knepley } 114d71ae5a4SJacob Faibussowitsch static void f0_bd_quadratic_q(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 115d71ae5a4SJacob Faibussowitsch { 11669b95281SMatthew G. Knepley PetscScalar potential; 11769b95281SMatthew G. Knepley PetscInt d; 11869b95281SMatthew G. Knepley 119*3ba16761SJacob Faibussowitsch PetscCallAbort(PETSC_COMM_SELF, quadratic_u(dim, t, x, dim, &potential, NULL)); 12069b95281SMatthew G. Knepley for (d = 0; d < dim; ++d) f0[d] = -potential * n[d]; 12169b95281SMatthew G. Knepley } 12269b95281SMatthew G. Knepley 123c4762a1bSJed Brown /* 2D Dirichlet potential example 124c4762a1bSJed Brown 125c4762a1bSJed Brown u = x (1-x) y (1-y) 126c4762a1bSJed Brown q = <(1-2x) y (1-y), x (1-x) (1-2y)> 127c4762a1bSJed Brown f = -y (1-y) - x (1-x) 128c4762a1bSJed Brown 129c4762a1bSJed Brown u|_\Gamma = 0 so that the boundary integral vanishes 130c4762a1bSJed Brown */ 131d71ae5a4SJacob Faibussowitsch static PetscErrorCode quartic_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 132d71ae5a4SJacob Faibussowitsch { 133c4762a1bSJed Brown PetscInt d; 134c4762a1bSJed Brown 135c4762a1bSJed Brown u[0] = 1.0; 136c4762a1bSJed Brown for (d = 0; d < dim; ++d) u[0] *= x[d] * (1.0 - x[d]); 137*3ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 138c4762a1bSJed Brown } 139d71ae5a4SJacob Faibussowitsch static PetscErrorCode quartic_q(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 140d71ae5a4SJacob Faibussowitsch { 141c4762a1bSJed Brown PetscInt c, d; 142c4762a1bSJed Brown 143c4762a1bSJed Brown for (c = 0; c < Nc; ++c) { 144c4762a1bSJed Brown u[c] = 1.0; 145c4762a1bSJed Brown for (d = 0; d < dim; ++d) { 146c4762a1bSJed Brown if (c == d) u[c] *= 1 - 2.0 * x[d]; 147c4762a1bSJed Brown else u[c] *= x[d] * (1.0 - x[d]); 148c4762a1bSJed Brown } 149c4762a1bSJed Brown } 150*3ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 151c4762a1bSJed Brown } 152c4762a1bSJed Brown 153d71ae5a4SJacob Faibussowitsch static void f0_quartic_u(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[]) 154d71ae5a4SJacob Faibussowitsch { 155c4762a1bSJed Brown PetscInt d; 156c4762a1bSJed Brown f0[0] = 0.0; 15769b95281SMatthew G. Knepley for (d = 0; d < dim; ++d) f0[0] += 2.0 * x[d] * (1.0 - x[d]); 15869b95281SMatthew G. Knepley f0_u(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, a_t, a_x, t, x, numConstants, constants, f0); 159c4762a1bSJed Brown } 160c4762a1bSJed Brown 16169b95281SMatthew G. Knepley /* 2D Dirichlet potential example 16269b95281SMatthew G. Knepley 16369b95281SMatthew G. Knepley u = x (1-x) y (1-y) 16469b95281SMatthew G. Knepley q = <(1-2x) y (1-y), x (1-x) (1-2y)> 16569b95281SMatthew G. Knepley f = -y (1-y) - x (1-x) 16669b95281SMatthew G. Knepley 16769b95281SMatthew G. Knepley du/dn_\Gamma = {(1-2x) y (1-y), x (1-x) (1-2y)} . n produces an essential condition on q 16869b95281SMatthew G. Knepley */ 16969b95281SMatthew G. Knepley 170d71ae5a4SJacob Faibussowitsch static void f0_q(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 171d71ae5a4SJacob Faibussowitsch { 172c4762a1bSJed Brown PetscInt c; 17369b95281SMatthew G. Knepley for (c = 0; c < dim; ++c) f0[c] = u[uOff[0] + c]; 174c4762a1bSJed Brown } 175c4762a1bSJed Brown 176c4762a1bSJed Brown /* <\nabla\cdot w, u> = <\nabla w, Iu> */ 177d71ae5a4SJacob Faibussowitsch static void f1_q(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]) 178d71ae5a4SJacob Faibussowitsch { 17969b95281SMatthew G. Knepley PetscInt c; 18069b95281SMatthew G. Knepley for (c = 0; c < dim; ++c) f1[c * dim + c] = u[uOff[1]]; 181c4762a1bSJed Brown } 182c4762a1bSJed Brown 18369b95281SMatthew G. Knepley /* <t, q> */ 184d71ae5a4SJacob Faibussowitsch static void g0_qq(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[]) 185d71ae5a4SJacob Faibussowitsch { 186c4762a1bSJed Brown PetscInt c; 187c4762a1bSJed Brown for (c = 0; c < dim; ++c) g0[c * dim + c] = 1.0; 188c4762a1bSJed Brown } 189c4762a1bSJed Brown 19069b95281SMatthew G. Knepley /* <\nabla\cdot t, u> = <\nabla t, Iu> */ 191d71ae5a4SJacob Faibussowitsch static void g2_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 g2[]) 192d71ae5a4SJacob Faibussowitsch { 193c4762a1bSJed Brown PetscInt d; 194c4762a1bSJed Brown for (d = 0; d < dim; ++d) g2[d * dim + d] = 1.0; 195c4762a1bSJed Brown } 196c4762a1bSJed Brown 19769b95281SMatthew G. Knepley /* <v, \nabla\cdot q> */ 198d71ae5a4SJacob Faibussowitsch static void g1_uq(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[]) 199d71ae5a4SJacob Faibussowitsch { 200c4762a1bSJed Brown PetscInt d; 20169b95281SMatthew G. Knepley for (d = 0; d < dim; ++d) g1[d * dim + d] = 1.0; 202c4762a1bSJed Brown } 203c4762a1bSJed Brown 204d71ae5a4SJacob Faibussowitsch static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options) 205d71ae5a4SJacob Faibussowitsch { 206c4762a1bSJed Brown PetscFunctionBeginUser; 207c4762a1bSJed Brown options->solType = SOL_LINEAR; 208d0609cedSBarry Smith PetscOptionsBegin(comm, "", "Poisson Problem Options", "DMPLEX"); 2099566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-sol_type", "Type of exact solution", "ex24.c", SolTypeNames, (PetscEnum)options->solType, (PetscEnum *)&options->solType, NULL)); 210d0609cedSBarry Smith PetscOptionsEnd(); 211*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 212c4762a1bSJed Brown } 213c4762a1bSJed Brown 214d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) 215d71ae5a4SJacob Faibussowitsch { 216c4762a1bSJed Brown PetscFunctionBeginUser; 2179566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 2189566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 2199566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dm, "Example Mesh")); 2209566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(*dm, user)); 2219566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(*dm)); 2229566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view")); 223*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 224c4762a1bSJed Brown } 225c4762a1bSJed Brown 226d71ae5a4SJacob Faibussowitsch static PetscErrorCode SetupPrimalProblem(DM dm, AppCtx *user) 227d71ae5a4SJacob Faibussowitsch { 22845480ffeSMatthew G. Knepley PetscDS ds; 22945480ffeSMatthew G. Knepley DMLabel label; 23045480ffeSMatthew G. Knepley PetscWeakForm wf; 231c4762a1bSJed Brown const PetscInt id = 1; 23245480ffeSMatthew G. Knepley PetscInt bd; 233c4762a1bSJed Brown 234c4762a1bSJed Brown PetscFunctionBeginUser; 2359566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &label)); 2369566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 2379566063dSJacob Faibussowitsch PetscCall(PetscDSSetResidual(ds, 0, f0_q, f1_q)); 2389566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_qq, NULL, NULL, NULL)); 2399566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 1, NULL, NULL, g2_qu, NULL)); 2409566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 1, 0, NULL, g1_uq, NULL, NULL)); 2419371c9d4SSatish Balay switch (user->solType) { 242c4762a1bSJed Brown case SOL_LINEAR: 2439566063dSJacob Faibussowitsch PetscCall(PetscDSSetResidual(ds, 1, f0_linear_u, NULL)); 2449566063dSJacob Faibussowitsch PetscCall(DMAddBoundary(dm, DM_BC_NATURAL, "Dirichlet Bd Integral", label, 1, &id, 0, 0, NULL, NULL, NULL, user, &bd)); 2459566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(ds, bd, &wf, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); 2469566063dSJacob Faibussowitsch PetscCall(PetscWeakFormSetIndexBdResidual(wf, label, 1, 0, 0, 0, f0_bd_linear_q, 0, NULL)); 2479566063dSJacob Faibussowitsch PetscCall(PetscDSSetExactSolution(ds, 0, linear_q, user)); 2489566063dSJacob Faibussowitsch PetscCall(PetscDSSetExactSolution(ds, 1, linear_u, user)); 249c4762a1bSJed Brown break; 250c4762a1bSJed Brown case SOL_QUADRATIC: 2519566063dSJacob Faibussowitsch PetscCall(PetscDSSetResidual(ds, 1, f0_quadratic_u, NULL)); 2529566063dSJacob Faibussowitsch PetscCall(DMAddBoundary(dm, DM_BC_NATURAL, "Dirichlet Bd Integral", label, 1, &id, 0, 0, NULL, NULL, NULL, user, &bd)); 2539566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(ds, bd, &wf, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); 2549566063dSJacob Faibussowitsch PetscCall(PetscWeakFormSetIndexBdResidual(wf, label, 1, 0, 0, 0, f0_bd_quadratic_q, 0, NULL)); 2559566063dSJacob Faibussowitsch PetscCall(PetscDSSetExactSolution(ds, 0, quadratic_q, user)); 2569566063dSJacob Faibussowitsch PetscCall(PetscDSSetExactSolution(ds, 1, quadratic_u, user)); 257c4762a1bSJed Brown break; 258c4762a1bSJed Brown case SOL_QUARTIC: 2599566063dSJacob Faibussowitsch PetscCall(PetscDSSetResidual(ds, 1, f0_quartic_u, NULL)); 2609566063dSJacob Faibussowitsch PetscCall(PetscDSSetExactSolution(ds, 0, quartic_q, user)); 2619566063dSJacob Faibussowitsch PetscCall(PetscDSSetExactSolution(ds, 1, quartic_u, user)); 262c4762a1bSJed Brown break; 26369b95281SMatthew G. Knepley case SOL_QUARTIC_NEUMANN: 2649566063dSJacob Faibussowitsch PetscCall(PetscDSSetResidual(ds, 1, f0_quartic_u, NULL)); 2659566063dSJacob Faibussowitsch PetscCall(PetscDSSetExactSolution(ds, 0, quartic_q, user)); 2669566063dSJacob Faibussowitsch PetscCall(PetscDSSetExactSolution(ds, 1, quartic_u, user)); 2679566063dSJacob Faibussowitsch PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "Flux condition", label, 1, &id, 0, 0, NULL, (void (*)(void))quartic_q, NULL, user, NULL)); 26869b95281SMatthew G. Knepley break; 269d71ae5a4SJacob Faibussowitsch default: 270d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid exact solution type %s", SolTypeNames[PetscMin(user->solType, SOL_UNKNOWN)]); 271c4762a1bSJed Brown } 272*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 273c4762a1bSJed Brown } 274c4762a1bSJed Brown 275d71ae5a4SJacob Faibussowitsch static PetscErrorCode SetupDiscretization(DM dm, PetscErrorCode (*setup)(DM, AppCtx *), AppCtx *user) 276d71ae5a4SJacob Faibussowitsch { 277c4762a1bSJed Brown DM cdm = dm; 278c4762a1bSJed Brown PetscFE feq, feu; 27969b95281SMatthew G. Knepley DMPolytopeType ct; 28069b95281SMatthew G. Knepley PetscBool simplex; 28169b95281SMatthew G. Knepley PetscInt dim, cStart; 282c4762a1bSJed Brown 283c4762a1bSJed Brown PetscFunctionBeginUser; 2849566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 2859566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL)); 2869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 28769b95281SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 288c4762a1bSJed Brown /* Create finite element */ 2899566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, dim, simplex, "field_", -1, &feq)); 2909566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)feq, "field")); 2919566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "potential_", -1, &feu)); 2929566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)feu, "potential")); 2939566063dSJacob Faibussowitsch PetscCall(PetscFECopyQuadrature(feq, feu)); 294c4762a1bSJed Brown /* Set discretization and boundary conditions for each mesh */ 2959566063dSJacob Faibussowitsch PetscCall(DMSetField(dm, 0, NULL, (PetscObject)feq)); 2969566063dSJacob Faibussowitsch PetscCall(DMSetField(dm, 1, NULL, (PetscObject)feu)); 2979566063dSJacob Faibussowitsch PetscCall(DMCreateDS(dm)); 2989566063dSJacob Faibussowitsch PetscCall((*setup)(dm, user)); 299c4762a1bSJed Brown while (cdm) { 3009566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, cdm)); 3019566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(cdm, &cdm)); 302c4762a1bSJed Brown } 3039566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&feq)); 3049566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&feu)); 305*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 306c4762a1bSJed Brown } 307c4762a1bSJed Brown 308d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 309d71ae5a4SJacob Faibussowitsch { 310c4762a1bSJed Brown DM dm; /* Problem specification */ 311c4762a1bSJed Brown SNES snes; /* Nonlinear solver */ 312c4762a1bSJed Brown Vec u; /* Solutions */ 313c4762a1bSJed Brown AppCtx user; /* User-defined work context */ 314c4762a1bSJed Brown 315327415f7SBarry Smith PetscFunctionBeginUser; 3169566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 3179566063dSJacob Faibussowitsch PetscCall(ProcessOptions(PETSC_COMM_WORLD, &user)); 318c4762a1bSJed Brown /* Primal system */ 3199566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes)); 3209566063dSJacob Faibussowitsch PetscCall(CreateMesh(PETSC_COMM_WORLD, &user, &dm)); 3219566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, dm)); 3229566063dSJacob Faibussowitsch PetscCall(SetupDiscretization(dm, SetupPrimalProblem, &user)); 3239566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &u)); 3249566063dSJacob Faibussowitsch PetscCall(VecSet(u, 0.0)); 3259566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)u, "potential")); 3269566063dSJacob Faibussowitsch PetscCall(DMPlexSetSNESLocalFEM(dm, &user, &user, &user)); 3279566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes)); 3289566063dSJacob Faibussowitsch PetscCall(DMSNESCheckFromOptions(snes, u)); 3299566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes, NULL, u)); 3309566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u)); 3319566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(u, NULL, "-potential_view")); 332c4762a1bSJed Brown /* Cleanup */ 3339566063dSJacob Faibussowitsch PetscCall(VecDestroy(&u)); 3349566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes)); 3359566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 3369566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 337b122ec5aSJacob Faibussowitsch return 0; 338c4762a1bSJed Brown } 339c4762a1bSJed Brown 340c4762a1bSJed Brown /*TEST 341c4762a1bSJed Brown 342c4762a1bSJed Brown test: 34369b95281SMatthew G. Knepley suffix: 2d_bdm1_p0 344c4762a1bSJed Brown requires: triangle 345c4762a1bSJed Brown args: -sol_type linear \ 34669b95281SMatthew G. Knepley -field_petscspace_degree 1 -field_petscdualspace_type bdm -dm_refine 1 \ 347c4762a1bSJed Brown -dmsnes_check .001 -snes_error_if_not_converged \ 348c4762a1bSJed Brown -ksp_rtol 1e-10 -ksp_error_if_not_converged \ 349c4762a1bSJed Brown -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full -pc_fieldsplit_schur_precondition full \ 350c4762a1bSJed Brown -fieldsplit_field_pc_type lu \ 351c4762a1bSJed Brown -fieldsplit_potential_ksp_rtol 1e-10 -fieldsplit_potential_pc_type lu 352c4762a1bSJed Brown test: 35369b95281SMatthew G. Knepley # Using -dm_refine 2 -convest_num_refine 3 we get L_2 convergence rate: [2.0, 1.0] 35469b95281SMatthew G. Knepley # Using -sol_type quadratic -dm_refine 2 -convest_num_refine 3 we get L_2 convergence rate: [2.9, 1.0] 35569b95281SMatthew G. Knepley suffix: 2d_bdm1_p0_conv 356c4762a1bSJed Brown requires: triangle 357c4762a1bSJed Brown args: -sol_type quartic \ 358c4762a1bSJed Brown -field_petscspace_degree 1 -field_petscdualspace_type bdm -dm_refine 0 -convest_num_refine 1 -snes_convergence_estimate \ 359c4762a1bSJed Brown -snes_error_if_not_converged \ 360c4762a1bSJed Brown -ksp_rtol 1e-10 -ksp_error_if_not_converged \ 361c4762a1bSJed Brown -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full -pc_fieldsplit_schur_precondition full \ 362c4762a1bSJed Brown -fieldsplit_field_pc_type lu \ 363c4762a1bSJed Brown -fieldsplit_potential_ksp_rtol 1e-10 -fieldsplit_potential_pc_type lu 364c4762a1bSJed Brown 365c4762a1bSJed Brown test: 36669b95281SMatthew G. Knepley # HDF5 output: -dm_view hdf5:${PETSC_DIR}/sol.h5 -potential_view hdf5:${PETSC_DIR}/sol.h5::append -exact_vec_view hdf5:${PETSC_DIR}/sol.h5::append 36769b95281SMatthew G. Knepley # VTK output: -potential_view vtk: -exact_vec_view vtk: 36869b95281SMatthew G. Knepley # VTU output: -potential_view vtk:multifield.vtu -exact_vec_view vtk:exact.vtu 36969b95281SMatthew G. Knepley suffix: 2d_q2_p0 370c4762a1bSJed Brown requires: triangle 37130602db0SMatthew G. Knepley args: -sol_type linear -dm_plex_simplex 0 \ 37269b95281SMatthew G. Knepley -field_petscspace_degree 2 -dm_refine 0 \ 373c4762a1bSJed Brown -dmsnes_check .001 -snes_error_if_not_converged \ 374c4762a1bSJed Brown -ksp_rtol 1e-10 -ksp_error_if_not_converged \ 375c4762a1bSJed Brown -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full -pc_fieldsplit_schur_precondition full \ 376c4762a1bSJed Brown -fieldsplit_field_pc_type lu \ 377c4762a1bSJed Brown -fieldsplit_potential_ksp_rtol 1e-10 -fieldsplit_potential_pc_type lu 378c4762a1bSJed Brown test: 37969b95281SMatthew G. Knepley # Using -dm_refine 1 -convest_num_refine 3 we get L_2 convergence rate: [0.0057, 1.0] 38069b95281SMatthew G. Knepley suffix: 2d_q2_p0_conv 381c4762a1bSJed Brown requires: triangle 38230602db0SMatthew G. Knepley args: -sol_type linear -dm_plex_simplex 0 \ 383c4762a1bSJed Brown -field_petscspace_degree 2 -dm_refine 0 -convest_num_refine 1 -snes_convergence_estimate \ 38469b95281SMatthew G. Knepley -snes_error_if_not_converged \ 385c4762a1bSJed Brown -ksp_rtol 1e-10 -ksp_error_if_not_converged \ 386c4762a1bSJed Brown -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full -pc_fieldsplit_schur_precondition full \ 387c4762a1bSJed Brown -fieldsplit_field_pc_type lu \ 388c4762a1bSJed Brown -fieldsplit_potential_ksp_rtol 1e-10 -fieldsplit_potential_pc_type lu 38969b95281SMatthew G. Knepley test: 39069b95281SMatthew G. Knepley # Using -dm_refine 1 -convest_num_refine 3 we get L_2 convergence rate: [-0.014, 0.0066] 39169b95281SMatthew G. Knepley suffix: 2d_q2_p0_neumann_conv 39269b95281SMatthew G. Knepley requires: triangle 39330602db0SMatthew G. Knepley args: -sol_type quartic_neumann -dm_plex_simplex 0 \ 39469b95281SMatthew G. Knepley -field_petscspace_degree 2 -dm_refine 0 -convest_num_refine 1 -snes_convergence_estimate \ 39569b95281SMatthew G. Knepley -snes_error_if_not_converged \ 39669b95281SMatthew G. Knepley -ksp_rtol 1e-10 -ksp_error_if_not_converged \ 39769b95281SMatthew G. Knepley -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full -pc_fieldsplit_schur_precondition full \ 39869b95281SMatthew G. Knepley -fieldsplit_field_pc_type lu \ 39969b95281SMatthew G. Knepley -fieldsplit_potential_ksp_rtol 1e-10 -fieldsplit_potential_pc_type svd 40069b95281SMatthew G. Knepley 401c4762a1bSJed Brown TEST*/ 402c4762a1bSJed Brown 403c4762a1bSJed Brown /* These tests will be active once tensor P^- is working 404c4762a1bSJed Brown 405c4762a1bSJed Brown test: 406c4762a1bSJed Brown suffix: 2d_bdmq1_p0_0 407c4762a1bSJed Brown requires: triangle 40830602db0SMatthew G. Knepley args: -dm_plex_simplex 0 -sol_type linear \ 409c4762a1bSJed Brown -field_petscspace_poly_type pminus_hdiv -field_petscspace_degree 1 -field_petscdualspace_type bdm -dm_refine 0 -convest_num_refine 3 -snes_convergence_estimate \ 410c4762a1bSJed Brown -dmsnes_check .001 -snes_error_if_not_converged \ 411c4762a1bSJed Brown -ksp_rtol 1e-10 -ksp_error_if_not_converged \ 412c4762a1bSJed Brown -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full -pc_fieldsplit_schur_precondition full \ 413c4762a1bSJed Brown -fieldsplit_field_pc_type lu \ 414c4762a1bSJed Brown -fieldsplit_potential_ksp_rtol 1e-10 -fieldsplit_potential_pc_type lu 415c4762a1bSJed Brown test: 416c4762a1bSJed Brown suffix: 2d_bdmq1_p0_2 417c4762a1bSJed Brown requires: triangle 41830602db0SMatthew G. Knepley args: -dm_plex_simplex 0 -sol_type quartic \ 419c4762a1bSJed Brown -field_petscspace_poly_type_no pminus_hdiv -field_petscspace_degree 1 -field_petscdualspace_type bdm -dm_refine 0 -convest_num_refine 3 -snes_convergence_estimate \ 420c4762a1bSJed Brown -dmsnes_check .001 -snes_error_if_not_converged \ 421c4762a1bSJed Brown -ksp_rtol 1e-10 -ksp_error_if_not_converged \ 422c4762a1bSJed Brown -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full -pc_fieldsplit_schur_precondition full \ 423c4762a1bSJed Brown -fieldsplit_field_pc_type lu \ 424c4762a1bSJed Brown -fieldsplit_potential_ksp_rtol 1e-10 -fieldsplit_potential_pc_type lu 425c4762a1bSJed Brown 426c4762a1bSJed Brown */ 427