Actual source code: cr.c
2: #include src/ksp/ksp/kspimpl.h
6: static PetscErrorCode KSPSetUp_CR(KSP ksp)
7: {
11: if (ksp->pc_side == PC_RIGHT) {SETERRQ(2,"no right preconditioning for KSPCR");}
12: else if (ksp->pc_side == PC_SYMMETRIC) {SETERRQ(2,"no symmetric preconditioning for KSPCR");}
13: KSPDefaultGetWork(ksp,6);
14: return(0);
15: }
19: static PetscErrorCode KSPSolve_CR(KSP ksp)
20: {
22: PetscInt i = 0;
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;
31: X = ksp->vec_sol;
32: B = ksp->vec_rhs;
33: R = ksp->work[0];
34: RT = ksp->work[1];
35: P = ksp->work[2];
36: AP = ksp->work[3];
37: ART = ksp->work[4];
38: Q = ksp->work[5];
40: /* R is the true residual norm, RT is the preconditioned residual norm */
41: PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);
42: if (!ksp->guess_zero) {
43: KSP_MatMult(ksp,Amat,X,R); /* R <- A*X */
44: VecAYPX(&mone,B,R); /* R <- B-R == B-A*X */
45: } else {
46: VecCopy(B,R); /* R <- B (X is 0) */
47: }
48: KSP_PCApply(ksp,R,P); /* P <- B*R */
49: KSP_MatMult(ksp,Amat,P,AP); /* AP <- A*P */
50: VecCopy(P,RT); /* RT <- P */
51: VecCopy(AP,ART); /* ART <- AP */
52: VecDot(RT,ART,&btop); /* (RT,ART) */
53: if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
54: VecNorm(RT,NORM_2,&dp); /* dp <- RT'*RT */
55: } else if (ksp->normtype == KSP_UNPRECONDITIONED_NORM) {
56: VecNorm(R,NORM_2,&dp); /* dp <- R'*R */
57: } else if (ksp->normtype == KSP_NATURAL_NORM) {
58: dp = sqrt(PetscAbsScalar(btop)); /* dp = sqrt(R,AR) */
59: }
60: ksp->its = 0;
61: KSPMonitor(ksp,0,dp);
62: PetscObjectTakeAccess(ksp);
63: ksp->rnorm = dp;
64: PetscObjectGrantAccess(ksp);
65: KSPLogResidualHistory(ksp,dp);
66: (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);
67: if (ksp->reason) return(0);
69: i = 0;
70: do {
71: KSP_PCApply(ksp,AP,Q);/* Q <- B* AP */
72: /* Step 3 */
74: VecDot(AP,Q,&apq);
75: ai = btop/apq; /* ai = (RT,ART)/(AP,Q) */
77: VecAXPY(&ai,P,X); /* X <- X + ai*P */
78: ai = -ai;
79: VecAXPY(&ai,Q,RT); /* RT <- RT - ai*Q */
80: KSP_MatMult(ksp,Amat,RT,ART);/* ART <- A*RT */
81: bbot = btop;
82: VecDot(RT,ART,&btop);
84: if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
85: VecNorm(RT,NORM_2,&dp); /* dp <- || RT || */
86: } else if (ksp->normtype == KSP_NATURAL_NORM) {
87: dp = sqrt(PetscAbsScalar(btop)); /* dp = sqrt(R,AR) */
88: } else if (ksp->normtype == KSP_NO_NORM) {
89: dp = 0.0;
90: } else if (ksp->normtype == KSP_UNPRECONDITIONED_NORM) {
91: VecAXPY(&ai,AP,R); /* R <- R - ai*AP */
92: VecNorm(R,NORM_2,&dp); /* dp <- R'*R */
93: } else {
94: SETERRQ1(PETSC_ERR_SUP,"KSPNormType of %d not supported",(int)ksp->normtype);
95: }
97: PetscObjectTakeAccess(ksp);
98: ksp->its++;
99: ksp->rnorm = dp;
100: PetscObjectGrantAccess(ksp);
102: KSPLogResidualHistory(ksp,dp);
103: KSPMonitor(ksp,i+1,dp);
104: (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);
105: if (ksp->reason) break;
107: bi = btop/bbot;
108: VecAYPX(&bi,RT,P); /* P <- RT + Bi P */
109: VecAYPX(&bi,ART,AP); /* AP <- ART + Bi AP */
110: i++;
111: } while (i<ksp->max_it);
112: if (i >= ksp->max_it) {
113: ksp->reason = KSP_DIVERGED_ITS;
114: }
115: return(0);
116: }
119: /*MC
120: KSPCR - This code implements the (preconditioned) conjugate residuals method
122: Options Database Keys:
123: . see KSPSolve()
125: Level: beginner
127: Notes: The operator and the preconditioner must be symmetric for this method
129: .seealso: KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP, KSPCG
130: M*/
134: PetscErrorCode KSPCreate_CR(KSP ksp)
135: {
137: ksp->pc_side = PC_LEFT;
138: ksp->ops->setup = KSPSetUp_CR;
139: ksp->ops->solve = KSPSolve_CR;
140: ksp->ops->destroy = KSPDefaultDestroy;
141: ksp->ops->buildsolution = KSPDefaultBuildSolution;
142: ksp->ops->buildresidual = KSPDefaultBuildResidual;
143: ksp->ops->setfromoptions = 0;
144: ksp->ops->view = 0;
145: return(0);
146: }