static PetscErrorCode KSPSolve_PREONLY(KSP ksp) { PetscErrorCode ierr; PetscTruth diagonalscale; PetscFunctionBegin; ierr = PCDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name); if (!ksp->guess_zero) { SETERRQ(PETSC_ERR_USER,"Running KSP of preonly doesn't make sense with nonzero initial guess\n\ you probably want a KSP type of Richardson"); }
PetscErrorCode KSPSolve_CG(KSP ksp) { PetscErrorCode ierr; PetscInt i,stored_max_it,eigs; PetscScalar dpi = 0.0,a = 1.0,beta,betaold = 1.0,b = 0,*e = 0,*d = 0,delta,dpiold; PetscReal dp = 0.0; Vec X,B,Z,R,P,S,W; KSP_CG *cg; Mat Amat,Pmat; MatStructure pflag; PetscTruth diagonalscale; PetscFunctionBegin; ierr = PCDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name); cg = (KSP_CG*)ksp->data; eigs = ksp->calc_sings; stored_max_it = ksp->max_it; X = ksp->vec_sol; B = ksp->vec_rhs; R = ksp->work[0]; Z = ksp->work[1]; P = ksp->work[2]; if (cg->singlereduction) { S = ksp->work[3]; W = ksp->work[4]; } else { S = 0; /* unused */ W = Z; } #if !defined(PETSC_USE_COMPLEX) #define VecXDot(x,y,a) VecDot(x,y,a) #else #define VecXDot(x,y,a) (((cg->type) == (KSP_CG_HERMITIAN)) ? VecDot(x,y,a) : VecTDot(x,y,a)) #endif if (eigs) {e = cg->e; d = cg->d; e[0] = 0.0; } ierr = PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);CHKERRQ(ierr); ksp->its = 0; if (!ksp->guess_zero) { ierr = KSP_MatMult(ksp,Amat,X,R);CHKERRQ(ierr); /* r <- b - Ax */ ierr = VecAYPX(R,-1.0,B);CHKERRQ(ierr); } else { ierr = VecCopy(B,R);CHKERRQ(ierr); /* r <- b (x is 0) */ } if (ksp->normtype == KSP_NORM_PRECONDITIONED) { ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ ierr = VecNorm(Z,NORM_2,&dp);CHKERRQ(ierr); /* dp <- z'*z = e'*A'*B'*B*A'*e' */ } else if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) { ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); /* dp <- r'*r = e'*A'*A*e */ } else if (ksp->normtype == KSP_NORM_NATURAL) { ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ if (cg->singlereduction) { ierr = KSP_MatMult(ksp,Amat,Z,S);CHKERRQ(ierr); ierr = VecXDot(Z,S,&delta);CHKERRQ(ierr); } ierr = VecXDot(Z,R,&beta);CHKERRQ(ierr); /* beta <- z'*r */ if PetscIsInfOrNanScalar(beta) SETERRQ(PETSC_ERR_FP,"Infinite or not-a-number generated in dot product"); dp = sqrt(PetscAbsScalar(beta)); /* dp <- r'*z = r'*B*r = e'*A'*B*A*e */ } else dp = 0.0;
static PetscErrorCode KSPSolve_LSQR(KSP ksp) { PetscErrorCode ierr; PetscInt i,size1,size2; PetscScalar rho,rhobar,phi,phibar,theta,c,s,tmp,tau,alphac; PetscReal beta,alpha,rnorm; Vec X,B,V,V1,U,U1,TMP,W,W2,SE,Z = PETSC_NULL; Mat Amat,Pmat; MatStructure pflag; KSP_LSQR *lsqr = (KSP_LSQR*)ksp->data; PetscTruth diagonalscale,nopreconditioner; PetscFunctionBegin; ierr = PCDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name); ierr = PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);CHKERRQ(ierr); ierr = PetscTypeCompare((PetscObject)ksp->pc,PCNONE,&nopreconditioner);CHKERRQ(ierr); /* nopreconditioner =PETSC_FALSE; */ /* Calculate norm of right hand side */ ierr = VecNorm(ksp->vec_rhs,NORM_2,&lsqr->rhs_norm);CHKERRQ(ierr); /* Calculate norm of matrix*/ ierr = MatNorm( Amat, NORM_FROBENIUS, &lsqr->anorm);CHKERRQ(ierr); /* vectors of length m, where system size is mxn */ B = ksp->vec_rhs; U = lsqr->vwork_m[0]; U1 = lsqr->vwork_m[1]; /* vectors of length n */ X = ksp->vec_sol; W = lsqr->vwork_n[0]; V = lsqr->vwork_n[1]; V1 = lsqr->vwork_n[2]; W2 = lsqr->vwork_n[3]; if (!nopreconditioner) { Z = lsqr->vwork_n[4]; } /* standard error vector */ SE = lsqr->se; if (SE){ ierr = VecGetSize(SE,&size1);CHKERRQ(ierr); ierr = VecGetSize(X ,&size2);CHKERRQ(ierr); if (size1 != size2) SETERRQ2(PETSC_ERR_ARG_SIZ,"Standard error vector (size %d) does not match solution vector (size %d)",size1,size2); ierr = VecSet(SE,0.0);CHKERRQ(ierr); } /* Compute initial residual, temporarily use work vector u */ if (!ksp->guess_zero) { ierr = KSP_MatMult(ksp,Amat,X,U);CHKERRQ(ierr); /* u <- b - Ax */ ierr = VecAYPX(U,-1.0,B);CHKERRQ(ierr); } else { ierr = VecCopy(B,U);CHKERRQ(ierr); /* u <- b (x is 0) */ } /* Test for nothing to do */ ierr = VecNorm(U,NORM_2,&rnorm);CHKERRQ(ierr); ierr = PetscObjectTakeAccess(ksp);CHKERRQ(ierr); ksp->its = 0; ksp->rnorm = rnorm; ierr = PetscObjectGrantAccess(ksp);CHKERRQ(ierr); KSPLogResidualHistory(ksp,rnorm); KSPMonitor(ksp,0,rnorm); ierr = (*ksp->converged)(ksp,0,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) PetscFunctionReturn(0); ierr = VecCopy(B,U);CHKERRQ(ierr); ierr = VecNorm(U,NORM_2,&beta);CHKERRQ(ierr); ierr = VecScale(U,1.0/beta);CHKERRQ(ierr); ierr = KSP_MatMultTranspose(ksp,Amat,U,V); CHKERRQ(ierr); if (nopreconditioner) { ierr = VecNorm(V,NORM_2,&alpha); CHKERRQ(ierr); } else { ierr = PCApply(ksp->pc,V,Z);CHKERRQ(ierr); ierr = VecDot(V,Z,&alphac);CHKERRQ(ierr); if (PetscRealPart(alphac) <= 0.0) { ksp->reason = KSP_DIVERGED_BREAKDOWN; PetscFunctionReturn(0); } alpha = sqrt(PetscRealPart(alphac)); ierr = VecScale(Z,1.0/alpha); CHKERRQ(ierr); } ierr = VecScale(V,1.0/alpha);CHKERRQ(ierr); if (nopreconditioner){ ierr = VecCopy(V,W);CHKERRQ(ierr); } else { ierr = VecCopy(Z,W);CHKERRQ(ierr); } ierr = VecSet(X,0.0);CHKERRQ(ierr); lsqr->arnorm = alpha * beta; phibar = beta; rhobar = alpha; tau = -beta; i = 0; do { if (nopreconditioner) { ierr = KSP_MatMult(ksp,Amat,V,U1);CHKERRQ(ierr); } else { ierr = KSP_MatMult(ksp,Amat,Z,U1);CHKERRQ(ierr); } ierr = VecAXPY(U1,-alpha,U);CHKERRQ(ierr); ierr = VecNorm(U1,NORM_2,&beta);CHKERRQ(ierr); if (beta == 0.0){ ksp->reason = KSP_DIVERGED_BREAKDOWN; break; } ierr = VecScale(U1,1.0/beta);CHKERRQ(ierr); ierr = KSP_MatMultTranspose(ksp,Amat,U1,V1);CHKERRQ(ierr); ierr = VecAXPY(V1,-beta,V);CHKERRQ(ierr); if (nopreconditioner) { ierr = VecNorm(V1,NORM_2,&alpha); CHKERRQ(ierr); } else { ierr = PCApply(ksp->pc,V1,Z);CHKERRQ(ierr); ierr = VecDot(V1,Z,&alphac);CHKERRQ(ierr); if (PetscRealPart(alphac) <= 0.0) { ksp->reason = KSP_DIVERGED_BREAKDOWN; break; } alpha = sqrt(PetscRealPart(alphac)); ierr = VecScale(Z,1.0/alpha);CHKERRQ(ierr); } ierr = VecScale(V1,1.0/alpha);CHKERRQ(ierr); rho = PetscSqrtScalar(rhobar*rhobar + beta*beta); c = rhobar / rho; s = beta / rho; theta = s * alpha; rhobar = - c * alpha; phi = c * phibar; phibar = s * phibar; tau = s * phi; ierr = VecAXPY(X,phi/rho,W);CHKERRQ(ierr); /* x <- x + (phi/rho) w */ if (SE) { ierr = VecCopy(W,W2);CHKERRQ(ierr); ierr = VecSquare(W2);CHKERRQ(ierr); ierr = VecScale(W2,1.0/(rho*rho));CHKERRQ(ierr); ierr = VecAXPY(SE, 1.0, W2);CHKERRQ(ierr); /* SE <- SE + (w^2/rho^2) */ } if (nopreconditioner) { ierr = VecAYPX(W,-theta/rho,V1);CHKERRQ(ierr); /* w <- v - (theta/rho) w */ } else { ierr = VecAYPX(W,-theta/rho,Z);CHKERRQ(ierr); /* w <- z - (theta/rho) w */ } lsqr->arnorm = alpha*PetscAbsScalar(tau); rnorm = PetscRealPart(phibar); ierr = PetscObjectTakeAccess(ksp);CHKERRQ(ierr); ksp->its++; ksp->rnorm = rnorm; ierr = PetscObjectGrantAccess(ksp);CHKERRQ(ierr); KSPLogResidualHistory(ksp,rnorm); KSPMonitor(ksp,i+1,rnorm); ierr = (*ksp->converged)(ksp,i+1,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; SWAP(U1,U,TMP); SWAP(V1,V,TMP); i++; } while (i<ksp->max_it); if (i >= ksp->max_it && !ksp->reason) { ksp->reason = KSP_DIVERGED_ITS; } /* Finish off the standard error estimates */ if (SE) { tmp = 1.0; ierr = MatGetSize(Amat,&size1,&size2);CHKERRQ(ierr); if ( size1 > size2 ) tmp = size1 - size2; tmp = rnorm / PetscSqrtScalar(tmp); ierr = VecSqrt(SE);CHKERRQ(ierr); ierr = VecScale(SE,tmp);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode KSPSolve_Chebychev(KSP ksp) { PetscErrorCode ierr; PetscInt k,kp1,km1,maxit,ktmp,i; PetscScalar alpha,omegaprod,mu,omega,Gamma,c[3],scale; PetscReal rnorm = 0.0; Vec x,b,p[3],r; KSP_Chebychev *chebychevP = (KSP_Chebychev*)ksp->data; Mat Amat,Pmat; MatStructure pflag; PetscTruth diagonalscale; PetscFunctionBegin; if (ksp->normtype == KSP_NORM_NATURAL) SETERRQ(PETSC_ERR_SUP,"Cannot use natural residual norm with KSPCHEBYCHEV"); ierr = PCDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name); ksp->its = 0; ierr = PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);CHKERRQ(ierr); maxit = ksp->max_it; /* These three point to the three active solutions, we rotate these three at each solution update */ km1 = 0; k = 1; kp1 = 2; x = ksp->vec_sol; b = ksp->vec_rhs; p[km1] = x; p[k] = ksp->work[0]; p[kp1] = ksp->work[1]; r = ksp->work[2]; /* use scale*B as our preconditioner */ scale = 2.0/(chebychevP->emax + chebychevP->emin); /* -alpha <= scale*lambda(B^{-1}A) <= alpha */ alpha = 1.0 - scale*(chebychevP->emin); ; Gamma = 1.0; mu = 1.0/alpha; omegaprod = 2.0/alpha; c[km1] = 1.0; c[k] = mu; if (!ksp->guess_zero) { ierr = KSP_MatMult(ksp,Amat,x,r);CHKERRQ(ierr); /* r = b - Ax */ ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr); } else { ierr = VecCopy(b,r);CHKERRQ(ierr); } ierr = KSP_PCApply(ksp,r,p[k]);CHKERRQ(ierr); /* p[k] = scale B^{-1}r + x */ ierr = VecAYPX(p[k],scale,x);CHKERRQ(ierr); for (i=0; i<maxit; i++) { ierr = PetscObjectTakeAccess(ksp);CHKERRQ(ierr); ksp->its++; ierr = PetscObjectGrantAccess(ksp);CHKERRQ(ierr); c[kp1] = 2.0*mu*c[k] - c[km1]; omega = omegaprod*c[k]/c[kp1]; ierr = KSP_MatMult(ksp,Amat,p[k],r);CHKERRQ(ierr); /* r = b - Ap[k] */ ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr); ierr = KSP_PCApply(ksp,r,p[kp1]);CHKERRQ(ierr); /* p[kp1] = B^{-1}z */ /* calculate residual norm if requested */ if (ksp->normtype != KSP_NORM_NO) { if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {ierr = VecNorm(r,NORM_2,&rnorm);CHKERRQ(ierr);} else {ierr = VecNorm(p[kp1],NORM_2,&rnorm);CHKERRQ(ierr);} ierr = PetscObjectTakeAccess(ksp);CHKERRQ(ierr); ksp->rnorm = rnorm; ierr = PetscObjectGrantAccess(ksp);CHKERRQ(ierr); ksp->vec_sol = p[k]; KSPLogResidualHistory(ksp,rnorm); KSPMonitor(ksp,i,rnorm); ierr = (*ksp->converged)(ksp,i,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; } /* y^{k+1} = omega(y^{k} - y^{k-1} + Gamma*r^{k}) + y^{k-1} */ ierr = VecScale(p[kp1],omega*Gamma*scale);CHKERRQ(ierr); ierr = VecAXPY(p[kp1],1.0-omega,p[km1]);CHKERRQ(ierr); ierr = VecAXPY(p[kp1],omega,p[k]);CHKERRQ(ierr); ktmp = km1; km1 = k; k = kp1; kp1 = ktmp; } if (!ksp->reason) { if (ksp->normtype != KSP_NORM_NO) { ierr = KSP_MatMult(ksp,Amat,p[k],r);CHKERRQ(ierr); /* r = b - Ap[k] */ ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr); if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) { ierr = VecNorm(r,NORM_2,&rnorm);CHKERRQ(ierr); } else { ierr = KSP_PCApply(ksp,r,p[kp1]);CHKERRQ(ierr); /* p[kp1] = B^{-1}z */ ierr = VecNorm(p[kp1],NORM_2,&rnorm);CHKERRQ(ierr); } ierr = PetscObjectTakeAccess(ksp);CHKERRQ(ierr); ksp->rnorm = rnorm; ierr = PetscObjectGrantAccess(ksp);CHKERRQ(ierr); ksp->vec_sol = p[k]; KSPLogResidualHistory(ksp,rnorm); KSPMonitor(ksp,i,rnorm); } if (ksp->its >= ksp->max_it) { if (ksp->normtype != KSP_NORM_NO) { ierr = (*ksp->converged)(ksp,i,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (!ksp->reason) ksp->reason = KSP_DIVERGED_ITS; } else { ksp->reason = KSP_CONVERGED_ITS; } } } /* make sure solution is in vector x */ ksp->vec_sol = x; if (k) { ierr = VecCopy(p[k],x);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode KSPSolve_BiCG(KSP ksp) { PetscErrorCode ierr; PetscInt i; PetscTruth diagonalscale; PetscScalar dpi,a=1.0,beta,betaold=1.0,b,ma; PetscReal dp; Vec X,B,Zl,Zr,Rl,Rr,Pl,Pr; Mat Amat,Pmat; MatStructure pflag; PetscFunctionBegin; if (ksp->normtype == KSP_NORM_NATURAL) SETERRQ(PETSC_ERR_SUP,"Cannot use natural residual norm with KSPIBCGS"); ierr = PCDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name); X = ksp->vec_sol; B = ksp->vec_rhs; Rl = ksp->work[0]; Zl = ksp->work[1]; Pl = ksp->work[2]; Rr = ksp->work[3]; Zr = ksp->work[4]; Pr = ksp->work[5]; ierr = PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);CHKERRQ(ierr); if (!ksp->guess_zero) { ierr = KSP_MatMult(ksp,Amat,X,Rr);CHKERRQ(ierr); /* r <- b - Ax */ ierr = VecAYPX(Rr,-1.0,B);CHKERRQ(ierr); } else { ierr = VecCopy(B,Rr);CHKERRQ(ierr); /* r <- b (x is 0) */ } ierr = VecCopy(Rr,Rl);CHKERRQ(ierr); ierr = KSP_PCApply(ksp,Rr,Zr);CHKERRQ(ierr); /* z <- Br */ ierr = VecConjugate(Rl);CHKERRQ(ierr); ierr = KSP_PCApplyTranspose(ksp,Rl,Zl);CHKERRQ(ierr); ierr = VecConjugate(Rl);CHKERRQ(ierr); ierr = VecConjugate(Zl);CHKERRQ(ierr); if (ksp->normtype == KSP_NORM_PRECONDITIONED) { ierr = VecNorm(Zr,NORM_2,&dp);CHKERRQ(ierr); /* dp <- z'*z */ } else { ierr = VecNorm(Rr,NORM_2,&dp);CHKERRQ(ierr); /* dp <- r'*r */ } KSPMonitor(ksp,0,dp); ierr = PetscObjectTakeAccess(ksp);CHKERRQ(ierr); ksp->its = 0; ksp->rnorm = dp; ierr = PetscObjectGrantAccess(ksp);CHKERRQ(ierr); KSPLogResidualHistory(ksp,dp); ierr = (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) PetscFunctionReturn(0); i = 0; do { ierr = VecDot(Zr,Rl,&beta);CHKERRQ(ierr); /* beta <- r'z */ if (!i) { if (beta == 0.0) { ksp->reason = KSP_DIVERGED_BREAKDOWN_BICG; PetscFunctionReturn(0); } ierr = VecCopy(Zr,Pr);CHKERRQ(ierr); /* p <- z */ ierr = VecCopy(Zl,Pl);CHKERRQ(ierr); } else { b = beta/betaold; ierr = VecAYPX(Pr,b,Zr);CHKERRQ(ierr); /* p <- z + b* p */ b = PetscConj(b); ierr = VecAYPX(Pl,b,Zl);CHKERRQ(ierr); } betaold = beta; ierr = KSP_MatMult(ksp,Amat,Pr,Zr);CHKERRQ(ierr); /* z <- Kp */ ierr = VecConjugate(Pl);CHKERRQ(ierr); ierr = KSP_MatMultTranspose(ksp,Amat,Pl,Zl);CHKERRQ(ierr); ierr = VecConjugate(Pl);CHKERRQ(ierr); ierr = VecConjugate(Zl);CHKERRQ(ierr); ierr = VecDot(Zr,Pl,&dpi);CHKERRQ(ierr); /* dpi <- z'p */ a = beta/dpi; /* a = beta/p'z */ ierr = VecAXPY(X,a,Pr);CHKERRQ(ierr); /* x <- x + ap */ ma = -a; ierr = VecAXPY(Rr,ma,Zr);CHKERRQ(ierr) ma = PetscConj(ma); ierr = VecAXPY(Rl,ma,Zl);CHKERRQ(ierr); if (ksp->normtype == KSP_NORM_PRECONDITIONED) { ierr = KSP_PCApply(ksp,Rr,Zr);CHKERRQ(ierr); /* z <- Br */ ierr = VecConjugate(Rl);CHKERRQ(ierr); ierr = KSP_PCApplyTranspose(ksp,Rl,Zl);CHKERRQ(ierr); ierr = VecConjugate(Rl);CHKERRQ(ierr); ierr = VecConjugate(Zl);CHKERRQ(ierr); ierr = VecNorm(Zr,NORM_2,&dp);CHKERRQ(ierr); /* dp <- z'*z */ } else { ierr = VecNorm(Rr,NORM_2,&dp);CHKERRQ(ierr); /* dp <- r'*r */ } ierr = PetscObjectTakeAccess(ksp);CHKERRQ(ierr); ksp->its = i+1; ksp->rnorm = dp; ierr = PetscObjectGrantAccess(ksp);CHKERRQ(ierr); KSPLogResidualHistory(ksp,dp); KSPMonitor(ksp,i+1,dp); ierr = (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) { ierr = KSP_PCApply(ksp,Rr,Zr);CHKERRQ(ierr); /* z <- Br */ ierr = VecConjugate(Rl);CHKERRQ(ierr); ierr = KSP_PCApplyTranspose(ksp,Rl,Zl);CHKERRQ(ierr); ierr = VecConjugate(Rl);CHKERRQ(ierr); ierr = VecConjugate(Zl);CHKERRQ(ierr); } i++; } while (i<ksp->max_it); if (i >= ksp->max_it) { ksp->reason = KSP_DIVERGED_ITS; } PetscFunctionReturn(0); }