static PetscErrorCode KSPSolve_PIPEFCG(KSP ksp) { PetscErrorCode ierr; KSP_PIPEFCG *pipefcg; PetscScalar gamma; PetscReal dp=0.0; Vec B,R,Z,X; Mat Amat,Pmat; #define VecXDot(x,y,a) (((pipefcg->type) == (KSP_CG_HERMITIAN)) ? VecDot (x,y,a) : VecTDot (x,y,a)) PetscFunctionBegin; ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr); pipefcg = (KSP_PIPEFCG*)ksp->data; X = ksp->vec_sol; B = ksp->vec_rhs; R = ksp->work[0]; Z = ksp->work[1]; ierr = PCGetOperators(ksp->pc,&Amat,&Pmat);CHKERRQ(ierr); /* Compute initial residual needed for convergence check*/ ksp->its = 0; if (!ksp->guess_zero) { ierr = KSP_MatMult(ksp,Amat,X,R);CHKERRQ(ierr); ierr = VecAYPX(R,-1.0,B);CHKERRQ(ierr); /* r <- b - Ax */ } 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 <- dqrt(z'*z) = sqrt(e'*A'*B'*B*A*e) */ break; case KSP_NORM_UNPRECONDITIONED: ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); /* dp <- sqrt(r'*r) = sqrt(e'*A'*A*e) */ break; case KSP_NORM_NATURAL: ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ ierr = VecXDot(Z,R,&gamma);CHKERRQ(ierr); dp = PetscSqrtReal(PetscAbsScalar(gamma)); /* dp <- sqrt(r'*z) = sqrt(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]); } /* Initial Convergence Check */ ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,dp);CHKERRQ(ierr); ksp->rnorm = dp; if (ksp->normtype == KSP_NORM_NONE) { ierr = KSPConvergedSkip (ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); } else { ierr = (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); } if (ksp->reason) PetscFunctionReturn(0); do { /* A cycle is broken only if a norm breakdown occurs. If not the entire solve happens in a single cycle. This is coded this way to allow both truncation and truncation-restart strategy (see KSPFCDGetNumOldDirections()) */ ierr = KSPSolve_PIPEFCG_cycle(ksp);CHKERRQ(ierr); if (ksp->reason) break; if (pipefcg->norm_breakdown) { pipefcg->n_restarts++; pipefcg->norm_breakdown = PETSC_FALSE; } } while (ksp->its < ksp->max_it); if (ksp->its >= 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 */ if (PetscIsInfOrNanScalar(beta)) { if (ksp->errorifnotconverged) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_NOT_CONVERGED,"KSPSolve has not converged due to Nan or Inf inner product"); else { ksp->reason = KSP_DIVERGED_NANORINF; PetscFunctionReturn(0); } } 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 */ if (PetscIsInfOrNanScalar(beta)) { if (ksp->errorifnotconverged) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_NOT_CONVERGED,"KSPSolve has not converged due to Nan or Inf inner product"); else { ksp->reason = KSP_DIVERGED_NANORINF; PetscFunctionReturn(0); } } } 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; if (PetscIsInfOrNanScalar(dpi)) { if (ksp->errorifnotconverged) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_NOT_CONVERGED,"KSPSolve has not converged due to Nan or Inf inner product"); else { ksp->reason = KSP_DIVERGED_NANORINF; PetscFunctionReturn(0); } } 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 */ } if (PetscIsInfOrNanScalar(beta)) { if (ksp->errorifnotconverged) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_NOT_CONVERGED,"KSPSolve has not converged due to Nan or Inf inner product"); else { ksp->reason = KSP_DIVERGED_NANORINF; PetscFunctionReturn(0); } } 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 */ 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 */ } if (PetscIsInfOrNanScalar(beta)) { if (ksp->errorifnotconverged) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_NOT_CONVERGED,"KSPSolve has not converged due to Nan or Inf inner product"); else { ksp->reason = KSP_DIVERGED_NANORINF; PetscFunctionReturn(0); } } } i++; } 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; /* 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_FCG(KSP ksp) { PetscErrorCode ierr; PetscInt i,k,idx,mi; KSP_FCG *fcg = (KSP_FCG*)ksp->data; PetscScalar alpha=0.0,beta = 0.0,dpi,s; PetscReal dp=0.0; Vec B,R,Z,X,Pcurr,Ccurr; Mat Amat,Pmat; PetscInt eigs = ksp->calc_sings; /* Variables for eigen estimation - START*/ PetscInt stored_max_it = ksp->max_it; PetscScalar alphaold = 0,betaold = 1.0,*e = 0,*d = 0;/* Variables for eigen estimation - FINISH */ PetscFunctionBegin; #define VecXDot(x,y,a) (((fcg->type) == (KSP_CG_HERMITIAN)) ? VecDot(x,y,a) : VecTDot(x,y,a)) #define VecXMDot(a,b,c,d) (((fcg->type) == (KSP_CG_HERMITIAN)) ? VecMDot(a,b,c,d) : VecMTDot(a,b,c,d)) X = ksp->vec_sol; B = ksp->vec_rhs; R = ksp->work[0]; Z = ksp->work[1]; ierr = PCGetOperators(ksp->pc,&Amat,&Pmat);CHKERRQ(ierr); if (eigs) {e = fcg->e; d = fcg->d; e[0] = 0.0; } /* Compute initial residual needed for convergence check*/ ksp->its = 0; if (!ksp->guess_zero) { ierr = KSP_MatMult(ksp,Amat,X,R);CHKERRQ(ierr); ierr = VecAYPX(R,-1.0,B);CHKERRQ(ierr); /* r <- b - Ax */ } 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 <- dqrt(z'*z) = sqrt(e'*A'*B'*B*A*e) */ break; case KSP_NORM_UNPRECONDITIONED: ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); /* dp <- sqrt(r'*r) = sqrt(e'*A'*A*e) */ break; case KSP_NORM_NATURAL: ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ ierr = VecXDot(R,Z,&s);CHKERRQ(ierr); dp = PetscSqrtReal(PetscAbsScalar(s)); /* dp <- sqrt(r'*z) = sqrt(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]); } /* Initial Convergence Check */ ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,dp);CHKERRQ(ierr); ksp->rnorm = dp; if (ksp->normtype == KSP_NORM_NONE) { ierr = KSPConvergedSkip(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); } else { ierr = (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); } if (ksp->reason) PetscFunctionReturn(0); /* Apply PC if not already done for convergence check */ if(ksp->normtype == KSP_NORM_UNPRECONDITIONED || ksp->normtype == KSP_NORM_NONE){ ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ } i = 0; do { ksp->its = i+1; /* If needbe, allocate a new chunk of vectors in P and C */ ierr = KSPAllocateVectors_FCG(ksp,i+1,fcg->vecb);CHKERRQ(ierr); /* Note that we wrap around and start clobbering old vectors */ idx = i % (fcg->mmax+1); Pcurr = fcg->Pvecs[idx]; Ccurr = fcg->Cvecs[idx]; /* Compute a new column of P (Currently does not support modified G-S or iterative refinement)*/ switch(fcg->truncstrat){ case KSP_FCG_TRUNC_TYPE_NOTAY : mi = PetscMax(1,i%(fcg->mmax+1)); break; case KSP_FCG_TRUNC_TYPE_STANDARD : mi = fcg->mmax; break; default: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unrecognized FCG Truncation Strategy");CHKERRQ(ierr); } ierr = VecCopy(Z,Pcurr);CHKERRQ(ierr); { PetscInt l,ndots; l = PetscMax(0,i-mi); ndots = i-l; if (ndots){ PetscInt j; Vec *Pold, *Cold; PetscScalar *dots; ierr = PetscMalloc3(ndots,&dots,ndots,&Cold,ndots,&Pold);CHKERRQ(ierr); for(k=l,j=0;j<ndots;++k,++j){ idx = k % (fcg->mmax+1); Cold[j] = fcg->Cvecs[idx]; Pold[j] = fcg->Pvecs[idx]; } ierr = VecXMDot(Z,ndots,Cold,dots);CHKERRQ(ierr); for(k=0;k<ndots;++k){ dots[k] = -dots[k]; } ierr = VecMAXPY(Pcurr,ndots,dots,Pold);CHKERRQ(ierr); ierr = PetscFree3(dots,Cold,Pold);CHKERRQ(ierr); } } /* Update X and R */ betaold = beta; ierr = VecXDot(Pcurr,R,&beta);CHKERRQ(ierr); /* beta <- pi'*r */ ierr = KSP_MatMult(ksp,Amat,Pcurr,Ccurr);CHKERRQ(ierr); /* w <- A*pi (stored in ci) */ ierr = VecXDot(Pcurr,Ccurr,&dpi);CHKERRQ(ierr); /* dpi <- pi'*w */ alphaold = alpha; alpha = beta / dpi; /* alpha <- beta/dpi */ ierr = VecAXPY(X,alpha,Pcurr);CHKERRQ(ierr); /* x <- x + alpha * pi */ ierr = VecAXPY(R,-alpha,Ccurr);CHKERRQ(ierr); /* r <- r - alpha * wi */ /* Compute norm for convergence check */ 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 <- sqrt(z'*z) = sqrt(e'*A'*B'*B*A*e) */ break; case KSP_NORM_UNPRECONDITIONED: ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); /* dp <- sqrt(r'*r) = sqrt(e'*A'*A*e) */ break; case KSP_NORM_NATURAL: ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ ierr = VecXDot(R,Z,&s);CHKERRQ(ierr); dp = PetscSqrtReal(PetscAbsScalar(s)); /* dp <- sqrt(r'*z) = sqrt(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]); } /* Check for convergence */ ksp->rnorm = dp; 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; /* Apply PC if not already done for convergence check */ if(ksp->normtype == KSP_NORM_UNPRECONDITIONED || ksp->normtype == KSP_NORM_NONE){ ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ } /* Compute current C (which is W/dpi) */ ierr = VecScale(Ccurr,1.0/dpi);CHKERRQ(ierr); /* w <- ci/dpi */ if (eigs) { if (i > 0) { 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(beta/betaold))/alphaold; d[i] = PetscSqrtReal(PetscAbsScalar(beta/betaold))*e[i] + 1.0/alpha; } else { d[i] = PetscSqrtReal(PetscAbsScalar(beta))*e[i] + 1.0/alpha; } } ++i; } while (i<ksp->max_it); if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS; if (eigs) fcg->ned = ksp->its-1; 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; 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;
PetscErrorCode KSPSolve_CGNE(KSP ksp) { PetscErrorCode ierr; PetscInt i,stored_max_it,eigs; PetscScalar dpi,a = 1.0,beta,betaold = 1.0,b = 0,*e = 0,*d = 0; PetscReal dp = 0.0; Vec X,B,Z,R,P,T; KSP_CG *cg; Mat Amat,Pmat; PetscBool diagonalscale,transpose_pc; 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); ierr = PCApplyTransposeExists(ksp->pc,&transpose_pc);CHKERRQ(ierr); 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]; T = ksp->work[3]; #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; ierr = MatMultTranspose(Amat,B,T);CHKERRQ(ierr); if (!ksp->guess_zero) { ierr = KSP_MatMult(ksp,Amat,X,P);CHKERRQ(ierr); ierr = KSP_MatMultTranspose(ksp,Amat,P,R);CHKERRQ(ierr); ierr = VecAYPX(R,-1.0,T);CHKERRQ(ierr); } else { ierr = VecCopy(T,R);CHKERRQ(ierr); /* r <- b (x is 0) */ } ierr = KSP_PCApply(ksp,R,T);CHKERRQ(ierr); if (transpose_pc) { ierr = KSP_PCApplyTranspose(ksp,T,Z);CHKERRQ(ierr); } else { ierr = KSP_PCApply(ksp,T,Z);CHKERRQ(ierr); } if (ksp->normtype == KSP_NORM_PRECONDITIONED) { ierr = VecNorm(Z,NORM_2,&dp);CHKERRQ(ierr); /* dp <- z'*z */ } else if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) { ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); /* dp <- r'*r */ } else if (ksp->normtype == KSP_NORM_NATURAL) { ierr = VecXDot(Z,R,&beta);CHKERRQ(ierr); dp = PetscSqrtReal(PetscAbsScalar(beta)); } else dp = 0.0; 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; ierr = VecXDot(Z,R,&beta);CHKERRQ(ierr); /* beta <- r'z */ 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 (beta < 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 */ } betaold = beta; ierr = MatMult(Amat,P,T);CHKERRQ(ierr); ierr = MatMultTranspose(Amat,T,Z);CHKERRQ(ierr); ierr = VecXDot(P,Z,&dpi);CHKERRQ(ierr); /* dpi <- z'p */ a = beta/dpi; /* a = beta/p'z */ 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,Z);CHKERRQ(ierr); /* r <- r - az */ if (ksp->normtype == KSP_NORM_PRECONDITIONED) { ierr = KSP_PCApply(ksp,R,T);CHKERRQ(ierr); if (transpose_pc) { ierr = KSP_PCApplyTranspose(ksp,T,Z);CHKERRQ(ierr); } else { ierr = KSP_PCApply(ksp,T,Z);CHKERRQ(ierr); } ierr = VecNorm(Z,NORM_2,&dp);CHKERRQ(ierr); /* dp <- z'*z */ } else if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) { ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); } else if (ksp->normtype == KSP_NORM_NATURAL) { dp = PetscSqrtReal(PetscAbsScalar(beta)); } else { dp = 0.0; } ksp->rnorm = dp; 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) { if (transpose_pc) { ierr = KSP_PCApplyTranspose(ksp,T,Z);CHKERRQ(ierr); } else { ierr = KSP_PCApply(ksp,T,Z);CHKERRQ(ierr); } } i++; } while (i<ksp->max_it); if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS; PetscFunctionReturn(0); }