void createOuterPC(OuterContext* ctx) { PCCreate(((ctx->data)->commAll), &(ctx->outerPC)); PCSetType(ctx->outerPC, PCSHELL); PCShellSetName(ctx->outerPC, "RSD"); PCShellSetContext(ctx->outerPC, ctx); PCShellSetApply(ctx->outerPC, &outerPCapply); }
int main(int Argc,char **Args) { PetscInt x_mesh = 15,levels = 3,cycles = 1,use_jacobi = 0; PetscInt i,smooths = 1,*N,its; PetscErrorCode ierr; PCMGType am = PC_MG_MULTIPLICATIVE; Mat cmat,mat[20],fmat; KSP cksp,ksp[20],kspmg; PetscReal e[3]; /* l_2 error,max error, residual */ const char *shellname; Vec x,solution,X[20],R[20],B[20]; PC pcmg,pc; PetscBool flg; PetscInitialize(&Argc,&Args,(char*)0,help); ierr = PetscOptionsGetInt(NULL,"-x",&x_mesh,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-l",&levels,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-c",&cycles,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-smooths",&smooths,NULL);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-a",&flg);CHKERRQ(ierr); if (flg) am = PC_MG_ADDITIVE; ierr = PetscOptionsHasName(NULL,"-f",&flg);CHKERRQ(ierr); if (flg) am = PC_MG_FULL; ierr = PetscOptionsHasName(NULL,"-j",&flg);CHKERRQ(ierr); if (flg) use_jacobi = 1; ierr = PetscMalloc1(levels,&N);CHKERRQ(ierr); N[0] = x_mesh; for (i=1; i<levels; i++) { N[i] = N[i-1]/2; if (N[i] < 1) SETERRQ(PETSC_COMM_WORLD,1,"Too many levels"); } ierr = Create1dLaplacian(N[levels-1],&cmat);CHKERRQ(ierr); ierr = KSPCreate(PETSC_COMM_WORLD,&kspmg);CHKERRQ(ierr); ierr = KSPGetPC(kspmg,&pcmg);CHKERRQ(ierr); ierr = KSPSetFromOptions(kspmg);CHKERRQ(ierr); ierr = PCSetType(pcmg,PCMG);CHKERRQ(ierr); ierr = PCMGSetLevels(pcmg,levels,NULL);CHKERRQ(ierr); ierr = PCMGSetType(pcmg,am);CHKERRQ(ierr); ierr = PCMGGetCoarseSolve(pcmg,&cksp);CHKERRQ(ierr); ierr = KSPSetOperators(cksp,cmat,cmat);CHKERRQ(ierr); ierr = KSPGetPC(cksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCLU);CHKERRQ(ierr); ierr = KSPSetType(cksp,KSPPREONLY);CHKERRQ(ierr); /* zero is finest level */ for (i=0; i<levels-1; i++) { ierr = PCMGSetResidual(pcmg,levels - 1 - i,residual,(Mat)0);CHKERRQ(ierr); ierr = MatCreateShell(PETSC_COMM_WORLD,N[i+1],N[i],N[i+1],N[i],(void*)0,&mat[i]);CHKERRQ(ierr); ierr = MatShellSetOperation(mat[i],MATOP_MULT,(void (*)(void))restrct);CHKERRQ(ierr); ierr = MatShellSetOperation(mat[i],MATOP_MULT_TRANSPOSE_ADD,(void (*)(void))interpolate);CHKERRQ(ierr); ierr = PCMGSetInterpolation(pcmg,levels - 1 - i,mat[i]);CHKERRQ(ierr); ierr = PCMGSetRestriction(pcmg,levels - 1 - i,mat[i]);CHKERRQ(ierr); ierr = PCMGSetCyclesOnLevel(pcmg,levels - 1 - i,cycles);CHKERRQ(ierr); /* set smoother */ ierr = PCMGGetSmoother(pcmg,levels - 1 - i,&ksp[i]);CHKERRQ(ierr); ierr = KSPGetPC(ksp[i],&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCSHELL);CHKERRQ(ierr); ierr = PCShellSetName(pc,"user_precond");CHKERRQ(ierr); ierr = PCShellGetName(pc,&shellname);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"level=%D, PCShell name is %s\n",i,shellname);CHKERRQ(ierr); /* this is a dummy! since KSP requires a matrix passed in */ ierr = KSPSetOperators(ksp[i],mat[i],mat[i]);CHKERRQ(ierr); /* We override the matrix passed in by forcing it to use Richardson with a user provided application. This is non-standard and this practice should be avoided. */ ierr = PCShellSetApplyRichardson(pc,gauss_seidel);CHKERRQ(ierr); if (use_jacobi) { ierr = PCShellSetApplyRichardson(pc,jacobi);CHKERRQ(ierr); } ierr = KSPSetType(ksp[i],KSPRICHARDSON);CHKERRQ(ierr); ierr = KSPSetInitialGuessNonzero(ksp[i],PETSC_TRUE);CHKERRQ(ierr); ierr = KSPSetTolerances(ksp[i],PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,smooths);CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,N[i],&x);CHKERRQ(ierr); X[levels - 1 - i] = x; if (i > 0) { ierr = PCMGSetX(pcmg,levels - 1 - i,x);CHKERRQ(ierr); } ierr = VecCreateSeq(PETSC_COMM_SELF,N[i],&x);CHKERRQ(ierr); B[levels -1 - i] = x; if (i > 0) { ierr = PCMGSetRhs(pcmg,levels - 1 - i,x);CHKERRQ(ierr); } ierr = VecCreateSeq(PETSC_COMM_SELF,N[i],&x);CHKERRQ(ierr); R[levels - 1 - i] = x; ierr = PCMGSetR(pcmg,levels - 1 - i,x);CHKERRQ(ierr); } /* create coarse level vectors */ ierr = VecCreateSeq(PETSC_COMM_SELF,N[levels-1],&x);CHKERRQ(ierr); ierr = PCMGSetX(pcmg,0,x);CHKERRQ(ierr); X[0] = x; ierr = VecCreateSeq(PETSC_COMM_SELF,N[levels-1],&x);CHKERRQ(ierr); ierr = PCMGSetRhs(pcmg,0,x);CHKERRQ(ierr); B[0] = x; /* create matrix multiply for finest level */ ierr = MatCreateShell(PETSC_COMM_WORLD,N[0],N[0],N[0],N[0],(void*)0,&fmat);CHKERRQ(ierr); ierr = MatShellSetOperation(fmat,MATOP_MULT,(void (*)(void))amult);CHKERRQ(ierr); ierr = KSPSetOperators(kspmg,fmat,fmat);CHKERRQ(ierr); ierr = CalculateSolution(N[0],&solution);CHKERRQ(ierr); ierr = CalculateRhs(B[levels-1]);CHKERRQ(ierr); ierr = VecSet(X[levels-1],0.0);CHKERRQ(ierr); ierr = residual((Mat)0,B[levels-1],X[levels-1],R[levels-1]);CHKERRQ(ierr); ierr = CalculateError(solution,X[levels-1],R[levels-1],e);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_SELF,"l_2 error %g max error %g resi %g\n",(double)e[0],(double)e[1],(double)e[2]);CHKERRQ(ierr); ierr = KSPSolve(kspmg,B[levels-1],X[levels-1]);CHKERRQ(ierr); ierr = KSPGetIterationNumber(kspmg,&its);CHKERRQ(ierr); ierr = residual((Mat)0,B[levels-1],X[levels-1],R[levels-1]);CHKERRQ(ierr); ierr = CalculateError(solution,X[levels-1],R[levels-1],e);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_SELF,"its %D l_2 error %g max error %g resi %g\n",its,(double)e[0],(double)e[1],(double)e[2]);CHKERRQ(ierr); ierr = PetscFree(N);CHKERRQ(ierr); ierr = VecDestroy(&solution);CHKERRQ(ierr); /* note we have to keep a list of all vectors allocated, this is not ideal, but putting it in MGDestroy is not so good either*/ for (i=0; i<levels; i++) { ierr = VecDestroy(&X[i]);CHKERRQ(ierr); ierr = VecDestroy(&B[i]);CHKERRQ(ierr); if (i) {ierr = VecDestroy(&R[i]);CHKERRQ(ierr);} } for (i=0; i<levels-1; i++) { ierr = MatDestroy(&mat[i]);CHKERRQ(ierr); } ierr = MatDestroy(&cmat);CHKERRQ(ierr); ierr = MatDestroy(&fmat);CHKERRQ(ierr); ierr = KSPDestroy(&kspmg);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
static int TaoSolve_BNLS(TAO_SOLVER tao, void*solver){ TAO_BNLS *bnls = (TAO_BNLS *)solver; int info; TaoInt lsflag,iter=0; TaoTerminateReason reason=TAO_CONTINUE_ITERATING; double f,f_full,gnorm,gdx,stepsize=1.0; TaoTruth success; TaoVec *XU, *XL; TaoVec *X, *G=bnls->G, *PG=bnls->PG; TaoVec *R=bnls->R, *DXFree=bnls->DXFree; TaoVec *DX=bnls->DX, *Work=bnls->Work; TaoMat *H, *Hsub=bnls->Hsub; TaoIndexSet *FreeVariables = bnls->FreeVariables; TaoFunctionBegin; /* Check if upper bound greater than lower bound. */ info = TaoGetSolution(tao,&X);CHKERRQ(info); bnls->X=X; info = TaoGetVariableBounds(tao,&XL,&XU);CHKERRQ(info); info = TaoEvaluateVariableBounds(tao,XL,XU); CHKERRQ(info); info = TaoGetHessian(tao,&H);CHKERRQ(info); bnls->H=H; /* Project the current point onto the feasible set */ info = X->Median(XL,X,XU); CHKERRQ(info); TaoLinearSolver *tls; // Modify the linear solver to a conjugate gradient method info = TaoGetLinearSolver(tao, &tls); CHKERRQ(info); TaoLinearSolverPetsc *pls; pls = dynamic_cast <TaoLinearSolverPetsc *> (tls); // set trust radius to zero // PETSc ignores this case and should return the negative curvature direction // at its current default length pls->SetTrustRadius(0.0); if(!bnls->M) bnls->M = new TaoLMVMMat(X); TaoLMVMMat *M = bnls->M; KSP pksp = pls->GetKSP(); // we will want to provide an initial guess in case neg curvature on the first iteration info = KSPSetInitialGuessNonzero(pksp,PETSC_TRUE); CHKERRQ(info); PC ppc; // Modify the preconditioner to use the bfgs approximation info = KSPGetPC(pksp, &ppc); CHKERRQ(info); PetscTruth BFGSPreconditioner=PETSC_FALSE;// debug flag info = PetscOptionsGetTruth(PETSC_NULL,"-bnls_pc_bfgs", &BFGSPreconditioner,PETSC_NULL); CHKERRQ(info); if( BFGSPreconditioner) { info=PetscInfo(tao,"TaoSolve_BNLS: using bfgs preconditioner\n"); info = KSPSetNormType(pksp, KSP_NORM_PRECONDITIONED); CHKERRQ(info); info = PCSetType(ppc, PCSHELL); CHKERRQ(info); info = PCShellSetName(ppc, "bfgs"); CHKERRQ(info); info = PCShellSetContext(ppc, M); CHKERRQ(info); info = PCShellSetApply(ppc, bfgs_apply); CHKERRQ(info); } else {// default to none info=PetscInfo(tao,"TaoSolve_BNLS: using no preconditioner\n"); info = PCSetType(ppc, PCNONE); CHKERRQ(info); } info = TaoComputeMeritFunctionGradient(tao,X,&f,G);CHKERRQ(info); info = PG->BoundGradientProjection(G,XL,X,XU);CHKERRQ(info); info = PG->Norm2(&gnorm); CHKERRQ(info); // Set initial scaling for the function if (f != 0.0) { info = M->SetDelta(2.0 * TaoAbsDouble(f) / (gnorm*gnorm)); CHKERRQ(info); } else { info = M->SetDelta(2.0 / (gnorm*gnorm)); CHKERRQ(info); } while (reason==TAO_CONTINUE_ITERATING){ /* Project the gradient and calculate the norm */ info = PG->BoundGradientProjection(G,XL,X,XU);CHKERRQ(info); info = PG->Norm2(&gnorm); CHKERRQ(info); info = M->Update(X, PG); CHKERRQ(info); PetscScalar ewAtol = PetscMin(0.5,gnorm)*gnorm; info = KSPSetTolerances(pksp,PETSC_DEFAULT,ewAtol, PETSC_DEFAULT, PETSC_DEFAULT); CHKERRQ(info); info=PetscInfo1(tao,"TaoSolve_BNLS: gnorm =%g\n",gnorm); pksp->printreason = PETSC_TRUE; info = KSPView(pksp,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(info); M->View(); info = TaoMonitor(tao,iter++,f,gnorm,0.0,stepsize,&reason); CHKERRQ(info); if (reason!=TAO_CONTINUE_ITERATING) break; info = FreeVariables->WhichEqual(PG,G); CHKERRQ(info); info = TaoComputeHessian(tao,X,H);CHKERRQ(info); /* Create a reduced linear system */ info = R->SetReducedVec(G,FreeVariables);CHKERRQ(info); info = R->Negate();CHKERRQ(info); /* Use gradient as initial guess */ PetscTruth UseGradientIG=PETSC_FALSE;// debug flag info = PetscOptionsGetTruth(PETSC_NULL,"-bnls_use_gradient_ig", &UseGradientIG,PETSC_NULL); CHKERRQ(info); if(UseGradientIG) info = DX->CopyFrom(G); else { info=PetscInfo(tao,"TaoSolve_BNLS: use bfgs init guess \n"); info = M->Solve(G, DX, &success); } CHKERRQ(info); info = DXFree->SetReducedVec(DX,FreeVariables);CHKERRQ(info); info = DXFree->Negate(); CHKERRQ(info); info = Hsub->SetReducedMatrix(H,FreeVariables,FreeVariables);CHKERRQ(info); bnls->gamma_factor /= 2; success = TAO_FALSE; while (success==TAO_FALSE) { /* Approximately solve the reduced linear system */ info = TaoPreLinearSolve(tao,Hsub);CHKERRQ(info); info = TaoLinearSolve(tao,Hsub,R,DXFree,&success);CHKERRQ(info); info = DX->SetToZero(); CHKERRQ(info); info = DX->ReducedXPY(DXFree,FreeVariables);CHKERRQ(info); info = DX->Dot(G,&gdx); CHKERRQ(info); if (gdx>=0 || success==TAO_FALSE) { /* use bfgs direction */ info = M->Solve(G, DX, &success); CHKERRQ(info); info = DX->BoundGradientProjection(DX,XL,X,XU); CHKERRQ(info); info = DX->Negate(); CHKERRQ(info); // Check for success (descent direction) info = DX->Dot(G,&gdx); CHKERRQ(info); if (gdx >= 0) { // Step is not descent or solve was not successful // Use steepest descent direction (scaled) if (f != 0.0) { info = M->SetDelta(2.0 * TaoAbsDouble(f) / (gnorm*gnorm)); CHKERRQ(info); } else { info = M->SetDelta(2.0 / (gnorm*gnorm)); CHKERRQ(info); } info = M->Reset(); CHKERRQ(info); info = M->Update(X, G); CHKERRQ(info); info = DX->CopyFrom(G); info = DX->Negate(); CHKERRQ(info); info = DX->Dot(G,&gdx); CHKERRQ(info); info=PetscInfo1(tao,"LMVM Solve Fail use steepest descent, gdx %22.12e \n",gdx); } else { info=PetscInfo1(tao,"Newton Solve Fail use BFGS direction, gdx %22.12e \n",gdx); } success = TAO_TRUE; // bnls->gamma_factor *= 2; // bnls->gamma = bnls->gamma_factor*(gnorm); //#if !defined(PETSC_USE_COMPLEX) // info=PetscInfo2(tao,"TaoSolve_NLS: modify diagonal (assume same nonzero structure), gamma_factor=%g, gamma=%g\n",bnls->gamma_factor,bnls->gamma); // CHKERRQ(info); //#else // info=PetscInfo3(tao,"TaoSolve_NLS: modify diagonal (asuume same nonzero structure), gamma_factor=%g, gamma=%g, gdx %22.12e \n", // bnls->gamma_factor,PetscReal(bnls->gamma),gdx);CHKERRQ(info); //#endif // info = Hsub->ShiftDiagonal(bnls->gamma);CHKERRQ(info); // if (f != 0.0) { // info = M->SetDelta(2.0 * TaoAbsDouble(f) / (gnorm*gnorm)); CHKERRQ(info); // } // else { // info = M->SetDelta(2.0 / (gnorm*gnorm)); CHKERRQ(info); // } // info = M->Reset(); CHKERRQ(info); // info = M->Update(X, G); CHKERRQ(info); // success = TAO_FALSE; } else { info=PetscInfo1(tao,"Newton Solve is descent direction, gdx %22.12e \n",gdx); success = TAO_TRUE; } } stepsize=1.0; info = TaoLineSearchApply(tao,X,G,DX,Work, &f,&f_full,&stepsize,&lsflag); CHKERRQ(info); } /* END MAIN LOOP */ TaoFunctionReturn(0); }
int main(int argc, char **argv) { PetscErrorCode ierr; PetscInt n=10000,its,dfid=1; Vec x,b,u; Mat A; KSP ksp; PC pc,pcnoise; PCNoise_Ctx ctx={0,NULL}; PetscReal eta=0.1,norm; PetscScalar(*diagfunc)(PetscInt,PetscInt); ierr = PetscInitialize(&argc,&argv,(char*)0,help);CHKERRQ(ierr); /* Process command line options */ ierr = PetscOptionsGetInt(NULL,"-n",&n,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,"-eta",&eta,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-diagfunc",&dfid,NULL);CHKERRQ(ierr); switch(dfid){ case 1: diagfunc = diagFunc1; break; case 2: diagfunc = diagFunc2; break; case 3: diagfunc = diagFunc3; break; default: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unrecognized diagfunc option"); } /* Create a diagonal matrix with a given distribution of diagonal elements */ ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr); ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,n,n);CHKERRQ(ierr); ierr = MatSetFromOptions(A);CHKERRQ(ierr); ierr = MatSetUp(A);CHKERRQ(ierr); ierr = AssembleDiagonalMatrix(A,diagfunc);CHKERRQ(ierr); /* Allocate vectors and manufacture an exact solution and rhs */ ierr = MatCreateVecs(A,&x,NULL);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)x,"Computed Solution");CHKERRQ(ierr); ierr = MatCreateVecs(A,&b,NULL);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)b,"RHS");CHKERRQ(ierr); ierr = MatCreateVecs(A,&u,NULL);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)u,"Reference Solution");CHKERRQ(ierr); ierr = VecSet(u,1.0);CHKERRQ(ierr); ierr = MatMult(A,u,b);CHKERRQ(ierr); /* Create a KSP object */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,A,A);CHKERRQ(ierr); /* Set up a composite preconditioner */ ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCCOMPOSITE);CHKERRQ(ierr); /* default composite with single Identity PC */ ierr = PCCompositeSetType(pc,PC_COMPOSITE_ADDITIVE);CHKERRQ(ierr); ierr = PCCompositeAddPC(pc,PCNONE);CHKERRQ(ierr); if(eta > 0){ ierr = PCCompositeAddPC(pc,PCSHELL);CHKERRQ(ierr); ierr = PCCompositeGetPC(pc,1,&pcnoise);CHKERRQ(ierr); ctx.eta = eta; ierr = PCShellSetContext(pcnoise,&ctx);CHKERRQ(ierr); ierr = PCShellSetApply(pcnoise,PCApply_Noise);CHKERRQ(ierr); ierr = PCShellSetSetUp(pcnoise,PCSetup_Noise);CHKERRQ(ierr); ierr = PCShellSetDestroy(pcnoise,PCDestroy_Noise);CHKERRQ(ierr); ierr = PCShellSetName(pcnoise,"Noise PC");CHKERRQ(ierr); } /* Set KSP from options (this can override the PC just defined) */ ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); /* Solve */ ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr); /* Compute error */ ierr = VecAXPY(x,-1.0,u);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)x,"Error");CHKERRQ(ierr); ierr = VecNorm(x,NORM_2,&norm);CHKERRQ(ierr); ierr = KSPGetIterationNumber(ksp,&its);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Norm of error %g, Iterations %D\n",(double)norm,its);CHKERRQ(ierr); /* Destroy objects and finalize */ ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = VecDestroy(&u);CHKERRQ(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 SolverLinearPetsc<T>::init () { // Initialize the data structures if not done so already. if ( !this->initialized() ) { this->setInitialized( true ); int ierr=0; // 2.1.x & earlier style #if (PETSC_VERSION_MAJOR == 2) && (PETSC_VERSION_MINOR <= 1) // Create the linear solver context ierr = SLESCreate ( this->worldComm().globalComm(), &M_sles ); CHKERRABORT( this->worldComm().globalComm(),ierr ); // Create the Krylov subspace & preconditioner contexts ierr = SLESGetKSP ( M_sles, &M_ksp ); CHKERRABORT( this->worldComm().globalComm(),ierr ); ierr = SLESGetPC ( M_sles, &M_pc ); CHKERRABORT( this->worldComm().globalComm(),ierr ); // Have the Krylov subspace method use our good initial guess rather than 0 ierr = KSPSetInitialGuessNonzero ( M_ksp, PETSC_TRUE ); CHKERRABORT( this->worldComm().globalComm(),ierr ); // Set user-specified solver and preconditioner types this->setPetscSolverType(); this->setPetscPreconditionerType(); this->setPetscConstantNullSpace(); // Set the options from user-input // 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 // SLESSetFromOptions() is called _after_ any other customization // routines. ierr = SLESSetFromOptions ( M_sles ); CHKERRABORT( this->worldComm().globalComm(),ierr ); // 2.2.0 & newer style #else // Create the linear solver context ierr = KSPCreate ( this->worldComm().globalComm(), &M_ksp ); CHKERRABORT( this->worldComm().globalComm(),ierr ); // Create the preconditioner context ierr = KSPGetPC ( M_ksp, &M_pc ); CHKERRABORT( this->worldComm().globalComm(),ierr ); // Have the Krylov subspace method use our good initial guess rather than 0 ierr = KSPSetInitialGuessNonzero ( M_ksp, PETSC_TRUE ); CHKERRABORT( this->worldComm().globalComm(),ierr ); // Set user-specified solver and preconditioner types this->setPetscSolverType(); this->setPetscConstantNullSpace(); // Set the options from user-input // 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 = PCSetFromOptions ( M_pc ); //CHKERRABORT( this->worldComm().globalComm(),ierr ); ierr = KSPSetFromOptions ( M_ksp ); CHKERRABORT( this->worldComm().globalComm(),ierr ); #endif // Have the Krylov subspace method use our good initial guess // rather than 0, unless the user requested a KSPType of // preonly, which complains if asked to use initial guesses. #if PETSC_VERSION_LESS_THAN(3,0,0) KSPType ksp_type; #else #if PETSC_VERSION_LESS_THAN(3,4,0) const KSPType ksp_type; #else KSPType ksp_type; #endif #endif ierr = KSPGetType ( M_ksp, &ksp_type ); CHKERRABORT( this->worldComm().globalComm(),ierr ); if ( std::string((char*)ksp_type) == std::string( ( char* )KSPPREONLY ) ) { ierr = KSPSetInitialGuessNonzero ( M_ksp, PETSC_FALSE ); CHKERRABORT( this->worldComm().globalComm(),ierr ); } if ( std::string((char*)ksp_type) == std::string( ( char* )KSPGMRES ) ) { int nRestartGMRES = option(_name="gmres-restart", _prefix=this->prefix() ).template as<int>(); ierr = KSPGMRESSetRestart( M_ksp, nRestartGMRES ); CHKERRABORT( this->worldComm().globalComm(),ierr ); } // Notify PETSc of location to store residual history. // This needs to be called before any solves, since // it sets the residual history length to zero. The default // behavior is for PETSc to allocate (internally) an array // of size 1000 to hold the residual norm history. ierr = KSPSetResidualHistory( M_ksp, PETSC_NULL, // pointer to the array which holds the history PETSC_DECIDE, // size of the array holding the history PETSC_TRUE ); // Whether or not to reset the history for each solve. CHKERRABORT( this->worldComm().globalComm(),ierr ); //If there is a preconditioner object we need to set the internal setup and apply routines if ( this->M_preconditioner ) { VLOG(2) << "preconditioner: " << this->M_preconditioner << "\n"; PCSetType(M_pc, PCSHELL); PCShellSetName( M_pc, this->M_preconditioner->name().c_str() ); PCShellSetContext( M_pc,( void* )this->M_preconditioner.get() ); PCShellSetSetUp( M_pc,__feel_petsc_preconditioner_setup ); PCShellSetApply( M_pc,__feel_petsc_preconditioner_apply ); PCShellSetView( M_pc,__feel_petsc_preconditioner_view ); #if PETSC_VERSION_LESS_THAN(3,4,0) const PCType pc_type; #else PCType pc_type; #endif ierr = PCGetType ( M_pc, &pc_type ); CHKERRABORT( this->worldComm().globalComm(),ierr ); VLOG(2) << "preconditioner set as " << pc_type << "\n"; } else { this->setPetscPreconditionerType(); // sets the software that is used to perform the factorization PetscPCFactorSetMatSolverPackage( M_pc,this->matSolverPackageType() ); } if ( Environment::vm(_name="ksp-monitor",_prefix=this->prefix()).template as<bool>() ) { KSPMonitorSet( M_ksp,KSPMonitorDefault,PETSC_NULL,PETSC_NULL ); } } }
*ierr = PCShellSetPostSolve(*pc,ourshellpostsolve); } PETSC_EXTERN void PETSC_STDCALL pcshellsetview_(PC *pc,void (PETSC_STDCALL *view)(void*,PetscViewer*,PetscErrorCode*),PetscErrorCode *ierr) { PetscObjectAllocateFortranPointers(*pc,9); ((PetscObject)*pc)->fortran_func_pointers[8] = (PetscVoidFunction)view; *ierr = PCShellSetView(*pc,ourshellview); } PETSC_EXTERN void PETSC_STDCALL pcshellsetname_(PC *pc,CHAR name PETSC_MIXED_LEN(len), PetscErrorCode *ierr PETSC_END_LEN(len)) { char *c; FIXCHAR(name,len,c); *ierr = PCShellSetName(*pc,c); FREECHAR(name,c); } PETSC_EXTERN void PETSC_STDCALL pcshellgetname_(PC *pc,CHAR name PETSC_MIXED_LEN(len), PetscErrorCode *ierr PETSC_END_LEN(len)) { const char *c; *ierr = PCShellGetName(*pc,&c);if (*ierr) return; *ierr = PetscStrncpy(name,c,len); } /* -----------------------------------------------------------------*/