PetscErrorCode KSPGMRESModifiedGramSchmidtOrthogonalization(KSP ksp,PetscInt it) { KSP_GMRES *gmres = (KSP_GMRES*)(ksp->data); PetscErrorCode ierr; PetscInt j; PetscScalar *hh,*hes; PetscFunctionBegin; ierr = PetscLogEventBegin(KSP_GMRESOrthogonalization,ksp,0,0,0);CHKERRQ(ierr); /* update Hessenberg matrix and do Gram-Schmidt */ hh = HH(0,it); hes = HES(0,it); for (j=0; j<=it; j++) { /* (vv(it+1), vv(j)) */ ierr = VecDot(VEC_VV(it+1),VEC_VV(j),hh);CHKERRQ(ierr); KSPCheckDot(ksp,*hh); *hes++ = *hh; /* vv(it+1) <- vv(it+1) - hh[it+1][j] vv(j) */ ierr = VecAXPY(VEC_VV(it+1),-(*hh++),VEC_VV(j));CHKERRQ(ierr); } ierr = PetscLogEventEnd(KSP_GMRESOrthogonalization,ksp,0,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode KSPSolve_TCQMR(KSP ksp) { PetscReal rnorm0,rnorm,dp1,Gamma; PetscScalar theta,ep,cl1,sl1,cl,sl,sprod,tau_n1,f; PetscScalar deltmp,rho,beta,eptmp,ta,s,c,tau_n,delta; PetscScalar dp11,dp2,rhom1,alpha,tmp; PetscErrorCode ierr; PetscFunctionBegin; ksp->its = 0; ierr = KSPInitialResidual(ksp,x,u,v,r,b);CHKERRQ(ierr); ierr = VecNorm(r,NORM_2,&rnorm0);CHKERRQ(ierr); /* rnorm0 = ||r|| */ KSPCheckNorm(ksp,rnorm0); ierr = (*ksp->converged)(ksp,0,rnorm0,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) PetscFunctionReturn(0); ierr = VecSet(um1,0.0);CHKERRQ(ierr); ierr = VecCopy(r,u);CHKERRQ(ierr); rnorm = rnorm0; tmp = 1.0/rnorm; ierr = VecScale(u,tmp);CHKERRQ(ierr); ierr = VecSet(vm1,0.0);CHKERRQ(ierr); ierr = VecCopy(u,v);CHKERRQ(ierr); ierr = VecCopy(u,v0);CHKERRQ(ierr); ierr = VecSet(pvec1,0.0);CHKERRQ(ierr); ierr = VecSet(pvec2,0.0);CHKERRQ(ierr); ierr = VecSet(p,0.0);CHKERRQ(ierr); theta = 0.0; ep = 0.0; cl1 = 0.0; sl1 = 0.0; cl = 0.0; sl = 0.0; sprod = 1.0; tau_n1= rnorm0; f = 1.0; Gamma = 1.0; rhom1 = 1.0; /* CALCULATE SQUARED LANCZOS vectors */ ierr = (*ksp->converged)(ksp,ksp->its,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); while (!ksp->reason) { ierr = KSPMonitor(ksp,ksp->its,rnorm);CHKERRQ(ierr); ksp->its++; ierr = KSP_PCApplyBAorAB(ksp,u,y,vtmp);CHKERRQ(ierr); /* y = A*u */ ierr = VecDot(y,v0,&dp11);CHKERRQ(ierr); KSPCheckDot(ksp,dp11); ierr = VecDot(u,v0,&dp2);CHKERRQ(ierr); alpha = dp11 / dp2; /* alpha = v0'*y/v0'*u */ deltmp = alpha; ierr = VecCopy(y,z);CHKERRQ(ierr); ierr = VecAXPY(z,-alpha,u);CHKERRQ(ierr); /* z = y - alpha u */ ierr = VecDot(u,v0,&rho);CHKERRQ(ierr); beta = rho / (f*rhom1); rhom1 = rho; ierr = VecCopy(z,utmp);CHKERRQ(ierr); /* up1 = (A-alpha*I)* (z-2*beta*p) + f*beta* beta*um1 */ ierr = VecAXPY(utmp,-2.0*beta,p);CHKERRQ(ierr); ierr = KSP_PCApplyBAorAB(ksp,utmp,up1,vtmp);CHKERRQ(ierr); ierr = VecAXPY(up1,-alpha,utmp);CHKERRQ(ierr); ierr = VecAXPY(up1,f*beta*beta,um1);CHKERRQ(ierr); ierr = VecNorm(up1,NORM_2,&dp1);CHKERRQ(ierr); KSPCheckNorm(ksp,dp1); f = 1.0 / dp1; ierr = VecScale(up1,f);CHKERRQ(ierr); ierr = VecAYPX(p,-beta,z);CHKERRQ(ierr); /* p = f*(z-beta*p) */ ierr = VecScale(p,f);CHKERRQ(ierr); ierr = VecCopy(u,um1);CHKERRQ(ierr); ierr = VecCopy(up1,u);CHKERRQ(ierr); beta = beta/Gamma; eptmp = beta; ierr = KSP_PCApplyBAorAB(ksp,v,vp1,vtmp);CHKERRQ(ierr); ierr = VecAXPY(vp1,-alpha,v);CHKERRQ(ierr); ierr = VecAXPY(vp1,-beta,vm1);CHKERRQ(ierr); ierr = VecNorm(vp1,NORM_2,&Gamma);CHKERRQ(ierr); KSPCheckNorm(ksp,Gamma); ierr = VecScale(vp1,1.0/Gamma);CHKERRQ(ierr); ierr = VecCopy(v,vm1);CHKERRQ(ierr); ierr = VecCopy(vp1,v);CHKERRQ(ierr); /* SOLVE Ax = b */ /* Apply last two Given's (Gl-1 and Gl) rotations to (beta,alpha,Gamma) */ if (ksp->its > 2) { theta = sl1*beta; eptmp = -cl1*beta; } if (ksp->its > 1) { ep = -cl*eptmp + sl*alpha; deltmp = -sl*eptmp - cl*alpha; } if (PetscAbsReal(Gamma) > PetscAbsScalar(deltmp)) { ta = -deltmp / Gamma; s = 1.0 / PetscSqrtScalar(1.0 + ta*ta); c = s*ta; } else { ta = -Gamma/deltmp; c = 1.0 / PetscSqrtScalar(1.0 + ta*ta); s = c*ta; } delta = -c*deltmp + s*Gamma; tau_n = -c*tau_n1; tau_n1 = -s*tau_n1; ierr = VecCopy(vm1,pvec);CHKERRQ(ierr); ierr = VecAXPY(pvec,-theta,pvec2);CHKERRQ(ierr); ierr = VecAXPY(pvec,-ep,pvec1);CHKERRQ(ierr); ierr = VecScale(pvec,1.0/delta);CHKERRQ(ierr); ierr = VecAXPY(x,tau_n,pvec);CHKERRQ(ierr); cl1 = cl; sl1 = sl; cl = c; sl = s; ierr = VecCopy(pvec1,pvec2);CHKERRQ(ierr); ierr = VecCopy(pvec,pvec1);CHKERRQ(ierr); /* Compute the upper bound on the residual norm r (See QMR paper p. 13) */ sprod = sprod*PetscAbsScalar(s); rnorm = rnorm0 * PetscSqrtReal((PetscReal)ksp->its+2.0) * PetscRealPart(sprod); ierr = (*ksp->converged)(ksp,ksp->its,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->its >= ksp->max_it) { if (!ksp->reason) ksp->reason = KSP_DIVERGED_ITS; break; } } ierr = KSPMonitor(ksp,ksp->its,rnorm);CHKERRQ(ierr); ierr = KSPUnwindPreconditioner(ksp,x,vtmp);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode KSPSolve_PIPECG(KSP ksp) { PetscErrorCode ierr; PetscInt i; PetscScalar alpha = 0.0,beta = 0.0,gamma = 0.0,gammaold = 0.0,delta = 0.0; PetscReal dp = 0.0; Vec X,B,Z,P,W,Q,U,M,N,R,S; Mat Amat,Pmat; PetscBool diagonalscale; PetscFunctionBegin; ierr = PCGetDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name); X = ksp->vec_sol; B = ksp->vec_rhs; M = ksp->work[0]; Z = ksp->work[1]; P = ksp->work[2]; N = ksp->work[3]; W = ksp->work[4]; Q = ksp->work[5]; U = ksp->work[6]; R = ksp->work[7]; S = ksp->work[8]; ierr = PCGetOperators(ksp->pc,&Amat,&Pmat);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) */ } ierr = KSP_PCApply(ksp,R,U);CHKERRQ(ierr); /* u <- Br */ switch (ksp->normtype) { case KSP_NORM_PRECONDITIONED: ierr = VecNormBegin(U,NORM_2,&dp);CHKERRQ(ierr); /* dp <- u'*u = e'*A'*B'*B*A'*e' */ ierr = PetscCommSplitReductionBegin(PetscObjectComm((PetscObject)U));CHKERRQ(ierr); ierr = KSP_MatMult(ksp,Amat,U,W);CHKERRQ(ierr); /* w <- Au */ ierr = VecNormEnd(U,NORM_2,&dp);CHKERRQ(ierr); break; case KSP_NORM_UNPRECONDITIONED: ierr = VecNormBegin(R,NORM_2,&dp);CHKERRQ(ierr); /* dp <- r'*r = e'*A'*A*e */ ierr = PetscCommSplitReductionBegin(PetscObjectComm((PetscObject)R));CHKERRQ(ierr); ierr = KSP_MatMult(ksp,Amat,U,W);CHKERRQ(ierr); /* w <- Au */ ierr = VecNormEnd(R,NORM_2,&dp);CHKERRQ(ierr); break; case KSP_NORM_NATURAL: ierr = VecDotBegin(R,U,&gamma);CHKERRQ(ierr); /* gamma <- u'*r */ ierr = PetscCommSplitReductionBegin(PetscObjectComm((PetscObject)R));CHKERRQ(ierr); ierr = KSP_MatMult(ksp,Amat,U,W);CHKERRQ(ierr); /* w <- Au */ ierr = VecDotEnd(R,U,&gamma);CHKERRQ(ierr); KSPCheckDot(ksp,gamma); dp = PetscSqrtReal(PetscAbsScalar(gamma)); /* dp <- r'*u = r'*B*r = e'*A'*B*A*e */ break; case KSP_NORM_NONE: ierr = KSP_MatMult(ksp,Amat,U,W);CHKERRQ(ierr); dp = 0.0; break; default: SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"%s",KSPNormTypes[ksp->normtype]); } ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,dp);CHKERRQ(ierr); ksp->rnorm = dp; ierr = (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); /* test for convergence */ if (ksp->reason) PetscFunctionReturn(0); i = 0; do { if (i > 0 && ksp->normtype == KSP_NORM_UNPRECONDITIONED) { ierr = VecNormBegin(R,NORM_2,&dp);CHKERRQ(ierr); } else if (i > 0 && ksp->normtype == KSP_NORM_PRECONDITIONED) { ierr = VecNormBegin(U,NORM_2,&dp);CHKERRQ(ierr); } if (!(i == 0 && ksp->normtype == KSP_NORM_NATURAL)) { ierr = VecDotBegin(R,U,&gamma);CHKERRQ(ierr); } ierr = VecDotBegin(W,U,&delta);CHKERRQ(ierr); ierr = PetscCommSplitReductionBegin(PetscObjectComm((PetscObject)R));CHKERRQ(ierr); ierr = KSP_PCApply(ksp,W,M);CHKERRQ(ierr); /* m <- Bw */ ierr = KSP_MatMult(ksp,Amat,M,N);CHKERRQ(ierr); /* n <- Am */ if (i > 0 && ksp->normtype == KSP_NORM_UNPRECONDITIONED) { ierr = VecNormEnd(R,NORM_2,&dp);CHKERRQ(ierr); } else if (i > 0 && ksp->normtype == KSP_NORM_PRECONDITIONED) { ierr = VecNormEnd(U,NORM_2,&dp);CHKERRQ(ierr); } if (!(i == 0 && ksp->normtype == KSP_NORM_NATURAL)) { ierr = VecDotEnd(R,U,&gamma);CHKERRQ(ierr); } ierr = VecDotEnd(W,U,&delta);CHKERRQ(ierr); if (i > 0) { if (ksp->normtype == KSP_NORM_NATURAL) dp = PetscSqrtReal(PetscAbsScalar(gamma)); else if (ksp->normtype == KSP_NORM_NONE) dp = 0.0; ksp->rnorm = dp; ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,i,dp);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,i,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; } if (i == 0) { alpha = gamma / delta; ierr = VecCopy(N,Z);CHKERRQ(ierr); /* z <- n */ ierr = VecCopy(M,Q);CHKERRQ(ierr); /* q <- m */ ierr = VecCopy(U,P);CHKERRQ(ierr); /* p <- u */ ierr = VecCopy(W,S);CHKERRQ(ierr); /* s <- w */ } else { beta = gamma / gammaold; alpha = gamma / (delta - beta / alpha * gamma); ierr = VecAYPX(Z,beta,N);CHKERRQ(ierr); /* z <- n + beta * z */ ierr = VecAYPX(Q,beta,M);CHKERRQ(ierr); /* q <- m + beta * q */ ierr = VecAYPX(P,beta,U);CHKERRQ(ierr); /* p <- u + beta * p */ ierr = VecAYPX(S,beta,W);CHKERRQ(ierr); /* s <- w + beta * s */ } ierr = VecAXPY(X, alpha,P);CHKERRQ(ierr); /* x <- x + alpha * p */ ierr = VecAXPY(U,-alpha,Q);CHKERRQ(ierr); /* u <- u - alpha * q */ ierr = VecAXPY(W,-alpha,Z);CHKERRQ(ierr); /* w <- w - alpha * z */ ierr = VecAXPY(R,-alpha,S);CHKERRQ(ierr); /* r <- r - alpha * s */ gammaold = gamma; i++; ksp->its = i; /* if (i%50 == 0) { */ /* ierr = KSP_MatMult(ksp,Amat,X,R);CHKERRQ(ierr); /\* w <- b - Ax *\/ */ /* ierr = VecAYPX(R,-1.0,B);CHKERRQ(ierr); */ /* ierr = KSP_PCApply(ksp,R,U);CHKERRQ(ierr); */ /* ierr = KSP_MatMult(ksp,Amat,U,W);CHKERRQ(ierr); */ /* } */ } while (i<ksp->max_it); if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS; PetscFunctionReturn(0); }
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; PetscBool diagonalscale; PetscFunctionBegin; ierr = PCGetDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),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; } #define VecXDot(x,y,a) (((cg->type) == (KSP_CG_HERMITIAN)) ? VecDot(x,y,a) : VecTDot(x,y,a)) if (eigs) {e = cg->e; d = cg->d; e[0] = 0.0; } ierr = PCGetOperators(ksp->pc,&Amat,&Pmat);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) */ } switch (ksp->normtype) { case 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' */ break; case KSP_NORM_UNPRECONDITIONED: ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); /* dp <- r'*r = e'*A'*A*e */ break; case 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 */ KSPCheckDot(ksp,beta); dp = PetscSqrtReal(PetscAbsScalar(beta)); /* dp <- r'*z = r'*B*r = e'*A'*B*A*e */ break; case KSP_NORM_NONE: dp = 0.0; break; default: SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"%s",KSPNormTypes[ksp->normtype]); } ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,dp);CHKERRQ(ierr); ksp->rnorm = dp; ierr = (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); /* test for convergence */ if (ksp->reason) PetscFunctionReturn(0); if (ksp->normtype != KSP_NORM_PRECONDITIONED && (ksp->normtype != KSP_NORM_NATURAL)) { ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ } if (ksp->normtype != KSP_NORM_NATURAL) { 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 */ KSPCheckDot(ksp,beta); } i = 0; do { ksp->its = i+1; if (beta == 0.0) { ksp->reason = KSP_CONVERGED_ATOL; ierr = PetscInfo(ksp,"converged due to beta = 0\n");CHKERRQ(ierr); break; #if !defined(PETSC_USE_COMPLEX) } else if ((i > 0) && (beta*betaold < 0.0)) { ksp->reason = KSP_DIVERGED_INDEFINITE_PC; ierr = PetscInfo(ksp,"diverging due to indefinite preconditioner\n");CHKERRQ(ierr); break; #endif } if (!i) { ierr = VecCopy(Z,P);CHKERRQ(ierr); /* p <- z */ b = 0.0; } else { b = beta/betaold; if (eigs) { if (ksp->max_it != stored_max_it) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Can not change maxit AND calculate eigenvalues"); e[i] = PetscSqrtReal(PetscAbsScalar(b))/a; } ierr = VecAYPX(P,b,Z);CHKERRQ(ierr); /* p <- z + b* p */ } dpiold = dpi; if (!cg->singlereduction || !i) { ierr = KSP_MatMult(ksp,Amat,P,W);CHKERRQ(ierr); /* w <- Ap */ ierr = VecXDot(P,W,&dpi);CHKERRQ(ierr); /* dpi <- p'w */ } else { ierr = VecAYPX(W,beta/betaold,S);CHKERRQ(ierr); /* w <- Ap */ dpi = delta - beta*beta*dpiold/(betaold*betaold); /* dpi <- p'w */ } betaold = beta; KSPCheckDot(ksp,beta); if ((dpi == 0.0) || ((i > 0) && (PetscRealPart(dpi*dpiold) <= 0.0))) { ksp->reason = KSP_DIVERGED_INDEFINITE_MAT; ierr = PetscInfo(ksp,"diverging due to indefinite or negative definite matrix\n");CHKERRQ(ierr); break; } a = beta/dpi; /* a = beta/p'w */ if (eigs) d[i] = PetscSqrtReal(PetscAbsScalar(b))*e[i] + 1.0/a; ierr = VecAXPY(X,a,P);CHKERRQ(ierr); /* x <- x + ap */ ierr = VecAXPY(R,-a,W);CHKERRQ(ierr); /* r <- r - aw */ if (ksp->normtype == KSP_NORM_PRECONDITIONED && ksp->chknorm < i+2) { ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ if (cg->singlereduction) { ierr = KSP_MatMult(ksp,Amat,Z,S);CHKERRQ(ierr); } ierr = VecNorm(Z,NORM_2,&dp);CHKERRQ(ierr); /* dp <- z'*z */ } else if (ksp->normtype == KSP_NORM_UNPRECONDITIONED && ksp->chknorm < i+2) { ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); /* dp <- r'*r */ } else if (ksp->normtype == KSP_NORM_NATURAL) { ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ if (cg->singlereduction) { PetscScalar tmp[2]; Vec vecs[2]; vecs[0] = S; vecs[1] = R; ierr = KSP_MatMult(ksp,Amat,Z,S);CHKERRQ(ierr); ierr = VecMDot(Z,2,vecs,tmp);CHKERRQ(ierr); delta = tmp[0]; beta = tmp[1]; } else { ierr = VecXDot(Z,R,&beta);CHKERRQ(ierr); /* beta <- r'*z */ } KSPCheckDot(ksp,beta); dp = PetscSqrtReal(PetscAbsScalar(beta)); } else { dp = 0.0; } ksp->rnorm = dp; CHKERRQ(ierr);KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); if (eigs) cg->ned = ksp->its; ierr = KSPMonitor(ksp,i+1,dp);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; if ((ksp->normtype != KSP_NORM_PRECONDITIONED && (ksp->normtype != KSP_NORM_NATURAL)) || (ksp->chknorm >= i+2)) { ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ if (cg->singlereduction) { ierr = KSP_MatMult(ksp,Amat,Z,S);CHKERRQ(ierr); } } if ((ksp->normtype != KSP_NORM_NATURAL) || (ksp->chknorm >= i+2)) { if (cg->singlereduction) { PetscScalar tmp[2]; Vec vecs[2]; vecs[0] = S; vecs[1] = R; ierr = VecMDot(Z,2,vecs,tmp);CHKERRQ(ierr); delta = tmp[0]; beta = tmp[1]; } else { ierr = VecXDot(Z,R,&beta);CHKERRQ(ierr); /* beta <- z'*r */ } KSPCheckDot(ksp,beta); } i++; } while (i<ksp->max_it); if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS; PetscFunctionReturn(0); }
static PetscErrorCode KSPSolve_CGS(KSP ksp) { PetscErrorCode ierr; PetscInt i; PetscScalar rho,rhoold,a,s,b; Vec X,B,V,P,R,RP,T,Q,U,AUQ; PetscReal dp = 0.0; PetscBool diagonalscale; PetscFunctionBegin; /* not sure what residual norm it does use, should use for right preconditioning */ ierr = PCGetDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name); X = ksp->vec_sol; B = ksp->vec_rhs; R = ksp->work[0]; RP = ksp->work[1]; V = ksp->work[2]; T = ksp->work[3]; Q = ksp->work[4]; P = ksp->work[5]; U = ksp->work[6]; AUQ = V; /* Compute initial preconditioned residual */ ierr = KSPInitialResidual(ksp,X,V,T,R,B);CHKERRQ(ierr); /* Test for nothing to do */ ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); KSPCheckNorm(ksp,dp); if (ksp->normtype == KSP_NORM_NATURAL) dp *= dp; ierr = PetscObjectSAWsTakeAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->its = 0; ksp->rnorm = dp; ierr = PetscObjectSAWsGrantAccess((PetscObject)ksp);CHKERRQ(ierr); ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,dp);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) PetscFunctionReturn(0); /* Make the initial Rp == R */ ierr = VecCopy(R,RP);CHKERRQ(ierr); /* added for Fidap */ /* Penalize Startup - Isaac Hasbani Trick for CGS Since most initial conditions result in a mostly 0 residual, we change all the 0 values in the vector RP to the maximum. */ if (ksp->normtype == KSP_NORM_NATURAL) { PetscReal vr0max; PetscScalar *tmp_RP=0; PetscInt numnp =0, *max_pos=0; ierr = VecMax(RP, max_pos, &vr0max);CHKERRQ(ierr); ierr = VecGetArray(RP, &tmp_RP);CHKERRQ(ierr); ierr = VecGetLocalSize(RP, &numnp);CHKERRQ(ierr); for (i=0; i<numnp; i++) { if (tmp_RP[i] == 0.0) tmp_RP[i] = vr0max; } ierr = VecRestoreArray(RP, &tmp_RP);CHKERRQ(ierr); } /* end of addition for Fidap */ /* Set the initial conditions */ ierr = VecDot(R,RP,&rhoold);CHKERRQ(ierr); /* rhoold = (r,rp) */ ierr = VecCopy(R,U);CHKERRQ(ierr); ierr = VecCopy(R,P);CHKERRQ(ierr); ierr = KSP_PCApplyBAorAB(ksp,P,V,T);CHKERRQ(ierr); i = 0; do { ierr = VecDot(V,RP,&s);CHKERRQ(ierr); /* s <- (v,rp) */ KSPCheckDot(ksp,s); a = rhoold / s; /* a <- rho / s */ ierr = VecWAXPY(Q,-a,V,U);CHKERRQ(ierr); /* q <- u - a v */ ierr = VecWAXPY(T,1.0,U,Q);CHKERRQ(ierr); /* t <- u + q */ ierr = VecAXPY(X,a,T);CHKERRQ(ierr); /* x <- x + a (u + q) */ ierr = KSP_PCApplyBAorAB(ksp,T,AUQ,U);CHKERRQ(ierr); ierr = VecAXPY(R,-a,AUQ);CHKERRQ(ierr); /* r <- r - a K (u + q) */ ierr = VecDot(R,RP,&rho);CHKERRQ(ierr); /* rho <- (r,rp) */ KSPCheckDot(ksp,rho); if (ksp->normtype == KSP_NORM_NATURAL) { dp = PetscAbsScalar(rho); } else { ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); KSPCheckNorm(ksp,dp); } ierr = PetscObjectSAWsTakeAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->its++; ksp->rnorm = dp; ierr = PetscObjectSAWsGrantAccess((PetscObject)ksp);CHKERRQ(ierr); ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,i+1,dp);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; b = rho / rhoold; /* b <- rho / rhoold */ ierr = VecWAXPY(U,b,Q,R);CHKERRQ(ierr); /* u <- r + b q */ ierr = VecAXPY(Q,b,P);CHKERRQ(ierr); ierr = VecWAXPY(P,b,Q,U);CHKERRQ(ierr); /* p <- u + b(q + b p) */ ierr = KSP_PCApplyBAorAB(ksp,P,V,Q);CHKERRQ(ierr); /* v <- K p */ rhoold = rho; i++; } while (i<ksp->max_it); if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS; ierr = KSPUnwindPreconditioner(ksp,X,T);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode KSPSolve_SYMMLQ(KSP ksp) { PetscErrorCode ierr; PetscInt i; PetscScalar alpha,beta,ibeta,betaold,beta1,ceta = 0,ceta_oold = 0.0, ceta_old = 0.0,ceta_bar; PetscScalar c = 1.0,cold=1.0,s=0.0,sold=0.0,coold,soold,rho0,rho1,rho2,rho3; PetscScalar dp = 0.0; PetscReal np,s_prod; Vec X,B,R,Z,U,V,W,UOLD,VOLD,Wbar; Mat Amat,Pmat; KSP_SYMMLQ *symmlq = (KSP_SYMMLQ*)ksp->data; PetscBool diagonalscale; PetscFunctionBegin; ierr = PCGetDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name); X = ksp->vec_sol; B = ksp->vec_rhs; R = ksp->work[0]; Z = ksp->work[1]; U = ksp->work[2]; V = ksp->work[3]; W = ksp->work[4]; UOLD = ksp->work[5]; VOLD = ksp->work[6]; Wbar = ksp->work[7]; ierr = PCGetOperators(ksp->pc,&Amat,&Pmat);CHKERRQ(ierr); ksp->its = 0; ierr = VecSet(UOLD,0.0);CHKERRQ(ierr); /* u_old <- zeros; */ ierr = VecCopy(UOLD,VOLD);CHKERRQ(ierr); /* v_old <- u_old; */ ierr = VecCopy(UOLD,W);CHKERRQ(ierr); /* w <- u_old; */ ierr = VecCopy(UOLD,Wbar);CHKERRQ(ierr); /* w_bar <- u_old; */ if (!ksp->guess_zero) { ierr = KSP_MatMult(ksp,Amat,X,R);CHKERRQ(ierr); /* r <- b - A*x */ ierr = VecAYPX(R,-1.0,B);CHKERRQ(ierr); } else { ierr = VecCopy(B,R);CHKERRQ(ierr); /* r <- b (x is 0) */ } ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- B*r */ ierr = VecDot(R,Z,&dp);CHKERRQ(ierr); /* dp = r'*z; */ KSPCheckDot(ksp,dp); if (PetscAbsScalar(dp) < symmlq->haptol) { ierr = PetscInfo2(ksp,"Detected happy breakdown %g tolerance %g\n",(double)PetscAbsScalar(dp),(double)symmlq->haptol);CHKERRQ(ierr); ksp->rnorm = 0.0; /* what should we really put here? */ ksp->reason = KSP_CONVERGED_HAPPY_BREAKDOWN; /* bugfix proposed by Lourens ([email protected]) */ PetscFunctionReturn(0); } #if !defined(PETSC_USE_COMPLEX) if (dp < 0.0) { ksp->reason = KSP_DIVERGED_INDEFINITE_PC; PetscFunctionReturn(0); } #endif dp = PetscSqrtScalar(dp); beta = dp; /* beta <- sqrt(r'*z) */ beta1 = beta; s_prod = PetscAbsScalar(beta1); ierr = VecCopy(R,V);CHKERRQ(ierr); /* v <- r; */ ierr = VecCopy(Z,U);CHKERRQ(ierr); /* u <- z; */ ibeta = 1.0 / beta; ierr = VecScale(V,ibeta);CHKERRQ(ierr); /* v <- ibeta*v; */ ierr = VecScale(U,ibeta);CHKERRQ(ierr); /* u <- ibeta*u; */ ierr = VecCopy(U,Wbar);CHKERRQ(ierr); /* w_bar <- u; */ ierr = VecNorm(Z,NORM_2,&np);CHKERRQ(ierr); /* np <- ||z|| */ KSPCheckNorm(ksp,np); ierr = KSPLogResidualHistory(ksp,np);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,np);CHKERRQ(ierr); ksp->rnorm = np; ierr = (*ksp->converged)(ksp,0,np,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); /* test for convergence */ if (ksp->reason) PetscFunctionReturn(0); i = 0; ceta = 0.; do { ksp->its = i+1; /* Update */ if (ksp->its > 1) { ierr = VecCopy(V,VOLD);CHKERRQ(ierr); /* v_old <- v; */ ierr = VecCopy(U,UOLD);CHKERRQ(ierr); /* u_old <- u; */ ierr = VecCopy(R,V);CHKERRQ(ierr); ierr = VecScale(V,1.0/beta);CHKERRQ(ierr); /* v <- ibeta*r; */ ierr = VecCopy(Z,U);CHKERRQ(ierr); ierr = VecScale(U,1.0/beta);CHKERRQ(ierr); /* u <- ibeta*z; */ ierr = VecCopy(Wbar,W);CHKERRQ(ierr); ierr = VecScale(W,c);CHKERRQ(ierr); ierr = VecAXPY(W,s,U);CHKERRQ(ierr); /* w <- c*w_bar + s*u; (w_k) */ ierr = VecScale(Wbar,-s);CHKERRQ(ierr); ierr = VecAXPY(Wbar,c,U);CHKERRQ(ierr); /* w_bar <- -s*w_bar + c*u; (w_bar_(k+1)) */ ierr = VecAXPY(X,ceta,W);CHKERRQ(ierr); /* x <- x + ceta * w; (xL_k) */ ceta_oold = ceta_old; ceta_old = ceta; } /* Lanczos */ ierr = KSP_MatMult(ksp,Amat,U,R);CHKERRQ(ierr); /* r <- Amat*u; */ ierr = VecDot(U,R,&alpha);CHKERRQ(ierr); /* alpha <- u'*r; */ ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- B*r; */ ierr = VecAXPY(R,-alpha,V);CHKERRQ(ierr); /* r <- r - alpha* v; */ ierr = VecAXPY(Z,-alpha,U);CHKERRQ(ierr); /* z <- z - alpha* u; */ ierr = VecAXPY(R,-beta,VOLD);CHKERRQ(ierr); /* r <- r - beta * v_old; */ ierr = VecAXPY(Z,-beta,UOLD);CHKERRQ(ierr); /* z <- z - beta * u_old; */ betaold = beta; /* beta_k */ ierr = VecDot(R,Z,&dp);CHKERRQ(ierr); /* dp <- r'*z; */ KSPCheckDot(ksp,dp); if (PetscAbsScalar(dp) < symmlq->haptol) { ierr = PetscInfo2(ksp,"Detected happy breakdown %g tolerance %g\n",(double)PetscAbsScalar(dp),(double)symmlq->haptol);CHKERRQ(ierr); dp = 0.0; } #if !defined(PETSC_USE_COMPLEX) if (dp < 0.0) { ksp->reason = KSP_DIVERGED_INDEFINITE_PC; break; } #endif beta = PetscSqrtScalar(dp); /* beta = sqrt(dp); */ /* QR factorization */ coold = cold; cold = c; soold = sold; sold = s; rho0 = cold * alpha - coold * sold * betaold; /* gamma_bar */ rho1 = PetscSqrtScalar(rho0*rho0 + beta*beta); /* gamma */ rho2 = sold * alpha + coold * cold * betaold; /* delta */ rho3 = soold * betaold; /* epsilon */ /* Givens rotation: [c -s; s c] (different from the Reference!) */ c = rho0 / rho1; s = beta / rho1; if (ksp->its==1) ceta = beta1/rho1; else ceta = -(rho2*ceta_old + rho3*ceta_oold)/rho1; s_prod = s_prod*PetscAbsScalar(s); if (c == 0.0) np = s_prod*1.e16; else np = s_prod/PetscAbsScalar(c); /* residual norm for xc_k (CGNORM) */ ksp->rnorm = np; ierr = KSPLogResidualHistory(ksp,np);CHKERRQ(ierr); ierr = KSPMonitor(ksp,i+1,np);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,i+1,np,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); /* test for convergence */ if (ksp->reason) break; i++; } while (i<ksp->max_it); /* move to the CG point: xc_(k+1) */ if (c == 0.0) ceta_bar = ceta*1.e15; else ceta_bar = ceta/c; ierr = VecAXPY(X,ceta_bar,Wbar);CHKERRQ(ierr); /* x <- x + ceta_bar*w_bar */ if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS; PetscFunctionReturn(0); }
static PetscErrorCode KSPCGSolve_NASH(KSP ksp) { #if defined(PETSC_USE_COMPLEX) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP, "NASH is not available for complex systems"); #else KSPCG_NASH *cg = (KSPCG_NASH*)ksp->data; PetscErrorCode ierr; Mat Qmat, Mmat; Vec r, z, p, d; PC pc; PetscReal norm_r, norm_d, norm_dp1, norm_p, dMp; PetscReal alpha, beta, kappa, rz, rzm1; PetscReal rr, r2, step; PetscInt max_cg_its; PetscBool diagonalscale; PetscFunctionBegin; /***************************************************************************/ /* Check the arguments and parameters. */ /***************************************************************************/ ierr = PCGetDiagonalScale(ksp->pc, &diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP, "Krylov method %s does not support diagonal scaling", ((PetscObject)ksp)->type_name); if (cg->radius < 0.0) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_OUTOFRANGE, "Input error: radius < 0"); /***************************************************************************/ /* Get the workspace vectors and initialize variables */ /***************************************************************************/ r2 = cg->radius * cg->radius; r = ksp->work[0]; z = ksp->work[1]; p = ksp->work[2]; d = ksp->vec_sol; pc = ksp->pc; ierr = PCGetOperators(pc, &Qmat, &Mmat);CHKERRQ(ierr); ierr = VecGetSize(d, &max_cg_its);CHKERRQ(ierr); max_cg_its = PetscMin(max_cg_its, ksp->max_it); ksp->its = 0; /***************************************************************************/ /* Initialize objective function and direction. */ /***************************************************************************/ cg->o_fcn = 0.0; ierr = VecSet(d, 0.0);CHKERRQ(ierr); /* d = 0 */ cg->norm_d = 0.0; /***************************************************************************/ /* Begin the conjugate gradient method. Check the right-hand side for */ /* numerical problems. The check for not-a-number and infinite values */ /* need be performed only once. */ /***************************************************************************/ ierr = VecCopy(ksp->vec_rhs, r);CHKERRQ(ierr); /* r = -grad */ ierr = VecDot(r, r, &rr);CHKERRQ(ierr); /* rr = r^T r */ KSPCheckDot(ksp,rr); /***************************************************************************/ /* Check the preconditioner for numerical problems and for positive */ /* definiteness. The check for not-a-number and infinite values need be */ /* performed only once. */ /***************************************************************************/ ierr = KSP_PCApply(ksp, r, z);CHKERRQ(ierr); /* z = inv(M) r */ ierr = VecDot(r, z, &rz);CHKERRQ(ierr); /* rz = r^T inv(M) r */ if (PetscIsInfOrNanScalar(rz)) { /*************************************************************************/ /* The preconditioner contains not-a-number or an infinite value. */ /* Return the gradient direction intersected with the trust region. */ /*************************************************************************/ ksp->reason = KSP_DIVERGED_NANORINF; ierr = PetscInfo1(ksp, "KSPCGSolve_NASH: bad preconditioner: rz=%g\n", (double)rz);CHKERRQ(ierr); if (cg->radius) { if (r2 >= rr) { alpha = 1.0; cg->norm_d = PetscSqrtReal(rr); } else { alpha = PetscSqrtReal(r2 / rr); cg->norm_d = cg->radius; } ierr = VecAXPY(d, alpha, r);CHKERRQ(ierr); /* d = d + alpha r */ /***********************************************************************/ /* Compute objective function. */ /***********************************************************************/ ierr = KSP_MatMult(ksp, Qmat, d, z);CHKERRQ(ierr); ierr = VecAYPX(z, -0.5, ksp->vec_rhs);CHKERRQ(ierr); ierr = VecDot(d, z, &cg->o_fcn);CHKERRQ(ierr); cg->o_fcn = -cg->o_fcn; ++ksp->its; } PetscFunctionReturn(0); } if (rz < 0.0) { /*************************************************************************/ /* The preconditioner is indefinite. Because this is the first */ /* and we do not have a direction yet, we use the gradient step. Note */ /* that we cannot use the preconditioned norm when computing the step */ /* because the matrix is indefinite. */ /*************************************************************************/ ksp->reason = KSP_DIVERGED_INDEFINITE_PC; ierr = PetscInfo1(ksp, "KSPCGSolve_NASH: indefinite preconditioner: rz=%g\n", (double)rz);CHKERRQ(ierr); if (cg->radius) { if (r2 >= rr) { alpha = 1.0; cg->norm_d = PetscSqrtReal(rr); } else { alpha = PetscSqrtReal(r2 / rr); cg->norm_d = cg->radius; } ierr = VecAXPY(d, alpha, r);CHKERRQ(ierr); /* d = d + alpha r */ /***********************************************************************/ /* Compute objective function. */ /***********************************************************************/ ierr = KSP_MatMult(ksp, Qmat, d, z);CHKERRQ(ierr); ierr = VecAYPX(z, -0.5, ksp->vec_rhs);CHKERRQ(ierr); ierr = VecDot(d, z, &cg->o_fcn);CHKERRQ(ierr); cg->o_fcn = -cg->o_fcn; ++ksp->its; } PetscFunctionReturn(0); } /***************************************************************************/ /* As far as we know, the preconditioner is positive semidefinite. */ /* Compute and log the residual. Check convergence because this */ /* initializes things, but do not terminate until at least one conjugate */ /* gradient iteration has been performed. */ /***************************************************************************/ switch (ksp->normtype) { case KSP_NORM_PRECONDITIONED: ierr = VecNorm(z, NORM_2, &norm_r);CHKERRQ(ierr); /* norm_r = |z| */ break; case KSP_NORM_UNPRECONDITIONED: norm_r = PetscSqrtReal(rr); /* norm_r = |r| */ break; case KSP_NORM_NATURAL: norm_r = PetscSqrtReal(rz); /* norm_r = |r|_M */ break; default: norm_r = 0.0; break; } ierr = KSPLogResidualHistory(ksp, norm_r);CHKERRQ(ierr); ierr = KSPMonitor(ksp, ksp->its, norm_r);CHKERRQ(ierr); ksp->rnorm = norm_r; ierr = (*ksp->converged)(ksp, ksp->its, norm_r, &ksp->reason, ksp->cnvP);CHKERRQ(ierr); /***************************************************************************/ /* Compute the first direction and update the iteration. */ /***************************************************************************/ ierr = VecCopy(z, p);CHKERRQ(ierr); /* p = z */ ierr = KSP_MatMult(ksp, Qmat, p, z);CHKERRQ(ierr); /* z = Q * p */ ++ksp->its; /***************************************************************************/ /* Check the matrix for numerical problems. */ /***************************************************************************/ ierr = VecDot(p, z, &kappa);CHKERRQ(ierr); /* kappa = p^T Q p */ if (PetscIsInfOrNanScalar(kappa)) { /*************************************************************************/ /* The matrix produced not-a-number or an infinite value. In this case, */ /* we must stop and use the gradient direction. This condition need */ /* only be checked once. */ /*************************************************************************/ ksp->reason = KSP_DIVERGED_NANORINF; ierr = PetscInfo1(ksp, "KSPCGSolve_NASH: bad matrix: kappa=%g\n", (double)kappa);CHKERRQ(ierr); if (cg->radius) { if (r2 >= rr) { alpha = 1.0; cg->norm_d = PetscSqrtReal(rr); } else { alpha = PetscSqrtReal(r2 / rr); cg->norm_d = cg->radius; } ierr = VecAXPY(d, alpha, r);CHKERRQ(ierr); /* d = d + alpha r */ /***********************************************************************/ /* Compute objective function. */ /***********************************************************************/ ierr = KSP_MatMult(ksp, Qmat, d, z);CHKERRQ(ierr); ierr = VecAYPX(z, -0.5, ksp->vec_rhs);CHKERRQ(ierr); ierr = VecDot(d, z, &cg->o_fcn);CHKERRQ(ierr); cg->o_fcn = -cg->o_fcn; ++ksp->its; } PetscFunctionReturn(0); } /***************************************************************************/ /* Initialize variables for calculating the norm of the direction. */ /***************************************************************************/ dMp = 0.0; norm_d = 0.0; switch (cg->dtype) { case NASH_PRECONDITIONED_DIRECTION: norm_p = rz; break; default: ierr = VecDot(p, p, &norm_p);CHKERRQ(ierr); break; } /***************************************************************************/ /* Check for negative curvature. */ /***************************************************************************/ if (kappa <= 0.0) { /*************************************************************************/ /* In this case, the matrix is indefinite and we have encountered a */ /* direction of negative curvature. Because negative curvature occurs */ /* during the first step, we must follow a direction. */ /*************************************************************************/ ksp->reason = KSP_CONVERGED_CG_NEG_CURVE; ierr = PetscInfo1(ksp, "KSPCGSolve_NASH: negative curvature: kappa=%g\n", (double)kappa);CHKERRQ(ierr); if (cg->radius && norm_p > 0.0) { /***********************************************************************/ /* Follow direction of negative curvature to the boundary of the */ /* trust region. */ /***********************************************************************/ step = PetscSqrtReal(r2 / norm_p); cg->norm_d = cg->radius; ierr = VecAXPY(d, step, p);CHKERRQ(ierr); /* d = d + step p */ /***********************************************************************/ /* Update objective function. */ /***********************************************************************/ cg->o_fcn += step * (0.5 * step * kappa - rz); } else if (cg->radius) { /***********************************************************************/ /* The norm of the preconditioned direction is zero; use the gradient */ /* step. */ /***********************************************************************/ if (r2 >= rr) { alpha = 1.0; cg->norm_d = PetscSqrtReal(rr); } else { alpha = PetscSqrtReal(r2 / rr); cg->norm_d = cg->radius; } ierr = VecAXPY(d, alpha, r);CHKERRQ(ierr); /* d = d + alpha r */ /***********************************************************************/ /* Compute objective function. */ /***********************************************************************/ ierr = KSP_MatMult(ksp, Qmat, d, z);CHKERRQ(ierr); ierr = VecAYPX(z, -0.5, ksp->vec_rhs);CHKERRQ(ierr); ierr = VecDot(d, z, &cg->o_fcn);CHKERRQ(ierr); cg->o_fcn = -cg->o_fcn; ++ksp->its; } PetscFunctionReturn(0); } /***************************************************************************/ /* Run the conjugate gradient method until either the problem is solved, */ /* we encounter the boundary of the trust region, or the conjugate */ /* gradient method breaks down. */ /***************************************************************************/ while (1) { /*************************************************************************/ /* Know that kappa is nonzero, because we have not broken down, so we */ /* can compute the steplength. */ /*************************************************************************/ alpha = rz / kappa; /*************************************************************************/ /* Compute the steplength and check for intersection with the trust */ /* region. */ /*************************************************************************/ norm_dp1 = norm_d + alpha*(2.0*dMp + alpha*norm_p); if (cg->radius && norm_dp1 >= r2) { /***********************************************************************/ /* In this case, the matrix is positive definite as far as we know. */ /* However, the full step goes beyond the trust region. */ /***********************************************************************/ ksp->reason = KSP_CONVERGED_CG_CONSTRAINED; ierr = PetscInfo1(ksp, "KSPCGSolve_NASH: constrained step: radius=%g\n", (double)cg->radius);CHKERRQ(ierr); if (norm_p > 0.0) { /*********************************************************************/ /* Follow the direction to the boundary of the trust region. */ /*********************************************************************/ step = (PetscSqrtReal(dMp*dMp+norm_p*(r2-norm_d))-dMp)/norm_p; cg->norm_d = cg->radius; ierr = VecAXPY(d, step, p);CHKERRQ(ierr); /* d = d + step p */ /*********************************************************************/ /* Update objective function. */ /*********************************************************************/ cg->o_fcn += step * (0.5 * step * kappa - rz); } else { /*********************************************************************/ /* The norm of the direction is zero; there is nothing to follow. */ /*********************************************************************/ } break; } /*************************************************************************/ /* Now we can update the direction and residual. */ /*************************************************************************/ ierr = VecAXPY(d, alpha, p);CHKERRQ(ierr); /* d = d + alpha p */ ierr = VecAXPY(r, -alpha, z);CHKERRQ(ierr); /* r = r - alpha Q p */ ierr = KSP_PCApply(ksp, r, z);CHKERRQ(ierr); /* z = inv(M) r */ switch (cg->dtype) { case NASH_PRECONDITIONED_DIRECTION: norm_d = norm_dp1; break; default: ierr = VecDot(d, d, &norm_d);CHKERRQ(ierr); break; } cg->norm_d = PetscSqrtReal(norm_d); /*************************************************************************/ /* Update objective function. */ /*************************************************************************/ cg->o_fcn -= 0.5 * alpha * rz; /*************************************************************************/ /* Check that the preconditioner appears positive semidefinite. */ /*************************************************************************/ rzm1 = rz; ierr = VecDot(r, z, &rz);CHKERRQ(ierr); /* rz = r^T z */ if (rz < 0.0) { /***********************************************************************/ /* The preconditioner is indefinite. */ /***********************************************************************/ ksp->reason = KSP_DIVERGED_INDEFINITE_PC; ierr = PetscInfo1(ksp, "KSPCGSolve_NASH: cg indefinite preconditioner: rz=%g\n", (double)rz);CHKERRQ(ierr); break; } /*************************************************************************/ /* As far as we know, the preconditioner is positive semidefinite. */ /* Compute the residual and check for convergence. */ /*************************************************************************/ switch (ksp->normtype) { case KSP_NORM_PRECONDITIONED: ierr = VecNorm(z, NORM_2, &norm_r);CHKERRQ(ierr); /* norm_r = |z| */ break; case KSP_NORM_UNPRECONDITIONED: ierr = VecNorm(r, NORM_2, &norm_r);CHKERRQ(ierr); /* norm_r = |r| */ break; case KSP_NORM_NATURAL: norm_r = PetscSqrtReal(rz); /* norm_r = |r|_M */ break; default: norm_r = 0.; break; } ierr = KSPLogResidualHistory(ksp, norm_r);CHKERRQ(ierr); ierr = KSPMonitor(ksp, ksp->its, norm_r);CHKERRQ(ierr); ksp->rnorm = norm_r; ierr = (*ksp->converged)(ksp, ksp->its, norm_r, &ksp->reason, ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) { /***********************************************************************/ /* The method has converged. */ /***********************************************************************/ ierr = PetscInfo2(ksp, "KSPCGSolve_NASH: truncated step: rnorm=%g, radius=%g\n", (double)norm_r, (double)cg->radius);CHKERRQ(ierr); break; } /*************************************************************************/ /* We have not converged yet. Check for breakdown. */ /*************************************************************************/ beta = rz / rzm1; if (PetscAbsReal(beta) <= 0.0) { /***********************************************************************/ /* Conjugate gradients has broken down. */ /***********************************************************************/ ksp->reason = KSP_DIVERGED_BREAKDOWN; ierr = PetscInfo1(ksp, "KSPCGSolve_NASH: breakdown: beta=%g\n", (double)beta);CHKERRQ(ierr); break; } /*************************************************************************/ /* Check iteration limit. */ /*************************************************************************/ if (ksp->its >= max_cg_its) { ksp->reason = KSP_DIVERGED_ITS; ierr = PetscInfo1(ksp, "KSPCGSolve_NASH: iterlim: its=%D\n", ksp->its);CHKERRQ(ierr); break; } /*************************************************************************/ /* Update p and the norms. */ /*************************************************************************/ ierr = VecAYPX(p, beta, z);CHKERRQ(ierr); /* p = z + beta p */ switch (cg->dtype) { case NASH_PRECONDITIONED_DIRECTION: dMp = beta*(dMp + alpha*norm_p); norm_p = beta*(rzm1 + beta*norm_p); break; default: ierr = VecDot(d, p, &dMp);CHKERRQ(ierr); ierr = VecDot(p, p, &norm_p);CHKERRQ(ierr); break; } /*************************************************************************/ /* Compute the new direction and update the iteration. */ /*************************************************************************/ ierr = KSP_MatMult(ksp, Qmat, p, z);CHKERRQ(ierr); /* z = Q * p */ ierr = VecDot(p, z, &kappa);CHKERRQ(ierr); /* kappa = p^T Q p */ ++ksp->its; /*************************************************************************/ /* Check for negative curvature. */ /*************************************************************************/ if (kappa <= 0.0) { /***********************************************************************/ /* In this case, the matrix is indefinite and we have encountered */ /* a direction of negative curvature. Stop at the base. */ /***********************************************************************/ ksp->reason = KSP_CONVERGED_CG_NEG_CURVE; ierr = PetscInfo1(ksp, "KSPCGSolve_NASH: negative curvature: kappa=%g\n", (double)kappa);CHKERRQ(ierr); break; } } PetscFunctionReturn(0); #endif }
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; PetscBool diagonalscale; /* Dingwen */ PetscInt itv_d, itv_c; PetscScalar CKSX1,CKSZ1,CKSR1,CKSP1,CKSS1,CKSW1; PetscScalar CKSX2,CKSZ2,CKSR2,CKSP2,CKSS2,CKSW2; Vec CKSAmat1; Vec CKSAmat2; Vec C1,C2; PetscScalar d1,d2; PetscScalar sumX1,sumR1; PetscScalar sumX2,sumR2; Vec CKPX,CKPP; PetscScalar CKPbetaold; PetscInt CKPi; PetscBool flag1 = PETSC_TRUE, flag2 = PETSC_TRUE; PetscInt pos; PetscScalar v; VecScatter ctx; Vec W_SEQ; PetscScalar *_W; /* Dingwen */ PetscFunctionBegin; ierr = PCGetDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),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]; /* Dingwen */ CKPX = ksp->work[3]; CKPP = ksp->work[4]; CKSAmat1 = ksp->work[5]; CKSAmat2 = ksp->work[6]; C1 = ksp->work[7]; C2 = ksp->work[8]; /* Dingwen */ /* Dingwen */ int rank; /* Get MPI variables */ MPI_Comm_rank (MPI_COMM_WORLD,&rank); /* Dingwen */ #define VecXDot(x,y,a) (((cg->type) == (KSP_CG_HERMITIAN)) ? VecDot(x,y,a) : VecTDot(x,y,a)) if (cg->singlereduction) { S = ksp->work[9]; W = ksp->work[10]; } else { S = 0; /* unused */ W = Z; } if (eigs) {e = cg->e; d = cg->d; e[0] = 0.0; } ierr = PCGetOperators(ksp->pc,&Amat,&Pmat);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) */ } /* Dingwen */ /* checksum coefficients initialization */ PetscInt size; ierr = VecGetSize(B,&size); for (i=0; i<size; i++) { v = 1.0; ierr = VecSetValues(C1,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); v = i; ierr = VecSetValues(C2,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); } d1 = 1.0; d2 = 2.0; /* Dingwen */ switch (ksp->normtype) { case 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' */ break; case KSP_NORM_UNPRECONDITIONED: ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); /* dp <- r'*r = e'*A'*A*e */ break; case 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); /* Dingwen */ ierr = VecXDot(C1,S,&CKSS1);CHKERRQ(ierr); /* Compute the initial checksum1(S) */ ierr = VecXDot(C2,S,&CKSS2);CHKERRQ(ierr); /* Compute the initial checksum2(S) */ /* Dingwen */ } ierr = VecXDot(Z,R,&beta);CHKERRQ(ierr); /* beta <- z'*r */ KSPCheckDot(ksp,beta); dp = PetscSqrtReal(PetscAbsScalar(beta)); /* dp <- r'*z = r'*B*r = e'*A'*B*A*e */ break; case KSP_NORM_NONE: dp = 0.0; break; default: SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"%s",KSPNormTypes[ksp->normtype]); } ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,dp);CHKERRQ(ierr); ksp->rnorm = dp; ierr = (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); /* test for convergence */ if (ksp->reason) PetscFunctionReturn(0); if (ksp->normtype != KSP_NORM_PRECONDITIONED && (ksp->normtype != KSP_NORM_NATURAL)) { ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ } if (ksp->normtype != KSP_NORM_NATURAL) { 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 */ KSPCheckDot(ksp,beta); } /* Dingwen */ /* Checksum Initialization */ ierr = VecXDot(C1,X,&CKSX1);CHKERRQ(ierr); /* Compute the initial checksum1(X) */ ierr = VecXDot(C1,W,&CKSW1);CHKERRQ(ierr); /* Compute the initial checksum1(W) */ ierr = VecXDot(C1,R,&CKSR1);CHKERRQ(ierr); /* Compute the initial checksum1(R) */ ierr = VecXDot(C1,Z,&CKSZ1);CHKERRQ(ierr); /* Compute the initial checksum1(Z) */ ierr = VecXDot(C2,X,&CKSX2);CHKERRQ(ierr); /* Compute the initial checksum2(X) */ ierr = VecXDot(C2,W,&CKSW2);CHKERRQ(ierr); /* Compute the initial checksum2(W) */ ierr = VecXDot(C2,R,&CKSR2);CHKERRQ(ierr); /* Compute the initial checksum2(R) */ ierr = VecXDot(C2,Z,&CKSZ2);CHKERRQ(ierr); /* Compute the initial checksum2(Z) */ ierr = KSP_MatMultTranspose(ksp,Amat,C1,CKSAmat1);CHKERRQ(ierr); ierr = VecAXPY(CKSAmat1,-d1,C1);CHKERRQ(ierr); ierr = VecAXPY(CKSAmat1,-d2,C2);CHKERRQ(ierr); /* Compute the initial checksum1(A) */ ierr = KSP_MatMultTranspose(ksp,Amat,C2,CKSAmat2);CHKERRQ(ierr); ierr = VecAXPY(CKSAmat2,-d2,C1);CHKERRQ(ierr); ierr = VecAXPY(CKSAmat2,-d1,C2);CHKERRQ(ierr); /* Compute the initial checksum2(A) */ itv_c = 2; itv_d = 10; /* Dingwen */ i = 0; do { /* Dingwen */ if ((i>0) && (i%itv_d == 0)) { ierr = VecXDot(C1,X,&sumX1);CHKERRQ(ierr); ierr = VecXDot(C1,R,&sumR1);CHKERRQ(ierr); if ((PetscAbsScalar(sumX1-CKSX1) > 1.0e-6) || (PetscAbsScalar(sumR1-CKSR1) > 1.0e-6)) { /* Rollback and Recovery */ if (rank==0) printf ("Recovery start...\n"); if (rank==0) printf ("Rollback from iteration-%d to iteration-%d\n",i,CKPi); betaold = CKPbetaold; /* Recovery scalar betaold by checkpoint*/ i = CKPi; /* Recovery integer i by checkpoint */ ierr = VecCopy(CKPP,P);CHKERRQ(ierr); /* Recovery vector P from checkpoint */ ierr = VecXDot(C1,P,&CKSP1);CHKERRQ(ierr); /* Recovery checksum1(P) by P */ ierr = VecXDot(C2,P,&CKSP2);CHKERRQ(ierr); /* Recovery checksum2(P) by P */ ierr = KSP_MatMult(ksp,Amat,P,W);CHKERRQ(ierr); /* Recovery vector W by P */ ierr = VecXDot(P,W,&dpi);CHKERRQ(ierr); /* Recovery scalar dpi by P and W */ ierr = VecCopy(CKPX,X);CHKERRQ(ierr); /* Recovery vector X from checkpoint */ ierr = VecXDot(C1,X,&CKSX1);CHKERRQ(ierr); /* Recovery checksum1(X) by X */ ierr = VecXDot(C2,X,&CKSX2);CHKERRQ(ierr); /* Recovery checksum2(X) by X */ ierr = KSP_MatMult(ksp,Amat,X,R);CHKERRQ(ierr); /* Recovery vector R by X */ ierr = VecAYPX(R,-1.0,B);CHKERRQ(ierr); ierr = VecXDot(C1,R,&CKSR1);CHKERRQ(ierr); /* Recovery checksum1(R) by R */ ierr = VecXDot(C2,R,&CKSR2);CHKERRQ(ierr); /* Recovery checksum2(R) by R */ ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* Recovery vector Z by R */ ierr = VecXDot(C1,Z,&CKSZ1);CHKERRQ(ierr); /* Recovery checksum1(Z) by Z */ ierr = VecXDot(C2,Z,&CKSZ2);CHKERRQ(ierr); /* Recovery checksum2(Z) by Z */ ierr = VecXDot(Z,R,&beta);CHKERRQ(ierr); /* Recovery scalar beta by Z and R */ if (rank==0) printf ("Recovery end.\n"); } else if (i%(itv_c*itv_d) == 0) { if (rank==0) printf ("Checkpoint iteration-%d\n",i); ierr = VecCopy(X,CKPX);CHKERRQ(ierr); ierr = VecCopy(P,CKPP);CHKERRQ(ierr); CKPbetaold = betaold; CKPi = i; } } ksp->its = i+1; if (beta == 0.0) { ksp->reason = KSP_CONVERGED_ATOL; ierr = PetscInfo(ksp,"converged due to beta = 0\n");CHKERRQ(ierr); break; #if !defined(PETSC_USE_COMPLEX) } else if ((i > 0) && (beta*betaold < 0.0)) { ksp->reason = KSP_DIVERGED_INDEFINITE_PC; ierr = PetscInfo(ksp,"diverging due to indefinite preconditioner\n");CHKERRQ(ierr); break; #endif } if (!i) { ierr = VecCopy(Z,P);CHKERRQ(ierr); /* p <- z */ b = 0.0; /* Dingwen */ ierr = VecXDot(C1,P, &CKSP1);CHKERRQ(ierr); /* Compute the initial checksum1(P) */ ierr = VecXDot(C2,P, &CKSP2);CHKERRQ(ierr); /* Compute the initial checksum2(P) */ /* Dingwen */ } else { b = beta/betaold; if (eigs) { if (ksp->max_it != stored_max_it) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Can not change maxit AND calculate eigenvalues"); e[i] = PetscSqrtReal(PetscAbsScalar(b))/a; } ierr = VecAYPX(P,b,Z);CHKERRQ(ierr); /* p <- z + b* p */ /* Dingwen */ CKSP1 = CKSZ1 + b*CKSP1; /* Update checksum1(P) = checksum1(Z) + b*checksum1(P); */ CKSP2 = CKSZ2 + b*CKSP2; /* Update checksum2(P) = checksum2(Z) + b*checksum2(P); */ /* Dingwen */ } dpiold = dpi; if (!cg->singlereduction || !i) { ierr = KSP_MatMult(ksp,Amat,P,W);CHKERRQ(ierr); /* w <- Ap */ /* MVM */ ierr = VecXDot(P,W,&dpi);CHKERRQ(ierr); /* dpi <- p'w */ /* Dingwen */ ierr = VecXDot(CKSAmat1, P, &CKSW1);CHKERRQ(ierr); CKSW1 = CKSW1 + d1*CKSP1 + d2*CKSP2; /* Update checksum1(W) = checksum1(A)P + d1*checksum1(P) + d2*checksum2(P); */ ierr = VecXDot(CKSAmat2, P, &CKSW2);CHKERRQ(ierr); CKSW2 = CKSW2 + d2*CKSP1 + d1*CKSP2; /* Update checksum2(W) = checksum2(A)P + d2*checksum1(P) + d1*checksum2(P); */ if((i==41)&&(flag2)) { pos = 100; v = 1000; ierr = VecSetValue(W,pos,v,INSERT_VALUES);CHKERRQ(ierr); VecAssemblyBegin(W); VecAssemblyEnd(W); if (rank==0) printf ("Inject an error in %d-th element of vector W after MVM W=AP at iteration-%d\n", pos,i); flag2 = PETSC_FALSE; } PetscScalar delta1,delta2; PetscScalar sumW1,sumW2; ierr = VecXDot(C1,W,&sumW1);CHKERRQ(ierr); ierr = VecXDot(C2,W,&sumW2);CHKERRQ(ierr); delta1 = sumW1 - CKSW1; delta2 = sumW2 - CKSW2; if (PetscAbsScalar(delta1) > 1.0e-6) { VecScatterCreateToAll(W,&ctx,&W_SEQ); VecScatterBegin(ctx,W,W_SEQ,INSERT_VALUES,SCATTER_FORWARD); VecScatterEnd(ctx,W,W_SEQ,INSERT_VALUES,SCATTER_FORWARD); VecGetArray(W_SEQ,&_W); pos = rint(delta2/delta1); v = _W[pos]; v = v - delta1; ierr = VecSetValues(W,1,&pos,&v,INSERT_VALUES);CHKERRQ(ierr); if (rank==0) printf ("Correct an error of %d-th elements of vector W after MVM W=AP at iteration-%d\n", pos, i); } } else { ierr = VecAYPX(W,beta/betaold,S);CHKERRQ(ierr); /* w <- Ap */ dpi = delta - beta*beta*dpiold/(betaold*betaold); /* dpi <- p'w */ /* Dingwen */ CKSW1 = beta/betaold*CKSW1 + CKSS1; /* Update checksum1(W) = checksum1(S) + beta/betaold*checksum1(W); */ CKSW2 = beta/betaold*CKSW2 + CKSS2; /* Update checksum2(W) = checksum2(S) + beta/betaold*checksum2(W); */ /* Dingwen */ } betaold = beta; KSPCheckDot(ksp,beta); if ((dpi == 0.0) || ((i > 0) && (PetscRealPart(dpi*dpiold) <= 0.0))) { ksp->reason = KSP_DIVERGED_INDEFINITE_MAT; ierr = PetscInfo(ksp,"diverging due to indefinite or negative definite matrix\n");CHKERRQ(ierr); break; } a = beta/dpi; /* a = beta/p'w */ if (eigs) d[i] = PetscSqrtReal(PetscAbsScalar(b))*e[i] + 1.0/a; ierr = VecAXPY(X,a,P);CHKERRQ(ierr); /* x <- x + ap */ /* Dingwen */ CKSX1 = CKSX1 + a*CKSP1; /* Update checksum1(X) = checksum1(X) + a*checksum1(P); */ CKSX2 = CKSX2 + a*CKSP2; /* Update checksum2(X) = checksum2(X) + a*checksum2(P); */ /* Dingwen */ ierr = VecAXPY(R,-a,W);CHKERRQ(ierr); /* r <- r - aw */ /* Dingwen */ CKSR1 = CKSR1 - a*CKSW1; /* Update checksum1(R) = checksum1(R) - a*checksum1(W); */ CKSR2 = CKSR2 - a*CKSW2; /* Update checksum2(R) = checksum2(R) - a*checksum2(W); */ /* Dingwen */ if (ksp->normtype == KSP_NORM_PRECONDITIONED && ksp->chknorm < i+2) { ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ /* Dingwen */ ierr = VecXDot(C1,Z, &CKSZ1);CHKERRQ(ierr); /* Update checksum1(Z) */ ierr = VecXDot(C2,Z, &CKSZ2);CHKERRQ(ierr); /* Update checksum2(Z) */ /* Dingwen */ if (cg->singlereduction) { ierr = KSP_MatMult(ksp,Amat,Z,S);CHKERRQ(ierr); /* MVM */ /* Dingwen */ ierr = VecXDot(CKSAmat1, Z, &CKSS1);CHKERRQ(ierr); CKSS1 = CKSS1 + d1*CKSZ1 + d2*CKSZ2; /* Update checksum1(S) = checksum1(A)Z + d1*chekcsum1(Z) + d2*checksum2(Z); */ ierr = VecXDot(CKSAmat2, Z, &CKSS2);CHKERRQ(ierr); CKSS2 = CKSS2 + d2*CKSZ1 + d1*CKSZ2; /* Update checksum2(S) = checksum2(A)Z + d2*chekcsum1(Z) + d1*checksum2(Z); */ /* Dingwen */ } ierr = VecNorm(Z,NORM_2,&dp);CHKERRQ(ierr); /* dp <- z'*z */ } else if (ksp->normtype == KSP_NORM_UNPRECONDITIONED && ksp->chknorm < i+2) { ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); /* dp <- r'*r */ } else if (ksp->normtype == KSP_NORM_NATURAL) { ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ /* Dingwen */ ierr = VecXDot(C1,Z, &CKSZ1);CHKERRQ(ierr); /* Update checksum1(Z) */ ierr = VecXDot(C2,Z, &CKSZ2);CHKERRQ(ierr); /* Update checksum2(Z) */ /* Dingwen */ if (cg->singlereduction) { PetscScalar tmp[2]; Vec vecs[2]; vecs[0] = S; vecs[1] = R; ierr = KSP_MatMult(ksp,Amat,Z,S);CHKERRQ(ierr); ierr = VecMDot(Z,2,vecs,tmp);CHKERRQ(ierr); delta = tmp[0]; beta = tmp[1]; } else { ierr = VecXDot(Z,R,&beta);CHKERRQ(ierr); /* beta <- r'*z */ } KSPCheckDot(ksp,beta); dp = PetscSqrtReal(PetscAbsScalar(beta)); } else { dp = 0.0; } ksp->rnorm = dp; CHKERRQ(ierr);KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,i+1,dp);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; if ((ksp->normtype != KSP_NORM_PRECONDITIONED && (ksp->normtype != KSP_NORM_NATURAL)) || (ksp->chknorm >= i+2)) { ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ /* Dingwen */ ierr = VecXDot(C1,Z, &CKSZ1);CHKERRQ(ierr); /* Update checksum1(Z) */ ierr = VecXDot(C2,Z, &CKSZ2);CHKERRQ(ierr); /* Update checksum2(Z) */ /* Dingwen */ if (cg->singlereduction) { ierr = KSP_MatMult(ksp,Amat,Z,S);CHKERRQ(ierr); } } if ((ksp->normtype != KSP_NORM_NATURAL) || (ksp->chknorm >= i+2)) { if (cg->singlereduction) { PetscScalar tmp[2]; Vec vecs[2]; vecs[0] = S; vecs[1] = R; ierr = VecMDot(Z,2,vecs,tmp);CHKERRQ(ierr); delta = tmp[0]; beta = tmp[1]; } else { ierr = VecXDot(Z,R,&beta);CHKERRQ(ierr); /* beta <- z'*r */ } KSPCheckDot(ksp,beta); } i++; /* Dingwen */ /* Inject error */ if ((i==50)&&(flag1)) { pos = 1000; v = -1; ierr = VecSetValues(X,1,&pos,&v,INSERT_VALUES);CHKERRQ(ierr); ierr = VecAssemblyBegin(X);CHKERRQ(ierr); ierr = VecAssemblyEnd(X);CHKERRQ(ierr); flag1 = PETSC_FALSE; if (rank==0)printf ("Inject an error in vector X at the end of iteration-%d\n", i-1); } /* Dingwen */ } while (i<ksp->max_it); /* Dingwen */ ierr = VecXDot(C1,X,&sumX1);CHKERRQ(ierr); ierr = VecXDot(C1,R,&sumR1);CHKERRQ(ierr); ierr = VecXDot(C2,X,&sumX2);CHKERRQ(ierr); ierr = VecXDot(C2,R,&sumR2);CHKERRQ(ierr); if (rank==0) { printf ("sum1 of X = %f\n", sumX1); printf ("checksum1(X) = %f\n", CKSX1); printf ("sum2 of X = %f\n", sumX2); printf ("checksum2(X) = %f\n", CKSX2); printf ("sum1 of R = %f\n", sumR1); printf ("checksum1(R) = %f\n", CKSR1); printf ("sum2 of R = %f\n", sumR2); printf ("checksum2(R) = %f\n", CKSR2); } VecDestroy(&W_SEQ); VecScatterDestroy(&ctx); /* Dingwen */ if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS; if (eigs) cg->ned = ksp->its; PetscFunctionReturn(0); }
PetscErrorCode KSPSolve_GROPPCG(KSP ksp) { PetscErrorCode ierr; PetscInt i; PetscScalar alpha,beta = 0.0,gamma,gammaNew,t; PetscReal dp = 0.0; Vec x,b,r,p,s,S,z,Z; Mat Amat,Pmat; PetscBool diagonalscale; PetscFunctionBegin; ierr = PCGetDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name); x = ksp->vec_sol; b = ksp->vec_rhs; r = ksp->work[0]; p = ksp->work[1]; s = ksp->work[2]; S = ksp->work[3]; z = ksp->work[4]; Z = ksp->work[5]; ierr = PCGetOperators(ksp->pc,&Amat,&Pmat);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) */ } ierr = KSP_PCApply(ksp,r,z);CHKERRQ(ierr); /* z <- Br */ ierr = VecCopy(z,p);CHKERRQ(ierr); /* p <- z */ ierr = VecDotBegin(r,z,&gamma);CHKERRQ(ierr); /* gamma <- z'*r */ ierr = PetscCommSplitReductionBegin(PetscObjectComm((PetscObject)r));CHKERRQ(ierr); ierr = KSP_MatMult(ksp,Amat,p,s);CHKERRQ(ierr); /* s <- Ap */ ierr = VecDotEnd(r,z,&gamma);CHKERRQ(ierr); /* gamma <- z'*r */ switch (ksp->normtype) { case KSP_NORM_PRECONDITIONED: /* This could be merged with the computation of gamma above */ ierr = VecNorm(z,NORM_2,&dp);CHKERRQ(ierr); /* dp <- z'*z = e'*A'*B'*B*A'*e' */ break; case KSP_NORM_UNPRECONDITIONED: /* This could be merged with the computation of gamma above */ ierr = VecNorm(r,NORM_2,&dp);CHKERRQ(ierr); /* dp <- r'*r = e'*A'*A*e */ break; case KSP_NORM_NATURAL: KSPCheckDot(ksp,gamma); dp = PetscSqrtReal(PetscAbsScalar(gamma)); /* dp <- r'*z = r'*B*r = e'*A'*B*A*e */ break; case KSP_NORM_NONE: dp = 0.0; break; default: SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"%s",KSPNormTypes[ksp->normtype]); } ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,dp);CHKERRQ(ierr); ksp->rnorm = dp; ierr = (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); /* test for convergence */ if (ksp->reason) PetscFunctionReturn(0); i = 0; do { ksp->its = i+1; i++; ierr = VecDotBegin(p,s,&t);CHKERRQ(ierr); ierr = PetscCommSplitReductionBegin(PetscObjectComm((PetscObject)p));CHKERRQ(ierr); ierr = KSP_PCApply(ksp,s,S);CHKERRQ(ierr); /* S <- Bs */ ierr = VecDotEnd(p,s,&t);CHKERRQ(ierr); alpha = gamma / t; ierr = VecAXPY(x, alpha,p);CHKERRQ(ierr); /* x <- x + alpha * p */ ierr = VecAXPY(r,-alpha,s);CHKERRQ(ierr); /* r <- r - alpha * s */ ierr = VecAXPY(z,-alpha,S);CHKERRQ(ierr); /* z <- z - alpha * S */ if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) { ierr = VecNormBegin(r,NORM_2,&dp);CHKERRQ(ierr); } else if (ksp->normtype == KSP_NORM_PRECONDITIONED) { ierr = VecNormBegin(z,NORM_2,&dp);CHKERRQ(ierr); } ierr = VecDotBegin(r,z,&gammaNew);CHKERRQ(ierr); ierr = PetscCommSplitReductionBegin(PetscObjectComm((PetscObject)r));CHKERRQ(ierr); ierr = KSP_MatMult(ksp,Amat,z,Z);CHKERRQ(ierr); /* Z <- Az */ if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) { ierr = VecNormEnd(r,NORM_2,&dp);CHKERRQ(ierr); } else if (ksp->normtype == KSP_NORM_PRECONDITIONED) { ierr = VecNormEnd(z,NORM_2,&dp);CHKERRQ(ierr); } ierr = VecDotEnd(r,z,&gammaNew);CHKERRQ(ierr); if (ksp->normtype == KSP_NORM_NATURAL) { KSPCheckDot(ksp,gammaNew); dp = PetscSqrtReal(PetscAbsScalar(gammaNew)); /* dp <- r'*z = r'*B*r = e'*A'*B*A*e */ } else if (ksp->normtype == KSP_NORM_NONE) { dp = 0.0; } ksp->rnorm = dp; ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,i,dp);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,i,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; beta = gammaNew / gamma; gamma = gammaNew; ierr = VecAYPX(p,beta,z);CHKERRQ(ierr); /* p <- z + beta * p */ ierr = VecAYPX(s,beta,Z);CHKERRQ(ierr); /* s <- Z + beta * s */ } while (i<ksp->max_it); if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS; PetscFunctionReturn(0); }