static PetscErrorCode TestLocalDofOrder(DM dm, AppCtx *ctx) { PetscFE fe[3]; PetscSection s; PetscInt dim, Nf, f; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) dm), dim, dim, ctx->simplex, "field0_", -1, &fe[0]);CHKERRQ(ierr); ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) dm), dim, 1, ctx->simplex, "field1_", -1, &fe[1]);CHKERRQ(ierr); ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) dm), dim, 1, ctx->simplex, "field2_", -1, &fe[2]);CHKERRQ(ierr); ierr = DMSetField(dm, 0, NULL, (PetscObject) fe[0]);CHKERRQ(ierr); ierr = DMSetField(dm, 1, NULL, (PetscObject) fe[1]);CHKERRQ(ierr); ierr = DMSetField(dm, 2, NULL, (PetscObject) fe[2]);CHKERRQ(ierr); ierr = DMCreateDS(dm);CHKERRQ(ierr); ierr = DMGetSection(dm, &s);CHKERRQ(ierr); ierr = PetscObjectViewFromOptions((PetscObject) s, NULL, "-dof_view");CHKERRQ(ierr); ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&fe[f]);CHKERRQ(ierr);} PetscFunctionReturn(0); }
/*@ PetscConvEstGetConvRate - Returns an estimate of the convergence rate for the discretization Not collective Input Parameter: . ce - The PetscConvEst object Output Parameter: . alpha - The convergence rate for each field Note: The convergence rate alpha is defined by $ || u_h - u_exact || < C h^alpha where u_h is the discrete solution, and h is a measure of the discretization size. We solve a series of problems on refined meshes, calculate an error based upon the exact solution in the DS, and then fit the result to our model above using linear regression. Options database keys: . -snes_convergence_estimate : Execute convergence estimation and print out the rate Level: intermediate .keywords: PetscConvEst, convergence .seealso: PetscConvEstSetSolver(), PetscConvEstCreate(), PetscConvEstGetConvRate() @*/ PetscErrorCode PetscConvEstGetConvRate(PetscConvEst ce, PetscReal alpha[]) { DM *dm; PetscObject disc; MPI_Comm comm; const char *uname, *dmname; void *ctx; Vec u; PetscReal t = 0.0, *x, *y, slope, intercept; PetscInt *dof, dim, Nr = ce->Nr, r, f, oldlevel, oldnlev; PetscLogEvent event; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject) ce, &comm);CHKERRQ(ierr); ierr = DMGetDimension(ce->idm, &dim);CHKERRQ(ierr); ierr = DMGetApplicationContext(ce->idm, &ctx);CHKERRQ(ierr); ierr = DMPlexSetRefinementUniform(ce->idm, PETSC_TRUE);CHKERRQ(ierr); ierr = DMGetRefineLevel(ce->idm, &oldlevel);CHKERRQ(ierr); ierr = PetscMalloc2((Nr+1), &dm, (Nr+1)*ce->Nf, &dof);CHKERRQ(ierr); dm[0] = ce->idm; for (f = 0; f < ce->Nf; ++f) alpha[f] = 0.0; /* Loop over meshes */ ierr = PetscLogEventRegister("ConvEst Error", PETSC_OBJECT_CLASSID, &event);CHKERRQ(ierr); for (r = 0; r <= Nr; ++r) { PetscLogStage stage; char stageName[PETSC_MAX_PATH_LEN]; ierr = PetscSNPrintf(stageName, PETSC_MAX_PATH_LEN-1, "ConvEst Refinement Level %D", r);CHKERRQ(ierr); ierr = PetscLogStageRegister(stageName, &stage);CHKERRQ(ierr); ierr = PetscLogStagePush(stage);CHKERRQ(ierr); if (r > 0) { ierr = DMRefine(dm[r-1], MPI_COMM_NULL, &dm[r]);CHKERRQ(ierr); ierr = DMSetCoarseDM(dm[r], dm[r-1]);CHKERRQ(ierr); ierr = DMCopyDisc(ce->idm, dm[r]);CHKERRQ(ierr); ierr = DMCopyTransform(ce->idm, dm[r]);CHKERRQ(ierr); ierr = PetscObjectGetName((PetscObject) dm[r-1], &dmname);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) dm[r], dmname);CHKERRQ(ierr); for (f = 0; f <= ce->Nf; ++f) { PetscErrorCode (*nspconstr)(DM, PetscInt, MatNullSpace *); ierr = DMGetNullSpaceConstructor(dm[r-1], f, &nspconstr);CHKERRQ(ierr); ierr = DMSetNullSpaceConstructor(dm[r], f, nspconstr);CHKERRQ(ierr); } } ierr = DMViewFromOptions(dm[r], NULL, "-conv_dm_view");CHKERRQ(ierr); /* Create solution */ ierr = DMCreateGlobalVector(dm[r], &u);CHKERRQ(ierr); ierr = DMGetField(dm[r], 0, NULL, &disc);CHKERRQ(ierr); ierr = PetscObjectGetName(disc, &uname);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) u, uname);CHKERRQ(ierr); /* Setup solver */ ierr = SNESReset(ce->snes);CHKERRQ(ierr); ierr = SNESSetDM(ce->snes, dm[r]);CHKERRQ(ierr); ierr = DMPlexSetSNESLocalFEM(dm[r], ctx, ctx, ctx);CHKERRQ(ierr); ierr = SNESSetFromOptions(ce->snes);CHKERRQ(ierr); /* Create initial guess */ ierr = DMProjectFunction(dm[r], t, ce->initGuess, ce->ctxs, INSERT_VALUES, u);CHKERRQ(ierr); ierr = SNESSolve(ce->snes, NULL, u);CHKERRQ(ierr); ierr = PetscLogEventBegin(event, ce, 0, 0, 0);CHKERRQ(ierr); ierr = DMComputeL2FieldDiff(dm[r], t, ce->exactSol, ce->ctxs, u, &ce->errors[r*ce->Nf]);CHKERRQ(ierr); ierr = PetscLogEventEnd(event, ce, 0, 0, 0);CHKERRQ(ierr); for (f = 0; f < ce->Nf; ++f) { PetscSection s, fs; PetscInt lsize; /* Could use DMGetOutputDM() to add in Dirichlet dofs */ ierr = DMGetSection(dm[r], &s);CHKERRQ(ierr); ierr = PetscSectionGetField(s, f, &fs);CHKERRQ(ierr); ierr = PetscSectionGetConstrainedStorageSize(fs, &lsize);CHKERRQ(ierr); ierr = MPI_Allreduce(&lsize, &dof[r*ce->Nf+f], 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) ce->snes));CHKERRQ(ierr); ierr = PetscLogEventSetDof(event, f, dof[r*ce->Nf+f]);CHKERRQ(ierr); ierr = PetscLogEventSetError(event, f, ce->errors[r*ce->Nf+f]);CHKERRQ(ierr); } /* Monitor */ if (ce->monitor) { PetscReal *errors = &ce->errors[r*ce->Nf]; ierr = PetscPrintf(comm, "L_2 Error: ");CHKERRQ(ierr); if (ce->Nf > 1) {ierr = PetscPrintf(comm, "[");CHKERRQ(ierr);} for (f = 0; f < ce->Nf; ++f) { if (f > 0) {ierr = PetscPrintf(comm, ", ");CHKERRQ(ierr);} if (errors[f] < 1.0e-11) {ierr = PetscPrintf(comm, "< 1e-11");CHKERRQ(ierr);} else {ierr = PetscPrintf(comm, "%g", (double)errors[f]);CHKERRQ(ierr);} } if (ce->Nf > 1) {ierr = PetscPrintf(comm, "]");CHKERRQ(ierr);} ierr = PetscPrintf(comm, "\n");CHKERRQ(ierr); } if (!r) { /* PCReset() does not wipe out the level structure */ KSP ksp; PC pc; ierr = SNESGetKSP(ce->snes, &ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PCMGGetLevels(pc, &oldnlev);CHKERRQ(ierr); } /* Cleanup */ ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); } for (r = 1; r <= Nr; ++r) { ierr = DMDestroy(&dm[r]);CHKERRQ(ierr); } /* Fit convergence rate */ ierr = PetscMalloc2(Nr+1, &x, Nr+1, &y);CHKERRQ(ierr); for (f = 0; f < ce->Nf; ++f) { for (r = 0; r <= Nr; ++r) { x[r] = PetscLog10Real(dof[r*ce->Nf+f]); y[r] = PetscLog10Real(ce->errors[r*ce->Nf+f]); } ierr = PetscLinearRegression(Nr+1, x, y, &slope, &intercept);CHKERRQ(ierr); /* Since h^{-dim} = N, lg err = s lg N + b = -s dim lg h + b */ alpha[f] = -slope * dim; } ierr = PetscFree2(x, y);CHKERRQ(ierr); ierr = PetscFree2(dm, dof);CHKERRQ(ierr); /* Restore solver */ ierr = SNESReset(ce->snes);CHKERRQ(ierr); { /* PCReset() does not wipe out the level structure */ KSP ksp; PC pc; ierr = SNESGetKSP(ce->snes, &ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PCMGSetLevels(pc, oldnlev, NULL);CHKERRQ(ierr); ierr = DMSetRefineLevel(ce->idm, oldlevel);CHKERRQ(ierr); /* The damn DMCoarsen() calls in PCMG can reset this */ } ierr = SNESSetDM(ce->snes, ce->idm);CHKERRQ(ierr); ierr = DMPlexSetSNESLocalFEM(ce->idm, ctx, ctx, ctx);CHKERRQ(ierr); ierr = SNESSetFromOptions(ce->snes);CHKERRQ(ierr); PetscFunctionReturn(0); }
//! Help PETSc identify the coarser DM dmc given the fine DM dmf PetscErrorCode libmesh_petsc_DMCoarsen(DM dmf, MPI_Comm /*comm*/, DM * dmc) { libmesh_assert(dmc); libmesh_assert(dmf); PetscErrorCode ierr; // Extract our context from the incoming dmf void * ctx_f = nullptr; ierr = DMShellGetContext(dmf, &ctx_f);LIBMESH_CHKERR(ierr); libmesh_assert(ctx_f); PetscDMContext * p_ctx = static_cast<PetscDMContext*>(ctx_f); // First, ensure that there exists a coarse DM that we want to // set. There ought to be as we created it while walking the // hierarchy. libmesh_assert(p_ctx->coarser_dm); libmesh_assert(*(p_ctx->coarser_dm)); // In situations using fieldsplit we need to (potentially) // provide a coarser DM which only has the relevant subfields in // it. Since we create global DMs for each mesh level, we need // to extract the section from the DM, and check the number of // fields. When less than all the fields are used, we need to // create the proper subsections. // Get the number of fields and their names from the incomming // fine DM and the global reference DM PetscInt nfieldsf, nfieldsg; char ** fieldnamesf; char ** fieldnamesg; libmesh_assert(p_ctx->global_dm); DM * globaldm = p_ctx->global_dm; ierr = DMCreateFieldIS(dmf, &nfieldsf, &fieldnamesf, nullptr); LIBMESH_CHKERR(ierr); ierr = DMCreateFieldIS(*globaldm, &nfieldsg, &fieldnamesg, nullptr); LIBMESH_CHKERR(ierr); // If the probed number of fields is less than the number of // global fields, this amounts to PETSc 'indicating' to us we // are doing FS. So, we must create subsections for the coarser // DMs. if ( nfieldsf < nfieldsg ) { PetscSection section; PetscSection subsection; std::vector<PetscInt> subfields(nfieldsf); // extracted fields // First, get the section from the coarse DM #if PETSC_VERSION_LESS_THAN(3,10,0) ierr = DMGetDefaultSection(*(p_ctx->coarser_dm), §ion); #else ierr = DMGetSection(*(p_ctx->coarser_dm), §ion); #endif LIBMESH_CHKERR(ierr); // Now, match fine grid DM field names to their global DM // counterparts. Since PETSc can internally reassign field // numbering under a fieldsplit, we must extract // subsections via the field names. This is admittedly // gross, but c'est la vie. for (int i = 0; i < nfieldsf ; i++) { for (int j = 0; j < nfieldsg ;j++) if ( strcmp( fieldnamesg[j], fieldnamesf[i] ) == 0 ) subfields[i] = j; } // Next, for the found fields we now make a subsection and set it for the coarser DM ierr = PetscSectionCreateSubsection(section, nfieldsf, subfields.data(), &subsection); LIBMESH_CHKERR(ierr); #if PETSC_VERSION_LESS_THAN(3,10,0) ierr = DMSetDefaultSection(*(p_ctx->coarser_dm) , subsection); #else ierr = DMSetSection(*(p_ctx->coarser_dm) , subsection); #endif LIBMESH_CHKERR(ierr); ierr = PetscSectionDestroy(&subsection); LIBMESH_CHKERR(ierr); } // Finally, set the coarser DM *(dmc) = *(p_ctx->coarser_dm); return 0; }
int main(int argc, char **argv) { DM dm; /* Problem specification */ SNES snes; /* Nonlinear solver */ Vec u; /* Solutions */ AppCtx user; /* User-defined work context */ PetscErrorCode ierr; ierr = PetscInitialize(&argc, &argv, NULL,help);if (ierr) return ierr; ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr); /* Primal system */ ierr = SNESCreate(PETSC_COMM_WORLD, &snes);CHKERRQ(ierr); ierr = CreateMesh(PETSC_COMM_WORLD, &user, &dm);CHKERRQ(ierr); ierr = SNESSetDM(snes, dm);CHKERRQ(ierr); ierr = SetupDiscretization(dm, "potential", SetupPrimalProblem, &user);CHKERRQ(ierr); ierr = DMCreateGlobalVector(dm, &u);CHKERRQ(ierr); ierr = VecSet(u, 0.0);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) u, "potential");CHKERRQ(ierr); ierr = DMPlexSetSNESLocalFEM(dm, &user, &user, &user);CHKERRQ(ierr); ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); ierr = SNESSolve(snes, NULL, u);CHKERRQ(ierr); ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr); ierr = VecViewFromOptions(u, NULL, "-potential_view");CHKERRQ(ierr); if (user.spectral) { PetscInt planeDir[2] = {0, 1}; PetscReal planeCoord[2] = {0., 1.}; ierr = ComputeSpectral(dm, u, 2, planeDir, planeCoord, &user);CHKERRQ(ierr); } /* Adjoint system */ if (user.adjoint) { DM dmAdj; SNES snesAdj; Vec uAdj; ierr = SNESCreate(PETSC_COMM_WORLD, &snesAdj);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject) snesAdj, "adjoint_");CHKERRQ(ierr); ierr = DMClone(dm, &dmAdj);CHKERRQ(ierr); ierr = SNESSetDM(snesAdj, dmAdj);CHKERRQ(ierr); ierr = SetupDiscretization(dmAdj, "adjoint", SetupAdjointProblem, &user);CHKERRQ(ierr); ierr = DMCreateGlobalVector(dmAdj, &uAdj);CHKERRQ(ierr); ierr = VecSet(uAdj, 0.0);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) uAdj, "adjoint");CHKERRQ(ierr); ierr = DMPlexSetSNESLocalFEM(dmAdj, &user, &user, &user);CHKERRQ(ierr); ierr = SNESSetFromOptions(snesAdj);CHKERRQ(ierr); ierr = SNESSolve(snesAdj, NULL, uAdj);CHKERRQ(ierr); ierr = SNESGetSolution(snesAdj, &uAdj);CHKERRQ(ierr); ierr = VecViewFromOptions(uAdj, NULL, "-adjoint_view");CHKERRQ(ierr); /* Error representation */ { DM dmErr, dmErrAux, dms[2]; Vec errorEst, errorL2, uErr, uErrLoc, uAdjLoc, uAdjProj; IS *subis; PetscReal errorEstTot, errorL2Norm, errorL2Tot; PetscInt N, i; PetscErrorCode (*funcs[1])(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *) = {trig_u}; void (*identity[1])(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]) = {f0_identityaux_u}; void *ctxs[1] = {0}; ctxs[0] = &user; ierr = DMClone(dm, &dmErr);CHKERRQ(ierr); ierr = SetupDiscretization(dmErr, "error", SetupErrorProblem, &user);CHKERRQ(ierr); ierr = DMGetGlobalVector(dmErr, &errorEst);CHKERRQ(ierr); ierr = DMGetGlobalVector(dmErr, &errorL2);CHKERRQ(ierr); /* Compute auxiliary data (solution and projection of adjoint solution) */ ierr = DMGetLocalVector(dmAdj, &uAdjLoc);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(dmAdj, uAdj, INSERT_VALUES, uAdjLoc);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(dmAdj, uAdj, INSERT_VALUES, uAdjLoc);CHKERRQ(ierr); ierr = DMGetGlobalVector(dm, &uAdjProj);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dm, "dmAux", (PetscObject) dmAdj);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dm, "A", (PetscObject) uAdjLoc);CHKERRQ(ierr); ierr = DMProjectField(dm, 0.0, u, identity, INSERT_VALUES, uAdjProj);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dm, "dmAux", NULL);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dm, "A", NULL);CHKERRQ(ierr); ierr = DMRestoreLocalVector(dmAdj, &uAdjLoc);CHKERRQ(ierr); /* Attach auxiliary data */ dms[0] = dm; dms[1] = dm; ierr = DMCreateSuperDM(dms, 2, &subis, &dmErrAux);CHKERRQ(ierr); if (0) { PetscSection sec; ierr = DMGetSection(dms[0], &sec);CHKERRQ(ierr); ierr = PetscSectionView(sec, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = DMGetSection(dms[1], &sec);CHKERRQ(ierr); ierr = PetscSectionView(sec, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = DMGetSection(dmErrAux, &sec);CHKERRQ(ierr); ierr = PetscSectionView(sec, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } ierr = DMViewFromOptions(dmErrAux, NULL, "-dm_err_view");CHKERRQ(ierr); ierr = ISViewFromOptions(subis[0], NULL, "-super_is_view");CHKERRQ(ierr); ierr = ISViewFromOptions(subis[1], NULL, "-super_is_view");CHKERRQ(ierr); ierr = DMGetGlobalVector(dmErrAux, &uErr);CHKERRQ(ierr); ierr = VecViewFromOptions(u, NULL, "-map_vec_view");CHKERRQ(ierr); ierr = VecViewFromOptions(uAdjProj, NULL, "-map_vec_view");CHKERRQ(ierr); ierr = VecViewFromOptions(uErr, NULL, "-map_vec_view");CHKERRQ(ierr); ierr = VecISCopy(uErr, subis[0], SCATTER_FORWARD, u);CHKERRQ(ierr); ierr = VecISCopy(uErr, subis[1], SCATTER_FORWARD, uAdjProj);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(dm, &uAdjProj);CHKERRQ(ierr); for (i = 0; i < 2; ++i) {ierr = ISDestroy(&subis[i]);CHKERRQ(ierr);} ierr = PetscFree(subis);CHKERRQ(ierr); ierr = DMGetLocalVector(dmErrAux, &uErrLoc);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(dm, uErr, INSERT_VALUES, uErrLoc);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(dm, uErr, INSERT_VALUES, uErrLoc);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(dmErrAux, &uErr);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dmAdj, "dmAux", (PetscObject) dmErrAux);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dmAdj, "A", (PetscObject) uErrLoc);CHKERRQ(ierr); /* Compute cellwise error estimate */ ierr = VecSet(errorEst, 0.0);CHKERRQ(ierr); ierr = DMPlexComputeCellwiseIntegralFEM(dmAdj, uAdj, errorEst, &user);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dmAdj, "dmAux", NULL);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dmAdj, "A", NULL);CHKERRQ(ierr); ierr = DMRestoreLocalVector(dmErrAux, &uErrLoc);CHKERRQ(ierr); ierr = DMDestroy(&dmErrAux);CHKERRQ(ierr); /* Plot cellwise error vector */ ierr = VecViewFromOptions(errorEst, NULL, "-error_view");CHKERRQ(ierr); /* Compute ratio of estimate (sum over cells) with actual L_2 error */ ierr = DMComputeL2Diff(dm, 0.0, funcs, ctxs, u, &errorL2Norm);CHKERRQ(ierr); ierr = DMPlexComputeL2DiffVec(dm, 0.0, funcs, ctxs, u, errorL2);CHKERRQ(ierr); ierr = VecViewFromOptions(errorL2, NULL, "-l2_error_view");CHKERRQ(ierr); ierr = VecNorm(errorL2, NORM_INFINITY, &errorL2Tot);CHKERRQ(ierr); ierr = VecNorm(errorEst, NORM_INFINITY, &errorEstTot);CHKERRQ(ierr); ierr = VecGetSize(errorEst, &N);CHKERRQ(ierr); ierr = VecPointwiseDivide(errorEst, errorEst, errorL2);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) errorEst, "Error ratio");CHKERRQ(ierr); ierr = VecViewFromOptions(errorEst, NULL, "-error_ratio_view");CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "N: %D L2 error: %g Error Ratio: %g/%g = %g\n", N, (double) errorL2Norm, (double) errorEstTot, (double) PetscSqrtReal(errorL2Tot), (double) errorEstTot/PetscSqrtReal(errorL2Tot));CHKERRQ(ierr); ierr = DMRestoreGlobalVector(dmErr, &errorEst);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(dmErr, &errorL2);CHKERRQ(ierr); ierr = DMDestroy(&dmErr);CHKERRQ(ierr); } ierr = DMDestroy(&dmAdj);CHKERRQ(ierr); ierr = VecDestroy(&uAdj);CHKERRQ(ierr); ierr = SNESDestroy(&snesAdj);CHKERRQ(ierr); } /* Cleanup */ ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = DMDestroy(&dm);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }