/*@ 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); }
PetscInt main(PetscInt argc,char **args) { Mat A,As; PetscBool flg,disp_mat=PETSC_FALSE; PetscErrorCode ierr; PetscMPIInt size,rank; PetscInt i,j; PetscScalar v,sigma2; PetscRandom rctx; PetscReal h2,sigma1=100.0; PetscInt dim,Ii,J,n = 3,use_random,rstart,rend; KSP ksp; PC pc; Mat F; PetscInt nneg, nzero, npos; PetscInitialize(&argc,&args,(char *)0,help); #if !defined(PETSC_USE_COMPLEX) SETERRQ(PETSC_COMM_WORLD,1,"This example requires complex numbers"); #endif ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = PetscOptionsHasName(PETSC_NULL, "-display_mat", &disp_mat);CHKERRQ(ierr); ierr = PetscOptionsGetReal(PETSC_NULL,"-sigma1",&sigma1,PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(PETSC_NULL,"-n",&n,PETSC_NULL);CHKERRQ(ierr); dim = n*n; ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr); ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,dim,dim);CHKERRQ(ierr); ierr = MatSetType(A,MATAIJ);CHKERRQ(ierr); ierr = MatSetFromOptions(A);CHKERRQ(ierr); ierr = PetscOptionsHasName(PETSC_NULL,"-norandom",&flg);CHKERRQ(ierr); if (flg) use_random = 0; else use_random = 1; if (use_random) { ierr = PetscRandomCreate(PETSC_COMM_WORLD,&rctx);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr); ierr = PetscRandomSetInterval(rctx,0.0,PETSC_i);CHKERRQ(ierr); ierr = PetscRandomGetValue(rctx,&sigma2);CHKERRQ(ierr); /* RealPart(sigma2) == 0.0 */ } else { sigma2 = 10.0*PETSC_i; } h2 = 1.0/((n+1)*(n+1)); ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr); for (Ii=rstart; Ii<rend; Ii++) { v = -1.0; i = Ii/n; j = Ii - i*n; if (i>0) { J = Ii-n; ierr = MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (i<n-1) { J = Ii+n; ierr = MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j>0) { J = Ii-1; ierr = MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j<n-1) { J = Ii+1; ierr = MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} v = 4.0 - sigma1*h2; ierr = MatSetValues(A,1,&Ii,1,&Ii,&v,ADD_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Check whether A is symmetric */ ierr = PetscOptionsHasName(PETSC_NULL, "-check_symmetric", &flg);CHKERRQ(ierr); if (flg) { Mat Trans; ierr = MatTranspose(A,MAT_INITIAL_MATRIX, &Trans); ierr = MatEqual(A, Trans, &flg); if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"A is not symmetric"); ierr = MatDestroy(&Trans);CHKERRQ(ierr); } ierr = MatSetOption(A,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); /* make A complex Hermitian */ Ii = 0; J = dim-1; if (Ii >= rstart && Ii < rend){ v = sigma2*h2; /* RealPart(v) = 0.0 */ ierr = MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr); v = -sigma2*h2; ierr = MatSetValues(A,1,&J,1,&Ii,&v,ADD_VALUES);CHKERRQ(ierr); } Ii = dim-2; J = dim-1; if (Ii >= rstart && Ii < rend){ v = sigma2*h2; /* RealPart(v) = 0.0 */ ierr = MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr); v = -sigma2*h2; ierr = MatSetValues(A,1,&J,1,&Ii,&v,ADD_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Check whether A is Hermitian */ ierr = PetscOptionsHasName(PETSC_NULL, "-check_Hermitian", &flg);CHKERRQ(ierr); if (flg) { Mat Hermit; if (disp_mat){ if (!rank) printf(" A:\n"); ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } ierr = MatHermitianTranspose(A,MAT_INITIAL_MATRIX, &Hermit); if (disp_mat){ if (!rank) printf(" A_Hermitian:\n"); ierr = MatView(Hermit,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } ierr = MatEqual(A, Hermit, &flg); if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"A is not Hermitian"); ierr = MatDestroy(&Hermit);CHKERRQ(ierr); } ierr = MatSetOption(A,MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr); /* Create a Hermitian matrix As in sbaij format */ ierr = MatConvert(A,MATSBAIJ,MAT_INITIAL_MATRIX,&As);CHKERRQ(ierr); if (disp_mat){ if (!rank) {ierr = PetscPrintf(PETSC_COMM_SELF," As:\n");CHKERRQ(ierr);} ierr = MatView(As,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } /* Test MatGetInertia() */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,As,As,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCCHOLESKY);CHKERRQ(ierr); ierr = PCSetFromOptions(pc);CHKERRQ(ierr); ierr = PCSetUp(pc);CHKERRQ(ierr); ierr = PCFactorGetMatrix(pc,&F);CHKERRQ(ierr); ierr = MatGetInertia(F,&nneg,&nzero,&npos);CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); if (!rank){ ierr = PetscPrintf(PETSC_COMM_SELF," MatInertia: nneg: %D, nzero: %D, npos: %D\n",nneg,nzero,npos);CHKERRQ(ierr); } /* Free spaces */ ierr = KSPDestroy(&ksp);CHKERRQ(ierr); if (use_random) {ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr);} ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = MatDestroy(&As);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
int main(int argc,char **argv) { PetscErrorCode ierr; PetscInt its,n,Nx=PETSC_DECIDE,Ny=PETSC_DECIDE,nlocal,i; PetscMPIInt size; PC pc; PetscInt mx,my; Mat A; GridCtx fine_ctx; KSP ksp; PetscBool flg; PetscInitialize(&argc,&argv,NULL,help); /* set up discretization matrix for fine grid */ /* ML requires input of fine-grid matrix. It determines nlevels. */ fine_ctx.mx = 9; fine_ctx.my = 9; ierr = PetscOptionsGetInt(NULL,"-mx",&mx,&flg);CHKERRQ(ierr); if (flg) fine_ctx.mx = mx; ierr = PetscOptionsGetInt(NULL,"-my",&my,&flg);CHKERRQ(ierr); if (flg) fine_ctx.my = my; ierr = PetscPrintf(PETSC_COMM_WORLD,"Fine grid size %D by %D\n",fine_ctx.mx,fine_ctx.my);CHKERRQ(ierr); n = fine_ctx.mx*fine_ctx.my; MPI_Comm_size(PETSC_COMM_WORLD,&size); ierr = PetscOptionsGetInt(NULL,"-Nx",&Nx,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-Ny",&Ny,NULL);CHKERRQ(ierr); ierr = DMDACreate2d(PETSC_COMM_WORLD, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE,DMDA_STENCIL_STAR,fine_ctx.mx, fine_ctx.my,Nx,Ny,1,1,NULL,NULL,&fine_ctx.da);CHKERRQ(ierr); ierr = DMCreateGlobalVector(fine_ctx.da,&fine_ctx.x);CHKERRQ(ierr); ierr = VecDuplicate(fine_ctx.x,&fine_ctx.b);CHKERRQ(ierr); ierr = VecGetLocalSize(fine_ctx.x,&nlocal);CHKERRQ(ierr); ierr = DMCreateLocalVector(fine_ctx.da,&fine_ctx.localX);CHKERRQ(ierr); ierr = VecDuplicate(fine_ctx.localX,&fine_ctx.localF);CHKERRQ(ierr); ierr = MatCreateAIJ(PETSC_COMM_WORLD,nlocal,nlocal,n,n,5,NULL,3,NULL,&A);CHKERRQ(ierr); ierr = FormJacobian_Grid(&fine_ctx,&A);CHKERRQ(ierr); /* create linear solver */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCML);CHKERRQ(ierr); /* set options, then solve system */ ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); /* calls PCSetFromOptions_MG/ML */ for (i=0; i<3; i++) { if (i<2) { /* test DIFFERENT_NONZERO_PATTERN */ /* set values for rhs vector */ ierr = VecSet(fine_ctx.b,i+1.0);CHKERRQ(ierr); /* modify A */ ierr = MatShift(A,1.0);CHKERRQ(ierr); ierr = MatScale(A,2.0);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); } else { /* test SAME_NONZERO_PATTERN */ ierr = KSPSetOperators(ksp,A,A,SAME_NONZERO_PATTERN);CHKERRQ(ierr); } ierr = KSPSolve(ksp,fine_ctx.b,fine_ctx.x);CHKERRQ(ierr); ierr = KSPGetIterationNumber(ksp,&its);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Number of iterations = %D\n",its);CHKERRQ(ierr); } /* free data structures */ ierr = VecDestroy(&fine_ctx.x);CHKERRQ(ierr); ierr = VecDestroy(&fine_ctx.b);CHKERRQ(ierr); ierr = DMDestroy(&fine_ctx.da);CHKERRQ(ierr); ierr = VecDestroy(&fine_ctx.localX);CHKERRQ(ierr); ierr = VecDestroy(&fine_ctx.localF);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
static PetscErrorCode TaoSolve_NTR(Tao tao) { TAO_NTR *tr = (TAO_NTR *)tao->data; PC pc; KSPConvergedReason ksp_reason; TaoConvergedReason reason; PetscReal fmin, ftrial, prered, actred, kappa, sigma, beta; PetscReal tau, tau_1, tau_2, tau_max, tau_min, max_radius; PetscReal f, gnorm; PetscReal delta; PetscReal norm_d; PetscErrorCode ierr; PetscInt iter = 0; PetscInt bfgsUpdates = 0; PetscInt needH; PetscInt i_max = 5; PetscInt j_max = 1; PetscInt i, j, N, n, its; PetscFunctionBegin; if (tao->XL || tao->XU || tao->ops->computebounds) { ierr = PetscPrintf(((PetscObject)tao)->comm,"WARNING: Variable bounds have been set but will be ignored by ntr algorithm\n");CHKERRQ(ierr); } tao->trust = tao->trust0; /* Modify the radius if it is too large or small */ tao->trust = PetscMax(tao->trust, tr->min_radius); tao->trust = PetscMin(tao->trust, tr->max_radius); if (NTR_PC_BFGS == tr->pc_type && !tr->M) { ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr); ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr); ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&tr->M);CHKERRQ(ierr); ierr = MatLMVMAllocateVectors(tr->M,tao->solution);CHKERRQ(ierr); } /* Check convergence criteria */ ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &f, tao->gradient);CHKERRQ(ierr); ierr = VecNorm(tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); needH = 1; ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, 1.0, &reason);CHKERRQ(ierr); if (reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); /* Create vectors for the limited memory preconditioner */ if ((NTR_PC_BFGS == tr->pc_type) && (BFGS_SCALE_BFGS != tr->bfgs_scale_type)) { if (!tr->Diag) { ierr = VecDuplicate(tao->solution, &tr->Diag);CHKERRQ(ierr); } } switch(tr->ksp_type) { case NTR_KSP_NASH: ierr = KSPSetType(tao->ksp, KSPNASH);CHKERRQ(ierr); if (tao->ksp->ops->setfromoptions) { (*tao->ksp->ops->setfromoptions)(tao->ksp); } break; case NTR_KSP_STCG: ierr = KSPSetType(tao->ksp, KSPSTCG);CHKERRQ(ierr); if (tao->ksp->ops->setfromoptions) { (*tao->ksp->ops->setfromoptions)(tao->ksp); } break; default: ierr = KSPSetType(tao->ksp, KSPGLTR);CHKERRQ(ierr); if (tao->ksp->ops->setfromoptions) { (*tao->ksp->ops->setfromoptions)(tao->ksp); } break; } /* Modify the preconditioner to use the bfgs approximation */ ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr); switch(tr->pc_type) { case NTR_PC_NONE: ierr = PCSetType(pc, PCNONE);CHKERRQ(ierr); if (pc->ops->setfromoptions) { (*pc->ops->setfromoptions)(pc); } break; case NTR_PC_AHESS: ierr = PCSetType(pc, PCJACOBI);CHKERRQ(ierr); if (pc->ops->setfromoptions) { (*pc->ops->setfromoptions)(pc); } ierr = PCJacobiSetUseAbs(pc);CHKERRQ(ierr); break; case NTR_PC_BFGS: ierr = PCSetType(pc, PCSHELL);CHKERRQ(ierr); if (pc->ops->setfromoptions) { (*pc->ops->setfromoptions)(pc); } ierr = PCShellSetName(pc, "bfgs");CHKERRQ(ierr); ierr = PCShellSetContext(pc, tr->M);CHKERRQ(ierr); ierr = PCShellSetApply(pc, MatLMVMSolveShell);CHKERRQ(ierr); break; default: /* Use the pc method set by pc_type */ break; } /* Initialize trust-region radius */ switch(tr->init_type) { case NTR_INIT_CONSTANT: /* Use the initial radius specified */ break; case NTR_INIT_INTERPOLATION: /* Use the initial radius specified */ max_radius = 0.0; for (j = 0; j < j_max; ++j) { fmin = f; sigma = 0.0; if (needH) { ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); needH = 0; } for (i = 0; i < i_max; ++i) { ierr = VecCopy(tao->solution, tr->W);CHKERRQ(ierr); ierr = VecAXPY(tr->W, -tao->trust/gnorm, tao->gradient);CHKERRQ(ierr); ierr = TaoComputeObjective(tao, tr->W, &ftrial);CHKERRQ(ierr); if (PetscIsInfOrNanReal(ftrial)) { tau = tr->gamma1_i; } else { if (ftrial < fmin) { fmin = ftrial; sigma = -tao->trust / gnorm; } ierr = MatMult(tao->hessian, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = VecDot(tao->gradient, tao->stepdirection, &prered);CHKERRQ(ierr); prered = tao->trust * (gnorm - 0.5 * tao->trust * prered / (gnorm * gnorm)); actred = f - ftrial; if ((PetscAbsScalar(actred) <= tr->epsilon) && (PetscAbsScalar(prered) <= tr->epsilon)) { kappa = 1.0; } else { kappa = actred / prered; } tau_1 = tr->theta_i * gnorm * tao->trust / (tr->theta_i * gnorm * tao->trust + (1.0 - tr->theta_i) * prered - actred); tau_2 = tr->theta_i * gnorm * tao->trust / (tr->theta_i * gnorm * tao->trust - (1.0 + tr->theta_i) * prered + actred); tau_min = PetscMin(tau_1, tau_2); tau_max = PetscMax(tau_1, tau_2); if (PetscAbsScalar(kappa - 1.0) <= tr->mu1_i) { /* Great agreement */ max_radius = PetscMax(max_radius, tao->trust); if (tau_max < 1.0) { tau = tr->gamma3_i; } else if (tau_max > tr->gamma4_i) { tau = tr->gamma4_i; } else { tau = tau_max; } } else if (PetscAbsScalar(kappa - 1.0) <= tr->mu2_i) { /* Good agreement */ max_radius = PetscMax(max_radius, tao->trust); if (tau_max < tr->gamma2_i) { tau = tr->gamma2_i; } else if (tau_max > tr->gamma3_i) { tau = tr->gamma3_i; } else { tau = tau_max; } } else { /* Not good agreement */ if (tau_min > 1.0) { tau = tr->gamma2_i; } else if (tau_max < tr->gamma1_i) { tau = tr->gamma1_i; } else if ((tau_min < tr->gamma1_i) && (tau_max >= 1.0)) { tau = tr->gamma1_i; } else if ((tau_1 >= tr->gamma1_i) && (tau_1 < 1.0) && ((tau_2 < tr->gamma1_i) || (tau_2 >= 1.0))) { tau = tau_1; } else if ((tau_2 >= tr->gamma1_i) && (tau_2 < 1.0) && ((tau_1 < tr->gamma1_i) || (tau_2 >= 1.0))) { tau = tau_2; } else { tau = tau_max; } } } tao->trust = tau * tao->trust; } if (fmin < f) { f = fmin; ierr = VecAXPY(tao->solution, sigma, tao->gradient);CHKERRQ(ierr); ierr = TaoComputeGradient(tao,tao->solution, tao->gradient);CHKERRQ(ierr); ierr = VecNorm(tao->gradient, NORM_2, &gnorm);CHKERRQ(ierr); if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); needH = 1; ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, 1.0, &reason);CHKERRQ(ierr); if (reason != TAO_CONTINUE_ITERATING) { PetscFunctionReturn(0); } } } tao->trust = PetscMax(tao->trust, max_radius); /* Modify the radius if it is too large or small */ tao->trust = PetscMax(tao->trust, tr->min_radius); tao->trust = PetscMin(tao->trust, tr->max_radius); break; default: /* Norm of the first direction will initialize radius */ tao->trust = 0.0; break; } /* Set initial scaling for the BFGS preconditioner This step is done after computing the initial trust-region radius since the function value may have decreased */ if (NTR_PC_BFGS == tr->pc_type) { if (f != 0.0) { delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); } else { delta = 2.0 / (gnorm*gnorm); } ierr = MatLMVMSetDelta(tr->M,delta);CHKERRQ(ierr); } /* Have not converged; continue with Newton method */ while (reason == TAO_CONTINUE_ITERATING) { ++iter; tao->ksp_its=0; /* Compute the Hessian */ if (needH) { ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); needH = 0; } if (NTR_PC_BFGS == tr->pc_type) { if (BFGS_SCALE_AHESS == tr->bfgs_scale_type) { /* Obtain diagonal for the bfgs preconditioner */ ierr = MatGetDiagonal(tao->hessian, tr->Diag);CHKERRQ(ierr); ierr = VecAbs(tr->Diag);CHKERRQ(ierr); ierr = VecReciprocal(tr->Diag);CHKERRQ(ierr); ierr = MatLMVMSetScale(tr->M,tr->Diag);CHKERRQ(ierr); } /* Update the limited memory preconditioner */ ierr = MatLMVMUpdate(tr->M, tao->solution, tao->gradient);CHKERRQ(ierr); ++bfgsUpdates; } while (reason == TAO_CONTINUE_ITERATING) { ierr = KSPSetOperators(tao->ksp, tao->hessian, tao->hessian_pre);CHKERRQ(ierr); /* Solve the trust region subproblem */ if (NTR_KSP_NASH == tr->ksp_type) { ierr = KSPNASHSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); tao->ksp_its+=its; tao->ksp_tot_its+=its; ierr = KSPNASHGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); } else if (NTR_KSP_STCG == tr->ksp_type) { ierr = KSPSTCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); tao->ksp_its+=its; tao->ksp_tot_its+=its; ierr = KSPSTCGGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); } else { /* NTR_KSP_GLTR */ ierr = KSPGLTRSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); tao->ksp_its+=its; tao->ksp_tot_its+=its; ierr = KSPGLTRGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); } if (0.0 == tao->trust) { /* Radius was uninitialized; use the norm of the direction */ if (norm_d > 0.0) { tao->trust = norm_d; /* Modify the radius if it is too large or small */ tao->trust = PetscMax(tao->trust, tr->min_radius); tao->trust = PetscMin(tao->trust, tr->max_radius); } else { /* The direction was bad; set radius to default value and re-solve the trust-region subproblem to get a direction */ tao->trust = tao->trust0; /* Modify the radius if it is too large or small */ tao->trust = PetscMax(tao->trust, tr->min_radius); tao->trust = PetscMin(tao->trust, tr->max_radius); if (NTR_KSP_NASH == tr->ksp_type) { ierr = KSPNASHSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); tao->ksp_its+=its; tao->ksp_tot_its+=its; ierr = KSPNASHGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); } else if (NTR_KSP_STCG == tr->ksp_type) { ierr = KSPSTCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); tao->ksp_its+=its; tao->ksp_tot_its+=its; ierr = KSPSTCGGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); } else { /* NTR_KSP_GLTR */ ierr = KSPGLTRSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&its);CHKERRQ(ierr); tao->ksp_its+=its; tao->ksp_tot_its+=its; ierr = KSPGLTRGetNormD(tao->ksp, &norm_d);CHKERRQ(ierr); } if (norm_d == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero"); } } ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); ierr = KSPGetConvergedReason(tao->ksp, &ksp_reason);CHKERRQ(ierr); if ((KSP_DIVERGED_INDEFINITE_PC == ksp_reason) && (NTR_PC_BFGS == tr->pc_type) && (bfgsUpdates > 1)) { /* Preconditioner is numerically indefinite; reset the approximate if using BFGS preconditioning. */ if (f != 0.0) { delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); } else { delta = 2.0 / (gnorm*gnorm); } ierr = MatLMVMSetDelta(tr->M, delta);CHKERRQ(ierr); ierr = MatLMVMReset(tr->M);CHKERRQ(ierr); ierr = MatLMVMUpdate(tr->M, tao->solution, tao->gradient);CHKERRQ(ierr); bfgsUpdates = 1; } if (NTR_UPDATE_REDUCTION == tr->update_type) { /* Get predicted reduction */ if (NTR_KSP_NASH == tr->ksp_type) { ierr = KSPNASHGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); } else if (NTR_KSP_STCG == tr->ksp_type) { ierr = KSPSTCGGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); } else { /* gltr */ ierr = KSPGLTRGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); } if (prered >= 0.0) { /* The predicted reduction has the wrong sign. This cannot happen in infinite precision arithmetic. Step should be rejected! */ tao->trust = tr->alpha1 * PetscMin(tao->trust, norm_d); } else { /* Compute trial step and function value */ ierr = VecCopy(tao->solution,tr->W);CHKERRQ(ierr); ierr = VecAXPY(tr->W, 1.0, tao->stepdirection);CHKERRQ(ierr); ierr = TaoComputeObjective(tao, tr->W, &ftrial);CHKERRQ(ierr); if (PetscIsInfOrNanReal(ftrial)) { tao->trust = tr->alpha1 * PetscMin(tao->trust, norm_d); } else { /* Compute and actual reduction */ actred = f - ftrial; prered = -prered; if ((PetscAbsScalar(actred) <= tr->epsilon) && (PetscAbsScalar(prered) <= tr->epsilon)) { kappa = 1.0; } else { kappa = actred / prered; } /* Accept or reject the step and update radius */ if (kappa < tr->eta1) { /* Reject the step */ tao->trust = tr->alpha1 * PetscMin(tao->trust, norm_d); } else { /* Accept the step */ if (kappa < tr->eta2) { /* Marginal bad step */ tao->trust = tr->alpha2 * PetscMin(tao->trust, norm_d); } else if (kappa < tr->eta3) { /* Reasonable step */ tao->trust = tr->alpha3 * tao->trust; } else if (kappa < tr->eta4) { /* Good step */ tao->trust = PetscMax(tr->alpha4 * norm_d, tao->trust); } else { /* Very good step */ tao->trust = PetscMax(tr->alpha5 * norm_d, tao->trust); } break; } } } } else { /* Get predicted reduction */ if (NTR_KSP_NASH == tr->ksp_type) { ierr = KSPNASHGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); } else if (NTR_KSP_STCG == tr->ksp_type) { ierr = KSPSTCGGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); } else { /* gltr */ ierr = KSPGLTRGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); } if (prered >= 0.0) { /* The predicted reduction has the wrong sign. This cannot happen in infinite precision arithmetic. Step should be rejected! */ tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); } else { ierr = VecCopy(tao->solution, tr->W);CHKERRQ(ierr); ierr = VecAXPY(tr->W, 1.0, tao->stepdirection);CHKERRQ(ierr); ierr = TaoComputeObjective(tao, tr->W, &ftrial);CHKERRQ(ierr); if (PetscIsInfOrNanReal(ftrial)) { tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); } else { ierr = VecDot(tao->gradient, tao->stepdirection, &beta);CHKERRQ(ierr); actred = f - ftrial; prered = -prered; if ((PetscAbsScalar(actred) <= tr->epsilon) && (PetscAbsScalar(prered) <= tr->epsilon)) { kappa = 1.0; } else { kappa = actred / prered; } tau_1 = tr->theta * beta / (tr->theta * beta - (1.0 - tr->theta) * prered + actred); tau_2 = tr->theta * beta / (tr->theta * beta + (1.0 + tr->theta) * prered - actred); tau_min = PetscMin(tau_1, tau_2); tau_max = PetscMax(tau_1, tau_2); if (kappa >= 1.0 - tr->mu1) { /* Great agreement; accept step and update radius */ if (tau_max < 1.0) { tao->trust = PetscMax(tao->trust, tr->gamma3 * norm_d); } else if (tau_max > tr->gamma4) { tao->trust = PetscMax(tao->trust, tr->gamma4 * norm_d); } else { tao->trust = PetscMax(tao->trust, tau_max * norm_d); } break; } else if (kappa >= 1.0 - tr->mu2) { /* Good agreement */ if (tau_max < tr->gamma2) { tao->trust = tr->gamma2 * PetscMin(tao->trust, norm_d); } else if (tau_max > tr->gamma3) { tao->trust = PetscMax(tao->trust, tr->gamma3 * norm_d); } else if (tau_max < 1.0) { tao->trust = tau_max * PetscMin(tao->trust, norm_d); } else { tao->trust = PetscMax(tao->trust, tau_max * norm_d); } break; } else { /* Not good agreement */ if (tau_min > 1.0) { tao->trust = tr->gamma2 * PetscMin(tao->trust, norm_d); } else if (tau_max < tr->gamma1) { tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); } else if ((tau_min < tr->gamma1) && (tau_max >= 1.0)) { tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); } else if ((tau_1 >= tr->gamma1) && (tau_1 < 1.0) && ((tau_2 < tr->gamma1) || (tau_2 >= 1.0))) { tao->trust = tau_1 * PetscMin(tao->trust, norm_d); } else if ((tau_2 >= tr->gamma1) && (tau_2 < 1.0) && ((tau_1 < tr->gamma1) || (tau_2 >= 1.0))) { tao->trust = tau_2 * PetscMin(tao->trust, norm_d); } else { tao->trust = tau_max * PetscMin(tao->trust, norm_d); } } } } } /* The step computed was not good and the radius was decreased. Monitor the radius to terminate. */ ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, tao->trust, &reason);CHKERRQ(ierr); } /* The radius may have been increased; modify if it is too large */ tao->trust = PetscMin(tao->trust, tr->max_radius); if (reason == TAO_CONTINUE_ITERATING) { ierr = VecCopy(tr->W, tao->solution);CHKERRQ(ierr); f = ftrial; ierr = TaoComputeGradient(tao, tao->solution, tao->gradient); ierr = VecNorm(tao->gradient, NORM_2, &gnorm);CHKERRQ(ierr); if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); needH = 1; ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, tao->trust, &reason);CHKERRQ(ierr); } } PetscFunctionReturn(0); }
void PETScMGSolver_UpdateSolvers( PETScMGSolver* self ) { PETScMGSolver_Level* level; PC pc; KSP levelKSP; PC levelPC; PetscErrorCode ec; unsigned l_i; PetscTruth smoothers_differ, flag; PetscMPIInt size; MPI_Comm comm; assert( self && Stg_CheckType( self, PETScMGSolver ) ); ec = KSPGetPC( self->mgData->ksp, &pc ); CheckPETScError( ec ); ec = PCMGSetLevels( pc, self->nLevels, PETSC_NULL ); CheckPETScError( ec ); ec = PCMGSetType( pc, PC_MG_MULTIPLICATIVE ); CheckPETScError( ec ); ec=PetscOptionsGetTruth( PETSC_NULL, "-pc_mg_different_smoothers", &smoothers_differ, &flag ); CheckPETScError(ec); ec=PetscObjectGetComm( (PetscObject)pc, &comm ); CheckPETScError(ec); MPI_Comm_size( comm, &size ); for( l_i = 1; l_i < self->nLevels; l_i++ ) { level = self->levels + l_i; printf("Configuring MG level %d \n", l_i ); ec = PCMGGetSmootherDown( pc, l_i, &levelKSP ); CheckPETScError( ec ); if(smoothers_differ==PETSC_TRUE) { ec=KSPAppendOptionsPrefix( levelKSP, "down_" ); CheckPETScError(ec); } ec = KSPSetType( levelKSP, KSPRICHARDSON ); CheckPETScError( ec ); ec = KSPGetPC( levelKSP, &levelPC ); CheckPETScError( ec ); if(size==1) { ec = PCSetType( levelPC, PCSOR ); CheckPETScError( ec ); } /* This does not work - bug with the order the operators are created I guess */ /* For parallel jobs you best bet is to use the command line args and let petsc work it out */ /* else { KSP *sub_ksp; PetscInt k, n_local, first_local; PC sub_pc; PCSetType( levelPC, PCBJACOBI ); KSPSetUp( levelKSP ); PCBJacobiGetSubKSP( levelPC, &n_local,&first_local,&sub_ksp); for(k=0;k<n_local;k++ ) { KSPSetType( sub_ksp[k], KSPFGMRES ); KSPGetPC( sub_ksp[k], &sub_pc ); PCSetType( sub_pc, PCSOR ); } } */ ec = KSPSetTolerances( levelKSP, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, level->nDownIts ); CheckPETScError( ec ); if( l_i == self->nLevels - 1 ) { ec = KSPSetInitialGuessNonzero( levelKSP, PETSC_TRUE ); CheckPETScError( ec ); } else { ec = KSPSetInitialGuessNonzero( levelKSP, PETSC_FALSE ); CheckPETScError( ec ); } ec = PCMGGetSmootherUp( pc, l_i, &levelKSP ); CheckPETScError( ec ); if(smoothers_differ==PETSC_TRUE) { ec=KSPAppendOptionsPrefix( levelKSP, "up_" ); CheckPETScError(ec); } ec = KSPSetType( levelKSP, KSPRICHARDSON ); CheckPETScError( ec ); ec = KSPGetPC( levelKSP, &levelPC ); CheckPETScError( ec ); if(size==1) { ec = PCSetType( levelPC, PCSOR ); CheckPETScError( ec ); } ec = KSPSetTolerances( levelKSP, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, level->nUpIts ); CheckPETScError( ec ); ec = KSPSetInitialGuessNonzero( levelKSP, PETSC_TRUE ); CheckPETScError( ec ); ec = PCMGSetCyclesOnLevel( pc, l_i, level->nCycles ); CheckPETScError( ec ); } }
int main(int argc,char **argv) { Userctx user; Vec p; PetscScalar *x_ptr; PetscErrorCode ierr; PetscMPIInt size; PetscInt i; KSP ksp; PC pc; PetscInt *idx2; Tao tao; TaoConvergedReason reason; Vec lowerb,upperb; PetscFunctionBeginUser; ierr = PetscInitialize(&argc,&argv,"petscoptions",help);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); if (size > 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Only for sequential runs"); ierr = VecCreateSeq(PETSC_COMM_WORLD,1,&user.vec_q);CHKERRQ(ierr); user.neqs_gen = 9*ngen; /* # eqs. for generator subsystem */ user.neqs_net = 2*nbus; /* # eqs. for network subsystem */ user.neqs_pgrid = user.neqs_gen + user.neqs_net; /* Create indices for differential and algebraic equations */ ierr = PetscMalloc1(7*ngen,&idx2);CHKERRQ(ierr); for (i=0; i<ngen; i++) { idx2[7*i] = 9*i; idx2[7*i+1] = 9*i+1; idx2[7*i+2] = 9*i+2; idx2[7*i+3] = 9*i+3; idx2[7*i+4] = 9*i+6; idx2[7*i+5] = 9*i+7; idx2[7*i+6] = 9*i+8; } ierr = ISCreateGeneral(PETSC_COMM_WORLD,7*ngen,idx2,PETSC_COPY_VALUES,&user.is_diff);CHKERRQ(ierr); ierr = ISComplement(user.is_diff,0,user.neqs_pgrid,&user.is_alg);CHKERRQ(ierr); ierr = PetscFree(idx2);CHKERRQ(ierr); /* Set run time options */ ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Transient stability fault options","");CHKERRQ(ierr); { user.tfaulton = 1.0; user.tfaultoff = 1.2; user.Rfault = 0.0001; user.faultbus = 8; ierr = PetscOptionsReal("-tfaulton","","",user.tfaulton,&user.tfaulton,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-tfaultoff","","",user.tfaultoff,&user.tfaultoff,NULL);CHKERRQ(ierr); ierr = PetscOptionsInt("-faultbus","","",user.faultbus,&user.faultbus,NULL);CHKERRQ(ierr); user.t0 = 0.0; user.tmax = 1.5; ierr = PetscOptionsReal("-t0","","",user.t0,&user.t0,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-tmax","","",user.tmax,&user.tmax,NULL);CHKERRQ(ierr); user.freq_u = 61.0; user.freq_l = 59.0; user.pow = 2; ierr = PetscOptionsReal("-frequ","","",user.freq_u,&user.freq_u,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-freql","","",user.freq_l,&user.freq_l,NULL);CHKERRQ(ierr); ierr = PetscOptionsInt("-pow","","",user.pow,&user.pow,NULL);CHKERRQ(ierr); } ierr = PetscOptionsEnd();CHKERRQ(ierr); /* Create DMs for generator and network subsystems */ ierr = DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,user.neqs_gen,1,1,NULL,&user.dmgen);CHKERRQ(ierr); ierr = DMSetOptionsPrefix(user.dmgen,"dmgen_");CHKERRQ(ierr); ierr = DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,user.neqs_net,1,1,NULL,&user.dmnet);CHKERRQ(ierr); ierr = DMSetOptionsPrefix(user.dmnet,"dmnet_");CHKERRQ(ierr); /* Create a composite DM packer and add the two DMs */ ierr = DMCompositeCreate(PETSC_COMM_WORLD,&user.dmpgrid);CHKERRQ(ierr); ierr = DMSetOptionsPrefix(user.dmpgrid,"pgrid_");CHKERRQ(ierr); ierr = DMCompositeAddDM(user.dmpgrid,user.dmgen);CHKERRQ(ierr); ierr = DMCompositeAddDM(user.dmpgrid,user.dmnet);CHKERRQ(ierr); /* Create TAO solver and set desired solution method */ ierr = TaoCreate(PETSC_COMM_WORLD,&tao);CHKERRQ(ierr); ierr = TaoSetType(tao,TAOBLMVM);CHKERRQ(ierr); /* Optimization starts */ /* Set initial solution guess */ ierr = VecCreateSeq(PETSC_COMM_WORLD,3,&p);CHKERRQ(ierr); ierr = VecGetArray(p,&x_ptr);CHKERRQ(ierr); x_ptr[0] = PG[0]; x_ptr[1] = PG[1]; x_ptr[2] = PG[2]; ierr = VecRestoreArray(p,&x_ptr);CHKERRQ(ierr); ierr = TaoSetInitialVector(tao,p);CHKERRQ(ierr); /* Set routine for function and gradient evaluation */ ierr = TaoSetObjectiveRoutine(tao,FormFunction,(void *)&user);CHKERRQ(ierr); ierr = TaoSetGradientRoutine(tao,TaoDefaultComputeGradient,(void *)&user);CHKERRQ(ierr); /* Set bounds for the optimization */ ierr = VecDuplicate(p,&lowerb);CHKERRQ(ierr); ierr = VecDuplicate(p,&upperb);CHKERRQ(ierr); ierr = VecGetArray(lowerb,&x_ptr);CHKERRQ(ierr); x_ptr[0] = 0.5; x_ptr[1] = 0.5; x_ptr[2] = 0.5; ierr = VecRestoreArray(lowerb,&x_ptr);CHKERRQ(ierr); ierr = VecGetArray(upperb,&x_ptr);CHKERRQ(ierr); x_ptr[0] = 2.0; x_ptr[1] = 2.0; x_ptr[2] = 2.0; ierr = VecRestoreArray(upperb,&x_ptr);CHKERRQ(ierr); ierr = TaoSetVariableBounds(tao,lowerb,upperb); /* Check for any TAO command line options */ ierr = TaoSetFromOptions(tao);CHKERRQ(ierr); ierr = TaoGetKSP(tao,&ksp);CHKERRQ(ierr); if (ksp) { ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr); } /* SOLVE THE APPLICATION */ ierr = TaoSolve(tao); CHKERRQ(ierr); /* Get information on termination */ ierr = TaoGetConvergedReason(tao,&reason);CHKERRQ(ierr); if (reason <= 0){ ierr=PetscPrintf(MPI_COMM_WORLD, "Try another method! \n");CHKERRQ(ierr); } ierr = VecView(p,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); /* Free TAO data structures */ ierr = TaoDestroy(&tao);CHKERRQ(ierr); ierr = VecDestroy(&user.vec_q);CHKERRQ(ierr); ierr = VecDestroy(&lowerb);CHKERRQ(ierr); ierr = VecDestroy(&upperb);CHKERRQ(ierr); ierr = VecDestroy(&p);CHKERRQ(ierr); ierr = DMDestroy(&user.dmgen);CHKERRQ(ierr); ierr = DMDestroy(&user.dmnet);CHKERRQ(ierr); ierr = DMDestroy(&user.dmpgrid);CHKERRQ(ierr); ierr = ISDestroy(&user.is_diff);CHKERRQ(ierr); ierr = ISDestroy(&user.is_alg);CHKERRQ(ierr); ierr = PetscFinalize(); return(0); }
/*@C PCMGSetLevels - Sets the number of levels to use with MG. Must be called before any other MG routine. Logically Collective on PC Input Parameters: + pc - the preconditioner context . levels - the number of levels - comms - optional communicators for each level; this is to allow solving the coarser problems on smaller sets of processors. Use NULL_OBJECT for default in Fortran Level: intermediate Notes: If the number of levels is one then the multigrid uses the -mg_levels prefix for setting the level options rather than the -mg_coarse prefix. .keywords: MG, set, levels, multigrid .seealso: PCMGSetType(), PCMGGetLevels() @*/ PetscErrorCode PCMGSetLevels(PC pc,PetscInt levels,MPI_Comm *comms) { PetscErrorCode ierr; PC_MG *mg = (PC_MG*)pc->data; MPI_Comm comm; PC_MG_Levels **mglevels = mg->levels; PCMGType mgtype = mg->am; PetscInt mgctype = (PetscInt) PC_MG_CYCLE_V; PetscInt i; PetscMPIInt size; const char *prefix; PC ipc; PetscInt n; PetscFunctionBegin; PetscValidHeaderSpecific(pc,PC_CLASSID,1); PetscValidLogicalCollectiveInt(pc,levels,2); ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); if (mg->nlevels == levels) PetscFunctionReturn(0); if (mglevels) { mgctype = mglevels[0]->cycles; /* changing the number of levels so free up the previous stuff */ ierr = PCReset_MG(pc);CHKERRQ(ierr); n = mglevels[0]->levels; for (i=0; i<n; i++) { if (mglevels[i]->smoothd != mglevels[i]->smoothu) { ierr = KSPDestroy(&mglevels[i]->smoothd);CHKERRQ(ierr); } ierr = KSPDestroy(&mglevels[i]->smoothu);CHKERRQ(ierr); ierr = PetscFree(mglevels[i]);CHKERRQ(ierr); } ierr = PetscFree(mg->levels);CHKERRQ(ierr); } mg->nlevels = levels; ierr = PetscMalloc1(levels,&mglevels);CHKERRQ(ierr); ierr = PetscLogObjectMemory((PetscObject)pc,levels*(sizeof(PC_MG*)));CHKERRQ(ierr); ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); mg->stageApply = 0; for (i=0; i<levels; i++) { ierr = PetscNewLog(pc,&mglevels[i]);CHKERRQ(ierr); mglevels[i]->level = i; mglevels[i]->levels = levels; mglevels[i]->cycles = mgctype; mg->default_smoothu = 2; mg->default_smoothd = 2; mglevels[i]->eventsmoothsetup = 0; mglevels[i]->eventsmoothsolve = 0; mglevels[i]->eventresidual = 0; mglevels[i]->eventinterprestrict = 0; if (comms) comm = comms[i]; ierr = KSPCreate(comm,&mglevels[i]->smoothd);CHKERRQ(ierr); ierr = KSPSetErrorIfNotConverged(mglevels[i]->smoothd,pc->erroriffailure);CHKERRQ(ierr); ierr = PetscObjectIncrementTabLevel((PetscObject)mglevels[i]->smoothd,(PetscObject)pc,levels-i);CHKERRQ(ierr); ierr = KSPSetOptionsPrefix(mglevels[i]->smoothd,prefix);CHKERRQ(ierr); ierr = PetscObjectComposedDataSetInt((PetscObject) mglevels[i]->smoothd, PetscMGLevelId, mglevels[i]->level);CHKERRQ(ierr); if (i || levels == 1) { char tprefix[128]; ierr = KSPSetType(mglevels[i]->smoothd,KSPCHEBYSHEV);CHKERRQ(ierr); ierr = KSPSetConvergenceTest(mglevels[i]->smoothd,KSPConvergedSkip,NULL,NULL);CHKERRQ(ierr); ierr = KSPSetNormType(mglevels[i]->smoothd,KSP_NORM_NONE);CHKERRQ(ierr); ierr = KSPGetPC(mglevels[i]->smoothd,&ipc);CHKERRQ(ierr); ierr = PCSetType(ipc,PCSOR);CHKERRQ(ierr); ierr = KSPSetTolerances(mglevels[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT, mg->default_smoothd);CHKERRQ(ierr); sprintf(tprefix,"mg_levels_%d_",(int)i); ierr = KSPAppendOptionsPrefix(mglevels[i]->smoothd,tprefix);CHKERRQ(ierr); } else { ierr = KSPAppendOptionsPrefix(mglevels[0]->smoothd,"mg_coarse_");CHKERRQ(ierr); /* coarse solve is (redundant) LU by default; set shifttype NONZERO to avoid annoying zero-pivot in LU preconditioner */ ierr = KSPSetType(mglevels[0]->smoothd,KSPPREONLY);CHKERRQ(ierr); ierr = KSPGetPC(mglevels[0]->smoothd,&ipc);CHKERRQ(ierr); ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); if (size > 1) { ierr = PCSetType(ipc,PCREDUNDANT);CHKERRQ(ierr); } else { ierr = PCSetType(ipc,PCLU);CHKERRQ(ierr); } ierr = PCFactorSetShiftType(ipc,MAT_SHIFT_INBLOCKS);CHKERRQ(ierr); } ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mglevels[i]->smoothd);CHKERRQ(ierr); mglevels[i]->smoothu = mglevels[i]->smoothd; mg->rtol = 0.0; mg->abstol = 0.0; mg->dtol = 0.0; mg->ttol = 0.0; mg->cyclesperpcapply = 1; } mg->levels = mglevels; ierr = PCMGSetType(pc,mgtype);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C KSPView - Prints the KSP data structure. Collective on KSP Input Parameters: + ksp - the Krylov space context - viewer - visualization context Options Database Keys: . -ksp_view - print the ksp data structure at the end of a KSPSolve call Note: The available visualization contexts include + PETSC_VIEWER_STDOUT_SELF - standard output (default) - PETSC_VIEWER_STDOUT_WORLD - synchronized standard output where only the first processor opens the file. All other processors send their data to the first processor to print. The user can open an alternative visualization context with PetscViewerASCIIOpen() - output to a specified file. Level: beginner .keywords: KSP, view .seealso: PCView(), PetscViewerASCIIOpen() @*/ PetscErrorCode KSPView(KSP ksp,PetscViewer viewer) { PetscErrorCode ierr; PetscBool iascii,isbinary,isdraw; #if defined(PETSC_HAVE_SAWS) PetscBool issaws; #endif PetscFunctionBegin; PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); if (!viewer) { ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ksp),&viewer);CHKERRQ(ierr); } PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); PetscCheckSameComm(ksp,1,viewer,2); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); #if defined(PETSC_HAVE_SAWS) ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);CHKERRQ(ierr); #endif if (iascii) { ierr = PetscObjectPrintClassNamePrefixType((PetscObject)ksp,viewer);CHKERRQ(ierr); if (ksp->ops->view) { ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); ierr = (*ksp->ops->view)(ksp,viewer);CHKERRQ(ierr); ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); } if (ksp->guess_zero) { ierr = PetscViewerASCIIPrintf(viewer," maximum iterations=%D, initial guess is zero\n",ksp->max_it);CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer," maximum iterations=%D\n", ksp->max_it);CHKERRQ(ierr); } if (ksp->guess_knoll) {ierr = PetscViewerASCIIPrintf(viewer," using preconditioner applied to right hand side for initial guess\n");CHKERRQ(ierr);} ierr = PetscViewerASCIIPrintf(viewer," tolerances: relative=%g, absolute=%g, divergence=%g\n",(double)ksp->rtol,(double)ksp->abstol,(double)ksp->divtol);CHKERRQ(ierr); if (ksp->pc_side == PC_RIGHT) { ierr = PetscViewerASCIIPrintf(viewer," right preconditioning\n");CHKERRQ(ierr); } else if (ksp->pc_side == PC_SYMMETRIC) { ierr = PetscViewerASCIIPrintf(viewer," symmetric preconditioning\n");CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer," left preconditioning\n");CHKERRQ(ierr); } if (ksp->guess) {ierr = PetscViewerASCIIPrintf(viewer," using Fischers initial guess method %D with size %D\n",ksp->guess->method,ksp->guess->maxl);CHKERRQ(ierr);} if (ksp->dscale) {ierr = PetscViewerASCIIPrintf(viewer," diagonally scaled system\n");CHKERRQ(ierr);} if (!ksp->guess_zero) {ierr = PetscViewerASCIIPrintf(viewer," using nonzero initial guess\n");CHKERRQ(ierr);} ierr = PetscViewerASCIIPrintf(viewer," using %s norm type for convergence test\n",KSPNormTypes[ksp->normtype]);CHKERRQ(ierr); } else if (isbinary) { PetscInt classid = KSP_FILE_CLASSID; MPI_Comm comm; PetscMPIInt rank; char type[256]; ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); if (!rank) { ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); ierr = PetscStrncpy(type,((PetscObject)ksp)->type_name,256);CHKERRQ(ierr); ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); } if (ksp->ops->view) { ierr = (*ksp->ops->view)(ksp,viewer);CHKERRQ(ierr); } } else if (isdraw) { PetscDraw draw; char str[36]; PetscReal x,y,bottom,h; PetscBool flg; ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPREONLY,&flg);CHKERRQ(ierr); if (!flg) { ierr = PetscStrcpy(str,"KSP: ");CHKERRQ(ierr); ierr = PetscStrcat(str,((PetscObject)ksp)->type_name);CHKERRQ(ierr); ierr = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr); bottom = y - h; } else { bottom = y; } ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); #if defined(PETSC_HAVE_SAWS) } else if (issaws) { PetscMPIInt rank; const char *name; ierr = PetscObjectGetName((PetscObject)ksp,&name);CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); if (!((PetscObject)ksp)->amsmem && !rank) { char dir[1024]; ierr = PetscObjectViewSAWs((PetscObject)ksp,viewer);CHKERRQ(ierr); ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/its",name);CHKERRQ(ierr); PetscStackCallSAWs(SAWs_Register,(dir,&ksp->its,1,SAWs_READ,SAWs_INT)); if (!ksp->res_hist) { ierr = KSPSetResidualHistory(ksp,NULL,PETSC_DECIDE,PETSC_TRUE);CHKERRQ(ierr); } ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/res_hist",name);CHKERRQ(ierr); PetscStackCallSAWs(SAWs_Register,(dir,ksp->res_hist,10,SAWs_READ,SAWs_DOUBLE)); } #endif } else if (ksp->ops->view) { ierr = (*ksp->ops->view)(ksp,viewer);CHKERRQ(ierr); } if (!ksp->skippcsetfromoptions) { if (!ksp->pc) {ierr = KSPGetPC(ksp,&ksp->pc);CHKERRQ(ierr);} ierr = PCView(ksp->pc,viewer);CHKERRQ(ierr); } if (isdraw) { PetscDraw draw; ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); } PetscFunctionReturn(0); }
int main(int argc,char **argv) { KSP ksp; PC pc; Mat A,M; Vec X,B,D; MPI_Comm comm; PetscScalar v; KSPConvergedReason reason; PetscInt i,j,its; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscInitialize(&argc,&argv,0,0);CHKERRQ(ierr); ierr = PetscOptionsSetValue("-options_left",PETSC_NULL);CHKERRQ(ierr); comm = MPI_COMM_SELF; /* * Construct the Kershaw matrix * and a suitable rhs / initial guess */ ierr = MatCreateSeqAIJ(comm,4,4,4,0,&A);CHKERRQ(ierr); ierr = VecCreateSeq(comm,4,&B);CHKERRQ(ierr); ierr = VecDuplicate(B,&X);CHKERRQ(ierr); for (i=0; i<4; i++) { v=3; ierr = MatSetValues(A,1,&i,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); v=1; ierr = VecSetValues(B,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); ierr = VecSetValues(X,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); } i=0; v=0; ierr = VecSetValues(X,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); for (i=0; i<3; i++) { v=-2; j=i+1; ierr = MatSetValues(A,1,&i,1,&j,&v,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(A,1,&j,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); } i=0; j=3; v=2; ierr = MatSetValues(A,1,&i,1,&j,&v,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(A,1,&j,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecAssemblyBegin(B);CHKERRQ(ierr); ierr = VecAssemblyEnd(B);CHKERRQ(ierr); printf("\nThe Kershaw matrix:\n\n"); MatView(A,0); /* * A Conjugate Gradient method * with ILU(0) preconditioning */ ierr = KSPCreate(comm,&ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPCG);CHKERRQ(ierr); ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr); /* * ILU preconditioner; * The iterative method will break down unless you comment in the SetShift * line below, or use the -pc_factor_shift_positive_definite option. * Run the code twice: once as given to see the negative pivot and the * divergence behaviour, then comment in the Shift line, or add the * command line option, and see that the pivots are all positive and * the method converges. */ ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCICC);CHKERRQ(ierr); /* ierr = PCFactorSetShiftType(prec,MAT_SHIFT_POSITIVE_DEFINITE);CHKERRQ(ierr); */ ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = KSPSetUp(ksp);CHKERRQ(ierr); /* * Now that the factorisation is done, show the pivots; * note that the last one is negative. This in itself is not an error, * but it will make the iterative method diverge. */ ierr = PCFactorGetMatrix(pc,&M);CHKERRQ(ierr); ierr = VecDuplicate(B,&D);CHKERRQ(ierr); ierr = MatGetDiagonal(M,D);CHKERRQ(ierr); printf("\nPivots:\n\n"); VecView(D,0); /* * Solve the system; * without the shift this will diverge with * an indefinite preconditioner */ ierr = KSPSolve(ksp,B,X);CHKERRQ(ierr); ierr = KSPGetConvergedReason(ksp,&reason);CHKERRQ(ierr); if (reason==KSP_DIVERGED_INDEFINITE_PC) { printf("\nDivergence because of indefinite preconditioner;\n"); printf("Run the executable again but with -pc_factor_shift_positive_definite option.\n"); } else if (reason<0) { printf("\nOther kind of divergence: this should not happen.\n"); } else { ierr = KSPGetIterationNumber(ksp,&its);CHKERRQ(ierr); printf("\nConvergence in %d iterations.\n",(int)its); } printf("\n"); ierr = KSPDestroy(ksp);CHKERRQ(ierr); ierr = MatDestroy(A);CHKERRQ(ierr); ierr = VecDestroy(B);CHKERRQ(ierr); ierr = VecDestroy(X);CHKERRQ(ierr); ierr = VecDestroy(D);CHKERRQ(ierr); PetscFinalize(); PetscFunctionReturn(0); }
/*@ KSPSetFromOptions - Sets KSP options from the options database. This routine must be called before KSPSetUp() if the user is to be allowed to set the Krylov type. Collective on KSP Input Parameters: . ksp - the Krylov space context Options Database Keys: + -ksp_max_it - maximum number of linear iterations . -ksp_rtol rtol - relative tolerance used in default determination of convergence, i.e. if residual norm decreases by this factor than convergence is declared . -ksp_atol abstol - absolute tolerance used in default convergence test, i.e. if residual norm is less than this then convergence is declared . -ksp_divtol tol - if residual norm increases by this factor than divergence is declared . -ksp_converged_use_initial_residual_norm - see KSPConvergedDefaultSetUIRNorm() . -ksp_converged_use_min_initial_residual_norm - see KSPConvergedDefaultSetUMIRNorm() . -ksp_norm_type - none - skip norms used in convergence tests (useful only when not using convergence test (say you always want to run with 5 iterations) to save on communication overhead preconditioned - default for left preconditioning unpreconditioned - see KSPSetNormType() natural - see KSPSetNormType() . -ksp_check_norm_iteration it - do not compute residual norm until iteration number it (does compute at 0th iteration) works only for PCBCGS, PCIBCGS and and PCCG . -ksp_lag_norm - compute the norm of the residual for the ith iteration on the i+1 iteration; this means that one can use the norm of the residual for convergence test WITHOUT an extra MPI_Allreduce() limiting global synchronizations. This will require 1 more iteration of the solver than usual. . -ksp_fischer_guess <model,size> - uses the Fischer initial guess generator for repeated linear solves . -ksp_constant_null_space - assume the operator (matrix) has the constant vector in its null space . -ksp_test_null_space - tests the null space set with KSPSetNullSpace() to see if it truly is a null space . -ksp_knoll - compute initial guess by applying the preconditioner to the right hand side . -ksp_monitor_cancel - cancel all previous convergene monitor routines set . -ksp_monitor <optional filename> - print residual norm at each iteration . -ksp_monitor_lg_residualnorm - plot residual norm at each iteration . -ksp_monitor_solution - plot solution at each iteration - -ksp_monitor_singular_value - monitor extremem singular values at each iteration Notes: To see all options, run your program with the -help option or consult Users-Manual: ch_ksp Level: beginner .keywords: KSP, set, from, options, database .seealso: KSPSetUseFischerGuess() @*/ PetscErrorCode KSPSetFromOptions(KSP ksp) { PetscErrorCode ierr; PetscInt indx; const char *convtests[] = {"default","skip"}; char type[256], monfilename[PETSC_MAX_PATH_LEN]; PetscViewer monviewer; PetscBool flg,flag,reuse; PetscInt model[2]={0,0},nmax; KSPNormType normtype; PCSide pcside; void *ctx; PetscFunctionBegin; PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); if (!ksp->pc) {ierr = KSPGetPC(ksp,&ksp->pc);CHKERRQ(ierr);} ierr = PCSetFromOptions(ksp->pc);CHKERRQ(ierr); if (!KSPRegisterAllCalled) {ierr = KSPRegisterAll();CHKERRQ(ierr);} ierr = PetscObjectOptionsBegin((PetscObject)ksp);CHKERRQ(ierr); ierr = PetscOptionsFList("-ksp_type","Krylov method","KSPSetType",KSPList,(char*)(((PetscObject)ksp)->type_name ? ((PetscObject)ksp)->type_name : KSPGMRES),type,256,&flg);CHKERRQ(ierr); if (flg) { ierr = KSPSetType(ksp,type);CHKERRQ(ierr); } /* Set the type if it was never set. */ if (!((PetscObject)ksp)->type_name) { ierr = KSPSetType(ksp,KSPGMRES);CHKERRQ(ierr); } ierr = PetscOptionsInt("-ksp_max_it","Maximum number of iterations","KSPSetTolerances",ksp->max_it,&ksp->max_it,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-ksp_rtol","Relative decrease in residual norm","KSPSetTolerances",ksp->rtol,&ksp->rtol,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-ksp_atol","Absolute value of residual norm","KSPSetTolerances",ksp->abstol,&ksp->abstol,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-ksp_divtol","Residual norm increase cause divergence","KSPSetTolerances",ksp->divtol,&ksp->divtol,NULL);CHKERRQ(ierr); flag = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_converged_use_initial_residual_norm","Use initial residual residual norm for computing relative convergence","KSPConvergedDefaultSetUIRNorm",flag,&flag,NULL);CHKERRQ(ierr); if (flag) {ierr = KSPConvergedDefaultSetUIRNorm(ksp);CHKERRQ(ierr);} flag = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_converged_use_min_initial_residual_norm","Use minimum of initial residual norm and b for computing relative convergence","KSPConvergedDefaultSetUMIRNorm",flag,&flag,NULL);CHKERRQ(ierr); if (flag) {ierr = KSPConvergedDefaultSetUMIRNorm(ksp);CHKERRQ(ierr);} ierr = KSPGetInitialGuessNonzero(ksp,&flag);CHKERRQ(ierr); ierr = PetscOptionsBool("-ksp_initial_guess_nonzero","Use the contents of the solution vector for initial guess","KSPSetInitialNonzero",flag,&flag,&flg);CHKERRQ(ierr); if (flg) { ierr = KSPSetInitialGuessNonzero(ksp,flag);CHKERRQ(ierr); } ierr = PCGetReusePreconditioner(ksp->pc,&reuse);CHKERRQ(ierr); ierr = PetscOptionsBool("-ksp_reuse_preconditioner","Use initial preconditioner and don't ever compute a new one ","KSPReusePreconditioner",reuse,&reuse,NULL);CHKERRQ(ierr); ierr = KSPSetReusePreconditioner(ksp,reuse);CHKERRQ(ierr); ierr = PetscOptionsBool("-ksp_knoll","Use preconditioner applied to b for initial guess","KSPSetInitialGuessKnoll",ksp->guess_knoll,&ksp->guess_knoll,NULL);CHKERRQ(ierr); ierr = PetscOptionsBool("-ksp_error_if_not_converged","Generate error if solver does not converge","KSPSetErrorIfNotConverged",ksp->errorifnotconverged,&ksp->errorifnotconverged,NULL);CHKERRQ(ierr); nmax = 2; ierr = PetscOptionsIntArray("-ksp_fischer_guess","Use Paul Fischer's algorithm for initial guess","KSPSetUseFischerGuess",model,&nmax,&flag);CHKERRQ(ierr); if (flag) { if (nmax != 2) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_OUTOFRANGE,"Must pass in model,size as arguments"); ierr = KSPSetUseFischerGuess(ksp,model[0],model[1]);CHKERRQ(ierr); } ierr = PetscOptionsEList("-ksp_convergence_test","Convergence test","KSPSetConvergenceTest",convtests,2,"default",&indx,&flg);CHKERRQ(ierr); if (flg) { switch (indx) { case 0: ierr = KSPConvergedDefaultCreate(&ctx);CHKERRQ(ierr); ierr = KSPSetConvergenceTest(ksp,KSPConvergedDefault,ctx,KSPConvergedDefaultDestroy);CHKERRQ(ierr); break; case 1: ierr = KSPSetConvergenceTest(ksp,KSPConvergedSkip,NULL,NULL);CHKERRQ(ierr); break; } } ierr = KSPSetUpNorms_Private(ksp,&normtype,&pcside);CHKERRQ(ierr); ierr = PetscOptionsEnum("-ksp_norm_type","KSP Norm type","KSPSetNormType",KSPNormTypes,(PetscEnum)normtype,(PetscEnum*)&normtype,&flg);CHKERRQ(ierr); if (flg) { ierr = KSPSetNormType(ksp,normtype);CHKERRQ(ierr); } ierr = PetscOptionsInt("-ksp_check_norm_iteration","First iteration to compute residual norm","KSPSetCheckNormIteration",ksp->chknorm,&ksp->chknorm,NULL);CHKERRQ(ierr); flag = ksp->lagnorm; ierr = PetscOptionsBool("-ksp_lag_norm","Lag the calculation of the residual norm","KSPSetLagNorm",flag,&flag,&flg);CHKERRQ(ierr); if (flg) { ierr = KSPSetLagNorm(ksp,flag);CHKERRQ(ierr); } ierr = KSPGetDiagonalScale(ksp,&flag);CHKERRQ(ierr); ierr = PetscOptionsBool("-ksp_diagonal_scale","Diagonal scale matrix before building preconditioner","KSPSetDiagonalScale",flag,&flag,&flg);CHKERRQ(ierr); if (flg) { ierr = KSPSetDiagonalScale(ksp,flag);CHKERRQ(ierr); } ierr = KSPGetDiagonalScaleFix(ksp,&flag);CHKERRQ(ierr); ierr = PetscOptionsBool("-ksp_diagonal_scale_fix","Fix diagonally scaled matrix after solve","KSPSetDiagonalScaleFix",flag,&flag,&flg);CHKERRQ(ierr); if (flg) { ierr = KSPSetDiagonalScaleFix(ksp,flag);CHKERRQ(ierr); } flg = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_constant_null_space","Add constant null space to Krylov solver","KSPSetNullSpace",flg,&flg,NULL);CHKERRQ(ierr); if (flg) { MatNullSpace nsp; ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)ksp),PETSC_TRUE,0,0,&nsp);CHKERRQ(ierr); ierr = KSPSetNullSpace(ksp,nsp);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nsp);CHKERRQ(ierr); } /* option is actually checked in KSPSetUp(), just here so goes into help message */ if (ksp->nullsp) { ierr = PetscOptionsName("-ksp_test_null_space","Is provided null space correct","None",&flg);CHKERRQ(ierr); } /* Prints reason for convergence or divergence of each linear solve */ flg = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_converged_reason","Print reason for converged or diverged","KSPSolve",flg,&flg,NULL);CHKERRQ(ierr); if (flg) ksp->printreason = PETSC_TRUE; flg = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_monitor_cancel","Remove any hardwired monitor routines","KSPMonitorCancel",flg,&flg,NULL);CHKERRQ(ierr); /* -----------------------------------------------------------------------*/ /* Cancels all monitors hardwired into code before call to KSPSetFromOptions() */ if (flg) { ierr = KSPMonitorCancel(ksp);CHKERRQ(ierr); } /* Prints preconditioned residual norm at each iteration */ ierr = PetscOptionsString("-ksp_monitor","Monitor preconditioned residual norm","KSPMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr); if (flg) { ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ksp),monfilename,&monviewer);CHKERRQ(ierr); ierr = KSPMonitorSet(ksp,KSPMonitorDefault,monviewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); } /* Prints preconditioned residual norm at each iteration */ ierr = PetscOptionsString("-ksp_monitor_range","Monitor percent of residual entries more than 10 percent of max","KSPMonitorRange","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr); if (flg) { ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ksp),monfilename,&monviewer);CHKERRQ(ierr); ierr = KSPMonitorSet(ksp,KSPMonitorRange,monviewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); } ierr = PetscObjectTypeCompare((PetscObject)ksp->pc,PCKSP,&flg);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)ksp->pc,PCBJACOBI,&flag);CHKERRQ(ierr); if (flg || flag) { /* A hack for using dynamic tolerance in preconditioner */ ierr = PetscOptionsString("-sub_ksp_dynamic_tolerance","Use dynamic tolerance for PC if PC is a KSP","KSPMonitorDynamicTolerance","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr); if (flg) { KSPDynTolCtx *scale = NULL; PetscReal defaultv = 1.0; ierr = PetscMalloc1(1,&scale);CHKERRQ(ierr); scale->bnrm = -1.0; scale->coef = defaultv; ierr = PetscOptionsReal("-sub_ksp_dynamic_tolerance_param","Parameter of dynamic tolerance for inner PCKSP","KSPMonitorDynamicToleranceParam",defaultv,&(scale->coef),&flg);CHKERRQ(ierr); ierr = KSPMonitorSet(ksp,KSPMonitorDynamicTolerance,scale,KSPMonitorDynamicToleranceDestroy);CHKERRQ(ierr); } } /* Plots the vector solution */ flg = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_monitor_solution","Monitor solution graphically","KSPMonitorSet",flg,&flg,NULL);CHKERRQ(ierr); if (flg) { ierr = KSPMonitorSet(ksp,KSPMonitorSolution,NULL,NULL);CHKERRQ(ierr); } /* Prints preconditioned and true residual norm at each iteration */ ierr = PetscOptionsString("-ksp_monitor_true_residual","Monitor true residual norm","KSPMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr); if (flg) { ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ksp),monfilename,&monviewer);CHKERRQ(ierr); ierr = KSPMonitorSet(ksp,KSPMonitorTrueResidualNorm,monviewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); } /* Prints with max norm at each iteration */ ierr = PetscOptionsString("-ksp_monitor_max","Monitor true residual max norm","KSPMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr); if (flg) { ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ksp),monfilename,&monviewer);CHKERRQ(ierr); ierr = KSPMonitorSet(ksp,KSPMonitorTrueResidualMaxNorm,monviewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); } /* Prints extreme eigenvalue estimates at each iteration */ ierr = PetscOptionsString("-ksp_monitor_singular_value","Monitor singular values","KSPMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr); if (flg) { ierr = KSPSetComputeSingularValues(ksp,PETSC_TRUE);CHKERRQ(ierr); ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ksp),monfilename,&monviewer);CHKERRQ(ierr); ierr = KSPMonitorSet(ksp,KSPMonitorSingularValue,monviewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); } /* Prints preconditioned residual norm with fewer digits */ ierr = PetscOptionsString("-ksp_monitor_short","Monitor preconditioned residual norm with fewer digits","KSPMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr); if (flg) { ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ksp),monfilename,&monviewer);CHKERRQ(ierr); ierr = KSPMonitorSet(ksp,KSPMonitorDefaultShort,monviewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); } /* Calls Python function */ ierr = PetscOptionsString("-ksp_monitor_python","Use Python function","KSPMonitorSet",0,monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr); if (flg) {ierr = PetscPythonMonitorSet((PetscObject)ksp,monfilename);CHKERRQ(ierr);} /* Graphically plots preconditioned residual norm */ flg = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_monitor_lg_residualnorm","Monitor graphically preconditioned residual norm","KSPMonitorSet",flg,&flg,NULL);CHKERRQ(ierr); if (flg) { PetscDrawLG ctx; ierr = KSPMonitorLGResidualNormCreate(0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,&ctx);CHKERRQ(ierr); ierr = KSPMonitorSet(ksp,KSPMonitorLGResidualNorm,ctx,(PetscErrorCode (*)(void**))KSPMonitorLGResidualNormDestroy);CHKERRQ(ierr); } /* Graphically plots preconditioned and true residual norm */ flg = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_monitor_lg_true_residualnorm","Monitor graphically true residual norm","KSPMonitorSet",flg,&flg,NULL);CHKERRQ(ierr); if (flg) { PetscDrawLG ctx; ierr = KSPMonitorLGTrueResidualNormCreate(PetscObjectComm((PetscObject)ksp),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,&ctx);CHKERRQ(ierr); ierr = KSPMonitorSet(ksp,KSPMonitorLGTrueResidualNorm,ctx,(PetscErrorCode (*)(void**))KSPMonitorLGTrueResidualNormDestroy);CHKERRQ(ierr); } /* Graphically plots preconditioned residual norm and range of residual element values */ flg = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_monitor_lg_range","Monitor graphically range of preconditioned residual norm","KSPMonitorSet",flg,&flg,NULL);CHKERRQ(ierr); if (flg) { PetscViewer ctx; ierr = PetscViewerDrawOpen(PetscObjectComm((PetscObject)ksp),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,&ctx);CHKERRQ(ierr); ierr = KSPMonitorSet(ksp,KSPMonitorLGRange,ctx,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); } #if defined(PETSC_HAVE_SAWS) /* Publish convergence information using AMS */ flg = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_monitor_saws","Publish KSP progress using SAWs","KSPMonitorSet",flg,&flg,NULL);CHKERRQ(ierr); if (flg) { void *ctx; ierr = KSPMonitorSAWsCreate(ksp,&ctx);CHKERRQ(ierr); ierr = KSPMonitorSet(ksp,KSPMonitorSAWs,ctx,KSPMonitorSAWsDestroy);CHKERRQ(ierr); ierr = KSPSetComputeSingularValues(ksp,PETSC_TRUE);CHKERRQ(ierr); } #endif /* -----------------------------------------------------------------------*/ ierr = KSPSetUpNorms_Private(ksp,&normtype,&pcside);CHKERRQ(ierr); ierr = PetscOptionsEnum("-ksp_pc_side","KSP preconditioner side","KSPSetPCSide",PCSides,(PetscEnum)pcside,(PetscEnum*)&pcside,&flg);CHKERRQ(ierr); if (flg) {ierr = KSPSetPCSide(ksp,pcside);CHKERRQ(ierr);} flg = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_compute_singularvalues","Compute singular values of preconditioned operator","KSPSetComputeSingularValues",flg,&flg,NULL);CHKERRQ(ierr); if (flg) { ierr = KSPSetComputeSingularValues(ksp,PETSC_TRUE);CHKERRQ(ierr); } flg = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_compute_eigenvalues","Compute eigenvalues of preconditioned operator","KSPSetComputeSingularValues",flg,&flg,NULL);CHKERRQ(ierr); if (flg) { ierr = KSPSetComputeSingularValues(ksp,PETSC_TRUE);CHKERRQ(ierr); } flg = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_plot_eigenvalues","Scatter plot extreme eigenvalues","KSPSetComputeSingularValues",flg,&flg,NULL);CHKERRQ(ierr); if (flg) { ierr = KSPSetComputeSingularValues(ksp,PETSC_TRUE);CHKERRQ(ierr); } #if defined(PETSC_HAVE_SAWS) { PetscBool set; flg = PETSC_FALSE; ierr = PetscOptionsBool("-ksp_saws_block","Block for SAWs at end of KSPSolve","PetscObjectSAWsBlock",((PetscObject)ksp)->amspublishblock,&flg,&set);CHKERRQ(ierr); if (set) { ierr = PetscObjectSAWsSetBlock((PetscObject)ksp,flg);CHKERRQ(ierr); } } #endif if (ksp->ops->setfromoptions) { ierr = (*ksp->ops->setfromoptions)(ksp);CHKERRQ(ierr); } /* process any options handlers added with PetscObjectAddOptionsHandler() */ ierr = PetscObjectProcessOptionsHandlers((PetscObject)ksp);CHKERRQ(ierr); ierr = PetscOptionsEnd();CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode port_lsd_bfbt(void) { Mat A; Vec x,b; KSP ksp_A; PC pc_A; IS isu,isp; PetscErrorCode ierr; PetscFunctionBeginUser; ierr = LoadTestMatrices(&A,&x,&b,&isu,&isp);CHKERRQ(ierr); ierr = KSPCreate(PETSC_COMM_WORLD,&ksp_A);CHKERRQ(ierr); ierr = KSPSetOptionsPrefix(ksp_A,"fc_");CHKERRQ(ierr); ierr = KSPSetOperators(ksp_A,A,A,SAME_NONZERO_PATTERN);CHKERRQ(ierr); ierr = KSPGetPC(ksp_A,&pc_A);CHKERRQ(ierr); ierr = PCSetType(pc_A,PCFIELDSPLIT);CHKERRQ(ierr); ierr = PCFieldSplitSetBlockSize(pc_A,2);CHKERRQ(ierr); ierr = PCFieldSplitSetIS(pc_A,"velocity",isu);CHKERRQ(ierr); ierr = PCFieldSplitSetIS(pc_A,"pressure",isp);CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp_A);CHKERRQ(ierr); ierr = KSPSolve(ksp_A,b,x);CHKERRQ(ierr); /* Pull u,p out of x */ { PetscInt loc; PetscReal max,norm; PetscScalar sum; Vec uvec,pvec; VecScatter uscat,pscat; Mat A11,A22; /* grab matrices and create the compatable u,p vectors */ ierr = MatGetSubMatrix(A,isu,isu,MAT_INITIAL_MATRIX,&A11);CHKERRQ(ierr); ierr = MatGetSubMatrix(A,isp,isp,MAT_INITIAL_MATRIX,&A22);CHKERRQ(ierr); ierr = MatGetVecs(A11,&uvec,PETSC_NULL);CHKERRQ(ierr); ierr = MatGetVecs(A22,&pvec,PETSC_NULL);CHKERRQ(ierr); /* perform the scatter from x -> (u,p) */ ierr = VecScatterCreate(x,isu,uvec,PETSC_NULL,&uscat);CHKERRQ(ierr); ierr = VecScatterBegin(uscat,x,uvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(uscat,x,uvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterCreate(x,isp,pvec,PETSC_NULL,&pscat);CHKERRQ(ierr); ierr = VecScatterBegin(pscat,x,pvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(pscat,x,pvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); PetscPrintf(PETSC_COMM_WORLD,"-- vector vector values --\n"); ierr = VecMin(uvec,&loc,&max);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Min(u) = %1.6F [loc=%d]\n",max,loc);CHKERRQ(ierr); ierr = VecMax(uvec,&loc,&max);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Max(u) = %1.6F [loc=%d]\n",max,loc);CHKERRQ(ierr); ierr = VecNorm(uvec,NORM_2,&norm);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Norm(u) = %1.6F \n",norm);CHKERRQ(ierr); ierr = VecSum(uvec,&sum);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Sum(u) = %1.6F \n",PetscRealPart(sum));CHKERRQ(ierr); PetscPrintf(PETSC_COMM_WORLD,"-- pressure vector values --\n"); ierr = VecMin(pvec,&loc,&max);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Min(p) = %1.6F [loc=%d]\n",max,loc);CHKERRQ(ierr); ierr = VecMax(pvec,&loc,&max);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Max(p) = %1.6F [loc=%d]\n",max,loc);CHKERRQ(ierr); ierr = VecNorm(pvec,NORM_2,&norm);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Norm(p) = %1.6F \n",norm);CHKERRQ(ierr); ierr = VecSum(pvec,&sum);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Sum(p) = %1.6F \n",PetscRealPart(sum));CHKERRQ(ierr); PetscPrintf(PETSC_COMM_WORLD,"-- Full vector values --\n"); ierr = VecMin(x,&loc,&max);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Min(u,p) = %1.6F [loc=%d]\n",max,loc);CHKERRQ(ierr); ierr = VecMax(x,&loc,&max);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Max(u,p) = %1.6F [loc=%d]\n",max,loc);CHKERRQ(ierr); ierr = VecNorm(x,NORM_2,&norm);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Norm(u,p) = %1.6F \n",norm);CHKERRQ(ierr); ierr = VecSum(x,&sum);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Sum(u,p) = %1.6F \n",PetscRealPart(sum));CHKERRQ(ierr); ierr = VecScatterDestroy(&uscat);CHKERRQ(ierr); ierr = VecScatterDestroy(&pscat);CHKERRQ(ierr); ierr = VecDestroy(&uvec);CHKERRQ(ierr); ierr = VecDestroy(&pvec);CHKERRQ(ierr); ierr = MatDestroy(&A11);CHKERRQ(ierr); ierr = MatDestroy(&A22);CHKERRQ(ierr); } ierr = KSPDestroy(&ksp_A);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = ISDestroy(&isu);CHKERRQ(ierr); ierr = ISDestroy(&isp);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode KSPSolve_FBCGSR(KSP ksp) { PetscErrorCode ierr; PetscInt i,j,N; PetscScalar tau,sigma,alpha,omega,beta; PetscReal rho; PetscScalar xi1,xi2,xi3,xi4; Vec X,B,P,P2,RP,R,V,S,T,S2; PetscScalar *PETSC_RESTRICT rp, *PETSC_RESTRICT r, *PETSC_RESTRICT p; PetscScalar *PETSC_RESTRICT v, *PETSC_RESTRICT s, *PETSC_RESTRICT t, *PETSC_RESTRICT s2; PetscScalar insums[4],outsums[4]; KSP_BCGS *bcgs = (KSP_BCGS*)ksp->data; PC pc; Mat mat; PetscFunctionBegin; if (!ksp->vec_rhs->petscnative) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Only coded for PETSc vectors"); ierr = VecGetLocalSize(ksp->vec_sol,&N);CHKERRQ(ierr); X = ksp->vec_sol; B = ksp->vec_rhs; P2 = ksp->work[0]; /* The followings are involved in modified inner product calculations and vector updates */ RP = ksp->work[1]; ierr = VecGetArray(RP,(PetscScalar**)&rp);CHKERRQ(ierr); ierr = VecRestoreArray(RP,NULL);CHKERRQ(ierr); R = ksp->work[2]; ierr = VecGetArray(R,(PetscScalar**)&r);CHKERRQ(ierr); ierr = VecRestoreArray(R,NULL);CHKERRQ(ierr); P = ksp->work[3]; ierr = VecGetArray(P,(PetscScalar**)&p);CHKERRQ(ierr); ierr = VecRestoreArray(P,NULL);CHKERRQ(ierr); V = ksp->work[4]; ierr = VecGetArray(V,(PetscScalar**)&v);CHKERRQ(ierr); ierr = VecRestoreArray(V,NULL);CHKERRQ(ierr); S = ksp->work[5]; ierr = VecGetArray(S,(PetscScalar**)&s);CHKERRQ(ierr); ierr = VecRestoreArray(S,NULL);CHKERRQ(ierr); T = ksp->work[6]; ierr = VecGetArray(T,(PetscScalar**)&t);CHKERRQ(ierr); ierr = VecRestoreArray(T,NULL);CHKERRQ(ierr); S2 = ksp->work[7]; ierr = VecGetArray(S2,(PetscScalar**)&s2);CHKERRQ(ierr); ierr = VecRestoreArray(S2,NULL);CHKERRQ(ierr); /* Only supports right preconditioning */ if (ksp->pc_side != PC_RIGHT) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"KSP fbcgsr does not support %s",PCSides[ksp->pc_side]); if (!ksp->guess_zero) { if (!bcgs->guess) { ierr = VecDuplicate(X,&bcgs->guess);CHKERRQ(ierr); } ierr = VecCopy(X,bcgs->guess);CHKERRQ(ierr); } else { ierr = VecSet(X,0.0);CHKERRQ(ierr); } /* Compute initial residual */ ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetUp(pc);CHKERRQ(ierr); ierr = PCGetOperators(pc,&mat,NULL);CHKERRQ(ierr); if (!ksp->guess_zero) { ierr = KSP_MatMult(ksp,mat,X,P2);CHKERRQ(ierr); /* P2 is used as temporary storage */ ierr = VecCopy(B,R);CHKERRQ(ierr); ierr = VecAXPY(R,-1.0,P2);CHKERRQ(ierr); } else { ierr = VecCopy(B,R);CHKERRQ(ierr); } /* Test for nothing to do */ ierr = VecNorm(R,NORM_2,&rho);CHKERRQ(ierr); ierr = PetscObjectSAWsTakeAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->its = 0; ksp->rnorm = rho; ierr = PetscObjectSAWsGrantAccess((PetscObject)ksp);CHKERRQ(ierr); ierr = KSPLogResidualHistory(ksp,rho);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,rho);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,0,rho,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) PetscFunctionReturn(0); /* Initialize iterates */ ierr = VecCopy(R,RP);CHKERRQ(ierr); /* rp <- r */ ierr = VecCopy(R,P);CHKERRQ(ierr); /* p <- r */ /* Big loop */ for (i=0; i<ksp->max_it; i++) { /* matmult and pc */ ierr = KSP_PCApply(ksp,P,P2);CHKERRQ(ierr); /* p2 <- K p */ ierr = KSP_MatMult(ksp,mat,P2,V);CHKERRQ(ierr); /* v <- A p2 */ /* inner prodcuts */ if (i==0) { tau = rho*rho; ierr = VecDot(V,RP,&sigma);CHKERRQ(ierr); /* sigma <- (v,rp) */ } else { ierr = PetscLogEventBegin(VEC_ReduceArithmetic,0,0,0,0);CHKERRQ(ierr); tau = sigma = 0.0; for (j=0; j<N; j++) { tau += r[j]*rp[j]; /* tau <- (r,rp) */ sigma += v[j]*rp[j]; /* sigma <- (v,rp) */ } ierr = PetscLogFlops(4.0*N);CHKERRQ(ierr); ierr = PetscLogEventEnd(VEC_ReduceArithmetic,0,0,0,0);CHKERRQ(ierr); insums[0] = tau; insums[1] = sigma; ierr = PetscLogEventBegin(VEC_ReduceCommunication,0,0,0,0);CHKERRQ(ierr); ierr = MPIU_Allreduce(insums,outsums,2,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)ksp));CHKERRQ(ierr); ierr = PetscLogEventEnd(VEC_ReduceCommunication,0,0,0,0);CHKERRQ(ierr); tau = outsums[0]; sigma = outsums[1]; } /* scalar update */ alpha = tau / sigma; /* vector update */ ierr = VecWAXPY(S,-alpha,V,R);CHKERRQ(ierr); /* s <- r - alpha v */ /* matmult and pc */ ierr = KSP_PCApply(ksp,S,S2);CHKERRQ(ierr); /* s2 <- K s */ ierr = KSP_MatMult(ksp,mat,S2,T);CHKERRQ(ierr); /* t <- A s2 */ /* inner prodcuts */ ierr = PetscLogEventBegin(VEC_ReduceArithmetic,0,0,0,0);CHKERRQ(ierr); xi1 = xi2 = xi3 = xi4 = 0.0; for (j=0; j<N; j++) { xi1 += s[j]*s[j]; /* xi1 <- (s,s) */ xi2 += t[j]*s[j]; /* xi2 <- (t,s) */ xi3 += t[j]*t[j]; /* xi3 <- (t,t) */ xi4 += t[j]*rp[j]; /* xi4 <- (t,rp) */ } ierr = PetscLogFlops(8.0*N);CHKERRQ(ierr); ierr = PetscLogEventEnd(VEC_ReduceArithmetic,0,0,0,0);CHKERRQ(ierr); insums[0] = xi1; insums[1] = xi2; insums[2] = xi3; insums[3] = xi4; ierr = PetscLogEventBegin(VEC_ReduceCommunication,0,0,0,0);CHKERRQ(ierr); ierr = MPIU_Allreduce(insums,outsums,4,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)ksp));CHKERRQ(ierr); ierr = PetscLogEventEnd(VEC_ReduceCommunication,0,0,0,0);CHKERRQ(ierr); xi1 = outsums[0]; xi2 = outsums[1]; xi3 = outsums[2]; xi4 = outsums[3]; /* test denominator */ if (xi3 == 0.0) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_PLIB,"Divide by zero"); if (sigma == 0.0) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_PLIB,"Divide by zero"); /* scalar updates */ omega = xi2 / xi3; beta = -xi4 / sigma; rho = PetscSqrtReal(PetscAbsScalar(xi1 - omega * xi2)); /* residual norm */ /* vector updates */ ierr = VecAXPBYPCZ(X,alpha,omega,1.0,P2,S2);CHKERRQ(ierr); /* x <- alpha * p2 + omega * s2 + x */ /* convergence test */ ierr = PetscObjectSAWsTakeAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->its++; ksp->rnorm = rho; ierr = PetscObjectSAWsGrantAccess((PetscObject)ksp);CHKERRQ(ierr); ierr = KSPLogResidualHistory(ksp,rho);CHKERRQ(ierr); ierr = KSPMonitor(ksp,i+1,rho);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,i+1,rho,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; /* vector updates */ ierr = PetscLogEventBegin(VEC_Ops,0,0,0,0);CHKERRQ(ierr); for (j=0; j<N; j++) { r[j] = s[j] - omega * t[j]; /* r <- s - omega t */ p[j] = r[j] + beta * (p[j] - omega * v[j]); /* p <- r + beta * (p - omega v) */ } ierr = PetscLogFlops(6.0*N);CHKERRQ(ierr); ierr = PetscLogEventEnd(VEC_Ops,0,0,0,0);CHKERRQ(ierr); } if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS; PetscFunctionReturn(0); }
int main(int argc,char **argv) { SNES snes; /* nonlinear solver context */ KSP ksp; /* linear solver context */ PC pc; /* preconditioner context */ Vec x,r; /* solution, residual vectors */ Mat J; /* Jacobian matrix */ PetscErrorCode ierr; PetscInt its; PetscMPIInt size; PetscScalar pfive = .5,*xx; PetscBool flg; PetscInitialize(&argc,&argv,(char*)0,help); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); if (size != 1) SETERRQ(PETSC_COMM_SELF,1,"This is a uniprocessor example only!"); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create nonlinear solver context - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create matrix and vector data structures; set corresponding routines - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Create vectors for solution and nonlinear function */ ierr = VecCreateSeq(PETSC_COMM_SELF,2,&x);CHKERRQ(ierr); ierr = VecDuplicate(x,&r);CHKERRQ(ierr); /* Create Jacobian matrix data structure */ ierr = MatCreate(PETSC_COMM_SELF,&J);CHKERRQ(ierr); ierr = MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,2,2);CHKERRQ(ierr); ierr = MatSetFromOptions(J);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-hard",&flg);CHKERRQ(ierr); if (!flg) { /* Set function evaluation routine and vector. */ ierr = SNESSetFunction(snes,r,FormFunction1,NULL);CHKERRQ(ierr); /* Set Jacobian matrix data structure and Jacobian evaluation routine */ ierr = SNESSetJacobian(snes,J,J,FormJacobian1,NULL);CHKERRQ(ierr); } else { ierr = SNESSetFunction(snes,r,FormFunction2,NULL);CHKERRQ(ierr); ierr = SNESSetJacobian(snes,J,J,FormJacobian2,NULL);CHKERRQ(ierr); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Customize nonlinear solver; set runtime options - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Set linear solver defaults for this problem. By extracting the KSP, KSP, and PC contexts from the SNES context, we can then directly call any KSP, KSP, and PC routines to set various options. */ ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr); ierr = KSPSetTolerances(ksp,1.e-4,PETSC_DEFAULT,PETSC_DEFAULT,20);CHKERRQ(ierr); /* Set SNES/KSP/KSP/PC runtime options, e.g., -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc> These options will override those specified above as long as SNESSetFromOptions() is called _after_ any other customization routines. */ ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Evaluate initial guess; then solve nonlinear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ if (!flg) { ierr = VecSet(x,pfive);CHKERRQ(ierr); } else { ierr = VecGetArray(x,&xx);CHKERRQ(ierr); xx[0] = 2.0; xx[1] = 3.0; ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); } /* Note: The user should initialize the vector, x, with the initial guess for the nonlinear solver prior to calling SNESSolve(). In particular, to employ an initial guess of zero, the user should explicitly set this vector to zero by calling VecSet(). */ ierr = SNESSolve(snes,NULL,x);CHKERRQ(ierr); ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); if (flg) { Vec f; ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = SNESGetFunction(snes,&f,0,0);CHKERRQ(ierr); ierr = VecView(r,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } ierr = PetscPrintf(PETSC_COMM_SELF,"number of SNES iterations = %D\n\n",its);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Free work space. All PETSc objects should be destroyed when they are no longer needed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&r);CHKERRQ(ierr); ierr = MatDestroy(&J);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
/** * Routine for solving a linear equation with PETSc. * * Note that this routine calls MPI teardown routines, so it should * not be called in the main process unless you want to break MPI for * the remainder of the process lifetime. * */ PetscErrorCode _solve_routine(JNIEnv *env, jint n, jintArray *index, jobjectArray *diagonals, jobjectArray *options, double *solution, jdoubleArray *rhs) { PetscErrorCode ierr; KSP ksp; PC pc; Mat A; Vec b; Vec x; PetscInitialize(0, NULL, (char*) NULL, NULL); // Set up matrix A in Ax = b int num_diags = (*env) -> GetArrayLength(env, *index); ierr = MatCreateSeqAIJ(PETSC_COMM_WORLD, n, n, num_diags, NULL, &A); CHKERRQ(ierr); ierr = MatSetUp(A); CHKERRQ(ierr); ierr = _fill_matrix(env, &A, index, diagonals); CHKERRQ(ierr); ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); // Set up vectors b and x in Ax = b ierr = VecCreate(PETSC_COMM_WORLD, &b); CHKERRQ(ierr); ierr = VecSetSizes(b, PETSC_DECIDE, n); CHKERRQ(ierr); ierr = VecSetType(b, VECSEQ); ierr = VecDuplicate(b, &x); ierr = _fill_vector(env, &b, rhs); CHKERRQ(ierr); ierr = VecAssemblyBegin(b); CHKERRQ(ierr); ierr = VecAssemblyEnd(b); CHKERRQ(ierr); // Set up solver ierr = KSPCreate(PETSC_COMM_WORLD, &ksp); CHKERRQ(ierr); ierr = KSPSetOperators(ksp, A, A); CHKERRQ(ierr); // Solver options ierr = KSPGetPC(ksp, &pc); CHKERRQ(ierr); for(int i = 0; i < (*env)->GetArrayLength(env, *options); i++) { jobject option = (*env)->GetObjectArrayElement(env, *options, i); jstring key = (*env)->GetObjectArrayElement(env, option, 0); jstring value = (*env)->GetObjectArrayElement(env, option, 1); const jchar *keyChars = (*env)->GetStringChars(env, key, NULL); const jchar *valChars = (*env)->GetStringChars(env, value, NULL); PetscOptionsSetValue((char*) keyChars, (char*) valChars); (*env)->ReleaseStringChars(env, key, keyChars); (*env)->ReleaseStringChars(env, value, valChars); } ierr = KSPSetFromOptions(ksp); CHKERRQ(ierr); ierr = KSPSetUp(ksp); CHKERRQ(ierr); // Solve ierr = KSPSolve(ksp, b, x); CHKERRQ(ierr); // Copy solution into JNI allocated memory ierr = _pvec_to_array(&x, solution); CHKERRQ(ierr); // Clean up and return ierr = MatDestroy(&A); CHKERRQ(ierr); ierr = VecDestroy(&b); CHKERRQ(ierr); ierr = VecDestroy(&x); CHKERRQ(ierr); ierr = KSPDestroy(&ksp); PetscFinalize(); return ierr; }
int main(int argc, char *argv[]) { // Initialize libMesh libMesh::LibMeshInit init(argc, argv); libMesh::Parallel::Communicator& WorldComm = init.comm(); libMesh::PetscMatrix<libMesh::Number> matrix_A(WorldComm); matrix_A.init(4,4,4,4); matrix_A.set(0,0,1.); // matrix_A.set(0,1,2.); // matrix_A.set(0,2,3.); // matrix_A.set(0,3,4.); // matrix_A.set(1,0,2.); matrix_A.set(1,1,5.); // matrix_A.set(1,2,3.); // matrix_A.set(1,3,7.); // matrix_A.set(2,0,3.); // matrix_A.set(2,1,3.); matrix_A.set(2,2,9.); // matrix_A.set(2,3,6.); // matrix_A.set(3,0,4.); // matrix_A.set(3,1,7.); // matrix_A.set(3,2,6.); matrix_A.set(3,3,1.); matrix_A.close(); Mat dummy_inv_A; MatCreate(PETSC_COMM_WORLD,&dummy_inv_A); MatSetType(dummy_inv_A,MATMPIAIJ); MatSetSizes(dummy_inv_A,PETSC_DECIDE,PETSC_DECIDE,4,4); MatMPIAIJSetPreallocation(dummy_inv_A,2,NULL,0,NULL); MatSetUp(dummy_inv_A); // Dummy matrices // Mat dummy_A, dummy_inv_A; // // libMesh::PetscVector<libMesh::Number> vector_unity(WorldComm,4,4); libMesh::PetscVector<libMesh::Number> vector_dummy_answer(WorldComm,4,4); VecSet(vector_unity.vec(),1); vector_unity.close(); VecSet(vector_dummy_answer.vec(),0); vector_dummy_answer.close(); // Solver // libMesh::PetscLinearSolver<libMesh::Number> KSP_dummy_solver(WorldComm); // KSP_dummy_solver.init(&matrix_A); // KSPSetOperators(KSP_dummy_solver.ksp(),matrix_A.mat(),NULL); KSP ksp; PC pc; KSPCreate(PETSC_COMM_WORLD,&ksp); KSPSetOperators(ksp, matrix_A.mat(), matrix_A.mat()); KSPGetPC(ksp,&pc); PCSetFromOptions(pc); PCType dummy_type; PCGetType(pc,&dummy_type); std::cout << std::endl << dummy_type << std::endl << std::endl; // PCSetType(pc,PCSPAI); // PCHYPRESetType(pc,"parasails"); KSPSetUp(ksp); KSPSolve(ksp,vector_unity.vec(),vector_dummy_answer.vec()); PCComputeExplicitOperator(pc,&dummy_inv_A); // KSPGetOperators(KSP_dummy_solver.ksp(),&dummy_A,&dummy_inv_A); libMesh::PetscMatrix<libMesh::Number> matrix_invA(dummy_inv_A,WorldComm); matrix_invA.close(); // // // KSP_dummy_solver.solve(matrix_A,vector_dummy_answer,vector_unity,1E-5,10000); // // vector_dummy_answer.print_matlab(); // // libMesh::PetscMatrix<libMesh::Number> product_mat(WorldComm); matrix_A.print_matlab(); matrix_invA.print_matlab(); vector_dummy_answer.print_matlab(); return 0; }
int main(int argc, char **argv){ PetscErrorCode ierr; int nx = 63, ny = 63; DM dm; PetscBool flg; Mat A; Vec u, b; KSP solver; PC pc; double norm; PetscInt stage; ierr = PetscInitialize(&argc, &argv, NULL, NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(PETSC_NULL, "-nx", &nx, PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(PETSC_NULL, "-ny", &ny, PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsHasName(PETSC_NULL, "-assemble", &flg);CHKERRQ(ierr); ierr = PetscLogStageRegister("preparing",&stage); CHKERRQ(ierr); ierr = PetscLogStagePush(stage);CHKERRQ(ierr); ierr = PetscLogStageRegister("Domain creation",&stage); CHKERRQ(ierr); ierr = PetscLogStagePush(stage);CHKERRQ(ierr); ierr = createDomain(&dm, nx, ny);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); ierr = PetscLogStageRegister("matrix creation",&stage); CHKERRQ(ierr); ierr = PetscLogStagePush(stage);CHKERRQ(ierr); ierr = createMat(dm, &A, flg);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); ierr = PetscLogStageRegister("Vector creation",&stage); CHKERRQ(ierr); ierr = PetscLogStagePush(stage);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); ierr = DMCreateGlobalVector(dm, &b);CHKERRQ(ierr); ierr = VecDuplicate(b, &u);CHKERRQ(ierr); ierr = PetscLogStageRegister("Domain initialisation",&stage); CHKERRQ(ierr); ierr = PetscLogStagePush(stage);CHKERRQ(ierr); ierr = init2d(dm, b);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); ierr = PetscLogStageRegister("solver creation",&stage); CHKERRQ(ierr); ierr = PetscLogStagePush(stage);CHKERRQ(ierr); ierr = KSPCreate(PETSC_COMM_WORLD, &solver);CHKERRQ(ierr); ierr = KSPSetOptionsPrefix(solver, "poisson_");CHKERRQ(ierr); ierr = KSPSetOperators(solver, A, A, DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = KSPSetType(solver, KSPCG); ierr = KSPGetPC(solver, &pc);CHKERRQ(ierr); ierr = PCSetType(pc, PCNONE);CHKERRQ(ierr); ierr = KSPSetFromOptions(solver);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); ierr = PetscLogStageRegister("Solving",&stage); CHKERRQ(ierr); ierr = PetscLogStagePush(stage);CHKERRQ(ierr); ierr = KSPSolve(solver, b, u);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); //ierr = VecView(u, PETSC_VIEWER_DRAW_WORLD);CHKERRQ(ierr); //sleep(10); VecDestroy(&u); VecDestroy(&b); MatDestroy(&A); DMDestroy(&dm); KSPDestroy(&solver); ierr = PetscFinalize(); return 0; }
int main(int argc,char **argv) { PetscErrorCode ierr; PetscInt time_steps=100,iout,NOUT=1; PetscMPIInt size; Vec global; PetscReal dt,ftime,ftime_original; TS ts; PetscViewer viewfile; Mat J = 0; Vec x; Data data; PetscInt mn; PetscBool flg; MatColoring mc; ISColoring iscoloring; MatFDColoring matfdcoloring = 0; PetscBool fd_jacobian_coloring = PETSC_FALSE; SNES snes; KSP ksp; PC pc; PetscViewer viewer; char pcinfo[120],tsinfo[120]; TSType tstype; PetscBool sundials; ierr = PetscInitialize(&argc,&argv,(char*)0,help);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); /* set data */ data.m = 9; data.n = 9; data.a = 1.0; data.epsilon = 0.1; data.dx = 1.0/(data.m+1.0); data.dy = 1.0/(data.n+1.0); mn = (data.m)*(data.n); ierr = PetscOptionsGetInt(NULL,"-time",&time_steps,NULL);CHKERRQ(ierr); /* set initial conditions */ ierr = VecCreate(PETSC_COMM_WORLD,&global);CHKERRQ(ierr); ierr = VecSetSizes(global,PETSC_DECIDE,mn);CHKERRQ(ierr); ierr = VecSetFromOptions(global);CHKERRQ(ierr); ierr = Initial(global,&data);CHKERRQ(ierr); ierr = VecDuplicate(global,&x);CHKERRQ(ierr); /* create timestep context */ ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr); ierr = TSMonitorSet(ts,Monitor,&data,NULL);CHKERRQ(ierr); #if defined(PETSC_HAVE_SUNDIALS) ierr = TSSetType(ts,TSSUNDIALS);CHKERRQ(ierr); #else ierr = TSSetType(ts,TSEULER);CHKERRQ(ierr); #endif dt = 0.1; ftime_original = data.tfinal = 1.0; ierr = TSSetInitialTimeStep(ts,0.0,dt);CHKERRQ(ierr); ierr = TSSetDuration(ts,time_steps,ftime_original);CHKERRQ(ierr); ierr = TSSetSolution(ts,global);CHKERRQ(ierr); /* set user provided RHSFunction and RHSJacobian */ ierr = TSSetRHSFunction(ts,NULL,RHSFunction,&data);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD,&J);CHKERRQ(ierr); ierr = MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,mn,mn);CHKERRQ(ierr); ierr = MatSetFromOptions(J);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(J,5,NULL);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(J,5,NULL,5,NULL);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-ts_fd",&flg);CHKERRQ(ierr); if (!flg) { ierr = TSSetRHSJacobian(ts,J,J,RHSJacobian,&data);CHKERRQ(ierr); } else { ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-fd_color",&fd_jacobian_coloring);CHKERRQ(ierr); if (fd_jacobian_coloring) { /* Use finite differences with coloring */ /* Get data structure of J */ PetscBool pc_diagonal; ierr = PetscOptionsHasName(NULL,"-pc_diagonal",&pc_diagonal);CHKERRQ(ierr); if (pc_diagonal) { /* the preconditioner of J is a diagonal matrix */ PetscInt rstart,rend,i; PetscScalar zero=0.0; ierr = MatGetOwnershipRange(J,&rstart,&rend);CHKERRQ(ierr); for (i=rstart; i<rend; i++) { ierr = MatSetValues(J,1,&i,1,&i,&zero,INSERT_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } else { /* Fill the structure using the expensive SNESComputeJacobianDefault. Temporarily set up the TS so we can call this function */ ierr = TSSetType(ts,TSBEULER);CHKERRQ(ierr); ierr = TSSetUp(ts);CHKERRQ(ierr); ierr = SNESComputeJacobianDefault(snes,x,J,J,ts);CHKERRQ(ierr); } /* create coloring context */ ierr = MatColoringCreate(J,&mc);CHKERRQ(ierr); ierr = MatColoringSetType(mc,MATCOLORINGSL);CHKERRQ(ierr); ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr); ierr = MatColoringApply(mc,&iscoloring);CHKERRQ(ierr); ierr = MatColoringDestroy(&mc);CHKERRQ(ierr); ierr = MatFDColoringCreate(J,iscoloring,&matfdcoloring);CHKERRQ(ierr); ierr = MatFDColoringSetFunction(matfdcoloring,(PetscErrorCode (*)(void))SNESTSFormFunction,ts);CHKERRQ(ierr); ierr = MatFDColoringSetFromOptions(matfdcoloring);CHKERRQ(ierr); ierr = MatFDColoringSetUp(J,iscoloring,matfdcoloring);CHKERRQ(ierr); ierr = SNESSetJacobian(snes,J,J,SNESComputeJacobianDefaultColor,matfdcoloring);CHKERRQ(ierr); ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr); } else { /* Use finite differences (slow) */ ierr = SNESSetJacobian(snes,J,J,SNESComputeJacobianDefault,NULL);CHKERRQ(ierr); } } /* Pick up a Petsc preconditioner */ /* one can always set method or preconditioner during the run time */ ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCJACOBI);CHKERRQ(ierr); ierr = TSSetFromOptions(ts);CHKERRQ(ierr); ierr = TSSetUp(ts);CHKERRQ(ierr); /* Test TSSetPostStep() */ ierr = PetscOptionsHasName(NULL,"-test_PostStep",&flg);CHKERRQ(ierr); if (flg) { ierr = TSSetPostStep(ts,PostStep);CHKERRQ(ierr); } ierr = PetscOptionsGetInt(NULL,"-NOUT",&NOUT,NULL);CHKERRQ(ierr); for (iout=1; iout<=NOUT; iout++) { ierr = TSSetDuration(ts,time_steps,iout*ftime_original/NOUT);CHKERRQ(ierr); ierr = TSSolve(ts,global);CHKERRQ(ierr); ierr = TSGetSolveTime(ts,&ftime);CHKERRQ(ierr); ierr = TSSetInitialTimeStep(ts,ftime,dt);CHKERRQ(ierr); } /* Interpolate solution at tfinal */ ierr = TSGetSolution(ts,&global);CHKERRQ(ierr); ierr = TSInterpolate(ts,ftime_original,global);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-matlab_view",&flg);CHKERRQ(ierr); if (flg) { /* print solution into a MATLAB file */ ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,"out.m",&viewfile);CHKERRQ(ierr); ierr = PetscViewerSetFormat(viewfile,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr); ierr = VecView(global,viewfile);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewfile);CHKERRQ(ierr); } /* display solver info for Sundials */ ierr = TSGetType(ts,&tstype);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)ts,TSSUNDIALS,&sundials);CHKERRQ(ierr); if (sundials) { ierr = PetscViewerStringOpen(PETSC_COMM_WORLD,tsinfo,120,&viewer);CHKERRQ(ierr); ierr = TSView(ts,viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); ierr = PetscViewerStringOpen(PETSC_COMM_WORLD,pcinfo,120,&viewer);CHKERRQ(ierr); ierr = PCView(pc,viewer);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"%d Procs,%s TSType, %s Preconditioner\n",size,tsinfo,pcinfo);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } /* free the memories */ ierr = TSDestroy(&ts);CHKERRQ(ierr); ierr = VecDestroy(&global);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = MatDestroy(&J);CHKERRQ(ierr); if (fd_jacobian_coloring) {ierr = MatFDColoringDestroy(&matfdcoloring);CHKERRQ(ierr);} ierr = PetscFinalize(); return 0; }
int main(int argc,char **args) { KSP ksp; PC pc; Mat A; Vec u, x, b; PetscReal error; PetscMPIInt rank, size, sized; PetscInt M = 8, N = 8, m, n, rstart, rend, r; PetscBool userSubdomains = PETSC_FALSE; PetscErrorCode ierr; ierr = PetscInitialize(&argc, &args, NULL,help);if (ierr) return ierr; ierr = PetscOptionsGetInt(NULL,NULL, "-M", &M, NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,NULL, "-N", &N, NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,NULL, "-user_subdomains", &userSubdomains, NULL);CHKERRQ(ierr); /* Do parallel decomposition */ ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size);CHKERRQ(ierr); sized = (PetscMPIInt) PetscSqrtReal((PetscReal) size); if (PetscSqr(sized) != size) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "This test may only be run on a nubmer of processes which is a perfect square, not %d", (int) size); if (M % sized) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "The number of x-vertices %D does not divide the number of x-processes %d", M, (int) sized); if (N % sized) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "The number of y-vertices %D does not divide the number of y-processes %d", N, (int) sized); /* Assemble the matrix for the five point stencil, YET AGAIN Every other process will be empty */ ierr = MatCreate(PETSC_COMM_WORLD, &A);CHKERRQ(ierr); m = (sized > 1) ? (rank % 2) ? 0 : 2*M/sized : M; n = N/sized; ierr = MatSetSizes(A, m*n, m*n, M*N, M*N);CHKERRQ(ierr); ierr = MatSetFromOptions(A);CHKERRQ(ierr); ierr = MatSetUp(A);CHKERRQ(ierr); ierr = MatGetOwnershipRange(A, &rstart, &rend);CHKERRQ(ierr); for (r = rstart; r < rend; ++r) { const PetscScalar diag = 4.0, offdiag = -1.0; const PetscInt i = r/N; const PetscInt j = r - i*N; PetscInt c; if (i > 0) {c = r - n; ierr = MatSetValues(A, 1, &r, 1, &c, &offdiag, INSERT_VALUES);CHKERRQ(ierr);} if (i < M-1) {c = r + n; ierr = MatSetValues(A, 1, &r, 1, &c, &offdiag, INSERT_VALUES);CHKERRQ(ierr);} if (j > 0) {c = r - 1; ierr = MatSetValues(A, 1, &r, 1, &c, &offdiag, INSERT_VALUES);CHKERRQ(ierr);} if (j < N-1) {c = r + 1; ierr = MatSetValues(A, 1, &r, 1, &c, &offdiag, INSERT_VALUES);CHKERRQ(ierr);} ierr = MatSetValues(A, 1, &r, 1, &r, &diag, INSERT_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Setup Solve */ ierr = VecCreate(PETSC_COMM_WORLD, &b);CHKERRQ(ierr); ierr = VecSetSizes(b, m*n, PETSC_DETERMINE);CHKERRQ(ierr); ierr = VecSetFromOptions(b);CHKERRQ(ierr); ierr = VecDuplicate(b, &u);CHKERRQ(ierr); ierr = VecDuplicate(b, &x);CHKERRQ(ierr); ierr = VecSet(u, 1.0);CHKERRQ(ierr); ierr = MatMult(A, u, b);CHKERRQ(ierr); ierr = KSPCreate(PETSC_COMM_WORLD, &ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp, A, A);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PCSetType(pc, PCASM);CHKERRQ(ierr); /* Setup ASM by hand */ if (userSubdomains) { IS is; PetscInt *rows; /* Use no overlap for now */ ierr = PetscMalloc1(rend-rstart, &rows);CHKERRQ(ierr); for (r = rstart; r < rend; ++r) rows[r-rstart] = r; ierr = ISCreateGeneral(PETSC_COMM_SELF, rend-rstart, rows, PETSC_OWN_POINTER, &is);CHKERRQ(ierr); ierr = PCASMSetLocalSubdomains(pc, 1, &is, &is);CHKERRQ(ierr); ierr = ISDestroy(&is);CHKERRQ(ierr); } ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); /* Solve and Compare */ ierr = KSPSolve(ksp, b, x);CHKERRQ(ierr); ierr = VecAXPY(x, -1.0, u);CHKERRQ(ierr); ierr = VecNorm(x, NORM_INFINITY, &error);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Infinity norm of the error: %g\n", (double) error);CHKERRQ(ierr); /* Cleanup */ ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
krylov_petsc_info_t krylov_petsc_solve ( p4est_t* p4est, problem_data_t* vecs, weakeqn_ptrs_t* fcns, p4est_ghost_t** ghost, element_data_t** ghost_data, dgmath_jit_dbase_t* dgmath_jit_dbase, krylov_petsc_params_t* krylov_params ) { krylov_petsc_info_t info; KSP ksp; Vec x,b; PC pc; /* double* u_temp; */ /* double* rhs_temp; */ KSPCreate(PETSC_COMM_WORLD,&ksp); VecCreate(PETSC_COMM_WORLD,&x);//CHKERRQ(ierr); VecSetSizes(x, vecs->local_nodes, PETSC_DECIDE);//CHKERRQ(ierr); VecSetFromOptions(x);//CHKERRQ(ierr); VecDuplicate(x,&b);//CHKERRQ(ierr); /* VecGetArray(x,&u_temp); */ /* VecGetArray(b,&rhs_temp); */ krylov_pc_ctx_t kct; kct.p4est = p4est; kct.vecs = vecs; kct.fcns = fcns; kct.ghost = ghost; kct.ghost_data = ghost_data; kct.dgmath_jit_dbase = dgmath_jit_dbase; kct.pc_data = krylov_params->pc_data; if (krylov_params->ksp_monitor) PetscOptionsSetValue(NULL,"-ksp_monitor",""); if (krylov_params->ksp_monitor) PetscOptionsSetValue(NULL,"-ksp_view",""); /* KSPMonitorSet(ksp, KSPMonitorDefault, NULL, NULL); */ /* PetscOptionsSetValue(NULL,"-ksp_converged_reason",""); */ PetscOptionsSetValue(NULL,"-ksp_atol","1e-20"); /* PetscOptionsSetValue(NULL,"-with-debugging","1"); */ PetscOptionsSetValue(NULL,"-ksp_rtol","1e-20"); PetscOptionsSetValue(NULL,"-ksp_max_it","1000000"); KSPGetPC(ksp,&pc); krylov_pc_t* kp = NULL; if (krylov_params != NULL && krylov_params->user_defined_pc) { PCSetType(pc,PCSHELL);//CHKERRQ(ierr); kp = krylov_params->pc_create(&kct); PCShellSetApply(pc, krylov_petsc_pc_apply);//CHKERRQ(ierr); PCShellSetSetUp(pc, krylov_petsc_pc_setup); PCShellSetContext(pc, kp);//CHKERRQ(ierr); } else { PCSetType(pc,PCNONE);//CHKERRQ(ierr); } KSPSetType(ksp, krylov_params->krylov_type); KSPSetFromOptions(ksp); /* Create matrix-free shell for Aij */ Mat A; MatCreateShell ( PETSC_COMM_WORLD, vecs->local_nodes, vecs->local_nodes, PETSC_DETERMINE, PETSC_DETERMINE, (void*)&kct, &A ); MatShellSetOperation(A,MATOP_MULT,(void(*)())krylov_petsc_apply_aij); /* Set Amat and Pmat, where Pmat is the matrix the Preconditioner needs */ KSPSetOperators(ksp,A,A); /* linalg_copy_1st_to_2nd(vecs->u, u_temp, vecs->local_nodes); */ /* linalg_copy_1st_to_2nd(vecs->rhs, rhs_temp, vecs->local_nodes); */ VecPlaceArray(b, vecs->rhs); VecPlaceArray(x, vecs->u); KSPSolve(ksp,b,x); if (krylov_params != NULL && krylov_params->user_defined_pc) { krylov_params->pc_destroy(kp); } KSPGetIterationNumber(ksp, &(info.iterations)); KSPGetResidualNorm(ksp, &(info.residual_norm)); /* linalg_copy_1st_to_2nd(u_temp, vecs->u, vecs->local_nodes); */ /* VecRestoreArray(x,&u_temp); */ /* VecRestoreArray(b,&rhs_temp); */ VecResetArray(b); VecResetArray(x); VecDestroy(&x); VecDestroy(&b); KSPDestroy(&ksp); return info; }
EXTERN_C_BEGIN #undef __FUNCT__ #define __FUNCT__ "KSPCreate_SpecEst" /*MC KSPSPECEST - Estimate the spectrum on the first KSPSolve, then use cheaper smoother for subsequent solves. Options Database Keys: + -ksp_specest_minfactor <0.9> - Multiplier on the minimum eigen/singular value . -ksp_specest_maxfactor <1.1> - Multiplier on the maximum eigen/singular value . -ksp_specest_richfactor <1> - Multiplier on the richimum eigen/singular value . -specest_ksp_type <type> - KSP used to estimate the spectrum (usually CG or GMRES) . -speccheap_ksp_type <type> - KSP used as a cheap smoother once the spectrum has been estimated (usually Chebyshev or Richardson) - see KSPSolve() for more Notes: This KSP estimates the extremal singular values on the first pass, then uses them to configure a smoother that uses fewer dot products. It is intended for use on the levels of multigrid, especially at high process counts, where dot products are very expensive. The same PC is used for both the estimator and the cheap smoother, it is only set up once. There are no options keys for -specest_pc_ or speccheap_pc_ since it is the same object as -pc_. Level: intermediate .seealso: KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP, KSPGMRES, KSPCG, KSPCHEBYSHEV, KSPRICHARDSON M*/ PetscErrorCode KSPCreate_SpecEst(KSP ksp) { KSP_SpecEst *spec; PetscErrorCode ierr; PetscFunctionBegin; ierr = KSPSetSupportedNorm(ksp,KSP_NORM_PRECONDITIONED,PC_LEFT,2);CHKERRQ(ierr); ierr = KSPSetSupportedNorm(ksp,KSP_NORM_PRECONDITIONED,PC_RIGHT,1);CHKERRQ(ierr); ierr = KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_LEFT,1);CHKERRQ(ierr); ierr = KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_RIGHT,1);CHKERRQ(ierr); ierr = PetscNewLog(ksp,KSP_SpecEst,&spec);CHKERRQ(ierr); ksp->data = (void*)spec; ksp->ops->setup = KSPSetUp_SpecEst; ksp->ops->solve = KSPSolve_SpecEst; ksp->ops->destroy = KSPDestroy_SpecEst; ksp->ops->buildsolution = KSPDefaultBuildSolution; ksp->ops->buildresidual = KSPDefaultBuildResidual; ksp->ops->setfromoptions = KSPSetFromOptions_SpecEst; ksp->ops->view = KSPView_SpecEst; spec->minfactor = 0.9; spec->maxfactor = 1.1; spec->richfactor = 1.0; ierr = KSPCreate(((PetscObject)ksp)->comm,&spec->kspest);CHKERRQ(ierr); ierr = KSPCreate(((PetscObject)ksp)->comm,&spec->kspcheap);CHKERRQ(ierr); /* Hold an empty PC */ ierr = KSPGetPC(spec->kspest,&spec->pcnone);CHKERRQ(ierr); ierr = PetscObjectReference((PetscObject)spec->pcnone);CHKERRQ(ierr); ierr = PCSetType(spec->pcnone,PCNONE);CHKERRQ(ierr); ierr = KSPSetPC(spec->kspcheap,spec->pcnone);CHKERRQ(ierr); ierr = KSPSetTolerances(spec->kspest,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,5);CHKERRQ(ierr); /* Make the "cheap" preconditioner cheap by default */ ierr = KSPSetConvergenceTest(spec->kspcheap,KSPSkipConverged,0,0);CHKERRQ(ierr); ierr = KSPSetNormType(spec->kspcheap,KSP_NORM_NONE);CHKERRQ(ierr); ierr = KSPSetTolerances(spec->kspcheap,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,5);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode PCSetUp_MG(PC pc) { PC_MG *mg = (PC_MG*)pc->data; PC_MG_Levels **mglevels = mg->levels; PetscErrorCode ierr; PetscInt i,n = mglevels[0]->levels; PC cpc; PetscBool dump = PETSC_FALSE,opsset,use_amat,missinginterpolate = PETSC_FALSE; Mat dA,dB; Vec tvec; DM *dms; PetscViewer viewer = 0; PetscFunctionBegin; /* FIX: Move this to PCSetFromOptions_MG? */ if (mg->usedmfornumberoflevels) { PetscInt levels; ierr = DMGetRefineLevel(pc->dm,&levels);CHKERRQ(ierr); levels++; if (levels > n) { /* the problem is now being solved on a finer grid */ ierr = PCMGSetLevels(pc,levels,NULL);CHKERRQ(ierr); n = levels; ierr = PCSetFromOptions(pc);CHKERRQ(ierr); /* it is bad to call this here, but otherwise will never be called for the new hierarchy */ mglevels = mg->levels; } } ierr = KSPGetPC(mglevels[0]->smoothd,&cpc);CHKERRQ(ierr); /* If user did not provide fine grid operators OR operator was not updated since last global KSPSetOperators() */ /* so use those from global PC */ /* Is this what we always want? What if user wants to keep old one? */ ierr = KSPGetOperatorsSet(mglevels[n-1]->smoothd,NULL,&opsset);CHKERRQ(ierr); if (opsset) { Mat mmat; ierr = KSPGetOperators(mglevels[n-1]->smoothd,NULL,&mmat);CHKERRQ(ierr); if (mmat == pc->pmat) opsset = PETSC_FALSE; } if (!opsset) { ierr = PCGetUseAmat(pc,&use_amat);CHKERRQ(ierr); if(use_amat){ ierr = PetscInfo(pc,"Using outer operators to define finest grid operator \n because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n");CHKERRQ(ierr); ierr = KSPSetOperators(mglevels[n-1]->smoothd,pc->mat,pc->pmat);CHKERRQ(ierr); } else { ierr = PetscInfo(pc,"Using matrix (pmat) operators to define finest grid operator \n because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n");CHKERRQ(ierr); ierr = KSPSetOperators(mglevels[n-1]->smoothd,pc->pmat,pc->pmat);CHKERRQ(ierr); } } for (i=n-1; i>0; i--) { if (!(mglevels[i]->interpolate || mglevels[i]->restrct)) { missinginterpolate = PETSC_TRUE; continue; } } /* Skipping if user has provided all interpolation/restriction needed (since DM might not be able to produce them (when coming from SNES/TS) Skipping for galerkin==2 (externally managed hierarchy such as ML and GAMG). Cleaner logic here would be great. Wrap ML/GAMG as DMs? */ if (missinginterpolate && pc->dm && mg->galerkin != 2 && !pc->setupcalled) { /* construct the interpolation from the DMs */ Mat p; Vec rscale; ierr = PetscMalloc1(n,&dms);CHKERRQ(ierr); dms[n-1] = pc->dm; /* Separately create them so we do not get DMKSP interference between levels */ for (i=n-2; i>-1; i--) {ierr = DMCoarsen(dms[i+1],MPI_COMM_NULL,&dms[i]);CHKERRQ(ierr);} for (i=n-2; i>-1; i--) { DMKSP kdm; PetscBool dmhasrestrict; ierr = KSPSetDM(mglevels[i]->smoothd,dms[i]);CHKERRQ(ierr); if (mg->galerkin) {ierr = KSPSetDMActive(mglevels[i]->smoothd,PETSC_FALSE);CHKERRQ(ierr);} ierr = DMGetDMKSPWrite(dms[i],&kdm);CHKERRQ(ierr); /* Ugly hack so that the next KSPSetUp() will use the RHS that we set. A better fix is to change dmActive to take * a bitwise OR of computing the matrix, RHS, and initial iterate. */ kdm->ops->computerhs = NULL; kdm->rhsctx = NULL; if (!mglevels[i+1]->interpolate) { ierr = DMCreateInterpolation(dms[i],dms[i+1],&p,&rscale);CHKERRQ(ierr); ierr = PCMGSetInterpolation(pc,i+1,p);CHKERRQ(ierr); if (rscale) {ierr = PCMGSetRScale(pc,i+1,rscale);CHKERRQ(ierr);} ierr = VecDestroy(&rscale);CHKERRQ(ierr); ierr = MatDestroy(&p);CHKERRQ(ierr); } ierr = DMHasCreateRestriction(dms[i],&dmhasrestrict);CHKERRQ(ierr); if (dmhasrestrict && !mglevels[i+1]->restrct){ ierr = DMCreateRestriction(dms[i],dms[i+1],&p);CHKERRQ(ierr); ierr = PCMGSetRestriction(pc,i+1,p);CHKERRQ(ierr); ierr = MatDestroy(&p);CHKERRQ(ierr); } } for (i=n-2; i>-1; i--) {ierr = DMDestroy(&dms[i]);CHKERRQ(ierr);} ierr = PetscFree(dms);CHKERRQ(ierr); } if (pc->dm && !pc->setupcalled) { /* finest smoother also gets DM but it is not active, independent of whether galerkin==2 */ ierr = KSPSetDM(mglevels[n-1]->smoothd,pc->dm);CHKERRQ(ierr); ierr = KSPSetDMActive(mglevels[n-1]->smoothd,PETSC_FALSE);CHKERRQ(ierr); } if (mg->galerkin == 1) { Mat B; /* currently only handle case where mat and pmat are the same on coarser levels */ ierr = KSPGetOperators(mglevels[n-1]->smoothd,&dA,&dB);CHKERRQ(ierr); if (!pc->setupcalled) { for (i=n-2; i>-1; i--) { if (!mglevels[i+1]->restrct && !mglevels[i+1]->interpolate) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must provide interpolation or restriction for each MG level except level 0"); if (!mglevels[i+1]->interpolate) { ierr = PCMGSetInterpolation(pc,i+1,mglevels[i+1]->restrct);CHKERRQ(ierr); } if (!mglevels[i+1]->restrct) { ierr = PCMGSetRestriction(pc,i+1,mglevels[i+1]->interpolate);CHKERRQ(ierr); } if (mglevels[i+1]->interpolate == mglevels[i+1]->restrct) { ierr = MatPtAP(dB,mglevels[i+1]->interpolate,MAT_INITIAL_MATRIX,1.0,&B);CHKERRQ(ierr); } else { ierr = MatMatMatMult(mglevels[i+1]->restrct,dB,mglevels[i+1]->interpolate,MAT_INITIAL_MATRIX,1.0,&B);CHKERRQ(ierr); } ierr = KSPSetOperators(mglevels[i]->smoothd,B,B);CHKERRQ(ierr); if (i != n-2) {ierr = PetscObjectDereference((PetscObject)dB);CHKERRQ(ierr);} dB = B; } if (n > 1) {ierr = PetscObjectDereference((PetscObject)dB);CHKERRQ(ierr);} } else { for (i=n-2; i>-1; i--) { if (!mglevels[i+1]->restrct && !mglevels[i+1]->interpolate) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must provide interpolation or restriction for each MG level except level 0"); if (!mglevels[i+1]->interpolate) { ierr = PCMGSetInterpolation(pc,i+1,mglevels[i+1]->restrct);CHKERRQ(ierr); } if (!mglevels[i+1]->restrct) { ierr = PCMGSetRestriction(pc,i+1,mglevels[i+1]->interpolate);CHKERRQ(ierr); } ierr = KSPGetOperators(mglevels[i]->smoothd,NULL,&B);CHKERRQ(ierr); if (mglevels[i+1]->interpolate == mglevels[i+1]->restrct) { ierr = MatPtAP(dB,mglevels[i+1]->interpolate,MAT_REUSE_MATRIX,1.0,&B);CHKERRQ(ierr); } else { ierr = MatMatMatMult(mglevels[i+1]->restrct,dB,mglevels[i+1]->interpolate,MAT_REUSE_MATRIX,1.0,&B);CHKERRQ(ierr); } ierr = KSPSetOperators(mglevels[i]->smoothd,B,B);CHKERRQ(ierr); dB = B; } } } else if (!mg->galerkin && pc->dm && pc->dm->x) { /* need to restrict Jacobian location to coarser meshes for evaluation */ for (i=n-2; i>-1; i--) { Mat R; Vec rscale; if (!mglevels[i]->smoothd->dm->x) { Vec *vecs; ierr = KSPCreateVecs(mglevels[i]->smoothd,1,&vecs,0,NULL);CHKERRQ(ierr); mglevels[i]->smoothd->dm->x = vecs[0]; ierr = PetscFree(vecs);CHKERRQ(ierr); } ierr = PCMGGetRestriction(pc,i+1,&R);CHKERRQ(ierr); ierr = PCMGGetRScale(pc,i+1,&rscale);CHKERRQ(ierr); ierr = MatRestrict(R,mglevels[i+1]->smoothd->dm->x,mglevels[i]->smoothd->dm->x);CHKERRQ(ierr); ierr = VecPointwiseMult(mglevels[i]->smoothd->dm->x,mglevels[i]->smoothd->dm->x,rscale);CHKERRQ(ierr); } } if (!mg->galerkin && pc->dm) { for (i=n-2; i>=0; i--) { DM dmfine,dmcoarse; Mat Restrict,Inject; Vec rscale; ierr = KSPGetDM(mglevels[i+1]->smoothd,&dmfine);CHKERRQ(ierr); ierr = KSPGetDM(mglevels[i]->smoothd,&dmcoarse);CHKERRQ(ierr); ierr = PCMGGetRestriction(pc,i+1,&Restrict);CHKERRQ(ierr); ierr = PCMGGetRScale(pc,i+1,&rscale);CHKERRQ(ierr); Inject = NULL; /* Callback should create it if it needs Injection */ ierr = DMRestrict(dmfine,Restrict,rscale,Inject,dmcoarse);CHKERRQ(ierr); } } if (!pc->setupcalled) { for (i=0; i<n; i++) { ierr = KSPSetFromOptions(mglevels[i]->smoothd);CHKERRQ(ierr); } for (i=1; i<n; i++) { if (mglevels[i]->smoothu && (mglevels[i]->smoothu != mglevels[i]->smoothd)) { ierr = KSPSetFromOptions(mglevels[i]->smoothu);CHKERRQ(ierr); } } /* insure that if either interpolation or restriction is set the other other one is set */ for (i=1; i<n; i++) { ierr = PCMGGetInterpolation(pc,i,NULL);CHKERRQ(ierr); ierr = PCMGGetRestriction(pc,i,NULL);CHKERRQ(ierr); } for (i=0; i<n-1; i++) { if (!mglevels[i]->b) { Vec *vec; ierr = KSPCreateVecs(mglevels[i]->smoothd,1,&vec,0,NULL);CHKERRQ(ierr); ierr = PCMGSetRhs(pc,i,*vec);CHKERRQ(ierr); ierr = VecDestroy(vec);CHKERRQ(ierr); ierr = PetscFree(vec);CHKERRQ(ierr); } if (!mglevels[i]->r && i) { ierr = VecDuplicate(mglevels[i]->b,&tvec);CHKERRQ(ierr); ierr = PCMGSetR(pc,i,tvec);CHKERRQ(ierr); ierr = VecDestroy(&tvec);CHKERRQ(ierr); } if (!mglevels[i]->x) { ierr = VecDuplicate(mglevels[i]->b,&tvec);CHKERRQ(ierr); ierr = PCMGSetX(pc,i,tvec);CHKERRQ(ierr); ierr = VecDestroy(&tvec);CHKERRQ(ierr); } } if (n != 1 && !mglevels[n-1]->r) { /* PCMGSetR() on the finest level if user did not supply it */ Vec *vec; ierr = KSPCreateVecs(mglevels[n-1]->smoothd,1,&vec,0,NULL);CHKERRQ(ierr); ierr = PCMGSetR(pc,n-1,*vec);CHKERRQ(ierr); ierr = VecDestroy(vec);CHKERRQ(ierr); ierr = PetscFree(vec);CHKERRQ(ierr); } } if (pc->dm) { /* need to tell all the coarser levels to rebuild the matrix using the DM for that level */ for (i=0; i<n-1; i++) { if (mglevels[i]->smoothd->setupstage != KSP_SETUP_NEW) mglevels[i]->smoothd->setupstage = KSP_SETUP_NEWMATRIX; } } for (i=1; i<n; i++) { if (mglevels[i]->smoothu == mglevels[i]->smoothd || mg->am == PC_MG_FULL || mg->am == PC_MG_KASKADE || mg->cyclesperpcapply > 1){ /* if doing only down then initial guess is zero */ ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothd,PETSC_TRUE);CHKERRQ(ierr); } if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} ierr = KSPSetUp(mglevels[i]->smoothd);CHKERRQ(ierr); if (mglevels[i]->smoothd->reason == KSP_DIVERGED_PCSETUP_FAILED) { pc->failedreason = PC_SUBPC_ERROR; } if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} if (!mglevels[i]->residual) { Mat mat; ierr = KSPGetOperators(mglevels[i]->smoothd,NULL,&mat);CHKERRQ(ierr); ierr = PCMGSetResidual(pc,i,PCMGResidualDefault,mat);CHKERRQ(ierr); } } for (i=1; i<n; i++) { if (mglevels[i]->smoothu && mglevels[i]->smoothu != mglevels[i]->smoothd) { Mat downmat,downpmat; /* check if operators have been set for up, if not use down operators to set them */ ierr = KSPGetOperatorsSet(mglevels[i]->smoothu,&opsset,NULL);CHKERRQ(ierr); if (!opsset) { ierr = KSPGetOperators(mglevels[i]->smoothd,&downmat,&downpmat);CHKERRQ(ierr); ierr = KSPSetOperators(mglevels[i]->smoothu,downmat,downpmat);CHKERRQ(ierr); } ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothu,PETSC_TRUE);CHKERRQ(ierr); if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} ierr = KSPSetUp(mglevels[i]->smoothu);CHKERRQ(ierr); if (mglevels[i]->smoothu->reason == KSP_DIVERGED_PCSETUP_FAILED) { pc->failedreason = PC_SUBPC_ERROR; } if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} } } if (mglevels[0]->eventsmoothsetup) {ierr = PetscLogEventBegin(mglevels[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} ierr = KSPSetUp(mglevels[0]->smoothd);CHKERRQ(ierr); if (mglevels[0]->smoothd->reason == KSP_DIVERGED_PCSETUP_FAILED) { pc->failedreason = PC_SUBPC_ERROR; } if (mglevels[0]->eventsmoothsetup) {ierr = PetscLogEventEnd(mglevels[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} /* Dump the interpolation/restriction matrices plus the Jacobian/stiffness on each level. This allows MATLAB users to easily check if the Galerkin condition A_c = R A_f R^T is satisfied. Only support one or the other at the same time. */ #if defined(PETSC_USE_SOCKET_VIEWER) ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_mg_dump_matlab",&dump,NULL);CHKERRQ(ierr); if (dump) viewer = PETSC_VIEWER_SOCKET_(PetscObjectComm((PetscObject)pc)); dump = PETSC_FALSE; #endif ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_mg_dump_binary",&dump,NULL);CHKERRQ(ierr); if (dump) viewer = PETSC_VIEWER_BINARY_(PetscObjectComm((PetscObject)pc)); if (viewer) { for (i=1; i<n; i++) { ierr = MatView(mglevels[i]->restrct,viewer);CHKERRQ(ierr); } for (i=0; i<n; i++) { ierr = KSPGetPC(mglevels[i]->smoothd,&pc);CHKERRQ(ierr); ierr = MatView(pc->mat,viewer);CHKERRQ(ierr); } } PetscFunctionReturn(0); }
/* * steady_state solves for the steady_state of the system * that was previously setup using the add_to_ham and add_lin * routines. Solver selection and parameterscan be controlled via PETSc * command line options. */ void steady_state(Vec x){ PetscViewer mat_view; PC pc; Vec b; KSP ksp; /* linear solver context */ PetscInt row,col,its,j,i,Istart,Iend; PetscScalar mat_tmp; long dim; int num_pop; double *populations; Mat solve_A; if (_lindblad_terms) { dim = total_levels*total_levels; solve_A = full_A; if (nid==0) { printf("Lindblad terms found, using Lindblad solver."); } } else { if (nid==0) { printf("Warning! Steady state not supported for Schrodinger.\n"); printf(" Defaulting to (less efficient) Lindblad Solver\n"); exit(0); } dim = total_levels*total_levels; solve_A = ham_A; } if (!stab_added){ if (nid==0) printf("Adding stabilization...\n"); /* * Add elements to the matrix to make the normalization work * I have no idea why this works, I am copying it from qutip * We add 1.0 in the 0th spot and every n+1 after */ if (nid==0) { row = 0; for (i=0;i<total_levels;i++){ col = i*(total_levels+1); mat_tmp = 1.0 + 0.*PETSC_i; MatSetValue(full_A,row,col,mat_tmp,ADD_VALUES); } /* Print dense ham, if it was asked for */ if (_print_dense_ham){ FILE *fp_ham; fp_ham = fopen("ham","w"); if (nid==0){ for (i=0;i<total_levels;i++){ for (j=0;j<total_levels;j++){ fprintf(fp_ham,"%e %e ",PetscRealPart(_hamiltonian[i][j]),PetscImaginaryPart(_hamiltonian[i][j])); } fprintf(fp_ham,"\n"); } } fclose(fp_ham); for (i=0;i<total_levels;i++){ free(_hamiltonian[i]); } free(_hamiltonian); _print_dense_ham = 0; } } stab_added = 1; } // if (!matrix_assembled) { MatGetOwnershipRange(full_A,&Istart,&Iend); /* * Explicitly add 0.0 to all diagonal elements; * this fixes a 'matrix in wrong state' message that PETSc * gives if the diagonal was never initialized. */ if (nid==0) printf("Adding 0 to diagonal elements...\n"); for (i=Istart;i<Iend;i++){ mat_tmp = 0 + 0.*PETSC_i; MatSetValue(full_A,i,i,mat_tmp,ADD_VALUES); } /* Tell PETSc to assemble the matrix */ MatAssemblyBegin(full_A,MAT_FINAL_ASSEMBLY); MatAssemblyEnd(full_A,MAT_FINAL_ASSEMBLY); if (nid==0) printf("Matrix Assembled.\n"); matrix_assembled = 1; // } /* Print information about the matrix. */ PetscViewerASCIIOpen(PETSC_COMM_WORLD,NULL,&mat_view); PetscViewerPushFormat(mat_view,PETSC_VIEWER_ASCII_INFO); MatView(full_A,mat_view); PetscViewerPopFormat(mat_view); PetscViewerDestroy(&mat_view); /* * Create parallel vectors. * - When using VecCreate(), VecSetSizes() and VecSetFromOptions(), * we specify only the vector's global * dimension; the parallel partitioning is determined at runtime. * - Note: We form 1 vector from scratch and then duplicate as needed. */ VecCreate(PETSC_COMM_WORLD,&b); VecSetSizes(b,PETSC_DECIDE,dim); VecSetFromOptions(b); // VecDuplicate(b,&x); Assume x is passed in /* * Set rhs, b, and solution, x to 1.0 in the first * element, 0.0 elsewhere. */ VecSet(b,0.0); VecSet(x,0.0); if(nid==0) { row = 0; mat_tmp = 1.0 + 0.0*PETSC_i; VecSetValue(x,row,mat_tmp,INSERT_VALUES); VecSetValue(b,row,mat_tmp,INSERT_VALUES); } /* Assemble x and b */ VecAssemblyBegin(x); VecAssemblyEnd(x); VecAssemblyBegin(b); VecAssemblyEnd(b); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -* * Create the linear solver and set various options * *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* * Create linear solver context */ KSPCreate(PETSC_COMM_WORLD,&ksp); /* * Set operators. Here the matrix that defines the linear system * also serves as the preconditioning matrix. */ KSPSetOperators(ksp,full_A,full_A); /* * Set good default options for solver */ /* relative tolerance */ KSPSetTolerances(ksp,default_rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); /* bjacobi preconditioner */ KSPGetPC(ksp,&pc); PCSetType(pc,PCASM); /* gmres solver with 100 restart*/ KSPSetType(ksp,KSPGMRES); KSPGMRESSetRestart(ksp,default_restart); /* * Set runtime options, e.g., * -ksp_type <type> -pc_type <type> -ksp_monitor -ksp_rtol <rtol> */ KSPSetFromOptions(ksp); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Solve the linear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ if (nid==0) printf("KSP set. Solving for steady state...\n"); KSPSolve(ksp,b,x); num_pop = get_num_populations(); populations = malloc(num_pop*sizeof(double)); get_populations(x,&populations); if(nid==0){ printf("Final populations: "); for(i=0;i<num_pop;i++){ printf(" %e ",populations[i]); } printf("\n"); } KSPGetIterationNumber(ksp,&its); PetscPrintf(PETSC_COMM_WORLD,"Iterations %D\n",its); /* Free work space */ KSPDestroy(&ksp); // VecDestroy(&x); VecDestroy(&b); return; }
void PETScMGSolver_UpdateWorkVectors( PETScMGSolver* self ) { PETScMGSolver_Level* level; PC pc; //unsigned size; PetscInt size, vecSize; PetscErrorCode ec; unsigned l_i; assert( self && Stg_CheckType( self, PETScMGSolver ) ); if( self->nLevels == 1 ) return; ec = KSPGetPC( self->mgData->ksp, &pc ); CheckPETScError( ec ); for( l_i = 0; l_i < self->nLevels; l_i++ ) { level = self->levels + l_i; //Matrix_GetLocalSize( level->A, &size, NULL ); MatGetLocalSize( level->A, &size, PETSC_NULL ); if( level->workRes ) VecGetLocalSize( level->workRes, &vecSize ); if( l_i > 0 && (!level->workRes || /*Vector_GetLocalSize( level->workRes )*/vecSize != size) ) { if( level->workRes ) Stg_VecDestroy(&level->workRes ); // FreeObject( level->workRes ); //Vector_Duplicate( self->curSolution, (void**)&level->workRes ); //Vector_SetLocalSize( level->workRes, size ); //ec = PCMGSetR( pc, l_i, level->workRes->petscVec ); VecCreate( MPI_COMM_WORLD, &level->workRes ); VecSetSizes( level->workRes, size, PETSC_DECIDE ); VecSetFromOptions( level->workRes ); #if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 ) VecSetOption( level->workRes, VEC_IGNORE_NEGATIVE_INDICES ); #elif( PETSC_VERSION_MAJOR >= 3 ) VecSetOption( level->workRes, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE ); #endif ec = PCMGSetR( pc, l_i, level->workRes ); CheckPETScError( ec ); } if( l_i < self->nLevels - 1 ) { if( level->workSol ) VecGetLocalSize( level->workSol, &vecSize ); if( !level->workSol || /*Vector_GetLocalSize( level->workSol )*/vecSize != size ) { if( level->workSol ) Stg_VecDestroy(&level->workSol ); // FreeObject( level->workSol ); //Vector_Duplicate( self->curSolution, (void**)&level->workSol ); //Vector_SetLocalSize( level->workSol, size ); //ec = PCMGSetX( pc, l_i, level->workSol->petscVec ); VecCreate( MPI_COMM_WORLD, &level->workSol ); VecSetSizes( level->workSol, size, PETSC_DECIDE ); VecSetFromOptions( level->workSol ); #if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 ) VecSetOption( level->workSol, VEC_IGNORE_NEGATIVE_INDICES ); #elif( PETSC_VERSION_MAJOR >= 3 ) VecSetOption( level->workSol, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE ); #endif ec = PCMGSetX( pc, l_i, level->workSol ); CheckPETScError( ec ); } if( level->workRHS ) VecGetLocalSize( level->workRHS, &vecSize ); if( !level->workRHS || /*Vector_GetLocalSize( level->workRHS )*/vecSize != size ) { if( level->workRHS ) Stg_VecDestroy(&level->workRHS ); // FreeObject( level->workRHS ); //Vector_Duplicate( self->curSolution, (void**)&level->workRHS ); //Vector_SetLocalSize( level->workRHS, size ); //ec = PCMGSetRhs( pc, l_i, level->workRHS->petscVec ); VecCreate( MPI_COMM_WORLD, &level->workRHS ); VecSetSizes( level->workRHS, size, PETSC_DECIDE ); VecSetFromOptions( level->workRHS ); #if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 ) VecSetOption( level->workRHS, VEC_IGNORE_NEGATIVE_INDICES ); #elif( PETSC_VERSION_MAJOR >= 3 ) VecSetOption( level->workRHS, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE ); #endif ec = PCMGSetRhs( pc, l_i, level->workRHS ); CheckPETScError( ec ); } } } }
int main(int argc,char **args) { Mat C; PetscScalar v,none = -1.0; PetscInt i,j,Ii,J,Istart,Iend,N,m = 4,n = 4,its,k; PetscErrorCode ierr; PetscMPIInt size,rank; PetscReal err_norm,res_norm,err_tol=1.e-7,res_tol=1.e-6; Vec x,b,u,u_tmp; PetscRandom r; PC pc; KSP ksp; PetscInitialize(&argc,&args,(char*)0,help); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-m",&m,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-n",&n,NULL);CHKERRQ(ierr); N = m*n; /* Generate matrix */ ierr = MatCreate(PETSC_COMM_WORLD,&C);CHKERRQ(ierr); ierr = MatSetSizes(C,PETSC_DECIDE,PETSC_DECIDE,N,N);CHKERRQ(ierr); ierr = MatSetFromOptions(C);CHKERRQ(ierr); ierr = MatSetUp(C);CHKERRQ(ierr); ierr = MatGetOwnershipRange(C,&Istart,&Iend);CHKERRQ(ierr); for (Ii=Istart; Ii<Iend; Ii++) { v = -1.0; i = Ii/n; j = Ii - i*n; if (i>0) {J = Ii - n; ierr = MatSetValues(C,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (i<m-1) {J = Ii + n; ierr = MatSetValues(C,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j>0) {J = Ii - 1; ierr = MatSetValues(C,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j<n-1) {J = Ii + 1; ierr = MatSetValues(C,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} v = 4.0; ierr = MatSetValues(C,1,&Ii,1,&Ii,&v,ADD_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* a shift can make C indefinite. Preconditioners LU, ILU (for BAIJ format) and ICC may fail */ /* ierr = MatShift(C,alpha);CHKERRQ(ierr); */ /* ierr = MatView(C,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ /* Setup and solve for system */ /* Create vectors. */ ierr = VecCreate(PETSC_COMM_WORLD,&x);CHKERRQ(ierr); ierr = VecSetSizes(x,PETSC_DECIDE,N);CHKERRQ(ierr); ierr = VecSetFromOptions(x);CHKERRQ(ierr); ierr = VecDuplicate(x,&b);CHKERRQ(ierr); ierr = VecDuplicate(x,&u);CHKERRQ(ierr); ierr = VecDuplicate(x,&u_tmp);CHKERRQ(ierr); /* Set exact solution u; then compute right-hand-side vector b. */ ierr = PetscRandomCreate(PETSC_COMM_SELF,&r);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr); ierr = VecSetRandom(u,r);CHKERRQ(ierr); ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); ierr = MatMult(C,u,b);CHKERRQ(ierr); for (k=0; k<3; k++) { if (k == 0) { /* CG */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,C,C);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"\n CG: \n");CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPCG);CHKERRQ(ierr); } else if (k == 1) { /* MINRES */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,C,C);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"\n MINRES: \n");CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPMINRES);CHKERRQ(ierr); } else { /* SYMMLQ */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,C,C);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"\n SYMMLQ: \n");CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPSYMMLQ);CHKERRQ(ierr); } ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); /* ierr = PCSetType(pc,PCICC);CHKERRQ(ierr); */ ierr = PCSetType(pc,PCJACOBI);CHKERRQ(ierr); ierr = KSPSetTolerances(ksp,1.e-7,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); /* Set runtime options, e.g., -ksp_type <type> -pc_type <type> -ksp_monitor -ksp_rtol <rtol> These options will override those specified above as long as KSPSetFromOptions() is called _after_ any other customization routines. */ ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); /* Solve linear system; */ ierr = KSPSetUp(ksp);CHKERRQ(ierr); ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr); ierr = KSPGetIterationNumber(ksp,&its);CHKERRQ(ierr); /* Check error */ ierr = VecCopy(u,u_tmp);CHKERRQ(ierr); ierr = VecAXPY(u_tmp,none,x);CHKERRQ(ierr); ierr = VecNorm(u_tmp,NORM_2,&err_norm);CHKERRQ(ierr); ierr = MatMult(C,x,u_tmp);CHKERRQ(ierr); ierr = VecAXPY(u_tmp,none,b);CHKERRQ(ierr); ierr = VecNorm(u_tmp,NORM_2,&res_norm);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Number of iterations = %3D\n",its);CHKERRQ(ierr); if (res_norm > res_tol) { ierr = PetscPrintf(PETSC_COMM_WORLD,"Residual norm %g;",(double)res_norm);CHKERRQ(ierr); } if (err_norm > err_tol) { ierr = PetscPrintf(PETSC_COMM_WORLD," Error norm %g.\n",(double)err_norm);CHKERRQ(ierr); } ierr = KSPDestroy(&ksp);CHKERRQ(ierr); } /* Free work space. All PETSc objects should be destroyed when they are no longer needed. */ ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&u_tmp);CHKERRQ(ierr); ierr = MatDestroy(&C);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
int main(int argc,char **args) { Mat A,B,F; PetscErrorCode ierr; KSP ksp; PC pc; PetscInt N, n=10, m, Istart, Iend, II, J, i,j; PetscInt nneg, nzero, npos; PetscScalar v,sigma; PetscBool flag,loadA=PETSC_FALSE,loadB=PETSC_FALSE; char file[2][PETSC_MAX_PATH_LEN]; PetscViewer viewer; PetscMPIInt rank; PetscInitialize(&argc,&args,(char *)0,help); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Compute the matrices that define the eigensystem, Ax=kBx - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = PetscOptionsGetString(PETSC_NULL,"-fA",file[0],PETSC_MAX_PATH_LEN,&loadA);CHKERRQ(ierr); if (loadA) { ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,file[0],FILE_MODE_READ,&viewer);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr); ierr = MatSetType(A,MATSBAIJ);CHKERRQ(ierr); ierr = MatLoad(A,viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); ierr = PetscOptionsGetString(PETSC_NULL,"-fB",file[1],PETSC_MAX_PATH_LEN,&loadB);CHKERRQ(ierr); if (loadB){ /* load B to get A = A + sigma*B */ ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,file[1],FILE_MODE_READ,&viewer);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD,&B);CHKERRQ(ierr); ierr = MatSetType(B,MATSBAIJ);CHKERRQ(ierr); ierr = MatLoad(B,viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } } if (!loadA) { /* Matrix A is copied from slepc-3.0.0-p6/src/examples/ex13.c. */ ierr = PetscOptionsGetInt(PETSC_NULL,"-n",&n,PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(PETSC_NULL,"-m",&m,&flag);CHKERRQ(ierr); if( flag==PETSC_FALSE ) m=n; N = n*m; ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr); ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,N,N);CHKERRQ(ierr); ierr = MatSetType(A,MATSBAIJ);CHKERRQ(ierr); ierr = MatSetFromOptions(A);CHKERRQ(ierr); ierr = MatSetUp(A);CHKERRQ(ierr); ierr = MatSetOption(A,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE);CHKERRQ(ierr); ierr = MatGetOwnershipRange(A,&Istart,&Iend);CHKERRQ(ierr); for( II=Istart; II<Iend; II++ ) { v = -1.0; i = II/n; j = II-i*n; if(i>0) { J=II-n; MatSetValues(A,1,&II,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr); } if(i<m-1) { J=II+n; MatSetValues(A,1,&II,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr); } if(j>0) { J=II-1; MatSetValues(A,1,&II,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr); } if(j<n-1) { J=II+1; MatSetValues(A,1,&II,1,&J,&v,INSERT_VALUES);CHKERRQ(ierr); } v=4.0; MatSetValues(A,1,&II,1,&II,&v,INSERT_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } /* ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ if (!loadB) { ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD,&B);CHKERRQ(ierr); ierr = MatSetSizes(B,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); ierr = MatSetType(B,MATSBAIJ);CHKERRQ(ierr); ierr = MatSetFromOptions(B);CHKERRQ(ierr); ierr = MatSetUp(B);CHKERRQ(ierr); ierr = MatSetOption(B,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE);CHKERRQ(ierr); ierr = MatGetOwnershipRange(A,&Istart,&Iend);CHKERRQ(ierr); for( II=Istart; II<Iend; II++ ) { /* v=4.0; MatSetValues(B,1,&II,1,&II,&v,INSERT_VALUES);CHKERRQ(ierr); */ v=1.0; MatSetValues(B,1,&II,1,&II,&v,INSERT_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } /* ierr = MatView(B,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ /* Set a shift: A = A - sigma*B */ ierr = PetscOptionsGetScalar(PETSC_NULL,"-sigma",&sigma,&flag);CHKERRQ(ierr); if (flag){ sigma = -1.0 * sigma; ierr = MatAXPY(A,sigma,B,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); /* A <- A - sigma*B */ /* ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ } /* Test MatGetInertia() */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCCHOLESKY);CHKERRQ(ierr); ierr = PCSetFromOptions(pc);CHKERRQ(ierr); ierr = PCSetUp(pc);CHKERRQ(ierr); ierr = PCFactorGetMatrix(pc,&F);CHKERRQ(ierr); ierr = MatGetInertia(F,&nneg,&nzero,&npos);CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); if (!rank){ ierr = PetscPrintf(PETSC_COMM_SELF," MatInertia: nneg: %D, nzero: %D, npos: %D\n",nneg,nzero,npos);CHKERRQ(ierr); } /* Destroy */ ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = MatDestroy(&B);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
/*@C KSPView - Prints the KSP data structure. Collective on KSP Input Parameters: + ksp - the Krylov space context - viewer - visualization context Options Database Keys: . -ksp_view - print the ksp data structure at the end of a KSPSolve call Note: The available visualization contexts include + PETSC_VIEWER_STDOUT_SELF - standard output (default) - PETSC_VIEWER_STDOUT_WORLD - synchronized standard output where only the first processor opens the file. All other processors send their data to the first processor to print. The user can open an alternative visualization context with PetscViewerASCIIOpen() - output to a specified file. Level: beginner .keywords: KSP, view .seealso: PCView(), PetscViewerASCIIOpen() @*/ PetscErrorCode KSPView(KSP ksp,PetscViewer viewer) { PetscErrorCode ierr; PetscBool iascii,isbinary,isdraw; #if defined(PETSC_HAVE_AMS) PetscBool isams; #endif PetscFunctionBegin; PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)ksp)); PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); PetscCheckSameComm(ksp,1,viewer,2); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); #if defined(PETSC_HAVE_AMS) ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERAMS,&isams);CHKERRQ(ierr); #endif if (iascii) { ierr = PetscObjectPrintClassNamePrefixType((PetscObject)ksp,viewer,"KSP Object");CHKERRQ(ierr); if (ksp->ops->view) { ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); ierr = (*ksp->ops->view)(ksp,viewer);CHKERRQ(ierr); ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); } if (ksp->guess_zero) { ierr = PetscViewerASCIIPrintf(viewer," maximum iterations=%D, initial guess is zero\n",ksp->max_it);CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer," maximum iterations=%D\n", ksp->max_it);CHKERRQ(ierr); } if (ksp->guess_knoll) {ierr = PetscViewerASCIIPrintf(viewer," using preconditioner applied to right hand side for initial guess\n");CHKERRQ(ierr);} ierr = PetscViewerASCIIPrintf(viewer," tolerances: relative=%G, absolute=%G, divergence=%G\n",ksp->rtol,ksp->abstol,ksp->divtol);CHKERRQ(ierr); if (ksp->pc_side == PC_RIGHT) { ierr = PetscViewerASCIIPrintf(viewer," right preconditioning\n");CHKERRQ(ierr); } else if (ksp->pc_side == PC_SYMMETRIC) { ierr = PetscViewerASCIIPrintf(viewer," symmetric preconditioning\n");CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(viewer," left preconditioning\n");CHKERRQ(ierr); } if (ksp->guess) {ierr = PetscViewerASCIIPrintf(viewer," using Fischers initial guess method %D with size %D\n",ksp->guess->method,ksp->guess->maxl);CHKERRQ(ierr);} if (ksp->dscale) {ierr = PetscViewerASCIIPrintf(viewer," diagonally scaled system\n");CHKERRQ(ierr);} if (ksp->nullsp) {ierr = PetscViewerASCIIPrintf(viewer," has attached null space\n");CHKERRQ(ierr);} if (!ksp->guess_zero) {ierr = PetscViewerASCIIPrintf(viewer," using nonzero initial guess\n");CHKERRQ(ierr);} ierr = PetscViewerASCIIPrintf(viewer," using %s norm type for convergence test\n",KSPNormTypes[ksp->normtype]);CHKERRQ(ierr); } else if (isbinary) { PetscInt classid = KSP_FILE_CLASSID; MPI_Comm comm; PetscMPIInt rank; char type[256]; ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); if (!rank) { ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); ierr = PetscStrncpy(type,((PetscObject)ksp)->type_name,256);CHKERRQ(ierr); ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); } if (ksp->ops->view) { ierr = (*ksp->ops->view)(ksp,viewer);CHKERRQ(ierr); } } else if (isdraw) { PetscDraw draw; char str[36]; PetscReal x,y,bottom,h; PetscBool flg; ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPREONLY,&flg);CHKERRQ(ierr); if (!flg) { ierr = PetscStrcpy(str,"KSP: ");CHKERRQ(ierr); ierr = PetscStrcat(str,((PetscObject)ksp)->type_name);CHKERRQ(ierr); ierr = PetscDrawBoxedString(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr); bottom = y - h; } else { bottom = y; } ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); #if defined(PETSC_HAVE_AMS) } else if (isams) { if (((PetscObject)ksp)->amsmem == -1) { ierr = PetscObjectViewAMS((PetscObject)ksp,viewer);CHKERRQ(ierr); PetscStackCallAMS(AMS_Memory_take_access,(((PetscObject)ksp)->amsmem)); PetscStackCallAMS(AMS_Memory_add_field,(((PetscObject)ksp)->amsmem,"its",&ksp->its,1,AMS_INT,AMS_READ,AMS_COMMON,AMS_REDUCT_UNDEF)); if (!ksp->res_hist) { ierr = KSPSetResidualHistory(ksp,NULL,PETSC_DECIDE,PETSC_FALSE);CHKERRQ(ierr); } PetscStackCallAMS(AMS_Memory_add_field,(((PetscObject)ksp)->amsmem,"res_hist",ksp->res_hist,10,AMS_DOUBLE,AMS_READ,AMS_COMMON,AMS_REDUCT_UNDEF)); PetscStackCallAMS(AMS_Memory_grant_access,(((PetscObject)ksp)->amsmem)); } #endif } else if (ksp->ops->view) { ierr = (*ksp->ops->view)(ksp,viewer);CHKERRQ(ierr); } if (!ksp->pc) {ierr = KSPGetPC(ksp,&ksp->pc);CHKERRQ(ierr);} ierr = PCView(ksp->pc,viewer);CHKERRQ(ierr); if (isdraw) { PetscDraw draw; ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode test_solve(void) { Mat A11, A12,A21,A22, A, tmp[2][2]; KSP ksp; PC pc; Vec b,x, f,h, diag, x1,x2; Vec tmp_x[2],*_tmp_x; int n, np, i,j; PetscErrorCode ierr; PetscFunctionBeginUser; PetscPrintf(PETSC_COMM_WORLD, "%s \n", PETSC_FUNCTION_NAME); n = 3; np = 2; /* Create matrices */ /* A11 */ ierr = VecCreate(PETSC_COMM_WORLD, &diag);CHKERRQ(ierr); ierr = VecSetSizes(diag, PETSC_DECIDE, n);CHKERRQ(ierr); ierr = VecSetFromOptions(diag);CHKERRQ(ierr); ierr = VecSet(diag, (1.0/10.0));CHKERRQ(ierr); /* so inverse = diag(10) */ /* As a test, create a diagonal matrix for A11 */ ierr = MatCreate(PETSC_COMM_WORLD, &A11);CHKERRQ(ierr); ierr = MatSetSizes(A11, PETSC_DECIDE, PETSC_DECIDE, n, n);CHKERRQ(ierr); ierr = MatSetType(A11, MATAIJ);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(A11, n, NULL);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(A11, np, NULL,np, NULL);CHKERRQ(ierr); ierr = MatDiagonalSet(A11, diag, INSERT_VALUES);CHKERRQ(ierr); ierr = VecDestroy(&diag);CHKERRQ(ierr); /* A12 */ ierr = MatCreate(PETSC_COMM_WORLD, &A12);CHKERRQ(ierr); ierr = MatSetSizes(A12, PETSC_DECIDE, PETSC_DECIDE, n, np);CHKERRQ(ierr); ierr = MatSetType(A12, MATAIJ);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(A12, np, NULL);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(A12, np, NULL,np, NULL);CHKERRQ(ierr); for (i=0; i<n; i++) { for (j=0; j<np; j++) { ierr = MatSetValue(A12, i,j, (PetscScalar)(i+j*n), INSERT_VALUES);CHKERRQ(ierr); } } ierr = MatSetValue(A12, 2,1, (PetscScalar)(4), INSERT_VALUES);CHKERRQ(ierr); ierr = MatAssemblyBegin(A12, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A12, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* A21 */ ierr = MatTranspose(A12, MAT_INITIAL_MATRIX, &A21);CHKERRQ(ierr); A22 = NULL; /* Create block matrix */ tmp[0][0] = A11; tmp[0][1] = A12; tmp[1][0] = A21; tmp[1][1] = A22; ierr = MatCreateNest(PETSC_COMM_WORLD,2,NULL,2,NULL,&tmp[0][0],&A);CHKERRQ(ierr); ierr = MatNestSetVecType(A,VECNEST);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Create vectors */ ierr = MatCreateVecs(A12, &h, &f);CHKERRQ(ierr); ierr = VecSet(f, 1.0);CHKERRQ(ierr); ierr = VecSet(h, 0.0);CHKERRQ(ierr); /* Create block vector */ tmp_x[0] = f; tmp_x[1] = h; ierr = VecCreateNest(PETSC_COMM_WORLD,2,NULL,tmp_x,&b);CHKERRQ(ierr); ierr = VecAssemblyBegin(b);CHKERRQ(ierr); ierr = VecAssemblyEnd(b);CHKERRQ(ierr); ierr = VecDuplicate(b, &x);CHKERRQ(ierr); ierr = KSPCreate(PETSC_COMM_WORLD, &ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp, A, A);CHKERRQ(ierr); ierr = KSPSetType(ksp, "gmres");CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PCSetType(pc, "none");CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = KSPSolve(ksp, b, x);CHKERRQ(ierr); ierr = VecNestGetSubVecs(x,NULL,&_tmp_x);CHKERRQ(ierr); x1 = _tmp_x[0]; x2 = _tmp_x[1]; PetscPrintf(PETSC_COMM_WORLD, "x1 \n"); PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); ierr = VecView(x1, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); PetscPrintf(PETSC_COMM_WORLD, "x2 \n"); ierr = VecView(x2, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = MatDestroy(&A11);CHKERRQ(ierr); ierr = MatDestroy(&A12);CHKERRQ(ierr); ierr = MatDestroy(&A21);CHKERRQ(ierr); ierr = VecDestroy(&f);CHKERRQ(ierr); ierr = VecDestroy(&h);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc,char **argv) { KSP solver; PC pc; Mat A,B; Vec X,Y,Z; MatScalar *a; PetscScalar *b,*x,*y,*z; PetscReal nrm; PetscErrorCode ierr,size=8,lda=10, i,j; PetscInitialize(&argc,&argv,0,help); /* Create matrix and three vectors: these are all normal */ ierr = PetscMalloc1(lda*size,&b);CHKERRQ(ierr); for (i=0; i<size; i++) { for (j=0; j<size; j++) { b[i+j*lda] = rand(); } } ierr = MatCreate(MPI_COMM_SELF,&A);CHKERRQ(ierr); ierr = MatSetSizes(A,size,size,size,size);CHKERRQ(ierr); ierr = MatSetType(A,MATSEQDENSE);CHKERRQ(ierr); ierr = MatSeqDenseSetPreallocation(A,NULL);CHKERRQ(ierr); ierr = MatDenseGetArray(A,&a);CHKERRQ(ierr); for (i=0; i<size; i++) { for (j=0; j<size; j++) { a[i+j*size] = b[i+j*lda]; } } ierr = MatDenseRestoreArray(A,&a);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatCreate(MPI_COMM_SELF,&B);CHKERRQ(ierr); ierr = MatSetSizes(B,size,size,size,size);CHKERRQ(ierr); ierr = MatSetType(B,MATSEQDENSE);CHKERRQ(ierr); ierr = MatSeqDenseSetPreallocation(B,b);CHKERRQ(ierr); ierr = MatSeqDenseSetLDA(B,lda);CHKERRQ(ierr); ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = PetscMalloc1(size,&x);CHKERRQ(ierr); for (i=0; i<size; i++) x[i] = 1.0; ierr = VecCreateSeqWithArray(MPI_COMM_SELF,1,size,x,&X);CHKERRQ(ierr); ierr = VecAssemblyBegin(X);CHKERRQ(ierr); ierr = VecAssemblyEnd(X);CHKERRQ(ierr); ierr = PetscMalloc1(size,&y);CHKERRQ(ierr); ierr = VecCreateSeqWithArray(MPI_COMM_SELF,1,size,y,&Y);CHKERRQ(ierr); ierr = VecAssemblyBegin(Y);CHKERRQ(ierr); ierr = VecAssemblyEnd(Y);CHKERRQ(ierr); ierr = PetscMalloc1(size,&z);CHKERRQ(ierr); ierr = VecCreateSeqWithArray(MPI_COMM_SELF,1,size,z,&Z);CHKERRQ(ierr); ierr = VecAssemblyBegin(Z);CHKERRQ(ierr); ierr = VecAssemblyEnd(Z);CHKERRQ(ierr); /* * Solve with A and B */ ierr = KSPCreate(MPI_COMM_SELF,&solver);CHKERRQ(ierr); ierr = KSPSetType(solver,KSPPREONLY);CHKERRQ(ierr); ierr = KSPGetPC(solver,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCLU);CHKERRQ(ierr); ierr = KSPSetOperators(solver,A,A);CHKERRQ(ierr); ierr = KSPSolve(solver,X,Y);CHKERRQ(ierr); ierr = KSPSetOperators(solver,B,B);CHKERRQ(ierr); ierr = KSPSolve(solver,X,Z);CHKERRQ(ierr); ierr = VecAXPY(Z,-1.0,Y);CHKERRQ(ierr); ierr = VecNorm(Z,NORM_2,&nrm); printf("Test1; error norm=%e\n",nrm); /* Free spaces */ ierr = PetscFree(b);CHKERRQ(ierr); ierr = PetscFree(x);CHKERRQ(ierr); ierr = PetscFree(y);CHKERRQ(ierr); ierr = PetscFree(z);CHKERRQ(ierr); ierr = VecDestroy(&X);CHKERRQ(ierr); ierr = VecDestroy(&Y);CHKERRQ(ierr); ierr = VecDestroy(&Z);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = MatDestroy(&B);CHKERRQ(ierr); ierr = KSPDestroy(&solver);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
int main(int argc,char **argv) { AppCtx user; /* user-defined work context */ PetscInt mx,my; PetscErrorCode ierr; MPI_Comm comm; DM da; Vec x; Mat J = NULL,Jmf = NULL; MatShellCtx matshellctx; PetscInt mlocal,nlocal; PC pc; KSP ksp; PetscBool errorinmatmult = PETSC_FALSE,errorinpcapply = PETSC_FALSE,errorinpcsetup = PETSC_FALSE; ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_matmult",&errorinmatmult,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_pcapply",&errorinpcapply,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_pcsetup",&errorinpcsetup,NULL);CHKERRQ(ierr); user.errorindomain = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_domain",&user.errorindomain,NULL);CHKERRQ(ierr); user.errorindomainmf = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_domainmf",&user.errorindomainmf,NULL);CHKERRQ(ierr); comm = PETSC_COMM_WORLD; ierr = SNESCreate(comm,&user.snes);CHKERRQ(ierr); /* Create distributed array object to manage parallel grid and vectors for principal unknowns (x) and governing residuals (f) */ ierr = DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_STAR,-4,-4,PETSC_DECIDE,PETSC_DECIDE,4,1,0,0,&da);CHKERRQ(ierr); ierr = SNESSetDM(user.snes,da);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&mx,&my,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE, PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr); /* Problem parameters (velocity of lid, prandtl, and grashof numbers) */ user.lidvelocity = 1.0/(mx*my); user.prandtl = 1.0; user.grashof = 1.0; ierr = PetscOptionsGetReal(NULL,NULL,"-lidvelocity",&user.lidvelocity,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,NULL,"-prandtl",&user.prandtl,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,NULL,"-grashof",&user.grashof,NULL);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,NULL,"-contours",&user.draw_contours);CHKERRQ(ierr); ierr = DMDASetFieldName(da,0,"x_velocity");CHKERRQ(ierr); ierr = DMDASetFieldName(da,1,"y_velocity");CHKERRQ(ierr); ierr = DMDASetFieldName(da,2,"Omega");CHKERRQ(ierr); ierr = DMDASetFieldName(da,3,"temperature");CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create user context, set problem data, create vector data structures. Also, compute the initial guess. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create nonlinear solver context - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr); ierr = DMDASNESSetFunctionLocal(da,INSERT_VALUES,(PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))FormFunctionLocal,&user);CHKERRQ(ierr); if (errorinmatmult) { ierr = MatCreateSNESMF(user.snes,&Jmf);CHKERRQ(ierr); ierr = MatSetFromOptions(Jmf);CHKERRQ(ierr); ierr = MatGetLocalSize(Jmf,&mlocal,&nlocal);CHKERRQ(ierr); matshellctx.Jmf = Jmf; ierr = MatCreateShell(PetscObjectComm((PetscObject)Jmf),mlocal,nlocal,PETSC_DECIDE,PETSC_DECIDE,&matshellctx,&J);CHKERRQ(ierr); ierr = MatShellSetOperation(J,MATOP_MULT,(void (*)(void))MatMult_MyShell);CHKERRQ(ierr); ierr = MatShellSetOperation(J,MATOP_ASSEMBLY_END,(void (*)(void))MatAssemblyEnd_MyShell);CHKERRQ(ierr); ierr = SNESSetJacobian(user.snes,J,J,MatMFFDComputeJacobian,NULL);CHKERRQ(ierr); } ierr = SNESSetFromOptions(user.snes);CHKERRQ(ierr); ierr = PetscPrintf(comm,"lid velocity = %g, prandtl # = %g, grashof # = %g\n",(double)user.lidvelocity,(double)user.prandtl,(double)user.grashof);CHKERRQ(ierr); if (errorinpcapply) { ierr = SNESGetKSP(user.snes,&ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCSHELL);CHKERRQ(ierr); ierr = PCShellSetApply(pc,PCApply_MyShell);CHKERRQ(ierr); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Solve the nonlinear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr); ierr = FormInitialGuess(&user,da,x);CHKERRQ(ierr); if (errorinpcsetup) { ierr = SNESSetUp(user.snes);CHKERRQ(ierr); ierr = SNESSetJacobian(user.snes,NULL,NULL,SNESComputeJacobian_MyShell,NULL);CHKERRQ(ierr); } ierr = SNESSolve(user.snes,NULL,x);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Free work space. All PETSc objects should be destroyed when they are no longer needed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = MatDestroy(&J);CHKERRQ(ierr); ierr = MatDestroy(&Jmf);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = SNESDestroy(&user.snes);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
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; PetscInitialize(&argc,&argv,(char *)0,help); ierr = PetscOptionsGetInt(PETSC_NULL,"-dof",&dof,PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(PETSC_NULL,"-M",&M,PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(PETSC_NULL,"-trans",&trans,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,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,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 = ComputeRHS(da,b);CHKERRQ(ierr); ierr = DMCreateMatrix(da,MATBAIJ,&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(PETSC_NULL, "-test_sbaij1", &flg,PETSC_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 { printf("Warning: A is non-symmetric\n"); } 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); 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(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; }