/*@ KSPSetDM - Sets the DM that may be used by some preconditioners Logically Collective on KSP Input Parameters: + ksp - the preconditioner context - dm - the dm, cannot be NULL Notes: If this is used then the KSP will attempt to use the DM to create the matrix and use the routine set with DMKSPSetComputeOperators(). Use KSPSetDMActive(ksp,PETSC_FALSE) to instead use the matrix you've provided with KSPSetOperators(). Level: intermediate .seealso: KSPGetDM(), KSPSetDMActive(), KSPSetComputeOperators(), KSPSetComputeRHS(), KSPSetComputeInitialGuess(), DMKSPSetComputeOperators(), DMKSPSetComputeRHS(), DMKSPSetComputeInitialGuess() @*/ PetscErrorCode KSPSetDM(KSP ksp,DM dm) { PetscErrorCode ierr; PC pc; PetscFunctionBegin; PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); PetscValidHeaderSpecific(dm,DM_CLASSID,2); ierr = PetscObjectReference((PetscObject)dm); CHKERRQ(ierr); if (ksp->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ if (ksp->dm->dmksp && !dm->dmksp) { DMKSP kdm; ierr = DMCopyDMKSP(ksp->dm,dm); CHKERRQ(ierr); ierr = DMGetDMKSP(ksp->dm,&kdm); CHKERRQ(ierr); if (kdm->originaldm == ksp->dm) kdm->originaldm = dm; /* Grant write privileges to the replacement DM */ } ierr = DMDestroy(&ksp->dm); CHKERRQ(ierr); } ksp->dm = dm; ksp->dmAuto = PETSC_FALSE; ierr = KSPGetPC(ksp,&pc); CHKERRQ(ierr); ierr = PCSetDM(pc,dm); CHKERRQ(ierr); ksp->dmActive = PETSC_TRUE; PetscFunctionReturn(0); }
PetscErrorCode PCSetUp_Exotic(PC pc) { PetscErrorCode ierr; Mat A; PC_MG *mg = (PC_MG*)pc->data; PC_Exotic *ex = (PC_Exotic*) mg->innerctx; MatReuse reuse = (ex->P) ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX; PetscFunctionBegin; if (!pc->dm) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Need to call PCSetDM() before using this PC"); ierr = PCGetOperators(pc,NULL,&A); CHKERRQ(ierr); if (ex->type == PC_EXOTIC_FACE) { ierr = DMDAGetFaceInterpolation(pc->dm,ex,A,reuse,&ex->P); CHKERRQ(ierr); } else if (ex->type == PC_EXOTIC_WIREBASKET) { ierr = DMDAGetWireBasketInterpolation(pc->dm,ex,A,reuse,&ex->P); CHKERRQ(ierr); } else SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Unknown exotic coarse space %d",ex->type); ierr = PCMGSetInterpolation(pc,1,ex->P); CHKERRQ(ierr); /* if PC has attached DM we must remove it or the PCMG will use it to compute incorrect sized vectors and interpolations */ ierr = PCSetDM(pc,NULL); CHKERRQ(ierr); ierr = PCSetUp_MG(pc); CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc,char **argv) { PetscErrorCode ierr; KSP ksp; PC pc; Vec x,b; DM da; Mat A; PetscInt dof=1; PetscBool flg; PetscScalar zero=0.0; PetscInitialize(&argc,&argv,(char *)0,help); ierr = PetscOptionsGetInt(PETSC_NULL,"-dof",&dof,PETSC_NULL);CHKERRQ(ierr); ierr = DMDACreate(PETSC_COMM_WORLD,&da);CHKERRQ(ierr); ierr = DMDASetDim(da,3);CHKERRQ(ierr); ierr = DMDASetBoundaryType(da,DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE);CHKERRQ(ierr); ierr = DMDASetStencilType(da,DMDA_STENCIL_STAR);CHKERRQ(ierr); ierr = DMDASetSizes(da,3,3,3);CHKERRQ(ierr); ierr = DMDASetNumProcs(da,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); ierr = DMDASetDof(da,dof);CHKERRQ(ierr); ierr = DMDASetStencilWidth(da,1);CHKERRQ(ierr); ierr = DMDASetOwnershipRanges(da,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); ierr = DMSetFromOptions(da);CHKERRQ(ierr); ierr = DMSetUp(da);CHKERRQ(ierr); ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr); ierr = DMCreateGlobalVector(da,&b);CHKERRQ(ierr); ierr = DMCreateMatrix(da,MATAIJ,&A);CHKERRQ(ierr); ierr = VecSet(b,zero);CHKERRQ(ierr); /* Test sbaij matrix */ flg = PETSC_FALSE; ierr = PetscOptionsGetBool(PETSC_NULL,"-test_sbaij",&flg,PETSC_NULL);CHKERRQ(ierr); if (flg) { Mat sA; ierr = MatSetOption(A,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); ierr = MatConvert(A,MATSBAIJ,MAT_INITIAL_MATRIX,&sA);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); A = sA; } ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,A,A,SAME_NONZERO_PATTERN);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetDM(pc,(DM)da);CHKERRQ(ierr); ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr); /* check final residual */ flg = PETSC_FALSE; ierr = PetscOptionsGetBool(PETSC_NULL, "-check_final_residual", &flg,PETSC_NULL);CHKERRQ(ierr); if (flg){ Vec b1; PetscReal norm; ierr = KSPGetSolution(ksp,&x);CHKERRQ(ierr); ierr = VecDuplicate(b,&b1);CHKERRQ(ierr); ierr = MatMult(A,x,b1);CHKERRQ(ierr); ierr = VecAXPY(b1,-1.0,b);CHKERRQ(ierr); ierr = VecNorm(b1,NORM_2,&norm);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Final residual %g\n",norm);CHKERRQ(ierr); ierr = VecDestroy(&b1);CHKERRQ(ierr); } ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
int main(int argc,char **argv) { PetscErrorCode ierr; KSP ksp; PC pc; Vec x,b; DM da; Mat A,Atrans; PetscInt dof=1,M=8; PetscBool flg,trans=PETSC_FALSE; ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; ierr = PetscOptionsGetInt(NULL,NULL,"-dof",&dof,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,NULL,"-M",&M,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,NULL,"-trans",&trans,NULL);CHKERRQ(ierr); ierr = DMDACreate(PETSC_COMM_WORLD,&da);CHKERRQ(ierr); ierr = DMSetDimension(da,3);CHKERRQ(ierr); ierr = DMDASetBoundaryType(da,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE);CHKERRQ(ierr); ierr = DMDASetStencilType(da,DMDA_STENCIL_STAR);CHKERRQ(ierr); ierr = DMDASetSizes(da,M,M,M);CHKERRQ(ierr); ierr = DMDASetNumProcs(da,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); ierr = DMDASetDof(da,dof);CHKERRQ(ierr); ierr = DMDASetStencilWidth(da,1);CHKERRQ(ierr); ierr = DMDASetOwnershipRanges(da,NULL,NULL,NULL);CHKERRQ(ierr); ierr = DMSetFromOptions(da);CHKERRQ(ierr); ierr = DMSetUp(da);CHKERRQ(ierr); ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr); ierr = DMCreateGlobalVector(da,&b);CHKERRQ(ierr); ierr = ComputeRHS(da,b);CHKERRQ(ierr); ierr = DMSetMatType(da,MATBAIJ);CHKERRQ(ierr); ierr = DMSetFromOptions(da);CHKERRQ(ierr); ierr = DMCreateMatrix(da,&A);CHKERRQ(ierr); ierr = ComputeMatrix(da,A);CHKERRQ(ierr); /* A is non-symmetric. Make A = 0.5*(A + Atrans) symmetric for testing icc and cholesky */ ierr = MatTranspose(A,MAT_INITIAL_MATRIX,&Atrans);CHKERRQ(ierr); ierr = MatAXPY(A,1.0,Atrans,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = MatScale(A,0.5);CHKERRQ(ierr); ierr = MatDestroy(&Atrans);CHKERRQ(ierr); /* Test sbaij matrix */ flg = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,NULL, "-test_sbaij1", &flg,NULL);CHKERRQ(ierr); if (flg) { Mat sA; PetscBool issymm; ierr = MatIsTranspose(A,A,0.0,&issymm);CHKERRQ(ierr); if (issymm) { ierr = MatSetOption(A,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); } else {ierr = PetscPrintf(PETSC_COMM_WORLD,"Warning: A is non-symmetric\n");CHKERRQ(ierr);} ierr = MatConvert(A,MATSBAIJ,MAT_INITIAL_MATRIX,&sA);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); A = sA; } ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,A,A);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetDM(pc,(DM)da);CHKERRQ(ierr); if (trans) { ierr = KSPSolveTranspose(ksp,b,x);CHKERRQ(ierr); } else { ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr); } /* check final residual */ flg = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,NULL, "-check_final_residual", &flg,NULL);CHKERRQ(ierr); if (flg) { Vec b1; PetscReal norm; ierr = KSPGetSolution(ksp,&x);CHKERRQ(ierr); ierr = VecDuplicate(b,&b1);CHKERRQ(ierr); ierr = MatMult(A,x,b1);CHKERRQ(ierr); ierr = VecAXPY(b1,-1.0,b);CHKERRQ(ierr); ierr = VecNorm(b1,NORM_2,&norm);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Final residual %g\n",norm);CHKERRQ(ierr); ierr = VecDestroy(&b1);CHKERRQ(ierr); } ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
int main(int Argc,char **Args) { PetscBool flg; PetscInt n = -6; PetscScalar rho = 1.0; PetscReal h; PetscReal beta = 1.0; DM da; PetscRandom rctx; PetscMPIInt comm_size; Mat H,HtH; PetscInt x, y, xs, ys, xm, ym; PetscReal r1, r2; PetscScalar uxy1, uxy2; MatStencil sxy, sxy_m; PetscScalar val, valconj; Vec b, Htb,xvec; KSP kspmg; PC pcmg; PetscErrorCode ierr; PetscInt ix[1] = {0}; PetscScalar vals[1] = {1.0}; PetscInitialize(&Argc,&Args,(char*)0,help); ierr = PetscOptionsGetInt(NULL,"-size",&n,&flg);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,"-beta",&beta,&flg);CHKERRQ(ierr); ierr = PetscOptionsGetScalar(NULL,"-rho",&rho,&flg);CHKERRQ(ierr); /* Set the fudge parameters, we scale the whole thing by 1/(2*h) later */ h = 1.; rho *= 1./(2.*h); /* Geometry info */ ierr = DMDACreate2d(PETSC_COMM_WORLD, DMDA_BOUNDARY_PERIODIC,DMDA_BOUNDARY_PERIODIC, DMDA_STENCIL_STAR, n, n, PETSC_DECIDE, PETSC_DECIDE, 2 /* this is the # of dof's */, 1, NULL, NULL, &da);CHKERRQ(ierr); /* Random numbers */ ierr = PetscRandomCreate(PETSC_COMM_WORLD,&rctx);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr); /* Single or multi processor ? */ ierr = MPI_Comm_size(PETSC_COMM_WORLD,&comm_size);CHKERRQ(ierr); /* construct matrix */ ierr = DMSetMatType(da,MATAIJ);CHKERRQ(ierr); ierr = DMCreateMatrix(da, &H);CHKERRQ(ierr); /* get local corners for this processor */ ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); /* Assemble the matrix */ for (x=xs; x<xs+xm; x++) { for (y=ys; y<ys+ym; y++) { /* each lattice point sets only the *forward* pointing parameters (right, down), i.e. Nabla_1^+ and Nabla_2^+. In this way we can use only local random number creation. That means we also have to set the corresponding backward pointing entries. */ /* Compute some normally distributed random numbers via Box-Muller */ ierr = PetscRandomGetValueReal(rctx, &r1);CHKERRQ(ierr); r1 = 1.-r1; /* to change from [0,1) to (0,1], which we need for the log */ ierr = PetscRandomGetValueReal(rctx, &r2);CHKERRQ(ierr); PetscReal R = PetscSqrtReal(-2.*PetscLogReal(r1)); PetscReal c = PetscCosReal(2.*PETSC_PI*r2); PetscReal s = PetscSinReal(2.*PETSC_PI*r2); /* use those to set the field */ uxy1 = PetscExpScalar(((PetscScalar) (R*c/beta))*PETSC_i); uxy2 = PetscExpScalar(((PetscScalar) (R*s/beta))*PETSC_i); sxy.i = x; sxy.j = y; /* the point where we are */ /* center action */ sxy.c = 0; /* spin 0, 0 */ ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy, &rho, ADD_VALUES);CHKERRQ(ierr); sxy.c = 1; /* spin 1, 1 */ val = -rho; ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); sxy_m.i = x+1; sxy_m.j = y; /* right action */ sxy.c = 0; sxy_m.c = 0; /* spin 0, 0 */ val = -uxy1; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy.c = 0; sxy_m.c = 1; /* spin 0, 1 */ val = -uxy1; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy.c = 1; sxy_m.c = 0; /* spin 1, 0 */ val = uxy1; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy.c = 1; sxy_m.c = 1; /* spin 1, 1 */ val = uxy1; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy_m.i = x; sxy_m.j = y+1; /* down action */ sxy.c = 0; sxy_m.c = 0; /* spin 0, 0 */ val = -uxy2; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy.c = 0; sxy_m.c = 1; /* spin 0, 1 */ val = -PETSC_i*uxy2; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy.c = 1; sxy_m.c = 0; /* spin 1, 0 */ val = -PETSC_i*uxy2; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy.c = 1; sxy_m.c = 1; /* spin 1, 1 */ val = PetscConj(uxy2); valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); } } ierr = MatAssemblyBegin(H, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(H, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* scale H */ ierr = MatScale(H, 1./(2.*h));CHKERRQ(ierr); /* it looks like H is Hermetian */ /* construct normal equations */ ierr = MatMatMult(H, H, MAT_INITIAL_MATRIX, 1., &HtH);CHKERRQ(ierr); /* permutation matrix to check whether H and HtH are identical to the ones in the paper */ /* Mat perm; */ /* ierr = DMCreateMatrix(da, &perm);CHKERRQ(ierr); */ /* PetscInt row, col; */ /* PetscScalar one = 1.0; */ /* for (PetscInt i=0; i<n; i++) { */ /* for (PetscInt j=0; j<n; j++) { */ /* row = (i*n+j)*2; col = i*n+j; */ /* ierr = MatSetValues(perm, 1, &row, 1, &col, &one, INSERT_VALUES);CHKERRQ(ierr); */ /* row = (i*n+j)*2+1; col = i*n+j + n*n; */ /* ierr = MatSetValues(perm, 1, &row, 1, &col, &one, INSERT_VALUES);CHKERRQ(ierr); */ /* } */ /* } */ /* ierr = MatAssemblyBegin(perm, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); */ /* ierr = MatAssemblyEnd(perm, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); */ /* Mat Hperm; */ /* ierr = MatPtAP(H, perm, MAT_INITIAL_MATRIX, 1.0, &Hperm);CHKERRQ(ierr); */ /* ierr = PetscPrintf(PETSC_COMM_WORLD, "Matrix H after construction\n");CHKERRQ(ierr); */ /* ierr = MatView(Hperm, PETSC_VIEWER_STDOUT_(PETSC_COMM_WORLD));CHKERRQ(ierr); */ /* Mat HtHperm; */ /* ierr = MatPtAP(HtH, perm, MAT_INITIAL_MATRIX, 1.0, &HtHperm);CHKERRQ(ierr); */ /* ierr = PetscPrintf(PETSC_COMM_WORLD, "Matrix HtH:\n");CHKERRQ(ierr); */ /* ierr = MatView(HtHperm, PETSC_VIEWER_STDOUT_(PETSC_COMM_WORLD));CHKERRQ(ierr); */ /* right hand side */ ierr = DMCreateGlobalVector(da, &b);CHKERRQ(ierr); ierr = VecSet(b,0.0);CHKERRQ(ierr); ierr = VecSetValues(b, 1, ix, vals, INSERT_VALUES);CHKERRQ(ierr); ierr = VecAssemblyBegin(b);CHKERRQ(ierr); ierr = VecAssemblyEnd(b);CHKERRQ(ierr); /* ierr = VecSetRandom(b, rctx);CHKERRQ(ierr); */ ierr = VecDuplicate(b, &Htb);CHKERRQ(ierr); ierr = MatMultTranspose(H, b, Htb);CHKERRQ(ierr); /* construct solver */ ierr = KSPCreate(PETSC_COMM_WORLD,&kspmg);CHKERRQ(ierr); ierr = KSPSetType(kspmg, KSPCG);CHKERRQ(ierr); ierr = KSPGetPC(kspmg,&pcmg);CHKERRQ(ierr); ierr = PCSetType(pcmg,PCASA);CHKERRQ(ierr); /* maybe user wants to override some of the choices */ ierr = KSPSetFromOptions(kspmg);CHKERRQ(ierr); ierr = KSPSetOperators(kspmg, HtH, HtH, DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = DMDASetRefinementFactor(da, 3, 3, 3);CHKERRQ(ierr); ierr = PCSetDM(pcmg,da);CHKERRQ(ierr); ierr = PCASASetTolerances(pcmg, 1.e-6, 1.e-10,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); ierr = VecDuplicate(b, &xvec);CHKERRQ(ierr); ierr = VecSet(xvec, 0.0);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Solve the linear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = KSPSolve(kspmg, Htb, xvec);CHKERRQ(ierr); /* ierr = VecView(xvec, PETSC_VIEWER_STDOUT_(PETSC_COMM_WORLD));CHKERRQ(ierr); */ ierr = KSPDestroy(&kspmg);CHKERRQ(ierr); ierr = VecDestroy(&xvec);CHKERRQ(ierr); /* seems to be destroyed by KSPDestroy */ ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = VecDestroy(&Htb);CHKERRQ(ierr); ierr = MatDestroy(&HtH);CHKERRQ(ierr); ierr = MatDestroy(&H);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }