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: }