Actual source code: cr.c
1: /*$Id: cr.c,v 1.64 2001/08/07 03:03:49 balay Exp $*/
3: #include src/ksp/ksp/kspimpl.h
7: static int KSPSetUp_CR(KSP ksp)
8: {
12: if (ksp->pc_side == PC_RIGHT) {SETERRQ(2,"no right preconditioning for KSPCR");}
13: else if (ksp->pc_side == PC_SYMMETRIC) {SETERRQ(2,"no symmetric preconditioning for KSPCR");}
14: KSPDefaultGetWork(ksp,6);
15: return(0);
16: }
20: static int KSPSolve_CR(KSP ksp)
21: {
22: int i = 0, ierr;
23: MatStructure pflag;
24: PetscReal dp;
25: PetscScalar ai, bi;
26: PetscScalar apq,btop, bbot, mone = -1.0;
27: Vec X,B,R,RT,P,AP,ART,Q;
28: Mat Amat, Pmat;
32: X = ksp->vec_sol;
33: B = ksp->vec_rhs;
34: R = ksp->work[0];
35: RT = ksp->work[1];
36: P = ksp->work[2];
37: AP = ksp->work[3];
38: ART = ksp->work[4];
39: Q = ksp->work[5];
41: /* R is the true residual norm, RT is the preconditioned residual norm */
42: PCGetOperators(ksp->B,&Amat,&Pmat,&pflag);
43: if (!ksp->guess_zero) {
44: KSP_MatMult(ksp,Amat,X,R); /* R <- A*X */
45: VecAYPX(&mone,B,R); /* R <- B-R == B-A*X */
46: } else {
47: VecCopy(B,R); /* R <- B (X is 0) */
48: }
49: KSP_PCApply(ksp,ksp->B,R,P); /* P <- B*R */
50: KSP_MatMult(ksp,Amat,P,AP); /* AP <- A*P */
51: VecCopy(P,RT); /* RT <- P */
52: VecCopy(AP,ART); /* ART <- AP */
53: VecDot(RT,ART,&btop); /* (RT,ART) */
54: if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
55: VecNorm(RT,NORM_2,&dp); /* dp <- RT'*RT */
56: } else if (ksp->normtype == KSP_UNPRECONDITIONED_NORM) {
57: VecNorm(R,NORM_2,&dp); /* dp <- R'*R */
58: } else if (ksp->normtype == KSP_NATURAL_NORM) {
59: dp = sqrt(PetscAbsScalar(btop)); /* dp = sqrt(R,AR) */
60: }
61: ksp->its = 0;
62: KSPMonitor(ksp,0,dp);
63: PetscObjectTakeAccess(ksp);
64: ksp->rnorm = dp;
65: PetscObjectGrantAccess(ksp);
66: KSPLogResidualHistory(ksp,dp);
67: (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);
68: if (ksp->reason) return(0);
70: i = 0;
71: do {
72: KSP_PCApply(ksp,ksp->B,AP,Q);/* Q <- B* AP */
73: /* Step 3 */
75: VecDot(AP,Q,&apq);
76: ai = btop/apq; /* ai = (RT,ART)/(AP,Q) */
78: VecAXPY(&ai,P,X); /* X <- X + ai*P */
79: ai = -ai;
80: VecAXPY(&ai,Q,RT); /* RT <- RT - ai*Q */
81: KSP_MatMult(ksp,Amat,RT,ART);/* ART <- A*RT */
82: bbot = btop;
83: VecDot(RT,ART,&btop);
85: if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
86: VecNorm(RT,NORM_2,&dp); /* dp <- || RT || */
87: } else if (ksp->normtype == KSP_NATURAL_NORM) {
88: dp = sqrt(PetscAbsScalar(btop)); /* dp = sqrt(R,AR) */
89: } else if (ksp->normtype == KSP_NO_NORM) {
90: dp = 0.0;
91: } else if (ksp->normtype == KSP_UNPRECONDITIONED_NORM) {
92: VecAXPY(&ai,AP,R); /* R <- R - ai*AP */
93: VecNorm(R,NORM_2,&dp); /* dp <- R'*R */
94: } else {
95: SETERRQ1(1,"KSPNormType of %d not supported",(int)ksp->normtype);
96: }
98: PetscObjectTakeAccess(ksp);
99: ksp->its++;
100: ksp->rnorm = dp;
101: PetscObjectGrantAccess(ksp);
103: KSPLogResidualHistory(ksp,dp);
104: KSPMonitor(ksp,i+1,dp);
105: (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);
106: if (ksp->reason) break;
108: bi = btop/bbot;
109: VecAYPX(&bi,RT,P); /* P <- RT + Bi P */
110: VecAYPX(&bi,ART,AP); /* AP <- ART + Bi AP */
111: i++;
112: } while (i<ksp->max_it);
113: if (i == ksp->max_it) {
114: ksp->reason = KSP_DIVERGED_ITS;
115: }
116: return(0);
117: }
120: /*MC
121: KSPCR - This code implements the (preconditioned) conjugate residuals method
123: Options Database Keys:
124: . see KSPSolve()
126: Level: beginner
128: Notes: The operator and the preconditioner must be symmetric for this method
130: .seealso: KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP, KSPCG
132: M*/
134: EXTERN_C_BEGIN
137: int KSPCreate_CR(KSP ksp)
138: {
140: ksp->pc_side = PC_LEFT;
141: ksp->ops->setup = KSPSetUp_CR;
142: ksp->ops->solve = KSPSolve_CR;
143: ksp->ops->destroy = KSPDefaultDestroy;
144: ksp->ops->buildsolution = KSPDefaultBuildSolution;
145: ksp->ops->buildresidual = KSPDefaultBuildResidual;
146: ksp->ops->setfromoptions = 0;
147: ksp->ops->view = 0;
148: return(0);
149: }
150: EXTERN_C_END