Actual source code: cr.c
1: /*$Id: cr.c,v 1.64 2001/08/07 03:03:49 balay Exp $*/
3: /*
4: This implements Preconditioned Conjugate Residuals.
5: */
6: #include src/sles/ksp/kspimpl.h
8: #undef __FUNCT__
10: static int KSPSetUp_CR(KSP ksp)
11: {
15: if (ksp->pc_side == PC_RIGHT) {SETERRQ(2,"no right preconditioning for KSPCR");}
16: else if (ksp->pc_side == PC_SYMMETRIC) {SETERRQ(2,"no symmetric preconditioning for KSPCR");}
17: KSPDefaultGetWork(ksp,6);
18: return(0);
19: }
21: #undef __FUNCT__
23: static int KSPSolve_CR(KSP ksp,int *its)
24: {
25: int i = 0, maxit, ierr;
26: MatStructure pflag;
27: PetscReal dp;
28: PetscScalar ai, bi;
29: PetscScalar apq,btop, bbot, mone = -1.0;
30: Vec X,B,R,RT,P,AP,ART,Q;
31: Mat Amat, Pmat;
35: maxit = ksp->max_it;
36: X = ksp->vec_sol;
37: B = ksp->vec_rhs;
38: R = ksp->work[0];
39: RT = ksp->work[1];
40: P = ksp->work[2];
41: AP = ksp->work[3];
42: ART = ksp->work[4];
43: Q = ksp->work[5];
45: /* R is the true residual norm, RT is the preconditioned residual norm */
46: PCGetOperators(ksp->B,&Amat,&Pmat,&pflag);
47: if (!ksp->guess_zero) {
48: KSP_MatMult(ksp,Amat,X,R); /* R <- A*X */
49: VecAYPX(&mone,B,R); /* R <- B-R == B-A*X */
50: } else {
51: VecCopy(B,R); /* R <- B (X is 0) */
52: }
53: KSP_PCApply(ksp,ksp->B,R,P); /* P <- B*R */
54: KSP_MatMult(ksp,Amat,P,AP); /* AP <- A*P */
55: VecCopy(P,RT); /* RT <- P */
56: VecCopy(AP,ART); /* ART <- AP */
57: ierr = VecDot(RT,ART,&btop); /* (RT,ART) */
58: if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
59: VecNorm(RT,NORM_2,&dp); /* dp <- RT'*RT */
60: } else if (ksp->normtype == KSP_UNPRECONDITIONED_NORM) {
61: VecNorm(R,NORM_2,&dp); /* dp <- R'*R */
62: } else if (ksp->normtype == KSP_NATURAL_NORM) {
63: dp = sqrt(PetscAbsScalar(btop)); /* dp = sqrt(R,AR) */
64: }
65: (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);
66: if (ksp->reason) {*its = 0; return(0);}
67: KSPMonitor(ksp,0,dp);
68: PetscObjectTakeAccess(ksp);
69: ksp->its = 0;
70: ksp->rnorm = dp;
71: PetscObjectGrantAccess(ksp);
72: KSPLogResidualHistory(ksp,dp);
74: for ( i=0; i<maxit; i++) {
75: ierr = KSP_PCApply(ksp,ksp->B,AP,Q);/* Q <- B* AP */
76: /* Step 3 */
78: ierr = VecDot(AP,Q,&apq);
79: ai = btop/apq; /* ai = (RT,ART)/(AP,Q) */
81: ierr = VecAXPY(&ai,P,X); /* X <- X + ai*P */
82: ai = -ai;
83: ierr = VecAXPY(&ai,Q,RT); /* RT <- RT - ai*Q */
84: ierr = KSP_MatMult(ksp,Amat,RT,ART);/* ART <- A*RT */
85: bbot = btop;
86: ierr = VecDot(RT,ART,&btop);
88: if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
89: VecNorm(RT,NORM_2,&dp); /* dp <- || RT || */
90: } else if (ksp->normtype == KSP_NATURAL_NORM) {
91: dp = sqrt(PetscAbsScalar(btop)); /* dp = sqrt(R,AR) */
92: } else if (ksp->normtype == KSP_NO_NORM) {
93: dp = 0.0;
94: } else if (ksp->normtype == KSP_UNPRECONDITIONED_NORM) {
95: VecAXPY(&ai,AP,R); /* R <- R - ai*AP */
96: VecNorm(R,NORM_2,&dp); /* dp <- R'*R */
97: } else {
98: SETERRQ1(1,"KSPNormType of %d not supported",(int)ksp->normtype);
99: }
101: PetscObjectTakeAccess(ksp);
102: ksp->its++;
103: ksp->rnorm = dp;
104: PetscObjectGrantAccess(ksp);
106: KSPLogResidualHistory(ksp,dp);
107: KSPMonitor(ksp,i+1,dp);
108: (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);
109: if (ksp->reason) break;
111: bi = btop/bbot;
112: VecAYPX(&bi,RT,P); /* P <- RT + Bi P */
113: VecAYPX(&bi,ART,AP); /* AP <- ART + Bi AP */
114: }
115: if (i == maxit) {
116: ksp->reason = KSP_DIVERGED_ITS;
117: }
118: *its = ksp->its;
119: return(0);
120: }
123: EXTERN_C_BEGIN
124: #undef __FUNCT__
126: int KSPCreate_CR(KSP ksp)
127: {
129: ksp->pc_side = PC_LEFT;
130: ksp->ops->setup = KSPSetUp_CR;
131: ksp->ops->solve = KSPSolve_CR;
132: ksp->ops->destroy = KSPDefaultDestroy;
133: ksp->ops->buildsolution = KSPDefaultBuildSolution;
134: ksp->ops->buildresidual = KSPDefaultBuildResidual;
135: ksp->ops->setfromoptions = 0;
136: ksp->ops->view = 0;
137: return(0);
138: }
139: EXTERN_C_END