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 */ 17d71ae5a4SJacob Faibussowitsch static PetscErrorCode linear_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *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 25d71ae5a4SJacob Faibussowitsch static PetscErrorCode linear_p(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *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 34d71ae5a4SJacob Faibussowitsch static PetscErrorCode linear_divu(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *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>.*/ 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> */ 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. */ 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 */ 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*/ 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 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 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; 105d092c84bSBrandon Whitchurch } UserCtx; 106d092c84bSBrandon Whitchurch 107d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateMesh(MPI_Comm comm, UserCtx *user, DM *mesh) 108d71ae5a4SJacob Faibussowitsch { 109d092c84bSBrandon Whitchurch PetscFunctionBegin; 1109566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 1119566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 1129566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(*mesh)); 1139566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(*mesh, user)); 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 */ 119d71ae5a4SJacob Faibussowitsch static PetscErrorCode SetupProblem(DM dm, UserCtx *user) 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)); 1379566063dSJacob Faibussowitsch PetscCall(PetscDSAddBoundary(ds, DM_BC_NATURAL, "Boundary Integral", label, 1, &id, 0, 0, NULL, (void (*)(void))NULL, NULL, user, &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 */ 147d71ae5a4SJacob Faibussowitsch static PetscErrorCode SetupDiscretization(DM mesh, DM mesh_sum, PetscErrorCode (*setup)(DM, UserCtx *), UserCtx *user) 148d71ae5a4SJacob Faibussowitsch { 149d092c84bSBrandon Whitchurch DM cdm = mesh, cdm_sum = mesh_sum; 150*12fc5b22SMatthew 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)); 158*12fc5b22SMatthew G. Knepley 159*12fc5b22SMatthew G. Knepley { 160*12fc5b22SMatthew G. Knepley PetscBool force; 161*12fc5b22SMatthew G. Knepley // Turn off automatic quadrature selection as a test 162*12fc5b22SMatthew G. Knepley PetscCall(DMGetDS(mesh_sum, &ds)); 163*12fc5b22SMatthew G. Knepley PetscCall(PetscDSGetForceQuad(ds, &force)); 164*12fc5b22SMatthew G. Knepley if (force) PetscCall(PetscDSSetForceQuad(ds, PETSC_FALSE)); 165*12fc5b22SMatthew G. Knepley } 166*12fc5b22SMatthew 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)); 1859566063dSJacob Faibussowitsch PetscCall((*setup)(mesh, user)); 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)); 1909566063dSJacob Faibussowitsch PetscCall((*setup)(mesh_sum, user)); 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 213d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 214d71ae5a4SJacob Faibussowitsch { 215d092c84bSBrandon Whitchurch UserCtx user; 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; 2239566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, (char *)0, 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)); 2279566063dSJacob Faibussowitsch PetscCall(CreateMesh(PETSC_COMM_WORLD, &user, &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)); 2329566063dSJacob Faibussowitsch PetscCall(CreateMesh(PETSC_COMM_WORLD, &user, &dm_sum)); 2339566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_sum, dm_sum)); 2349566063dSJacob Faibussowitsch PetscCall(SetupDiscretization(dm, dm_sum, SetupProblem, &user)); 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")); 2409566063dSJacob Faibussowitsch PetscCall(DMPlexSetSNESLocalFEM(dm, &user, &user, &user)); 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")); 2519566063dSJacob Faibussowitsch PetscCall(DMPlexSetSNESLocalFEM(dm_sum, &user, &user, &user)); 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