Actual source code: tcqmr.c

petsc-3.3-p7 2013-05-11
  2: /*
  3:     This file contains an implementation of Tony Chan's transpose-free QMR.

  5:     Note: The vector dot products in the code have not been checked for the
  6:     complex numbers version, so most probably some are incorrect.
  7: */

  9: #include <petsc-private/kspimpl.h>
 10: #include <../src/ksp/ksp/impls/tcqmr/tcqmrimpl.h>

 14: static PetscErrorCode KSPSolve_TCQMR(KSP ksp)
 15: {
 16:   PetscReal      rnorm0,rnorm,dp1,Gamma;
 17:   PetscScalar    theta,ep,cl1,sl1,cl,sl,sprod,tau_n1,f;
 18:   PetscScalar    deltmp,rho,beta,eptmp,ta,s,c,tau_n,delta;
 19:   PetscScalar    dp11,dp2,rhom1,alpha,tmp;

 23:   ksp->its = 0;

 25:   KSPInitialResidual(ksp,x,u,v,r,b);
 26:   VecNorm(r,NORM_2,&rnorm0);         /*  rnorm0 = ||r|| */

 28:   (*ksp->converged)(ksp,0,rnorm0,&ksp->reason,ksp->cnvP);
 29:   if (ksp->reason) return(0);

 31:   VecSet(um1,0.0);
 32:   VecCopy(r,u);
 33:   rnorm = rnorm0;
 34:   tmp   = 1.0/rnorm; VecScale(u,tmp);
 35:   VecSet(vm1,0.0);
 36:   VecCopy(u,v);
 37:   VecCopy(u,v0);
 38:   VecSet(pvec1,0.0);
 39:   VecSet(pvec2,0.0);
 40:   VecSet(p,0.0);
 41:   theta = 0.0;
 42:   ep    = 0.0;
 43:   cl1   = 0.0;
 44:   sl1   = 0.0;
 45:   cl    = 0.0;
 46:   sl    = 0.0;
 47:   sprod = 1.0;
 48:   tau_n1= rnorm0;
 49:   f     = 1.0;
 50:   Gamma = 1.0;
 51:   rhom1 = 1.0;

 53:   /*
 54:    CALCULATE SQUARED LANCZOS  vectors
 55:    */
 56:   (*ksp->converged)(ksp,ksp->its,rnorm,&ksp->reason,ksp->cnvP);
 57:   while (!ksp->reason){
 58:     KSPMonitor(ksp,ksp->its,rnorm);
 59:     ksp->its++;

 61:     KSP_PCApplyBAorAB(ksp,u,y,vtmp); /* y = A*u */
 62:     VecDot(y,v0,&dp11);
 63:     VecDot(u,v0,&dp2);
 64:     alpha  = dp11 / dp2;                          /* alpha = v0'*y/v0'*u */
 65:     deltmp = alpha;
 66:     VecCopy(y,z);
 67:     VecAXPY(z,-alpha,u); /* z = y - alpha u */
 68:     VecDot(u,v0,&rho);
 69:     beta   = rho / (f*rhom1);
 70:     rhom1  = rho;
 71:     VecCopy(z,utmp);    /* up1 = (A-alpha*I)*
 72:                                                  (z-2*beta*p) + f*beta*
 73:                                                  beta*um1 */
 74:     VecAXPY(utmp,-2.0*beta,p);
 75:     KSP_PCApplyBAorAB(ksp,utmp,up1,vtmp);
 76:     VecAXPY(up1,-alpha,utmp);
 77:     VecAXPY(up1,f*beta*beta,um1);
 78:     VecNorm(up1,NORM_2,&dp1);
 79:     f      = 1.0 / dp1;
 80:     VecScale(up1,f);
 81:     VecAYPX(p,-beta,z);   /* p = f*(z-beta*p) */
 82:     VecScale(p,f);
 83:     VecCopy(u,um1);
 84:     VecCopy(up1,u);
 85:     beta   = beta/Gamma;
 86:     eptmp  = beta;
 87:     KSP_PCApplyBAorAB(ksp,v,vp1,vtmp);
 88:     VecAXPY(vp1,-alpha,v);
 89:     VecAXPY(vp1,-beta,vm1);
 90:     VecNorm(vp1,NORM_2,&Gamma);
 91:     VecScale(vp1,1.0/Gamma);
 92:     VecCopy(v,vm1);
 93:     VecCopy(vp1,v);

 95:   /*
 96:      SOLVE  Ax = b
 97:    */
 98:   /* Apply last two Given's (Gl-1 and Gl) rotations to (beta,alpha,Gamma) */
 99:     if (ksp->its > 2) {
100:       theta =  sl1*beta;
101:       eptmp = -cl1*beta;
102:     }
103:     if (ksp->its > 1) {
104:       ep     = -cl*eptmp + sl*alpha;
105:       deltmp = -sl*eptmp - cl*alpha;
106:     }
107:     if (PetscAbsReal(Gamma) > PetscAbsScalar(deltmp)) {
108:       ta = -deltmp / Gamma;
109:       s  = 1.0 / PetscSqrtScalar(1.0 + ta*ta);
110:       c  = s*ta;
111:     } else {
112:       ta = -Gamma/deltmp;
113:       c  = 1.0 / PetscSqrtScalar(1.0 + ta*ta);
114:       s  = c*ta;
115:     }

117:     delta  = -c*deltmp + s*Gamma;
118:     tau_n  = -c*tau_n1; tau_n1 = -s*tau_n1;
119:     VecCopy(vm1,pvec);
120:     VecAXPY(pvec,-theta,pvec2);
121:     VecAXPY(pvec,-ep,pvec1);
122:     VecScale(pvec,1.0/delta);
123:     VecAXPY(x,tau_n,pvec);
124:     cl1    = cl; sl1 = sl; cl = c; sl = s;

126:     VecCopy(pvec1,pvec2);
127:     VecCopy(pvec,pvec1);

129:     /* Compute the upper bound on the residual norm r (See QMR paper p. 13) */
130:     sprod = sprod*PetscAbsScalar(s);
131: #if defined(PETSC_USE_COMPLEX)
132:     rnorm = rnorm0 * PetscSqrtReal((PetscReal)ksp->its+2.0) * PetscRealPart(sprod);
133: #else
134:     rnorm = rnorm0 * PetscSqrtReal((PetscReal)ksp->its+2.0) * sprod;
135: #endif
136:     (*ksp->converged)(ksp,ksp->its,rnorm,&ksp->reason,ksp->cnvP);
137:     if (ksp->its >= ksp->max_it) {
138:       if (!ksp->reason) ksp->reason = KSP_DIVERGED_ITS;
139:       break;
140:     }
141:   }
142:   KSPMonitor(ksp,ksp->its,rnorm);
143:   KSPUnwindPreconditioner(ksp,x,vtmp);

145:   return(0);
146: }

150: static PetscErrorCode KSPSetUp_TCQMR(KSP ksp)
151: {

155:   if (ksp->pc_side == PC_SYMMETRIC) SETERRQ(((PetscObject)ksp)->comm,PETSC_ERR_SUP,"no symmetric preconditioning for KSPTCQMR");
156:   KSPDefaultGetWork(ksp,TCQMR_VECS);
157:   return(0);
158: }

160: /*MC
161:      KSPTCQMR - A variant of QMR (quasi minimal residual) developed by Tony Chan

163:    Options Database Keys:
164: .   see KSPSolve()

166:    Level: beginner

168:   Notes: Supports either left or right preconditioning, but not symmetric
169:   
170:           The "residual norm" computed in this algorithm is actually just an upper bound on the actual residual norm.
171:           That is for left preconditioning it is a bound on the preconditioned residual and for right preconditioning 
172:           it is a bound on the true residual.

174:   References:
175:   Transpose-free formulations of Lanczos-type methods for nonsymmetric linear systems, 
176:   Tony F. Chan, Lisette de Pillis, and Henk van der Vorst, Numerical Algorithms,         
177:   Volume 17, Numbers 1-2 / May, 1998 pp. 51-66.

179: .seealso:  KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP, KSPTFQMR

181: M*/

183: EXTERN_C_BEGIN
186: PetscErrorCode  KSPCreate_TCQMR(KSP ksp)
187: {

191:   KSPSetSupportedNorm(ksp,KSP_NORM_PRECONDITIONED,PC_LEFT,2);
192:   KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_RIGHT,1);
193:   ksp->data                = (void*)0;
194:   ksp->ops->buildsolution  = KSPDefaultBuildSolution;
195:   ksp->ops->buildresidual  = KSPDefaultBuildResidual;
196:   ksp->ops->setup          = KSPSetUp_TCQMR;
197:   ksp->ops->solve          = KSPSolve_TCQMR;
198:   ksp->ops->destroy        = KSPDefaultDestroy;
199:   ksp->ops->setfromoptions = 0;
200:   ksp->ops->view           = 0;
201:   return(0);
202: }
203: EXTERN_C_END