Actual source code: bicg.c
petsc-3.13.6 2020-09-29
2: #include <petsc/private/kspimpl.h>
4: static PetscErrorCode KSPSetUp_BiCG(KSP ksp)
5: {
9: /* check user parameters and functions */
10: if (ksp->pc_side == PC_RIGHT) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"no right preconditioning for KSPBiCG");
11: else if (ksp->pc_side == PC_SYMMETRIC) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"no symmetric preconditioning for KSPBiCG");
12: KSPSetWorkVecs(ksp,6);
13: return(0);
14: }
16: static PetscErrorCode KSPSolve_BiCG(KSP ksp)
17: {
19: PetscInt i;
20: PetscBool diagonalscale;
21: PetscScalar dpi,a=1.0,beta,betaold=1.0,b,ma;
22: PetscReal dp;
23: Vec X,B,Zl,Zr,Rl,Rr,Pl,Pr;
24: Mat Amat,Pmat;
27: PCGetDiagonalScale(ksp->pc,&diagonalscale);
28: if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name);
30: X = ksp->vec_sol;
31: B = ksp->vec_rhs;
32: Rl = ksp->work[0];
33: Zl = ksp->work[1];
34: Pl = ksp->work[2];
35: Rr = ksp->work[3];
36: Zr = ksp->work[4];
37: Pr = ksp->work[5];
39: PCGetOperators(ksp->pc,&Amat,&Pmat);
41: if (!ksp->guess_zero) {
42: KSP_MatMult(ksp,Amat,X,Rr); /* r <- b - Ax */
43: VecAYPX(Rr,-1.0,B);
44: } else {
45: VecCopy(B,Rr); /* r <- b (x is 0) */
46: }
47: VecCopy(Rr,Rl);
48: KSP_PCApply(ksp,Rr,Zr); /* z <- Br */
49: VecConjugate(Rl);
50: KSP_PCApplyTranspose(ksp,Rl,Zl);
51: VecConjugate(Rl);
52: VecConjugate(Zl);
53: if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
54: VecNorm(Zr,NORM_2,&dp); /* dp <- z'*z */
55: } else {
56: VecNorm(Rr,NORM_2,&dp); /* dp <- r'*r */
57: }
58: KSPCheckNorm(ksp,dp);
59: KSPMonitor(ksp,0,dp);
60: PetscObjectSAWsTakeAccess((PetscObject)ksp);
61: ksp->its = 0;
62: ksp->rnorm = dp;
63: PetscObjectSAWsGrantAccess((PetscObject)ksp);
64: KSPLogResidualHistory(ksp,dp);
65: (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);
66: if (ksp->reason) return(0);
68: i = 0;
69: do {
70: VecDot(Zr,Rl,&beta); /* beta <- r'z */
71: KSPCheckDot(ksp,beta);
72: if (!i) {
73: if (beta == 0.0) {
74: ksp->reason = KSP_DIVERGED_BREAKDOWN_BICG;
75: return(0);
76: }
77: VecCopy(Zr,Pr); /* p <- z */
78: VecCopy(Zl,Pl);
79: } else {
80: b = beta/betaold;
81: VecAYPX(Pr,b,Zr); /* p <- z + b* p */
82: b = PetscConj(b);
83: VecAYPX(Pl,b,Zl);
84: }
85: betaold = beta;
86: KSP_MatMult(ksp,Amat,Pr,Zr); /* z <- Kp */
87: VecConjugate(Pl);
88: KSP_MatMultTranspose(ksp,Amat,Pl,Zl);
89: VecConjugate(Pl);
90: VecConjugate(Zl);
91: VecDot(Zr,Pl,&dpi); /* dpi <- z'p */
92: KSPCheckDot(ksp,dpi);
93: a = beta/dpi; /* a = beta/p'z */
94: VecAXPY(X,a,Pr); /* x <- x + ap */
95: ma = -a;
96: VecAXPY(Rr,ma,Zr);
97: ma = PetscConj(ma);
98: VecAXPY(Rl,ma,Zl);
99: if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
100: KSP_PCApply(ksp,Rr,Zr); /* z <- Br */
101: VecConjugate(Rl);
102: KSP_PCApplyTranspose(ksp,Rl,Zl);
103: VecConjugate(Rl);
104: VecConjugate(Zl);
105: VecNorm(Zr,NORM_2,&dp); /* dp <- z'*z */
106: } else {
107: VecNorm(Rr,NORM_2,&dp); /* dp <- r'*r */
108: }
109: KSPCheckNorm(ksp,dp);
110: PetscObjectSAWsTakeAccess((PetscObject)ksp);
111: ksp->its = i+1;
112: ksp->rnorm = dp;
113: PetscObjectSAWsGrantAccess((PetscObject)ksp);
114: KSPLogResidualHistory(ksp,dp);
115: KSPMonitor(ksp,i+1,dp);
116: (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);
117: if (ksp->reason) break;
118: if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
119: KSP_PCApply(ksp,Rr,Zr); /* z <- Br */
120: VecConjugate(Rl);
121: KSP_PCApplyTranspose(ksp,Rl,Zl);
122: VecConjugate(Rl);
123: VecConjugate(Zl);
124: }
125: i++;
126: } while (i<ksp->max_it);
127: if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS;
128: return(0);
129: }
131: /*MC
132: KSPBICG - Implements the Biconjugate gradient method (similar to running the conjugate
133: gradient on the normal equations).
135: Options Database Keys:
136: . see KSPSolve()
138: Level: beginner
140: Notes:
141: this method requires that one be apply to apply the transpose of the preconditioner and operator
142: as well as the operator and preconditioner.
143: Supports only left preconditioning
145: See KSPCGNE for code that EXACTLY runs the preconditioned conjugate gradient method on the
146: normal equations
148: .seealso: KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP, KSPBCGS, KSPCGNE
150: M*/
151: PETSC_EXTERN PetscErrorCode KSPCreate_BiCG(KSP ksp)
152: {
156: ksp->data = (void*)0;
157: KSPSetSupportedNorm(ksp,KSP_NORM_PRECONDITIONED,PC_LEFT,3);
158: KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_LEFT,2);
160: ksp->ops->setup = KSPSetUp_BiCG;
161: ksp->ops->solve = KSPSolve_BiCG;
162: ksp->ops->destroy = KSPDestroyDefault;
163: ksp->ops->view = 0;
164: ksp->ops->setfromoptions = 0;
165: ksp->ops->buildsolution = KSPBuildSolutionDefault;
166: ksp->ops->buildresidual = KSPBuildResidualDefault;
167: return(0);
168: }