Actual source code: bicg.c
1: #define PETSCKSP_DLL
3: #include private/kspimpl.h
7: PetscErrorCode KSPSetUp_BiCG(KSP ksp)
8: {
12: /* check user parameters and functions */
13: if (ksp->pc_side == PC_RIGHT) {
14: SETERRQ(PETSC_ERR_SUP,"no right preconditioning for KSPBiCG");
15: } else if (ksp->pc_side == PC_SYMMETRIC) {
16: SETERRQ(PETSC_ERR_SUP,"no symmetric preconditioning for KSPBiCG");
17: }
19: /* get work vectors from user code */
20: KSPDefaultGetWork(ksp,6);
21: return(0);
22: }
26: PetscErrorCode KSPSolve_BiCG(KSP ksp)
27: {
29: PetscInt i;
30: PetscTruth diagonalscale;
31: PetscScalar dpi,a=1.0,beta,betaold=1.0,b,ma;
32: PetscReal dp;
33: Vec X,B,Zl,Zr,Rl,Rr,Pl,Pr;
34: Mat Amat,Pmat;
35: MatStructure pflag;
38: if (ksp->normtype == KSP_NORM_NATURAL) SETERRQ(PETSC_ERR_SUP,"Cannot use natural residual norm with KSPIBCGS");
39: if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) SETERRQ(PETSC_ERR_SUP,"Cannot use unpreconditioned residual norm and KSPIBCGS");
41: PCDiagonalScale(ksp->pc,&diagonalscale);
42: if (diagonalscale) SETERRQ1(PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name);
44: X = ksp->vec_sol;
45: B = ksp->vec_rhs;
46: Rl = ksp->work[0];
47: Zl = ksp->work[1];
48: Pl = ksp->work[2];
49: Rr = ksp->work[3];
50: Zr = ksp->work[4];
51: Pr = ksp->work[5];
53: PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);
55: if (!ksp->guess_zero) {
56: KSP_MatMult(ksp,Amat,X,Rr); /* r <- b - Ax */
57: VecAYPX(Rr,-1.0,B);
58: } else {
59: VecCopy(B,Rr); /* r <- b (x is 0) */
60: }
61: VecCopy(Rr,Rl);
62: KSP_PCApply(ksp,Rr,Zr); /* z <- Br */
63: VecConjugate(Rl);
64: KSP_PCApplyTranspose(ksp,Rl,Zl);
65: VecConjugate(Rl);
66: VecConjugate(Zl);
67: if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
68: VecNorm(Zr,NORM_2,&dp); /* dp <- z'*z */
69: } else {
70: VecNorm(Rr,NORM_2,&dp); /* dp <- r'*r */
71: }
72: KSPMonitor(ksp,0,dp);
73: PetscObjectTakeAccess(ksp);
74: ksp->its = 0;
75: ksp->rnorm = dp;
76: PetscObjectGrantAccess(ksp);
77: KSPLogResidualHistory(ksp,dp);
78: (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);
79: if (ksp->reason) return(0);
81: i = 0;
82: do {
83: VecDot(Zr,Rl,&beta); /* beta <- r'z */
84: if (!i) {
85: if (beta == 0.0) {
86: ksp->reason = KSP_DIVERGED_BREAKDOWN_BICG;
87: return(0);
88: }
89: VecCopy(Zr,Pr); /* p <- z */
90: VecCopy(Zl,Pl);
91: } else {
92: b = beta/betaold;
93: VecAYPX(Pr,b,Zr); /* p <- z + b* p */
94: b = PetscConj(b);
95: VecAYPX(Pl,b,Zl);
96: }
97: betaold = beta;
98: KSP_MatMult(ksp,Amat,Pr,Zr); /* z <- Kp */
99: VecConjugate(Pl);
100: KSP_MatMultTranspose(ksp,Amat,Pl,Zl);
101: VecConjugate(Pl);
102: VecConjugate(Zl);
103: VecDot(Zr,Pl,&dpi); /* dpi <- z'p */
104: a = beta/dpi; /* a = beta/p'z */
105: VecAXPY(X,a,Pr); /* x <- x + ap */
106: ma = -a;
107: VecAXPY(Rr,ma,Zr);CHKERRQ(ierr)
108: ma = PetscConj(ma);
109: VecAXPY(Rl,ma,Zl);
110: if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
111: KSP_PCApply(ksp,Rr,Zr); /* z <- Br */
112: VecConjugate(Rl);
113: KSP_PCApplyTranspose(ksp,Rl,Zl);
114: VecConjugate(Rl);
115: VecConjugate(Zl);
116: VecNorm(Zr,NORM_2,&dp); /* dp <- z'*z */
117: } else {
118: VecNorm(Rr,NORM_2,&dp); /* dp <- r'*r */
119: }
120: PetscObjectTakeAccess(ksp);
121: ksp->its = i+1;
122: ksp->rnorm = dp;
123: PetscObjectGrantAccess(ksp);
124: KSPLogResidualHistory(ksp,dp);
125: KSPMonitor(ksp,i+1,dp);
126: (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);
127: if (ksp->reason) break;
128: if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
129: KSP_PCApply(ksp,Rr,Zr); /* z <- Br */
130: VecConjugate(Rl);
131: KSP_PCApplyTranspose(ksp,Rl,Zl);
132: VecConjugate(Rl);
133: VecConjugate(Zl);
134: }
135: i++;
136: } while (i<ksp->max_it);
137: if (i >= ksp->max_it) {
138: ksp->reason = KSP_DIVERGED_ITS;
139: }
140: return(0);
141: }
145: PetscErrorCode KSPDestroy_BiCG(KSP ksp)
146: {
150: KSPDefaultFreeWork(ksp);
151: return(0);
152: }
154: /*MC
155: KSPBICG - Implements the Biconjugate gradient method (similar to running the conjugate
156: gradient on the normal equations).
158: Options Database Keys:
159: . see KSPSolve()
161: Level: beginner
163: Note: this method requires that one be apply to apply the transpose of the preconditioner and operator
164: as well as the operator and preconditioner.
166: See KSPCGNE for code that EXACTLY runs the preconditioned conjugate gradient method on the
167: normal equations
169: .seealso: KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP, KSPBCGS, KSPCGNE
171: M*/
175: PetscErrorCode KSPCreate_BiCG(KSP ksp)
176: {
178: ksp->data = (void*)0;
179: ksp->pc_side = PC_LEFT;
180: ksp->ops->setup = KSPSetUp_BiCG;
181: ksp->ops->solve = KSPSolve_BiCG;
182: ksp->ops->destroy = KSPDestroy_BiCG;
183: ksp->ops->view = 0;
184: ksp->ops->setfromoptions = 0;
185: ksp->ops->buildsolution = KSPDefaultBuildSolution;
186: ksp->ops->buildresidual = KSPDefaultBuildResidual;
188: return(0);
189: }