xref: /petsc/src/snes/impls/ngmres/snesngmres.c (revision 6e733865832a5113aefd2ec614b1437c918d0f39)
113a62661SPeter Brune #include <../src/snes/impls/ngmres/snesngmres.h> /*I "petscsnes.h" I*/
219653cdaSPeter Brune #include <petscblaslapack.h>
3a312c225SMatthew G Knepley 
413a62661SPeter Brune const char *SNESNGMRESRestartTypes[] = {"NONE","PERIODIC","DIFFERENCE","SNESNGMRESRestartType","SNES_NGMRES_RESTART_",0};
513a62661SPeter Brune const char *SNESNGMRESSelectTypes[] = {"NONE","DIFFERENCE","LINESEARCH","SNESNGMRESSelectType","SNES_NGMRES_SELECT_",0};
613a62661SPeter Brune 
7a312c225SMatthew G Knepley #undef __FUNCT__
8a312c225SMatthew G Knepley #define __FUNCT__ "SNESReset_NGMRES"
9a312c225SMatthew G Knepley PetscErrorCode SNESReset_NGMRES(SNES snes)
10a312c225SMatthew G Knepley {
11a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres = (SNES_NGMRES*) snes->data;
12a312c225SMatthew G Knepley   PetscErrorCode ierr;
13a312c225SMatthew G Knepley 
14a312c225SMatthew G Knepley   PetscFunctionBegin;
15f109b39eSPeter Brune   ierr = VecDestroyVecs(ngmres->msize, &ngmres->Fdot);CHKERRQ(ierr);
16f109b39eSPeter Brune   ierr = VecDestroyVecs(ngmres->msize, &ngmres->Xdot);CHKERRQ(ierr);
17f1c6b773SPeter Brune   ierr = SNESLineSearchDestroy(&ngmres->additive_linesearch);CHKERRQ(ierr);
189e764e56SPeter Brune 
19a312c225SMatthew G Knepley   PetscFunctionReturn(0);
20a312c225SMatthew G Knepley }
21a312c225SMatthew G Knepley 
22a312c225SMatthew G Knepley #undef __FUNCT__
23a312c225SMatthew G Knepley #define __FUNCT__ "SNESDestroy_NGMRES"
24a312c225SMatthew G Knepley PetscErrorCode SNESDestroy_NGMRES(SNES snes)
25a312c225SMatthew G Knepley {
26a312c225SMatthew G Knepley   PetscErrorCode ierr;
2778440776SJed Brown   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
28a312c225SMatthew G Knepley 
29a312c225SMatthew G Knepley   PetscFunctionBegin;
30a312c225SMatthew G Knepley   ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr);
31f109b39eSPeter Brune   ierr = PetscFree5(ngmres->h, ngmres->beta, ngmres->xi, ngmres->fnorms, ngmres->q);CHKERRQ(ierr);
3219653cdaSPeter Brune   ierr = PetscFree(ngmres->s);CHKERRQ(ierr);
3318aa0c0cSPeter Brune   ierr = PetscFree(ngmres->xnorms);CHKERRQ(ierr);
3419653cdaSPeter Brune #if PETSC_USE_COMPLEX
3519653cdaSPeter Brune   ierr = PetscFree(ngmres->rwork);
3619653cdaSPeter Brune #endif
3719653cdaSPeter Brune   ierr = PetscFree(ngmres->work);
3819653cdaSPeter Brune   ierr = PetscFree(snes->data);
39a312c225SMatthew G Knepley   PetscFunctionReturn(0);
40a312c225SMatthew G Knepley }
41a312c225SMatthew G Knepley 
42a312c225SMatthew G Knepley #undef __FUNCT__
43a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetUp_NGMRES"
44a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes)
45a312c225SMatthew G Knepley {
46a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES *) snes->data;
47e7058c64SPeter Brune   const char     *optionsprefix;
4819653cdaSPeter Brune   PetscInt       msize,hsize;
49a312c225SMatthew G Knepley   PetscErrorCode ierr;
50a312c225SMatthew G Knepley 
51a312c225SMatthew G Knepley   PetscFunctionBegin;
5278440776SJed Brown   ierr = SNESDefaultGetWork(snes,5);CHKERRQ(ierr);
5378440776SJed Brown   if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);}
5478440776SJed Brown   if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);}
5578440776SJed Brown   if (!ngmres->setup_called) {
56087dfb9eSxuemin     msize         = ngmres->msize;  /* restart size */
5719653cdaSPeter Brune     hsize         = msize * msize;
58087dfb9eSxuemin 
5998b3e84cSPeter Brune     /* explicit least squares minimization solve */
6019653cdaSPeter Brune     ierr = PetscMalloc5(hsize,PetscScalar,&ngmres->h,
6119653cdaSPeter Brune                         msize,PetscScalar,&ngmres->beta,
6219653cdaSPeter Brune                         msize,PetscScalar,&ngmres->xi,
63f109b39eSPeter Brune                         msize,PetscReal,  &ngmres->fnorms,
6419653cdaSPeter Brune                         hsize,PetscScalar,&ngmres->q);CHKERRQ(ierr);
6518aa0c0cSPeter Brune     if (ngmres->singlereduction) {
6618aa0c0cSPeter Brune       ierr = PetscMalloc(msize*sizeof(PetscReal),&ngmres->xnorms);CHKERRQ(ierr);
6718aa0c0cSPeter Brune     }
6819653cdaSPeter Brune     ngmres->nrhs = 1;
6919653cdaSPeter Brune     ngmres->lda = msize;
7019653cdaSPeter Brune     ngmres->ldb = msize;
7119653cdaSPeter Brune     ierr = PetscMalloc(msize*sizeof(PetscScalar),&ngmres->s);CHKERRQ(ierr);
7219653cdaSPeter Brune     ierr = PetscMemzero(ngmres->h,   hsize*sizeof(PetscScalar));CHKERRQ(ierr);
7319653cdaSPeter Brune     ierr = PetscMemzero(ngmres->q,   hsize*sizeof(PetscScalar));CHKERRQ(ierr);
7419653cdaSPeter Brune     ierr = PetscMemzero(ngmres->xi,  msize*sizeof(PetscScalar));CHKERRQ(ierr);
7519653cdaSPeter Brune     ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr);
7619653cdaSPeter Brune     ngmres->lwork = 12*msize;
7719653cdaSPeter Brune #if PETSC_USE_COMPLEX
7819653cdaSPeter Brune     ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork);
7919653cdaSPeter Brune #endif
8019653cdaSPeter Brune     ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work);
8178440776SJed Brown   }
82e7058c64SPeter Brune 
83e7058c64SPeter Brune   /* linesearch setup */
84e7058c64SPeter Brune   ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr);
85e7058c64SPeter Brune 
8613a62661SPeter Brune   if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) {
87f1c6b773SPeter Brune     ierr = SNESLineSearchCreate(((PetscObject)snes)->comm, &ngmres->additive_linesearch);CHKERRQ(ierr);
88f1c6b773SPeter Brune     ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch, snes);CHKERRQ(ierr);
891a4f838cSPeter Brune     ierr = SNESLineSearchSetType(ngmres->additive_linesearch, SNESLINESEARCHL2);CHKERRQ(ierr);
90f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch, "additive_");CHKERRQ(ierr);
91f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch, optionsprefix);CHKERRQ(ierr);
92f1c6b773SPeter Brune     ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr);
93e7058c64SPeter Brune   }
94e7058c64SPeter Brune 
9578440776SJed Brown   ngmres->setup_called = PETSC_TRUE;
96a312c225SMatthew G Knepley   PetscFunctionReturn(0);
97a312c225SMatthew G Knepley }
98a312c225SMatthew G Knepley 
99a312c225SMatthew G Knepley #undef __FUNCT__
100a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES"
101a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes)
102a312c225SMatthew G Knepley {
103a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres = (SNES_NGMRES *) snes->data;
104a312c225SMatthew G Knepley   PetscErrorCode ierr;
105dfbf837cSBarry Smith   PetscBool      debug;
106f1c6b773SPeter Brune   SNESLineSearch linesearch;
107a312c225SMatthew G Knepley   PetscFunctionBegin;
108a312c225SMatthew G Knepley   ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr);
10913a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes,
11013a62661SPeter Brune                           (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,PETSC_NULL);CHKERRQ(ierr);
11113a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes,
11213a62661SPeter Brune                           (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,PETSC_NULL);CHKERRQ(ierr);
113d2e16ddcSPeter Brune   ierr = PetscOptionsBool("-snes_ngmres_anderson", "Use Anderson mixing storage",        "SNES", ngmres->anderson,  &ngmres->anderson, PETSC_NULL);CHKERRQ(ierr);
11419653cdaSPeter Brune   ierr = PetscOptionsInt("-snes_ngmres_m",         "Number of directions",               "SNES", ngmres->msize,  &ngmres->msize, PETSC_NULL);CHKERRQ(ierr);
1150c777b0cSPeter Brune   ierr = PetscOptionsInt("-snes_ngmres_restart",   "Iterations before forced restart",   "SNES", ngmres->restart_periodic,  &ngmres->restart_periodic, PETSC_NULL);CHKERRQ(ierr);
11628ed4a04SPeter Brune   ierr = PetscOptionsInt("-snes_ngmres_restart_it","Tolerance iterations before restart","SNES", ngmres->restart_it,  &ngmres->restart_it, PETSC_NULL);CHKERRQ(ierr);
117dfbf837cSBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_monitor",  "Monitor actions of NGMRES",          "SNES", ngmres->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);CHKERRQ(ierr);
118dfbf837cSBarry Smith   if (debug) {
119dfbf837cSBarry Smith     ngmres->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr);
120dfbf837cSBarry Smith   }
1216a7cf640SPeter Brune   ierr = PetscOptionsReal("-snes_ngmres_gammaA",   "Residual selection constant",   "SNES", ngmres->gammaA, &ngmres->gammaA, PETSC_NULL);CHKERRQ(ierr);
1226a7cf640SPeter Brune   ierr = PetscOptionsReal("-snes_ngmres_gammaC", "  Residual restart constant",     "SNES", ngmres->gammaC, &ngmres->gammaC, PETSC_NULL);CHKERRQ(ierr);
1236a7cf640SPeter Brune   ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES", ngmres->epsilonB, &ngmres->epsilonB, PETSC_NULL);CHKERRQ(ierr);
1246a7cf640SPeter Brune   ierr = PetscOptionsReal("-snes_ngmres_deltaB",   "Difference residual selection constant", "SNES", ngmres->deltaB, &ngmres->deltaB, PETSC_NULL);CHKERRQ(ierr);
1254d116c7dSPeter Brune   ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions",  "SNES", ngmres->singlereduction, &ngmres->singlereduction, PETSC_NULL);CHKERRQ(ierr);
126a312c225SMatthew G Knepley   ierr = PetscOptionsTail();CHKERRQ(ierr);
1276a7cf640SPeter Brune   if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA;
1289e764e56SPeter Brune 
1299e764e56SPeter Brune   /* set the default type of the line search if the user hasn't already. */
1309e764e56SPeter Brune   if (!snes->linesearch) {
131f1c6b773SPeter Brune     ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
1321a4f838cSPeter Brune     ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC);CHKERRQ(ierr);
1339e764e56SPeter Brune   }
134a312c225SMatthew G Knepley   PetscFunctionReturn(0);
135a312c225SMatthew G Knepley }
136a312c225SMatthew G Knepley 
137a312c225SMatthew G Knepley #undef __FUNCT__
138a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES"
139a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes, PetscViewer viewer)
140a312c225SMatthew G Knepley {
141a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres = (SNES_NGMRES *) snes->data;
142a312c225SMatthew G Knepley   PetscBool      iascii;
143a312c225SMatthew G Knepley   PetscErrorCode ierr;
144a312c225SMatthew G Knepley 
145a312c225SMatthew G Knepley   PetscFunctionBegin;
146251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
147a312c225SMatthew G Knepley   if (iascii) {
1489e764e56SPeter Brune 
149f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer, "  Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr);
150f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer, "  Residual selection: gammaA=%1.0e, gammaC=%1.0e\n", ngmres->gammaA, ngmres->gammaC);CHKERRQ(ierr);
151f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer, "  Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n", ngmres->epsilonB, ngmres->deltaB);CHKERRQ(ierr);
152a312c225SMatthew G Knepley   }
153a312c225SMatthew G Knepley   PetscFunctionReturn(0);
154a312c225SMatthew G Knepley }
155a312c225SMatthew G Knepley 
156a312c225SMatthew G Knepley #undef __FUNCT__
157a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES"
158211b2d39SPeter Brune 
159a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes)
160a312c225SMatthew G Knepley {
161087dfb9eSxuemin   SNES_NGMRES        *ngmres = (SNES_NGMRES *) snes->data;
16298b3e84cSPeter Brune   /* present solution, residual, and preconditioned residual */
1639f425c49SPeter Brune   Vec                 X, F, B, D, Y;
164f109b39eSPeter Brune 
165f109b39eSPeter Brune   /* candidate linear combination answers */
1664b32a720SPeter Brune   Vec                 XA, FA, XM, FM, FPC;
16719653cdaSPeter Brune 
16898b3e84cSPeter Brune   /* previous iterations to construct the subspace */
169f109b39eSPeter Brune   Vec                 *Fdot = ngmres->Fdot;
170f109b39eSPeter Brune   Vec                 *Xdot = ngmres->Xdot;
17119653cdaSPeter Brune 
17298b3e84cSPeter Brune   /* coefficients and RHS to the minimization problem */
17319653cdaSPeter Brune   PetscScalar         *beta = ngmres->beta;
17419653cdaSPeter Brune   PetscScalar         *xi   = ngmres->xi;
17518aa0c0cSPeter Brune   PetscReal           fnorm, fMnorm, fAnorm;
17619653cdaSPeter Brune   PetscReal           nu;
17719653cdaSPeter Brune   PetscScalar         alph_total = 0.;
17828ed4a04SPeter Brune   PetscInt            i, j, k, k_restart, l, ivec, restart_count = 0;
17919653cdaSPeter Brune 
18098b3e84cSPeter Brune   /* solution selection data */
18119653cdaSPeter Brune   PetscBool           selectA, selectRestart;
18274b542b2SMatthew G Knepley   PetscReal           dnorm, dminnorm = 0.0, dcurnorm;
183f109b39eSPeter Brune   PetscReal           fminnorm;
18419653cdaSPeter Brune 
1851e633543SBarry Smith   SNESConvergedReason reason;
186*6e733865SPeter Brune   PetscBool           lssucceed,changed_y,changed_w;
187a312c225SMatthew G Knepley   PetscErrorCode      ierr;
188a312c225SMatthew G Knepley 
189a312c225SMatthew G Knepley   PetscFunctionBegin;
19098b3e84cSPeter Brune   /* variable initialization */
191a312c225SMatthew G Knepley   snes->reason  = SNES_CONVERGED_ITERATING;
192f109b39eSPeter Brune   X             = snes->vec_sol;
193f109b39eSPeter Brune   F             = snes->vec_func;
194f109b39eSPeter Brune   B             = snes->vec_rhs;
195f109b39eSPeter Brune   XA            = snes->vec_sol_update;
196f109b39eSPeter Brune   FA            = snes->work[0];
197f109b39eSPeter Brune   D             = snes->work[1];
198f109b39eSPeter Brune 
199f109b39eSPeter Brune   /* work for the line search */
200f109b39eSPeter Brune   Y             = snes->work[2];
2019f425c49SPeter Brune   XM            = snes->work[3];
2029f425c49SPeter Brune   FM            = snes->work[4];
203a312c225SMatthew G Knepley 
204a312c225SMatthew G Knepley   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
205a312c225SMatthew G Knepley   snes->iter = 0;
206a312c225SMatthew G Knepley   snes->norm = 0.;
207a312c225SMatthew G Knepley   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
20819653cdaSPeter Brune 
20998b3e84cSPeter Brune   /* initialization */
21019653cdaSPeter Brune 
21198b3e84cSPeter Brune   /* r = F(x) */
212e4ed7901SPeter Brune   if (!snes->vec_func_init_set) {
213f109b39eSPeter Brune     ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr);
214a312c225SMatthew G Knepley     if (snes->domainerror) {
215a312c225SMatthew G Knepley       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
216a312c225SMatthew G Knepley       PetscFunctionReturn(0);
217a312c225SMatthew G Knepley     }
218e4ed7901SPeter Brune   } else {
219e4ed7901SPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
220e4ed7901SPeter Brune   }
22119653cdaSPeter Brune 
222e4ed7901SPeter Brune   if (!snes->norm_init_set) {
223f109b39eSPeter Brune     ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr);
224f109b39eSPeter Brune     if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation");
225e4ed7901SPeter Brune   } else {
226e4ed7901SPeter Brune     fnorm = snes->norm_init;
227e4ed7901SPeter Brune     snes->norm_init_set = PETSC_FALSE;
228e4ed7901SPeter Brune   }
229e4ed7901SPeter Brune   fminnorm = fnorm;
230e4ed7901SPeter Brune   /* nu = (r, r) */
231e4ed7901SPeter Brune   nu = fnorm*fnorm;
23219653cdaSPeter Brune 
23398b3e84cSPeter Brune   /* q_{00} = nu  */
23419653cdaSPeter Brune   Q(0,0) = nu;
235f109b39eSPeter Brune   ngmres->fnorms[0] = fnorm;
236f109b39eSPeter Brune   /* Fdot[0] = F */
237f109b39eSPeter Brune   ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr);
238f109b39eSPeter Brune   ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr);
239087dfb9eSxuemin 
240a312c225SMatthew G Knepley   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
241f109b39eSPeter Brune   snes->norm = fnorm;
242a312c225SMatthew G Knepley   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
243f109b39eSPeter Brune   SNESLogConvHistory(snes, fnorm, 0);
244f109b39eSPeter Brune   ierr = SNESMonitor(snes, 0, fnorm);CHKERRQ(ierr);
245f109b39eSPeter Brune   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
246a312c225SMatthew G Knepley   if (snes->reason) PetscFunctionReturn(0);
247a312c225SMatthew G Knepley 
24819653cdaSPeter Brune   k_restart = 1;
24919653cdaSPeter Brune   l = 1;
25009c08436SPeter Brune   for (k=1; k < snes->max_its+1; k++) {
25198b3e84cSPeter Brune     /* select which vector of the stored subspace will be updated */
25298b3e84cSPeter Brune     ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */
25319653cdaSPeter Brune 
25498b3e84cSPeter Brune     /* Computation of x^M */
2558cc86e31SPeter Brune     if (snes->pc) {
2569f425c49SPeter Brune       ierr = VecCopy(X, XM);CHKERRQ(ierr);
257e4ed7901SPeter Brune       ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr);
258e4ed7901SPeter Brune       ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr);
2599f425c49SPeter Brune       ierr = SNESSolve(snes->pc, B, XM);CHKERRQ(ierr);
2608cc86e31SPeter Brune       ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
2618cc86e31SPeter Brune       if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
2628cc86e31SPeter Brune         snes->reason = SNES_DIVERGED_INNER;
2638cc86e31SPeter Brune         PetscFunctionReturn(0);
2648cc86e31SPeter Brune       }
2654b32a720SPeter Brune       ierr = SNESGetFunction(snes->pc, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr);
2664b32a720SPeter Brune       ierr = VecCopy(FPC, FM);CHKERRQ(ierr);
2674b32a720SPeter Brune       ierr = SNESGetFunctionNorm(snes->pc, &fMnorm);CHKERRQ(ierr);
2688cc86e31SPeter Brune     } else {
269f109b39eSPeter Brune       /* no preconditioner -- just take gradient descent with line search */
270f109b39eSPeter Brune       ierr = VecCopy(F, Y);CHKERRQ(ierr);
271e7058c64SPeter Brune       ierr = VecCopy(F, FM);CHKERRQ(ierr);
272e7058c64SPeter Brune       ierr = VecCopy(X, XM);CHKERRQ(ierr);
273e7058c64SPeter Brune       fMnorm = fnorm;
274f1c6b773SPeter Brune       ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr);
275f1c6b773SPeter Brune       ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssucceed);CHKERRQ(ierr);
276f109b39eSPeter Brune       if (!lssucceed) {
277f109b39eSPeter Brune         if (++snes->numFailures >= snes->maxFailures) {
278f109b39eSPeter Brune           snes->reason = SNES_DIVERGED_LINE_SEARCH;
279f109b39eSPeter Brune           PetscFunctionReturn(0);
280f109b39eSPeter Brune         }
281f109b39eSPeter Brune       }
2826634f59bSPeter Brune     }
2831e633543SBarry Smith 
28498b3e84cSPeter Brune     /* r = F(x) */
2859f425c49SPeter Brune     nu = fMnorm*fMnorm;
2869f425c49SPeter Brune     if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of F^M */
28719653cdaSPeter Brune 
28898b3e84cSPeter Brune     /* construct the right hand side and xi factors */
2898c09b6b7SPeter Brune     ierr = VecMDot(FM, l, Fdot, xi);CHKERRQ(ierr);
2908c09b6b7SPeter Brune 
29119653cdaSPeter Brune     for (i = 0; i < l; i++) {
29219653cdaSPeter Brune       beta[i] = nu - xi[i];
29319653cdaSPeter Brune     }
29419653cdaSPeter Brune 
29598b3e84cSPeter Brune     /* construct h */
29619653cdaSPeter Brune     for (j = 0; j < l; j++) {
29719653cdaSPeter Brune       for (i = 0; i < l; i++) {
29819653cdaSPeter Brune         H(i, j) = Q(i, j) - xi[i] - xi[j] + nu;
29919653cdaSPeter Brune       }
30019653cdaSPeter Brune     }
301f109b39eSPeter Brune 
302f109b39eSPeter Brune     if(l == 1) {
303f109b39eSPeter Brune       /* simply set alpha[0] = beta[0] / H[0, 0] */
304bf08dd53SPeter Brune       if (H(0, 0) != 0.) {
305f109b39eSPeter Brune         beta[0] = beta[0] / H(0, 0);
306f109b39eSPeter Brune       } else {
307bf08dd53SPeter Brune         beta[0] = 0.;
308bf08dd53SPeter Brune       }
309bf08dd53SPeter Brune     } else {
31019653cdaSPeter Brune #ifdef PETSC_MISSING_LAPACK_GELSS
31119653cdaSPeter Brune     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "NGMRES with LS requires the LAPACK GELSS routine.");
3124a0c5b0cSMatthew G Knepley #else
31319653cdaSPeter Brune     ngmres->m = PetscBLASIntCast(l);
31419653cdaSPeter Brune     ngmres->n = PetscBLASIntCast(l);
31519653cdaSPeter Brune     ngmres->info = PetscBLASIntCast(0);
31619653cdaSPeter Brune     ngmres->rcond = -1.;
3178e57ea43SSatish Balay     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
31819653cdaSPeter Brune #ifdef PETSC_USE_COMPLEX
31919653cdaSPeter Brune     LAPACKgelss_(&ngmres->m,
32019653cdaSPeter Brune                  &ngmres->n,
32119653cdaSPeter Brune                  &ngmres->nrhs,
32219653cdaSPeter Brune                  ngmres->h,
32319653cdaSPeter Brune                  &ngmres->lda,
32419653cdaSPeter Brune                  ngmres->beta,
32519653cdaSPeter Brune                  &ngmres->ldb,
32619653cdaSPeter Brune                  ngmres->s,
32719653cdaSPeter Brune                  &ngmres->rcond,
32819653cdaSPeter Brune                  &ngmres->rank,
32919653cdaSPeter Brune                  ngmres->work,
33019653cdaSPeter Brune                  &ngmres->lwork,
33119653cdaSPeter Brune                  ngmres->rwork,
33219653cdaSPeter Brune                  &ngmres->info);
33319653cdaSPeter Brune #else
33419653cdaSPeter Brune     LAPACKgelss_(&ngmres->m,
33519653cdaSPeter Brune                  &ngmres->n,
33619653cdaSPeter Brune                  &ngmres->nrhs,
33719653cdaSPeter Brune                  ngmres->h,
33819653cdaSPeter Brune                  &ngmres->lda,
33919653cdaSPeter Brune                  ngmres->beta,
34019653cdaSPeter Brune                  &ngmres->ldb,
34119653cdaSPeter Brune                  ngmres->s,
34219653cdaSPeter Brune                  &ngmres->rcond,
34319653cdaSPeter Brune                  &ngmres->rank,
34419653cdaSPeter Brune                  ngmres->work,
34519653cdaSPeter Brune                  &ngmres->lwork,
34619653cdaSPeter Brune                  &ngmres->info);
34719653cdaSPeter Brune #endif
3488e57ea43SSatish Balay     ierr = PetscFPTrapPop();CHKERRQ(ierr);
34919653cdaSPeter Brune     if (ngmres->info < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to GELSS");
35019653cdaSPeter Brune     if (ngmres->info > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SVD failed to converge");
351a312c225SMatthew G Knepley #endif
352f109b39eSPeter Brune     }
353a312c225SMatthew G Knepley 
35419653cdaSPeter Brune     alph_total = 0.;
35519653cdaSPeter Brune     for (i = 0; i < l; i++) {
35619653cdaSPeter Brune       alph_total += beta[i];
357c0bbabecSxuemin     }
358f109b39eSPeter Brune 
3599f425c49SPeter Brune     ierr = VecCopy(XM, XA);CHKERRQ(ierr);
360f109b39eSPeter Brune     ierr = VecScale(XA, 1. - alph_total);CHKERRQ(ierr);
361087dfb9eSxuemin 
3628c09b6b7SPeter Brune     ierr = VecMAXPY(XA, l, beta, Xdot);CHKERRQ(ierr);
363*6e733865SPeter Brune 
364*6e733865SPeter Brune     /* check the validity of the step */
365*6e733865SPeter Brune     ierr = VecCopy(Y,XA);CHKERRQ(ierr);
366*6e733865SPeter Brune     ierr = VecAXPY(Y,-1.0,X);CHKERRQ(ierr);
367*6e733865SPeter Brune     ierr = SNESLineSearchPostCheck(snes->linesearch,X,Y,XA,&changed_y,&changed_w);CHKERRQ(ierr);
368f109b39eSPeter Brune     ierr = SNESComputeFunction(snes, XA, FA);CHKERRQ(ierr);
36919653cdaSPeter Brune 
3709f425c49SPeter Brune     /* differences for selection and restart */
37113a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) {
37218aa0c0cSPeter Brune       if (ngmres->singlereduction) {
37318aa0c0cSPeter Brune         dminnorm = -1.0;
374f109b39eSPeter Brune         ierr=VecCopy(XA, D);CHKERRQ(ierr);
37518aa0c0cSPeter Brune         ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr);
37618aa0c0cSPeter Brune         for(i=0;i<l;i++) {
37718aa0c0cSPeter Brune           ierr=VecAXPY(Xdot[i],-1.0,XA);CHKERRQ(ierr);
37818aa0c0cSPeter Brune         }
37918aa0c0cSPeter Brune         ierr = VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
38018aa0c0cSPeter Brune         ierr = VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr);
38118aa0c0cSPeter Brune         for (i=0;i<l;i++) {
38218aa0c0cSPeter Brune           ierr = VecNormBegin(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr);
38318aa0c0cSPeter Brune         }
38418aa0c0cSPeter Brune         ierr = VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
38518aa0c0cSPeter Brune         ierr = VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr);
38618aa0c0cSPeter Brune         for (i=0;i<l;i++) {
38718aa0c0cSPeter Brune           ierr = VecNormEnd(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr);
38818aa0c0cSPeter Brune         }
38918aa0c0cSPeter Brune         for(i=0;i<l;i++) {
39018aa0c0cSPeter Brune           dcurnorm = ngmres->xnorms[i];
39118aa0c0cSPeter Brune           if ((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm;
39218aa0c0cSPeter Brune           ierr=VecAXPY(Xdot[i],1.0,XA);CHKERRQ(ierr);
39318aa0c0cSPeter Brune         }
39418aa0c0cSPeter Brune       } else {
39518aa0c0cSPeter Brune         ierr=VecCopy(XA, D);CHKERRQ(ierr);
39618aa0c0cSPeter Brune         ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr);
39718aa0c0cSPeter Brune         ierr=VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr);
39818aa0c0cSPeter Brune         ierr=VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
39918aa0c0cSPeter Brune         ierr=VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr);
40018aa0c0cSPeter Brune         ierr=VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
401f109b39eSPeter Brune         dminnorm = -1.0;
40219653cdaSPeter Brune         for(i=0;i<l;i++) {
403f109b39eSPeter Brune           ierr=VecCopy(XA, D);CHKERRQ(ierr);
404f109b39eSPeter Brune           ierr=VecAXPY(D, -1.0, Xdot[i]);CHKERRQ(ierr);
405f109b39eSPeter Brune           ierr=VecNorm(D, NORM_2, &dcurnorm);CHKERRQ(ierr);
406f109b39eSPeter Brune           if((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm;
40719653cdaSPeter Brune         }
40818aa0c0cSPeter Brune       }
40913a62661SPeter Brune     } else {
41013a62661SPeter Brune       ierr = VecNorm(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
41113a62661SPeter Brune     }
4129f425c49SPeter Brune     /* combination (additive) or selection (multiplicative) of the N-GMRES solution */
41313a62661SPeter Brune     if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) {
4149f425c49SPeter Brune       /* X = X + \lambda(XA - X) */
4159f425c49SPeter Brune       if (ngmres->monitor) {
4169f425c49SPeter Brune         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr);
4179f425c49SPeter Brune       }
41813a62661SPeter Brune       ierr = VecCopy(FM, F);CHKERRQ(ierr);
41913a62661SPeter Brune       ierr = VecCopy(XM, X);CHKERRQ(ierr);
4209f425c49SPeter Brune       ierr = VecCopy(XA, Y);CHKERRQ(ierr);
42113a62661SPeter Brune       fnorm = fMnorm;
422eb1825c3SPeter Brune       ierr = VecAYPX(Y, -1.0, X);CHKERRQ(ierr);
423f1c6b773SPeter Brune       ierr = SNESLineSearchApply(ngmres->additive_linesearch,X,F,&fnorm,Y);CHKERRQ(ierr);
424f1c6b773SPeter Brune       ierr = SNESLineSearchGetSuccess(ngmres->additive_linesearch, &lssucceed);CHKERRQ(ierr);
4259f425c49SPeter Brune       if (!lssucceed) {
4269f425c49SPeter Brune         if (++snes->numFailures >= snes->maxFailures) {
4279f425c49SPeter Brune           snes->reason = SNES_DIVERGED_LINE_SEARCH;
4289f425c49SPeter Brune           PetscFunctionReturn(0);
4299f425c49SPeter Brune         }
4309f425c49SPeter Brune       }
4319f425c49SPeter Brune       if (ngmres->monitor) {
4329f425c49SPeter Brune         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Additive solution: ||F||_2 = %e\n", fnorm);CHKERRQ(ierr);
4339f425c49SPeter Brune       }
43413a62661SPeter Brune     } else if (ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) {
4359f425c49SPeter Brune       selectA = PETSC_TRUE;
4369f425c49SPeter Brune       /* Conditions for choosing the accelerated answer */
4379f425c49SPeter Brune       /* Criterion A -- the norm of the function isn't increased above the minimum by too much */
4389f425c49SPeter Brune       if (fAnorm >= ngmres->gammaA*fminnorm) {
4399f425c49SPeter Brune         selectA = PETSC_FALSE;
4409f425c49SPeter Brune       }
4419f425c49SPeter Brune       /* Criterion B -- the choice of x^A isn't too close to some other choice */
442cf22de31SPeter Brune       if (ngmres->epsilonB*dnorm<dminnorm || PetscSqrtReal(fnorm)<ngmres->deltaB*PetscSqrtReal(fminnorm)) {
44319653cdaSPeter Brune       } else {
44419653cdaSPeter Brune         selectA=PETSC_FALSE;
44519653cdaSPeter Brune       }
44619653cdaSPeter Brune       if (selectA) {
447dfbf837cSBarry Smith         if (ngmres->monitor) {
4489e764e56SPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_A, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr);
449dfbf837cSBarry Smith         }
45098b3e84cSPeter Brune         /* copy it over */
451f109b39eSPeter Brune         fnorm = fAnorm;
452f109b39eSPeter Brune         nu = fnorm*fnorm;
453f109b39eSPeter Brune         ierr = VecCopy(FA, F);CHKERRQ(ierr);
454f109b39eSPeter Brune         ierr = VecCopy(XA, X);CHKERRQ(ierr);
45519653cdaSPeter Brune       } else {
456dfbf837cSBarry Smith         if (ngmres->monitor) {
457f109b39eSPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_M, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fnorm);CHKERRQ(ierr);
458dfbf837cSBarry Smith         }
4599f425c49SPeter Brune         fnorm = fMnorm;
4609f425c49SPeter Brune         nu = fnorm*fnorm;
4619f425c49SPeter Brune         ierr = VecCopy(FM, F);CHKERRQ(ierr);
4629f425c49SPeter Brune         ierr = VecCopy(XM, X);CHKERRQ(ierr);
4639f425c49SPeter Brune       }
46413a62661SPeter Brune     } else { /* none */
46513a62661SPeter Brune       fnorm = fAnorm;
46613a62661SPeter Brune       nu = fnorm*fnorm;
46713a62661SPeter Brune       ierr = VecCopy(FA, F);CHKERRQ(ierr);
46813a62661SPeter Brune       ierr = VecCopy(XA, X);CHKERRQ(ierr);
46919653cdaSPeter Brune     }
470211b2d39SPeter Brune 
47119653cdaSPeter Brune     selectRestart = PETSC_FALSE;
47213a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) {
47398b3e84cSPeter Brune       /* difference stagnation restart */
474cf22de31SPeter Brune       if((ngmres->epsilonB*dnorm > dminnorm) && (PetscSqrtReal(fAnorm) > ngmres->deltaB*PetscSqrtReal(fminnorm))) {
475dfbf837cSBarry Smith         if (ngmres->monitor) {
476f109b39eSPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "difference restart: %e > %e\n", ngmres->epsilonB*dnorm, dminnorm);CHKERRQ(ierr);
477dfbf837cSBarry Smith         }
47819653cdaSPeter Brune         selectRestart = PETSC_TRUE;
47919653cdaSPeter Brune       }
48098b3e84cSPeter Brune       /* residual stagnation restart */
481cf22de31SPeter Brune       if (PetscSqrtReal(fAnorm) > ngmres->gammaC*PetscSqrtReal(fminnorm)) {
482dfbf837cSBarry Smith         if (ngmres->monitor) {
483cf22de31SPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "residual restart: %e > %e\n", PetscSqrtReal(fAnorm), ngmres->gammaC*PetscSqrtReal(fminnorm));CHKERRQ(ierr);
484dfbf837cSBarry Smith         }
48519653cdaSPeter Brune         selectRestart = PETSC_TRUE;
48619653cdaSPeter Brune       }
48728ed4a04SPeter Brune       /* if the restart conditions persist for more than restart_it iterations, restart. */
48819653cdaSPeter Brune       if (selectRestart) {
48928ed4a04SPeter Brune         restart_count++;
49028ed4a04SPeter Brune       } else {
49128ed4a04SPeter Brune         restart_count = 0;
49228ed4a04SPeter Brune       }
49313a62661SPeter Brune     } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) {
49413a62661SPeter Brune       if (k_restart > ngmres->restart_periodic) {
49513a62661SPeter Brune         if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor, "periodic restart after %D iterations\n", k_restart);CHKERRQ(ierr);
49613a62661SPeter Brune         restart_count = ngmres->restart_it;
49713a62661SPeter Brune       }
49813a62661SPeter Brune     }
49928ed4a04SPeter Brune     /* restart after restart conditions have persisted for a fixed number of iterations */
50028ed4a04SPeter Brune     if (restart_count >= ngmres->restart_it) {
501dfbf837cSBarry Smith       if (ngmres->monitor){
502dfbf837cSBarry Smith         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Restarted at iteration %d\n", k_restart);CHKERRQ(ierr);
503dfbf837cSBarry Smith       }
50428ed4a04SPeter Brune       restart_count = 0;
50519653cdaSPeter Brune       k_restart = 1;
50619653cdaSPeter Brune       l = 1;
50798b3e84cSPeter Brune       /* q_{00} = nu */
508d2e16ddcSPeter Brune       if (ngmres->anderson) {
509d2e16ddcSPeter Brune         ngmres->fnorms[0] = fMnorm;
510d2e16ddcSPeter Brune         nu = fMnorm*fMnorm;
511d2e16ddcSPeter Brune         Q(0,0) = nu;
512d2e16ddcSPeter Brune         /* Fdot[0] = F */
513d2e16ddcSPeter Brune         ierr = VecCopy(XM, Xdot[0]);CHKERRQ(ierr);
514d2e16ddcSPeter Brune         ierr = VecCopy(FM, Fdot[0]);CHKERRQ(ierr);
515d2e16ddcSPeter Brune       } else {
516f109b39eSPeter Brune         ngmres->fnorms[0] = fnorm;
517f109b39eSPeter Brune         nu = fnorm*fnorm;
51819653cdaSPeter Brune         Q(0,0) = nu;
519f109b39eSPeter Brune         /* Fdot[0] = F */
520f109b39eSPeter Brune         ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr);
521f109b39eSPeter Brune         ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr);
522d2e16ddcSPeter Brune       }
52319653cdaSPeter Brune     } else {
52498b3e84cSPeter Brune       /* select the current size of the subspace */
5251e633543SBarry Smith       if (l < ngmres->msize) l++;
52619653cdaSPeter Brune       k_restart++;
52798b3e84cSPeter Brune       /* place the current entry in the list of previous entries */
528d2e16ddcSPeter Brune       if (ngmres->anderson) {
529d2e16ddcSPeter Brune         ierr = VecCopy(FM, Fdot[ivec]);CHKERRQ(ierr);
530d2e16ddcSPeter Brune         ierr = VecCopy(XM, Xdot[ivec]);CHKERRQ(ierr);
531d2e16ddcSPeter Brune         ngmres->fnorms[ivec] = fMnorm;
532d2e16ddcSPeter Brune         if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of FM */
53318aa0c0cSPeter Brune         xi[ivec] = fMnorm*fMnorm;
534d2e16ddcSPeter Brune         for (i = 0; i < l; i++) {
53518aa0c0cSPeter Brune           Q(i, ivec) = xi[i];
53618aa0c0cSPeter Brune           Q(ivec, i) = xi[i];
537d2e16ddcSPeter Brune         }
538d2e16ddcSPeter Brune       } else {
539f109b39eSPeter Brune         ierr = VecCopy(F, Fdot[ivec]);CHKERRQ(ierr);
540f109b39eSPeter Brune         ierr = VecCopy(X, Xdot[ivec]);CHKERRQ(ierr);
541f109b39eSPeter Brune         ngmres->fnorms[ivec] = fnorm;
542d2e16ddcSPeter Brune         if (fminnorm > fnorm) fminnorm = fnorm;  /* the minimum norm is now of FA */
54318aa0c0cSPeter Brune         ierr = VecMDot(F, l, Fdot, xi);CHKERRQ(ierr);
54419653cdaSPeter Brune         for (i = 0; i < l; i++) {
54518aa0c0cSPeter Brune           Q(i, ivec) = xi[i];
54618aa0c0cSPeter Brune           Q(ivec, i) = xi[i];
54719653cdaSPeter Brune         }
54819653cdaSPeter Brune       }
549d2e16ddcSPeter Brune     }
55019653cdaSPeter Brune 
5518409ca45SMatthew G Knepley     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
552087dfb9eSxuemin     snes->iter = k;
553f109b39eSPeter Brune     snes->norm = fnorm;
5548409ca45SMatthew G Knepley     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
5558409ca45SMatthew G Knepley     SNESLogConvHistory(snes, snes->norm, snes->iter);
5568409ca45SMatthew G Knepley     ierr = SNESMonitor(snes, snes->iter, snes->norm);CHKERRQ(ierr);
5578409ca45SMatthew G Knepley 
55818aa0c0cSPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
559087dfb9eSxuemin     if (snes->reason) PetscFunctionReturn(0);
560a312c225SMatthew G Knepley   }
561a312c225SMatthew G Knepley   snes->reason = SNES_DIVERGED_MAX_IT;
562a312c225SMatthew G Knepley   PetscFunctionReturn(0);
563a312c225SMatthew G Knepley }
564a312c225SMatthew G Knepley 
56513a62661SPeter Brune #undef __FUNCT__
56613a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType"
56713a62661SPeter Brune /*@
56813a62661SPeter Brune     SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES.
56913a62661SPeter Brune 
57013a62661SPeter Brune     Logically Collective on SNES
57113a62661SPeter Brune 
57213a62661SPeter Brune     Input Parameters:
57313a62661SPeter Brune +   snes - the iterative context
57413a62661SPeter Brune -   rtype - restart type
57513a62661SPeter Brune 
57613a62661SPeter Brune     Options Database:
57713a62661SPeter Brune +   -snes_ngmres_restart_type<difference,periodic,none> - set the restart type
5780c777b0cSPeter Brune -   -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic
57913a62661SPeter Brune 
58013a62661SPeter Brune     Level: intermediate
58113a62661SPeter Brune 
58213a62661SPeter Brune     SNESNGMRESRestartTypes:
58313a62661SPeter Brune +   SNES_NGMRES_RESTART_NONE - never restart
58413a62661SPeter Brune .   SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria
58513a62661SPeter Brune -   SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations
58613a62661SPeter Brune 
58713a62661SPeter Brune     Notes:
58813a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
58913a62661SPeter Brune 
59013a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch
59113a62661SPeter Brune @*/
59213a62661SPeter Brune PetscErrorCode SNESNGMRESSetRestartType(SNES snes, SNESNGMRESRestartType rtype) {
59313a62661SPeter Brune   PetscErrorCode ierr;
59413a62661SPeter Brune   PetscFunctionBegin;
59513a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
59613a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr);
59713a62661SPeter Brune   PetscFunctionReturn(0);
59813a62661SPeter Brune }
59913a62661SPeter Brune 
60013a62661SPeter Brune #undef __FUNCT__
60113a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType"
60213a62661SPeter Brune /*@
60313a62661SPeter Brune     SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES.  This determines how the candidate solution and
60413a62661SPeter Brune     combined solution are used to create the next iterate.
60513a62661SPeter Brune 
60613a62661SPeter Brune     Logically Collective on SNES
60713a62661SPeter Brune 
60813a62661SPeter Brune     Input Parameters:
60913a62661SPeter Brune +   snes - the iterative context
61013a62661SPeter Brune -   stype - selection type
61113a62661SPeter Brune 
61213a62661SPeter Brune     Options Database:
61313a62661SPeter Brune .   -snes_ngmres_select_type<difference,none,linesearch>
61413a62661SPeter Brune 
61513a62661SPeter Brune     Level: intermediate
61613a62661SPeter Brune 
61713a62661SPeter Brune     SNESNGMRESSelectTypes:
61813a62661SPeter Brune +   SNES_NGMRES_SELECT_NONE - choose the combined solution all the time
61913a62661SPeter Brune .   SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria
62013a62661SPeter Brune -   SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination
62113a62661SPeter Brune 
62213a62661SPeter Brune     Notes:
62313a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
62413a62661SPeter Brune 
62513a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch
62613a62661SPeter Brune @*/
62713a62661SPeter Brune 
62813a62661SPeter Brune PetscErrorCode SNESNGMRESSetSelectType(SNES snes, SNESNGMRESSelectType stype) {
62913a62661SPeter Brune   PetscErrorCode ierr;
63013a62661SPeter Brune   PetscFunctionBegin;
63113a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
63213a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr);
63313a62661SPeter Brune   PetscFunctionReturn(0);
63413a62661SPeter Brune }
63513a62661SPeter Brune 
63613a62661SPeter Brune 
63713a62661SPeter Brune EXTERN_C_BEGIN
63813a62661SPeter Brune #undef __FUNCT__
63913a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES"
64013a62661SPeter Brune 
64113a62661SPeter Brune PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes, SNESNGMRESSelectType stype) {
64213a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES *)snes->data;
64313a62661SPeter Brune   PetscFunctionBegin;
64413a62661SPeter Brune   ngmres->select_type = stype;
64513a62661SPeter Brune   PetscFunctionReturn(0);
64613a62661SPeter Brune }
64713a62661SPeter Brune 
64813a62661SPeter Brune #undef __FUNCT__
64913a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES"
65013a62661SPeter Brune 
65113a62661SPeter Brune PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes, SNESNGMRESRestartType rtype) {
65213a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES *)snes->data;
65313a62661SPeter Brune   PetscFunctionBegin;
65413a62661SPeter Brune   ngmres->restart_type = rtype;
65513a62661SPeter Brune   PetscFunctionReturn(0);
65613a62661SPeter Brune }
65713a62661SPeter Brune EXTERN_C_END
65813a62661SPeter Brune 
65913a62661SPeter Brune 
660dfbf837cSBarry Smith /*MC
6611867fe5bSPeter Brune   SNESNGMRES - The Nonlinear Generalized Minimum Residual method.
662a312c225SMatthew G Knepley 
663dfbf837cSBarry Smith    Level: beginner
664dfbf837cSBarry Smith 
6651867fe5bSPeter Brune    Options Database:
66613a62661SPeter Brune +  -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution
66713a62661SPeter Brune +  -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions
66813a62661SPeter Brune .  -snes_ngmres_anderson         - Use Anderson mixing NGMRES variant which combines candidate solutions instead of actual solutions
66913a62661SPeter Brune .  -snes_ngmres_m                - Number of stored previous solutions and residuals
67013a62661SPeter Brune .  -snes_ngmres_restart_it       - Number of iterations the restart conditions hold before restart
67113a62661SPeter Brune .  -snes_ngmres_gammaA           - Residual tolerance for solution select between the candidate and combination
67213a62661SPeter Brune .  -snes_ngmres_gammaC           - Residual tolerance for restart
67313a62661SPeter Brune .  -snes_ngmres_epsilonB         - Difference tolerance between subsequent solutions triggering restart
67413a62661SPeter Brune .  -snes_ngmres_deltaB           - Difference tolerance between residuals triggering restart
67513a62661SPeter Brune .  -snes_ngmres_monitor          - Prints relevant information about the ngmres iteration
67613a62661SPeter Brune .  -snes_linesearch_type <basic,basicnonorms,quadratic,critical> - Line search type used for the default smoother
67713a62661SPeter Brune -  -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type
6781867fe5bSPeter Brune 
6791867fe5bSPeter Brune    Notes:
6801867fe5bSPeter Brune 
6811867fe5bSPeter Brune    The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized
6821867fe5bSPeter Brune    optimization problem at each iteration.
6831867fe5bSPeter Brune 
6841867fe5bSPeter Brune    References:
6851867fe5bSPeter Brune 
686dfbf837cSBarry Smith    "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio,
687dfbf837cSBarry Smith    SIAM Journal on Scientific Computing, 21(5), 2000.
688dfbf837cSBarry Smith 
689dfbf837cSBarry Smith    This is also the same as the algorithm called Anderson acceleration introduced in "D. G. Anderson. Iterative procedures for nonlinear integral equations.
690dfbf837cSBarry Smith    J. Assoc. Comput. Mach., 12:547–560, 1965."
691dfbf837cSBarry Smith 
692dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types)
693dfbf837cSBarry Smith M*/
694a312c225SMatthew G Knepley 
695a312c225SMatthew G Knepley EXTERN_C_BEGIN
696a312c225SMatthew G Knepley #undef __FUNCT__
697a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES"
698a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes)
699a312c225SMatthew G Knepley {
700a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres;
701a312c225SMatthew G Knepley   PetscErrorCode ierr;
702a312c225SMatthew G Knepley 
703a312c225SMatthew G Knepley   PetscFunctionBegin;
704a312c225SMatthew G Knepley   snes->ops->destroy        = SNESDestroy_NGMRES;
705a312c225SMatthew G Knepley   snes->ops->setup          = SNESSetUp_NGMRES;
706a312c225SMatthew G Knepley   snes->ops->setfromoptions = SNESSetFromOptions_NGMRES;
707a312c225SMatthew G Knepley   snes->ops->view           = SNESView_NGMRES;
708a312c225SMatthew G Knepley   snes->ops->solve          = SNESSolve_NGMRES;
709a312c225SMatthew G Knepley   snes->ops->reset          = SNESReset_NGMRES;
710a312c225SMatthew G Knepley 
71142f4f86dSBarry Smith   snes->usespc          = PETSC_TRUE;
7122c155ee1SBarry Smith   snes->usesksp         = PETSC_FALSE;
7132c155ee1SBarry Smith 
714a312c225SMatthew G Knepley   ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr);
715a312c225SMatthew G Knepley   snes->data = (void*) ngmres;
716d2e16ddcSPeter Brune   ngmres->msize = 30;
71719653cdaSPeter Brune 
71888976e71SPeter Brune   if (!snes->tolerancesset) {
7190e444f03SPeter Brune     snes->max_funcs = 30000;
7200e444f03SPeter Brune     snes->max_its   = 10000;
72188976e71SPeter Brune   }
7220e444f03SPeter Brune 
723d2e16ddcSPeter Brune   ngmres->anderson   = PETSC_FALSE;
724d2e16ddcSPeter Brune 
725e7058c64SPeter Brune   ngmres->additive_linesearch = PETSC_NULL;
726e7058c64SPeter Brune 
72728ed4a04SPeter Brune   ngmres->restart_it = 2;
72813a62661SPeter Brune   ngmres->restart_periodic = 30;
729f109b39eSPeter Brune   ngmres->gammaA     = 2.0;
730f109b39eSPeter Brune   ngmres->gammaC     = 2.0;
731cac108bcSPeter Brune   ngmres->deltaB     = 0.9;
732cac108bcSPeter Brune   ngmres->epsilonB   = 0.1;
733e7058c64SPeter Brune 
73413a62661SPeter Brune   ngmres->restart_type   = SNES_NGMRES_RESTART_DIFFERENCE;
73513a62661SPeter Brune   ngmres->select_type    = SNES_NGMRES_SELECT_DIFFERENCE;
73613a62661SPeter Brune 
73713a62661SPeter Brune   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNGMRESSetSelectType_C","SNESNGMRESSetSelectType_NGMRES", SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr);
73813a62661SPeter Brune   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNGMRESSetRestartType_C","SNESNGMRESSetRestartType_NGMRES", SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr);
73913a62661SPeter Brune 
740a312c225SMatthew G Knepley   PetscFunctionReturn(0);
741a312c225SMatthew G Knepley }
742a312c225SMatthew G Knepley EXTERN_C_END
743