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: static int KSPSetUp_CR(KSP ksp)
9: {
13: if (ksp->pc_side == PC_RIGHT) {SETERRQ(2,"no right preconditioning for KSPCR");}
14: else if (ksp->pc_side == PC_SYMMETRIC) {SETERRQ(2,"no symmetric preconditioning for KSPCR");}
15: KSPDefaultGetWork(ksp,6);
16: return(0);
17: }
19: static int KSPSolve_CR(KSP ksp,int *its)
20: {
21: int i = 0, maxit, cerr = 0, ierr;
22: MatStructure pflag;
23: PetscReal dp;
24: PetscScalar ai, bi;
25: PetscScalar apq,btop, bbot, tmp, mone = -1.0;
26: Vec X,B,R,RT,P,AP,ART,Q;
27: Mat Amat, Pmat;
31: maxit = ksp->max_it;
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: /* we follow Rati Chandra's PhD */
42: PCGetOperators(ksp->B,&Amat,&Pmat,&pflag);
43: /* */
44: if (!ksp->guess_zero) {
45: KSP_MatMult(ksp,Amat,X,R); /* r <- Ax */
46: VecAYPX(&mone,B,R); /* r <- b-r == b-Ax */
47: } else {
48: VecCopy(B,R); /* r <- b (x is 0) */
49: }
50: KSP_PCApply(ksp,ksp->B,R,P); /* P <- Br */
51: KSP_MatMult(ksp,Amat,P,AP); /* AP <- A p */
52: VecCopy(P,RT); /* rt <- p */
53: VecCopy(AP,ART); /* ART <- AP */
54: ierr = VecDot(RT,ART,&btop); /* (RT,ART) */
55: if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
56: VecNorm(P,NORM_2,&dp); /* dp <- z'*z */
57: } else if (ksp->normtype == KSP_UNPRECONDITIONED_NORM) {
58: VecNorm(R,NORM_2,&dp); /* dp <- r'*r */
59: } else if (ksp->normtype == KSP_NATURAL_NORM) {
60: dp = PetscAbsScalar(btop); /* dp = (R,AR) (fdi)*/
61: }
62: (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);
63: if (ksp->reason) {*its = 0; return(0);}
64: KSPMonitor(ksp,0,dp);
65: PetscObjectTakeAccess(ksp);
66: ksp->its = 0;
67: ksp->rnorm = dp;
68: PetscObjectGrantAccess(ksp);
69: KSPLogResidualHistory(ksp,dp);
71: for ( i=0; i<maxit; i++) {
72: ierr = KSP_PCApply(ksp,ksp->B,AP,Q); /* q <- B AP */
73: /* Step 3 */
75: ierr = VecDot(AP,Q,&apq);
76: ai = btop/apq; /* ai = (RT,ART)/(AP,Q) */
78: ierr = VecAXPY(&ai,P,X); /* x <- x + ai p */
79: tmp = -ai;
80: ierr = VecAXPY(&tmp,Q,RT); /* rt <- rt - ai q */
81: ierr = KSP_MatMult(ksp,Amat,RT,ART); /* RT <- ART */
82: bbot = btop;
83: ierr = VecDot(RT,ART,&btop);
85: if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
86: VecNorm(RT,NORM_2,&dp); /* dp <- r'*r */
87: } else if (ksp->normtype == KSP_NATURAL_NORM) {
88: dp = PetscAbsScalar(btop); /* dp = (R,AR) (fdi)*/
89: } else { dp = 0.0; }
91: PetscObjectTakeAccess(ksp);
92: ksp->its++;
93: ksp->rnorm = dp;
94: PetscObjectGrantAccess(ksp);
95: /* Step 2 */
96: KSPLogResidualHistory(ksp,dp);
97: KSPMonitor(ksp,i+1,dp);
98: (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);
99: if (ksp->reason) break;
101: bi = btop/bbot;
102: VecAYPX(&bi,RT,P); /* P <- rt + Bi P */
103: VecAYPX(&bi,ART,AP); /* AP <- Art + Bi AP */
104: }
105: if (i == maxit) i--;
106: if (cerr <= 0) *its = -(i+1);
107: else *its = i + 1;
108: return(0);
109: }
112: EXTERN_C_BEGIN
113: int KSPCreate_CR(KSP ksp)
114: {
116: ksp->pc_side = PC_LEFT;
117: ksp->ops->setup = KSPSetUp_CR;
118: ksp->ops->solve = KSPSolve_CR;
119: ksp->ops->destroy = KSPDefaultDestroy;
120: ksp->ops->buildsolution = KSPDefaultBuildSolution;
121: ksp->ops->buildresidual = KSPDefaultBuildResidual;
122: ksp->ops->setfromoptions = 0;
123: ksp->ops->view = 0;
124: return(0);
125: }
126: EXTERN_C_END