Actual source code: broyden.c
2: #include <../src/ksp/ksp/impls/broyden/broydenimpl.h> /*I "petscksp.h" I*/
5: /*
6: KSPSetUp_Broyden - Sets up the workspace needed by the Broyden method.
8: This is called once, usually automatically by KSPSolve() or KSPSetUp().
9: */
12: PetscErrorCode KSPSetUp_Broyden(KSP ksp)
13: {
14: KSP_Broyden *cgP = (KSP_Broyden*)ksp->data;
18: /*
19: This implementation of Broyden only handles left preconditioning
20: so generate an error otherwise.
21: */
22: if (ksp->pc_side == PC_RIGHT) SETERRQ(((PetscObject)ksp)->comm,PETSC_ERR_SUP,"No right preconditioning for KSPBroyden");
23: else if (ksp->pc_side == PC_SYMMETRIC) SETERRQ(((PetscObject)ksp)->comm,PETSC_ERR_SUP,"No symmetric preconditioning for KSPBroyden");
24: KSPGetVecs(ksp,cgP->msize,&cgP->v,cgP->msize,&cgP->w);
25: KSPDefaultGetWork(ksp,3);
26: return(0);
27: }
29: /*
30: KSPSolve_Broyden - This routine actually applies the method
33: Input Parameter:
34: . ksp - the Krylov space object that was set to use conjugate gradient, by, for
35: example, KSPCreate(MPI_Comm,KSP *ksp); KSPSetType(ksp,KSPBROYDEN);
36: */
39: PetscErrorCode KSPSolve_Broyden(KSP ksp)
40: {
42: PetscInt i,j,k;
43: KSP_Broyden *cg = (KSP_Broyden*)ksp->data;
44: Mat Amat;
45: Vec X,B,R,Pold,P,*V = cg->v,*W = cg->w;
46: PetscScalar gdot,A0;
47: PetscReal gnorm;
50: X = ksp->vec_sol;
51: B = ksp->vec_rhs;
52: R = ksp->work[0];
53: Pold = ksp->work[1];
54: P = ksp->work[2];
55: PCGetOperators(ksp->pc,&Amat,PETSC_NULL,PETSC_NULL);
57: if (!ksp->guess_zero) {
58: KSP_MatMult(ksp,Amat,X,R); /* r <- b - Ax */
59: VecAYPX(R,-1.0,B);
60: } else {
61: VecCopy(B,R); /* r <- b (x is 0) */
62: }
63: PCApply(ksp->pc,R,Pold); /* p = B r */
64: if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
65: VecNorm(R,NORM_2,&gnorm);
66: } else if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
67: VecNorm(Pold,NORM_2,&gnorm);
68: } else SETERRQ(((PetscObject)ksp)->comm,PETSC_ERR_SUP,"NormType not supported");
69: KSPLogResidualHistory(ksp,gnorm);
70: KSPMonitor(ksp,0,gnorm);
71: (*ksp->converged)(ksp,0,gnorm,&ksp->reason,ksp->cnvP);
73: if (1) {
74: PetscScalar rdot,abr;
75: Vec y,w;
76: VecDuplicate(P,&y);
77: VecDuplicate(P,&w);
78: MatMult(Amat,Pold,y);
79: KSP_PCApplyBAorAB(ksp,Pold,y,w); /* y = BAp */
80: VecDotNorm2(Pold,y,&rdot,&abr); /* rdot = (p)^T(BAp); abr = (BAp)^T (BAp) */
81: VecDestroy(&y);
82: VecDestroy(&w);
83: A0 = rdot/abr;
84: VecAXPY(X,A0,Pold); /* x <- x + scale p */
85: } else {
86: VecAXPY(X,1.0,Pold); /* x = x + p */
87: }
89: for (k=0; k<ksp->max_it; k += cg->msize) {
90: for (i=0; i<cg->msize && k+i<ksp->max_it; i++) {
91: KSP_MatMult(ksp,Amat,X,R); /* r <- b - Ax */
92: VecAYPX(R,-1.0,B);
94: PCApply(ksp->pc,R,P); /* p = B r */
95: if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
96: VecNorm(R,NORM_2,&gnorm);
97: } else if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
98: VecNorm(P,NORM_2,&gnorm);
99: } else SETERRQ(((PetscObject)ksp)->comm,PETSC_ERR_SUP,"NormType not supported");
100: KSPLogResidualHistory(ksp,gnorm);
101: KSPMonitor(ksp,(1+k+i),gnorm);
102: (*ksp->converged)(ksp,1+k+i,gnorm,&ksp->reason,ksp->cnvP);
103: if (ksp->reason) return(0);
105: if (1) {
106: VecScale(P,A0);
107: }
109: for (j=0; j<i; j++) { /* p = product_{j<i} [I+v(j)w(j)^T]*p */
110: VecDot(W[j],P,&gdot);
111: VecAXPY(P,gdot,V[j]);
112: }
113: VecCopy(Pold,W[i]); /* w[i] = Pold */
115: VecAXPY(Pold,-1.0,P); /* v[i] = p */
116: VecDot(W[i],Pold,&gdot); /* ----------------- */
117: VecCopy(P,V[i]); /* w[i]'*(Pold - p) */
118: VecScale(V[i],1.0/gdot);
120: VecDot(W[i],P,&gdot); /* p = (I + v[i]*w[i]')*p */
121: VecAXPY(P,gdot,V[i]);
122: VecCopy(P,Pold);
124: if (1) {
125: PetscScalar rdot,abr;
126: Vec y,w;
127: VecDuplicate(P,&y);
128: VecDuplicate(P,&w);
129: MatMult(Amat,P,y);
130: KSP_PCApplyBAorAB(ksp,P,y,w); /* y = BAp */
131: VecDotNorm2(P,y,&rdot,&abr); /* rdot = (p)^T(BAp); abr = (BAp)^T (BAp) */
132: VecDestroy(&y);
133: VecDestroy(&w);
134: VecAXPY(X,rdot/abr,P); /* x <- x + scale p */
135: } else {
136: VecAXPY(X,1.0,P); /* x = x + p */
137: }
138: }
139: }
140: ksp->reason = KSP_DIVERGED_ITS;
141: return(0);
142: }
143: /*
144: KSPDestroy_Broyden - Frees all memory space used by the Krylov method
146: */
149: PetscErrorCode KSPReset_Broyden(KSP ksp)
150: {
151: KSP_Broyden *cg = (KSP_Broyden*)ksp->data;
155: if (cg->v) {VecDestroyVecs(cg->msize,&cg->v);}
156: if (cg->w) {VecDestroyVecs(cg->msize,&cg->w);}
157: return(0);
158: }
162: PetscErrorCode KSPDestroy_Broyden(KSP ksp)
163: {
167: KSPReset_Broyden(ksp);
168: KSPDefaultDestroy(ksp);
169: return(0);
170: }
172: /*
173: KSPView_Broyden - Prints information about the current Krylov method being used
175: */
178: PetscErrorCode KSPView_Broyden(KSP ksp,PetscViewer viewer)
179: {
180: KSP_Broyden *cg = (KSP_Broyden *)ksp->data;
182: PetscBool iascii;
185: PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
186: if (iascii) {
187: PetscViewerASCIIPrintf(viewer," Size of space %d\n",cg->msize);
188: } else {
189: SETERRQ1(((PetscObject)ksp)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for KSP cg",((PetscObject)viewer)->type_name);
190: }
191: return(0);
192: }
194: /*
195: KSPSetFromOptions_Broyden - Checks the options database for options related to the method
196: */
199: PetscErrorCode KSPSetFromOptions_Broyden(KSP ksp)
200: {
202: KSP_Broyden *cg = (KSP_Broyden *)ksp->data;
205: PetscOptionsHead("KSP Broyden options");
206: PetscOptionsInt("-ksp_broyden_restart","Number of directions","None",cg->msize,&cg->msize,PETSC_NULL);
207: PetscOptionsTail();
208: return(0);
209: }
211: /*
212: KSPCreate_Broyden - Creates the data structure for the Krylov method Broyden and sets the
213: function pointers for all the routines it needs to call (KSPSolve_Broyden() etc)
216: */
217: /*MC
218: KSPBROYDEN - Limited memory "bad" Broyden method implemented for linear problems.
220: Level: beginner
222: Notes: Supports only left preconditioning
224: Implemented for experimentation reasons, not intended to replace any of the Krylov methods
226: .seealso: KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP
228: M*/
232: PetscErrorCode KSPCreate_Broyden(KSP ksp)
233: {
235: KSP_Broyden *cg;
238: PetscNewLog(ksp,KSP_Broyden,&cg);
239: ksp->data = (void*)cg;
240: cg->msize = 30;
241: cg->csize = 0;
243: KSPSetSupportedNorm(ksp,KSP_NORM_PRECONDITIONED,PC_LEFT,2);
244: KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_LEFT,1);
246: /*
247: Sets the functions that are associated with this data structure
248: (in C++ this is the same as defining virtual functions)
249: */
250: ksp->ops->setup = KSPSetUp_Broyden;
251: ksp->ops->solve = KSPSolve_Broyden;
252: ksp->ops->reset = KSPReset_Broyden;
253: ksp->ops->destroy = KSPDestroy_Broyden;
254: ksp->ops->view = KSPView_Broyden;
255: ksp->ops->setfromoptions = KSPSetFromOptions_Broyden;
256: ksp->ops->buildsolution = KSPDefaultBuildSolution;
257: ksp->ops->buildresidual = KSPDefaultBuildResidual;
258: return(0);
259: }