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");
40: PCDiagonalScale(ksp->pc,&diagonalscale);
41: if (diagonalscale) SETERRQ1(PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name);
43: X = ksp->vec_sol;
44: B = ksp->vec_rhs;
45: Rl = ksp->work[0];
46: Zl = ksp->work[1];
47: Pl = ksp->work[2];
48: Rr = ksp->work[3];
49: Zr = ksp->work[4];
50: Pr = ksp->work[5];
52: PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);
54: if (!ksp->guess_zero) {
55: KSP_MatMult(ksp,Amat,X,Rr); /* r <- b - Ax */
56: VecAYPX(Rr,-1.0,B);
57: } else {
58: VecCopy(B,Rr); /* r <- b (x is 0) */
59: }
60: VecCopy(Rr,Rl);
61: KSP_PCApply(ksp,Rr,Zr); /* z <- Br */
62: VecConjugate(Rl);
63: KSP_PCApplyTranspose(ksp,Rl,Zl);
64: VecConjugate(Rl);
65: VecConjugate(Zl);
66: if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
67: VecNorm(Zr,NORM_2,&dp); /* dp <- z'*z */
68: } else {
69: VecNorm(Rr,NORM_2,&dp); /* dp <- r'*r */
70: }
71: KSPMonitor(ksp,0,dp);
72: PetscObjectTakeAccess(ksp);
73: ksp->its = 0;
74: ksp->rnorm = dp;
75: PetscObjectGrantAccess(ksp);
76: KSPLogResidualHistory(ksp,dp);
77: (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);
78: if (ksp->reason) return(0);
80: i = 0;
81: do {
82: VecDot(Zr,Rl,&beta); /* beta <- r'z */
83: if (!i) {
84: if (beta == 0.0) {
85: ksp->reason = KSP_DIVERGED_BREAKDOWN_BICG;
86: return(0);
87: }
88: VecCopy(Zr,Pr); /* p <- z */
89: VecCopy(Zl,Pl);
90: } else {
91: b = beta/betaold;
92: VecAYPX(Pr,b,Zr); /* p <- z + b* p */
93: b = PetscConj(b);
94: VecAYPX(Pl,b,Zl);
95: }
96: betaold = beta;
97: KSP_MatMult(ksp,Amat,Pr,Zr); /* z <- Kp */
98: VecConjugate(Pl);
99: KSP_MatMultTranspose(ksp,Amat,Pl,Zl);
100: VecConjugate(Pl);
101: VecConjugate(Zl);
102: VecDot(Zr,Pl,&dpi); /* dpi <- z'p */
103: a = beta/dpi; /* a = beta/p'z */
104: VecAXPY(X,a,Pr); /* x <- x + ap */
105: ma = -a;
106: VecAXPY(Rr,ma,Zr);CHKERRQ(ierr)
107: ma = PetscConj(ma);
108: VecAXPY(Rl,ma,Zl);
109: if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
110: KSP_PCApply(ksp,Rr,Zr); /* z <- Br */
111: VecConjugate(Rl);
112: KSP_PCApplyTranspose(ksp,Rl,Zl);
113: VecConjugate(Rl);
114: VecConjugate(Zl);
115: VecNorm(Zr,NORM_2,&dp); /* dp <- z'*z */
116: } else {
117: VecNorm(Rr,NORM_2,&dp); /* dp <- r'*r */
118: }
119: PetscObjectTakeAccess(ksp);
120: ksp->its = i+1;
121: ksp->rnorm = dp;
122: PetscObjectGrantAccess(ksp);
123: KSPLogResidualHistory(ksp,dp);
124: KSPMonitor(ksp,i+1,dp);
125: (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);
126: if (ksp->reason) break;
127: if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
128: KSP_PCApply(ksp,Rr,Zr); /* z <- Br */
129: VecConjugate(Rl);
130: KSP_PCApplyTranspose(ksp,Rl,Zl);
131: VecConjugate(Rl);
132: VecConjugate(Zl);
133: }
134: i++;
135: } while (i<ksp->max_it);
136: if (i >= ksp->max_it) {
137: ksp->reason = KSP_DIVERGED_ITS;
138: }
139: return(0);
140: }
144: PetscErrorCode KSPDestroy_BiCG(KSP ksp)
145: {
149: KSPDefaultFreeWork(ksp);
150: return(0);
151: }
153: /*MC
154: KSPBICG - Implements the Biconjugate gradient method (similar to running the conjugate
155: gradient on the normal equations).
157: Options Database Keys:
158: . see KSPSolve()
160: Level: beginner
162: Note: this method requires that one be apply to apply the transpose of the preconditioner and operator
163: as well as the operator and preconditioner.
165: See KSPCGNE for code that EXACTLY runs the preconditioned conjugate gradient method on the
166: normal equations
168: .seealso: KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP, KSPBCGS, KSPCGNE
170: M*/
174: PetscErrorCode KSPCreate_BiCG(KSP ksp)
175: {
177: ksp->data = (void*)0;
178: ksp->pc_side = PC_LEFT;
179: ksp->ops->setup = KSPSetUp_BiCG;
180: ksp->ops->solve = KSPSolve_BiCG;
181: ksp->ops->destroy = KSPDestroy_BiCG;
182: ksp->ops->view = 0;
183: ksp->ops->setfromoptions = 0;
184: ksp->ops->buildsolution = KSPDefaultBuildSolution;
185: ksp->ops->buildresidual = KSPDefaultBuildResidual;
187: return(0);
188: }