Actual source code: cgs.c
1: /*$Id: cgs.c,v 1.63 2001/03/23 23:23:36 balay Exp $*/
3: /*
4: This code implements the CGS (Conjugate Gradient Squared) method.
5: Reference: Sonneveld, 1989.
7: Note that for the complex numbers version, the VecDot() arguments
8: within the code MUST remain in the order given for correct computation
9: of inner products.
10: */
11: #include src/sles/ksp/kspimpl.h
13: static int KSPSetUp_CGS(KSP ksp)
14: {
18: if (ksp->pc_side == PC_SYMMETRIC) SETERRQ(2,"no symmetric preconditioning for KSPCGS");
19: KSPDefaultGetWork(ksp,8);
20: return(0);
21: }
23: static int KSPSolve_CGS(KSP ksp,int *its)
24: {
25: int i,maxit,ierr;
26: Scalar rho,rhoold,a,s,b,tmp,one = 1.0;
27: Vec X,B,V,P,R,RP,T,Q,U,BINVF,AUQ;
28: PetscReal dp = 0.0;
29: PetscTruth diagonalscale;
32: ierr = PCDiagonalScale(ksp->B,&diagonalscale);
33: if (diagonalscale) SETERRQ1(1,"Krylov method %s does not support diagonal scaling",ksp->type_name);
35: maxit = ksp->max_it;
36: X = ksp->vec_sol;
37: B = ksp->vec_rhs;
38: R = ksp->work[0];
39: RP = ksp->work[1];
40: V = ksp->work[2];
41: T = ksp->work[3];
42: Q = ksp->work[4];
43: P = ksp->work[5];
44: BINVF = ksp->work[6];
45: U = ksp->work[7];
46: AUQ = V;
48: /* Compute initial preconditioned residual */
49: KSPInitialResidual(ksp,X,V,T,R,BINVF,B);
51: /* Test for nothing to do */
52: if (!ksp->avoidnorms) {
53: VecNorm(R,NORM_2,&dp);
54: }
55: PetscObjectTakeAccess(ksp);
56: ksp->its = 0;
57: ksp->rnorm = dp;
58: PetscObjectGrantAccess(ksp);
59: KSPLogResidualHistory(ksp,dp);
60: KSPMonitor(ksp,0,dp);
61: (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);
62: if (ksp->reason) {*its = 0; return(0);}
64: /* Make the initial Rp == R */
65: VecCopy(R,RP);
67: /* Set the initial conditions */
68: VecDot(R,RP,&rhoold); /* rhoold = (r,rp) */
69: VecCopy(R,U);
70: VecCopy(R,P);
71: KSP_PCApplyBAorAB(ksp,ksp->B,ksp->pc_side,P,V,T);
73: for (i=0; i<maxit; i++) {
75: VecDot(V,RP,&s); /* s <- (v,rp) */
76: a = rhoold / s; /* a <- rho / s */
77: tmp = -a;
78: VecWAXPY(&tmp,V,U,Q); /* q <- u - a v */
79: VecWAXPY(&one,U,Q,T); /* t <- u + q */
80: VecAXPY(&a,T,X); /* x <- x + a (u + q) */
81: KSP_PCApplyBAorAB(ksp,ksp->B,ksp->pc_side,T,AUQ,U);
82: VecAXPY(&tmp,AUQ,R); /* r <- r - a K (u + q) */
83: if (!ksp->avoidnorms) {
84: VecNorm(R,NORM_2,&dp);
85: }
87: PetscObjectTakeAccess(ksp);
88: ksp->its++;
89: ksp->rnorm = dp;
90: PetscObjectGrantAccess(ksp);
91: KSPLogResidualHistory(ksp,dp);
92: KSPMonitor(ksp,i+1,dp);
93: (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);
94: if (ksp->reason) break;
96: VecDot(R,RP,&rho); /* rho <- (r,rp) */
97: b = rho / rhoold; /* b <- rho / rhoold */
98: VecWAXPY(&b,Q,R,U); /* u <- r + b q */
99: VecAXPY(&b,P,Q);
100: VecWAXPY(&b,Q,U,P); /* p <- u + b(q + b p) */
101: KSP_PCApplyBAorAB(ksp,ksp->B,ksp->pc_side,P,V,Q); /* v <- K p */
102: rhoold = rho;
103: }
104: if (i == maxit) {
105: i--;
106: ksp->reason = KSP_DIVERGED_ITS;
107: }
108: *its = i+1;
110: KSPUnwindPreconditioner(ksp,X,T);
111: return(0);
112: }
114: EXTERN_C_BEGIN
115: int KSPCreate_CGS(KSP ksp)
116: {
118: ksp->data = (void*)0;
119: ksp->pc_side = PC_LEFT;
120: ksp->calc_res = PETSC_TRUE;
121: ksp->ops->setup = KSPSetUp_CGS;
122: ksp->ops->solve = KSPSolve_CGS;
123: ksp->ops->destroy = KSPDefaultDestroy;
124: ksp->ops->buildsolution = KSPDefaultBuildSolution;
125: ksp->ops->buildresidual = KSPDefaultBuildResidual;
126: ksp->ops->setfromoptions = 0;
127: ksp->ops->view = 0;
128: return(0);
129: }
130: EXTERN_C_END