Actual source code: broyden.c

  1: #define PETSCKSP_DLL

 3:  #include ../src/ksp/ksp/impls/broyden/broydenimpl.h


  6: /*
  7:      KSPSetUp_Broyden - Sets up the workspace needed by the Broyden method. 

  9:       This is called once, usually automatically by KSPSolve() or KSPSetUp()
 10:      but can be called directly by KSPSetUp()
 11: */
 14: PetscErrorCode KSPSetUp_Broyden(KSP ksp)
 15: {
 16:   KSP_Broyden    *cgP = (KSP_Broyden*)ksp->data;

 20:   /* 
 21:        This implementation of Broyden only handles left preconditioning
 22:      so generate an error otherwise.
 23:   */
 24:   if (ksp->pc_side == PC_RIGHT) {
 25:     SETERRQ(PETSC_ERR_SUP,"No right preconditioning for KSPBroyden");
 26:   } else if (ksp->pc_side == PC_SYMMETRIC) {
 27:     SETERRQ(PETSC_ERR_SUP,"No symmetric preconditioning for KSPBroyden");
 28:   }
 29:   KSPGetVecs(ksp,cgP->msize,&cgP->v,cgP->msize,&cgP->w);
 30:   KSPDefaultGetWork(ksp,3);
 31:   return(0);
 32: }

 34: /*
 35:        KSPSolve_Broyden - This routine actually applies the method


 38:    Input Parameter:
 39: .     ksp - the Krylov space object that was set to use conjugate gradient, by, for 
 40:             example, KSPCreate(MPI_Comm,KSP *ksp); KSPSetType(ksp,KSPBROYDEN);
 41: */
 44: PetscErrorCode  KSPSolve_Broyden(KSP ksp)
 45: {
 47:   PetscInt       i,j,k;
 48:   KSP_Broyden    *cg = (KSP_Broyden*)ksp->data;
 49:   Mat            Amat;
 50:   Vec            X,B,R,Pold,P,*V = cg->v,*W = cg->w;
 51:   PetscScalar    gdot;
 52:   PetscReal      gnorm;

 55:   X             = ksp->vec_sol;
 56:   B             = ksp->vec_rhs;
 57:   R             = ksp->work[0];
 58:   Pold          = ksp->work[1];
 59:   P             = ksp->work[2];
 60:   PCGetOperators(ksp->pc,&Amat,PETSC_NULL,PETSC_NULL);

 62:   if (!ksp->guess_zero) {
 63:     KSP_MatMult(ksp,Amat,X,R);            /*     r <- b - Ax     */
 64:     VecAYPX(R,-1.0,B);
 65:   } else {
 66:     VecCopy(B,R);                         /*     r <- b (x is 0) */
 67:   }
 68:   PCApply(ksp->pc,R,Pold);                /*     p = B r */
 69:   if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
 70:     VecNorm(R,NORM_2,&gnorm);
 71:   } else if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
 72:     VecNorm(Pold,NORM_2,&gnorm);
 73:   } else SETERRQ(PETSC_ERR_SUP,"NormType not supported");
 74:   KSPLogResidualHistory(ksp,gnorm);
 75:   KSPMonitor(ksp,0,gnorm);
 76:   (*ksp->converged)(ksp,0,gnorm,&ksp->reason,ksp->cnvP);

 78:   VecAXPY(X,1.0,Pold);                    /*     x = x + p */

 80:   for (k=0; k<ksp->max_it; k += cg->msize) {
 81:     for (i=0; i<cg->msize && k+i<ksp->max_it; i++) {
 82:       KSP_MatMult(ksp,Amat,X,R);            /*     r <- b - Ax     */
 83:       VecAYPX(R,-1.0,B);

 85:       PCApply(ksp->pc,R,P);                 /*     p = B r */
 86:       if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
 87:         VecNorm(R,NORM_2,&gnorm);
 88:       } else if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
 89:         VecNorm(P,NORM_2,&gnorm);
 90:       } else SETERRQ(PETSC_ERR_SUP,"NormType not supported");
 91:       KSPLogResidualHistory(ksp,gnorm);
 92:       KSPMonitor(ksp,(1+k+i),gnorm);
 93:       (*ksp->converged)(ksp,1+k+i,gnorm,&ksp->reason,ksp->cnvP);
 94:       if (ksp->reason) return(0);

 96:       for (j=0; j<i; j++) {                                     /* r = product_i [I+v(i)w(i)^T]* */
 97:         VecDot(W[j],P,&gdot);
 98:         VecAXPY(P,gdot,V[j]);
 99:       }
100:       VecCopy(Pold,W[i]);                   /* W[i] = Pold */

102:       VecAXPY(Pold,-1.0,P);                 /* V[i] =       P           */
103:       VecDot(W[i],Pold,&gdot);             /*        ----------------- */
104:       VecCopy(P,V[i]);                      /*         W[i]'*(Pold - P)    */
105:       VecScale(V[i],1.0/gdot);

107:       VecDot(W[i],P,&gdot);                /* P = (I + V[i]*W[i]')*P  */
108:       VecAXPY(P,gdot,V[i]);
109:       VecCopy(P,Pold);

111:       VecAXPY(X,1.0,P);                    /* X = X + P */
112:     }
113:   }
114:   ksp->reason = KSP_DIVERGED_ITS;
115:   return(0);
116: }
117: /*
118:        KSPDestroy_Broyden - Frees all memory space used by the Krylov method

120: */
123: PetscErrorCode KSPDestroy_Broyden(KSP ksp)
124: {
125:   KSP_Broyden    *cg = (KSP_Broyden*)ksp->data;

129:   VecDestroyVecs(cg->v,cg->msize);
130:   VecDestroyVecs(cg->w,cg->msize);
131:   KSPDefaultDestroy(ksp);
132:   return(0);
133: }

135: /*
136:      KSPView_Broyden - Prints information about the current Krylov method being used

138:       Currently this only prints information to a file (or stdout) about the 
139:       symmetry of the problem. If your Krylov method has special options or 
140:       flags that information should be printed here.

142: */
145: PetscErrorCode KSPView_Broyden(KSP ksp,PetscViewer viewer)
146: {
147:   KSP_Broyden    *cg = (KSP_Broyden *)ksp->data;
149:   PetscTruth     iascii;

152:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
153:   if (iascii) {
154:     PetscViewerASCIIPrintf(viewer,"  Size of space %d\n",cg->msize);
155:   } else {
156:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for KSP cg",((PetscObject)viewer)->type_name);
157:   }
158:   return(0);
159: }

161: /*
162:     KSPSetFromOptions_Broyden - Checks the options database for options related to the  method
163: */
166: PetscErrorCode KSPSetFromOptions_Broyden(KSP ksp)
167: {
169:   KSP_Broyden    *cg = (KSP_Broyden *)ksp->data;

172:   PetscOptionsHead("KSP Broyden options");
173:     PetscOptionsInt("-ksp_broyden_restart","Number of directions","None",cg->msize,&cg->msize,PETSC_NULL);
174:   PetscOptionsTail();
175:   return(0);
176: }

178: /*
179:     KSPCreate_Broyden - Creates the data structure for the Krylov method Broyden and sets the 
180:        function pointers for all the routines it needs to call (KSPSolve_Broyden() etc)

183: */
184: /*MC
185:      KSPBROYDEN - The preconditioned conjugate gradient (Broyden) iterative method

187:    Level: beginner

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

191: M*/
195: PetscErrorCode  KSPCreate_Broyden(KSP ksp)
196: {
198:   KSP_Broyden    *cg;

201:   PetscNewLog(ksp,KSP_Broyden,&cg);
202:   cg->msize                      = 30;
203:   cg->csize                      = 0;

205:   ksp->data                      = (void*)cg;
206:   ksp->pc_side                   = PC_LEFT;

208:   /*
209:        Sets the functions that are associated with this data structure 
210:        (in C++ this is the same as defining virtual functions)
211:   */
212:   ksp->ops->setup                = KSPSetUp_Broyden;
213:   ksp->ops->solve                = KSPSolve_Broyden;
214:   ksp->ops->destroy              = KSPDestroy_Broyden;
215:   ksp->ops->view                 = KSPView_Broyden;
216:   ksp->ops->setfromoptions       = KSPSetFromOptions_Broyden;
217:   ksp->ops->buildsolution        = KSPDefaultBuildSolution;
218:   ksp->ops->buildresidual        = KSPDefaultBuildResidual;
219:   return(0);
220: }