xref: /petsc/src/snes/impls/ngmres/snesngmres.c (revision 5fd668637986a8d8518383a9159eebc368e1d5b4)
113a62661SPeter Brune #include <../src/snes/impls/ngmres/snesngmres.h> /*I "petscsnes.h" I*/
219653cdaSPeter Brune #include <petscblaslapack.h>
3a312c225SMatthew G Knepley 
46a6fc655SJed Brown const char *const SNESNGMRESRestartTypes[] = {"NONE","PERIODIC","DIFFERENCE","SNESNGMRESRestartType","SNES_NGMRES_RESTART_",0};
56a6fc655SJed Brown const char *const 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);
18a312c225SMatthew G Knepley   PetscFunctionReturn(0);
19a312c225SMatthew G Knepley }
20a312c225SMatthew G Knepley 
21a312c225SMatthew G Knepley #undef __FUNCT__
22a312c225SMatthew G Knepley #define __FUNCT__ "SNESDestroy_NGMRES"
23a312c225SMatthew G Knepley PetscErrorCode SNESDestroy_NGMRES(SNES snes)
24a312c225SMatthew G Knepley {
25a312c225SMatthew G Knepley   PetscErrorCode ierr;
2678440776SJed Brown   SNES_NGMRES    *ngmres = (SNES_NGMRES*)snes->data;
27a312c225SMatthew G Knepley 
28a312c225SMatthew G Knepley   PetscFunctionBegin;
29a312c225SMatthew G Knepley   ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr);
30f109b39eSPeter Brune   ierr = PetscFree5(ngmres->h, ngmres->beta, ngmres->xi, ngmres->fnorms, ngmres->q);CHKERRQ(ierr);
3119653cdaSPeter Brune   ierr = PetscFree(ngmres->s);CHKERRQ(ierr);
3218aa0c0cSPeter Brune   ierr = PetscFree(ngmres->xnorms);CHKERRQ(ierr);
3319653cdaSPeter Brune #if PETSC_USE_COMPLEX
3422d28d08SBarry Smith   ierr = PetscFree(ngmres->rwork);CHKERRQ(ierr);
3519653cdaSPeter Brune #endif
3622d28d08SBarry Smith   ierr = PetscFree(ngmres->work);CHKERRQ(ierr);
3722d28d08SBarry Smith   ierr = PetscFree(snes->data);CHKERRQ(ierr);
38a312c225SMatthew G Knepley   PetscFunctionReturn(0);
39a312c225SMatthew G Knepley }
40a312c225SMatthew G Knepley 
41a312c225SMatthew G Knepley #undef __FUNCT__
42a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetUp_NGMRES"
43a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes)
44a312c225SMatthew G Knepley {
45a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES *) snes->data;
46e7058c64SPeter Brune   const char     *optionsprefix;
4719653cdaSPeter Brune   PetscInt       msize,hsize;
48a312c225SMatthew G Knepley   PetscErrorCode ierr;
49a312c225SMatthew G Knepley 
50a312c225SMatthew G Knepley   PetscFunctionBegin;
5178440776SJed Brown   ierr = SNESDefaultGetWork(snes,5);CHKERRQ(ierr);
5278440776SJed Brown   if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);}
5378440776SJed Brown   if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);}
5478440776SJed Brown   if (!ngmres->setup_called) {
55087dfb9eSxuemin     msize         = ngmres->msize;  /* restart size */
5619653cdaSPeter Brune     hsize         = msize * msize;
57087dfb9eSxuemin 
5898b3e84cSPeter Brune     /* explicit least squares minimization solve */
5919653cdaSPeter Brune     ierr = PetscMalloc5(hsize,PetscScalar,&ngmres->h,
6019653cdaSPeter Brune                         msize,PetscScalar,&ngmres->beta,
6119653cdaSPeter Brune                         msize,PetscScalar,&ngmres->xi,
62f109b39eSPeter Brune                         msize,PetscReal,  &ngmres->fnorms,
6319653cdaSPeter Brune                         hsize,PetscScalar,&ngmres->q);CHKERRQ(ierr);
6418aa0c0cSPeter Brune     if (ngmres->singlereduction) {
6518aa0c0cSPeter Brune       ierr = PetscMalloc(msize*sizeof(PetscReal),&ngmres->xnorms);CHKERRQ(ierr);
6618aa0c0cSPeter Brune     }
6719653cdaSPeter Brune     ngmres->nrhs = 1;
6819653cdaSPeter Brune     ngmres->lda = msize;
6919653cdaSPeter Brune     ngmres->ldb = msize;
7019653cdaSPeter Brune     ierr = PetscMalloc(msize*sizeof(PetscScalar),&ngmres->s);CHKERRQ(ierr);
7119653cdaSPeter Brune     ierr = PetscMemzero(ngmres->h,   hsize*sizeof(PetscScalar));CHKERRQ(ierr);
7219653cdaSPeter Brune     ierr = PetscMemzero(ngmres->q,   hsize*sizeof(PetscScalar));CHKERRQ(ierr);
7319653cdaSPeter Brune     ierr = PetscMemzero(ngmres->xi,  msize*sizeof(PetscScalar));CHKERRQ(ierr);
7419653cdaSPeter Brune     ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr);
7519653cdaSPeter Brune     ngmres->lwork = 12*msize;
7619653cdaSPeter Brune #if PETSC_USE_COMPLEX
7722d28d08SBarry Smith     ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork);CHKERRQ(ierr);
7819653cdaSPeter Brune #endif
7922d28d08SBarry Smith     ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work);CHKERRQ(ierr);
8078440776SJed Brown   }
81e7058c64SPeter Brune 
82e7058c64SPeter Brune   /* linesearch setup */
83e7058c64SPeter Brune   ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr);
84e7058c64SPeter Brune 
8513a62661SPeter Brune   if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) {
86f1c6b773SPeter Brune     ierr = SNESLineSearchCreate(((PetscObject)snes)->comm, &ngmres->additive_linesearch);CHKERRQ(ierr);
87f1c6b773SPeter Brune     ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch, snes);CHKERRQ(ierr);
881a4f838cSPeter Brune     ierr = SNESLineSearchSetType(ngmres->additive_linesearch, SNESLINESEARCHL2);CHKERRQ(ierr);
89f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch, "additive_");CHKERRQ(ierr);
90f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch, optionsprefix);CHKERRQ(ierr);
91f1c6b773SPeter Brune     ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr);
92e7058c64SPeter Brune   }
93e7058c64SPeter Brune 
9478440776SJed Brown   ngmres->setup_called = PETSC_TRUE;
95a312c225SMatthew G Knepley   PetscFunctionReturn(0);
96a312c225SMatthew G Knepley }
97a312c225SMatthew G Knepley 
98a312c225SMatthew G Knepley #undef __FUNCT__
99a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES"
100a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes)
101a312c225SMatthew G Knepley {
102a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres = (SNES_NGMRES *) snes->data;
103a312c225SMatthew G Knepley   PetscErrorCode ierr;
104dfbf837cSBarry Smith   PetscBool      debug;
105f1c6b773SPeter Brune   SNESLineSearch linesearch;
1060adebc6cSBarry Smith 
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) {
148f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer, "  Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr);
149f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer, "  Residual selection: gammaA=%1.0e, gammaC=%1.0e\n", ngmres->gammaA, ngmres->gammaC);CHKERRQ(ierr);
150f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer, "  Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n", ngmres->epsilonB, ngmres->deltaB);CHKERRQ(ierr);
151a312c225SMatthew G Knepley   }
152a312c225SMatthew G Knepley   PetscFunctionReturn(0);
153a312c225SMatthew G Knepley }
154a312c225SMatthew G Knepley 
155a312c225SMatthew G Knepley #undef __FUNCT__
156a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES"
157a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes)
158a312c225SMatthew G Knepley {
159087dfb9eSxuemin   SNES_NGMRES        *ngmres = (SNES_NGMRES *) snes->data;
16098b3e84cSPeter Brune   /* present solution, residual, and preconditioned residual */
1619f425c49SPeter Brune   Vec                 X, F, B, D, Y;
162f109b39eSPeter Brune 
163f109b39eSPeter Brune   /* candidate linear combination answers */
1644b32a720SPeter Brune   Vec                 XA, FA, XM, FM, FPC;
16519653cdaSPeter Brune 
16698b3e84cSPeter Brune   /* previous iterations to construct the subspace */
167f109b39eSPeter Brune   Vec                 *Fdot = ngmres->Fdot;
168f109b39eSPeter Brune   Vec                 *Xdot = ngmres->Xdot;
16919653cdaSPeter Brune 
17098b3e84cSPeter Brune   /* coefficients and RHS to the minimization problem */
17119653cdaSPeter Brune   PetscScalar         *beta = ngmres->beta;
17219653cdaSPeter Brune   PetscScalar         *xi   = ngmres->xi;
17318aa0c0cSPeter Brune   PetscReal           fnorm, fMnorm, fAnorm;
17419653cdaSPeter Brune   PetscReal           nu;
17519653cdaSPeter Brune   PetscScalar         alph_total = 0.;
17628ed4a04SPeter Brune   PetscInt            i, j, k, k_restart, l, ivec, restart_count = 0;
17719653cdaSPeter Brune 
17898b3e84cSPeter Brune   /* solution selection data */
17919653cdaSPeter Brune   PetscBool           selectA, selectRestart;
18074b542b2SMatthew G Knepley   PetscReal           dnorm, dminnorm = 0.0, dcurnorm;
181d484d688SPeter Brune   PetscReal           fminnorm,xnorm,ynorm;
18219653cdaSPeter Brune 
1831e633543SBarry Smith   SNESConvergedReason reason;
1846e733865SPeter Brune   PetscBool           lssucceed,changed_y,changed_w;
185a312c225SMatthew G Knepley   PetscErrorCode      ierr;
186a312c225SMatthew G Knepley 
187a312c225SMatthew G Knepley   PetscFunctionBegin;
18898b3e84cSPeter Brune   /* variable initialization */
189a312c225SMatthew G Knepley   snes->reason  = SNES_CONVERGED_ITERATING;
190f109b39eSPeter Brune   X             = snes->vec_sol;
191f109b39eSPeter Brune   F             = snes->vec_func;
192f109b39eSPeter Brune   B             = snes->vec_rhs;
193f109b39eSPeter Brune   XA            = snes->vec_sol_update;
194f109b39eSPeter Brune   FA            = snes->work[0];
195f109b39eSPeter Brune   D             = snes->work[1];
196f109b39eSPeter Brune 
197f109b39eSPeter Brune   /* work for the line search */
198f109b39eSPeter Brune   Y             = snes->work[2];
1999f425c49SPeter Brune   XM            = snes->work[3];
2009f425c49SPeter Brune   FM            = snes->work[4];
201a312c225SMatthew G Knepley 
202a312c225SMatthew G Knepley   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
203a312c225SMatthew G Knepley   snes->iter = 0;
204a312c225SMatthew G Knepley   snes->norm = 0.;
205a312c225SMatthew G Knepley   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
20619653cdaSPeter Brune 
20798b3e84cSPeter Brune   /* initialization */
20819653cdaSPeter Brune 
20998b3e84cSPeter Brune   /* r = F(x) */
210e4ed7901SPeter Brune   if (!snes->vec_func_init_set) {
211f109b39eSPeter Brune     ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr);
212a312c225SMatthew G Knepley     if (snes->domainerror) {
213a312c225SMatthew G Knepley       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
214a312c225SMatthew G Knepley       PetscFunctionReturn(0);
215a312c225SMatthew G Knepley     }
216e4ed7901SPeter Brune   } else {
217e4ed7901SPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
218e4ed7901SPeter Brune   }
21919653cdaSPeter Brune 
220e4ed7901SPeter Brune   if (!snes->norm_init_set) {
221f109b39eSPeter Brune     ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr);
222b707f0f7SPeter Brune     if (PetscIsInfOrNanReal(fnorm)) SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation");
223e4ed7901SPeter Brune   } else {
224e4ed7901SPeter Brune     fnorm = snes->norm_init;
225e4ed7901SPeter Brune     snes->norm_init_set = PETSC_FALSE;
226e4ed7901SPeter Brune   }
227e4ed7901SPeter Brune   fminnorm = fnorm;
228e4ed7901SPeter Brune   /* nu = (r, r) */
229e4ed7901SPeter Brune   nu = fnorm*fnorm;
23019653cdaSPeter Brune 
23198b3e84cSPeter Brune   /* q_{00} = nu  */
23219653cdaSPeter Brune   Q(0,0) = nu;
233f109b39eSPeter Brune   ngmres->fnorms[0] = fnorm;
234f109b39eSPeter Brune   /* Fdot[0] = F */
235f109b39eSPeter Brune   ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr);
236f109b39eSPeter Brune   ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr);
237087dfb9eSxuemin 
238a312c225SMatthew G Knepley   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
239f109b39eSPeter Brune   snes->norm = fnorm;
240a312c225SMatthew G Knepley   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
241f109b39eSPeter Brune   SNESLogConvHistory(snes, fnorm, 0);
242f109b39eSPeter Brune   ierr = SNESMonitor(snes, 0, fnorm);CHKERRQ(ierr);
243f109b39eSPeter Brune   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
244a312c225SMatthew G Knepley   if (snes->reason) PetscFunctionReturn(0);
245a312c225SMatthew G Knepley 
24619653cdaSPeter Brune   k_restart = 1;
24719653cdaSPeter Brune   l = 1;
24809c08436SPeter Brune   for (k=1; k < snes->max_its+1; k++) {
24998b3e84cSPeter Brune     /* select which vector of the stored subspace will be updated */
25098b3e84cSPeter Brune     ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */
25119653cdaSPeter Brune 
25298b3e84cSPeter Brune     /* Computation of x^M */
253c40d0f55SPeter Brune     if (snes->pc && snes->pcside == PC_RIGHT) {
2549f425c49SPeter Brune       ierr = VecCopy(X, XM);CHKERRQ(ierr);
255e4ed7901SPeter Brune       ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr);
256e4ed7901SPeter Brune       ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr);
25763e7833aSPeter Brune 
25863e7833aSPeter Brune       ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr);
2599f425c49SPeter Brune       ierr = SNESSolve(snes->pc, B, XM);CHKERRQ(ierr);
26063e7833aSPeter Brune       ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr);
26163e7833aSPeter Brune 
2628cc86e31SPeter Brune       ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
2638cc86e31SPeter Brune       if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
2648cc86e31SPeter Brune         snes->reason = SNES_DIVERGED_INNER;
2658cc86e31SPeter Brune         PetscFunctionReturn(0);
2668cc86e31SPeter Brune       }
2674b32a720SPeter Brune       ierr = SNESGetFunction(snes->pc, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr);
2684b32a720SPeter Brune       ierr = VecCopy(FPC, FM);CHKERRQ(ierr);
2694b32a720SPeter Brune       ierr = SNESGetFunctionNorm(snes->pc, &fMnorm);CHKERRQ(ierr);
2708cc86e31SPeter Brune     } else {
271f109b39eSPeter Brune       /* no preconditioner -- just take gradient descent with line search */
272f109b39eSPeter Brune       ierr = VecCopy(F, Y);CHKERRQ(ierr);
273e7058c64SPeter Brune       ierr = VecCopy(F, FM);CHKERRQ(ierr);
274e7058c64SPeter Brune       ierr = VecCopy(X, XM);CHKERRQ(ierr);
275e7058c64SPeter Brune       fMnorm = fnorm;
276f1c6b773SPeter Brune       ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr);
277f1c6b773SPeter Brune       ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssucceed);CHKERRQ(ierr);
278f109b39eSPeter Brune       if (!lssucceed) {
279f109b39eSPeter Brune         if (++snes->numFailures >= snes->maxFailures) {
280f109b39eSPeter Brune           snes->reason = SNES_DIVERGED_LINE_SEARCH;
281f109b39eSPeter Brune           PetscFunctionReturn(0);
282f109b39eSPeter Brune         }
283f109b39eSPeter Brune       }
2846634f59bSPeter Brune     }
2851e633543SBarry Smith 
28698b3e84cSPeter Brune     /* r = F(x) */
2879f425c49SPeter Brune     nu = fMnorm*fMnorm;
2889f425c49SPeter Brune     if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of F^M */
28919653cdaSPeter Brune 
29098b3e84cSPeter Brune     /* construct the right hand side and xi factors */
2918c09b6b7SPeter Brune     ierr = VecMDot(FM, l, Fdot, xi);CHKERRQ(ierr);
2928c09b6b7SPeter Brune 
29319653cdaSPeter Brune     for (i = 0; i < l; i++) {
29419653cdaSPeter Brune       beta[i] = nu - xi[i];
29519653cdaSPeter Brune     }
29619653cdaSPeter Brune 
29798b3e84cSPeter Brune     /* construct h */
29819653cdaSPeter Brune     for (j = 0; j < l; j++) {
29919653cdaSPeter Brune       for (i = 0; i < l; i++) {
30019653cdaSPeter Brune         H(i, j) = Q(i, j) - xi[i] - xi[j] + nu;
30119653cdaSPeter Brune       }
30219653cdaSPeter Brune     }
303f109b39eSPeter Brune 
304f109b39eSPeter Brune     if (l == 1) {
305f109b39eSPeter Brune       /* simply set alpha[0] = beta[0] / H[0, 0] */
306bf08dd53SPeter Brune       if (H(0, 0) != 0.) {
307f109b39eSPeter Brune         beta[0] = beta[0] / H(0, 0);
308f109b39eSPeter Brune       } else {
309bf08dd53SPeter Brune         beta[0] = 0.;
310bf08dd53SPeter Brune       }
311bf08dd53SPeter Brune     } else {
312519f805aSKarl Rupp #if defined(PETSC_MISSING_LAPACK_GELSS)
313b707f0f7SPeter Brune       SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_SUP, "NGMRES with LS requires the LAPACK GELSS routine.");
3144a0c5b0cSMatthew G Knepley #else
315c5df96a5SBarry Smith       ierr = PetscBLASIntCast(l,&ngmres->m);CHKERRQ(ierr);
316c5df96a5SBarry Smith       ierr = PetscBLASIntCast(l,&ngmres->n);CHKERRQ(ierr);
317c5df96a5SBarry Smith       ngmres->info =   0;
31819653cdaSPeter Brune       ngmres->rcond = -1.;
3198e57ea43SSatish Balay       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
320519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
321c5df96a5SBarry Smith       LAPACKgelss_(&ngmres->m,&ngmres->n,&ngmres->nrhs,ngmres->h,&ngmres->lda,ngmres->beta,&ngmres->ldb,ngmres->s,&ngmres->rcond,
322c5df96a5SBarry Smith                    &ngmres->rank,ngmres->work,&ngmres->lwork,ngmres->rwork,&ngmres->info);
32319653cdaSPeter Brune #else
324c5df96a5SBarry Smith       LAPACKgelss_(&ngmres->m,&ngmres->n,&ngmres->nrhs,ngmres->h,&ngmres->lda,ngmres->beta,&ngmres->ldb,ngmres->s,&ngmres->rcond,
325c5df96a5SBarry Smith                    &ngmres->rank,ngmres->work,&ngmres->lwork,&ngmres->info);
32619653cdaSPeter Brune #endif
3278e57ea43SSatish Balay       ierr = PetscFPTrapPop();CHKERRQ(ierr);
328b707f0f7SPeter Brune       if (ngmres->info < 0) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_LIB,"Bad argument to GELSS");
329b707f0f7SPeter Brune       if (ngmres->info > 0) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_LIB,"SVD failed to converge");
330a312c225SMatthew G Knepley #endif
331f109b39eSPeter Brune     }
332a312c225SMatthew G Knepley 
333b707f0f7SPeter Brune     for (i=0;i<l;i++) {
334f23aa3ddSBarry Smith       if (PetscIsInfOrNanScalar(beta[i])) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_LIB,"SVD generated inconsistent output: NaN or Inf");
335b707f0f7SPeter Brune     }
336b707f0f7SPeter Brune 
33719653cdaSPeter Brune     alph_total = 0.;
33819653cdaSPeter Brune     for (i = 0; i < l; i++) {
33919653cdaSPeter Brune       alph_total += beta[i];
340c0bbabecSxuemin     }
341f109b39eSPeter Brune 
3429f425c49SPeter Brune     ierr = VecCopy(XM, XA);CHKERRQ(ierr);
343f109b39eSPeter Brune     ierr = VecScale(XA, 1. - alph_total);CHKERRQ(ierr);
344087dfb9eSxuemin 
3458c09b6b7SPeter Brune     ierr = VecMAXPY(XA, l, beta, Xdot);CHKERRQ(ierr);
3466e733865SPeter Brune 
3476e733865SPeter Brune     /* check the validity of the step */
348f89ba88eSPeter Brune     ierr = VecCopy(XA,Y);CHKERRQ(ierr);
3496e733865SPeter Brune     ierr = VecAXPY(Y,-1.0,X);CHKERRQ(ierr);
3506e733865SPeter Brune     ierr = SNESLineSearchPostCheck(snes->linesearch,X,Y,XA,&changed_y,&changed_w);CHKERRQ(ierr);
351f109b39eSPeter Brune     ierr = SNESComputeFunction(snes, XA, FA);CHKERRQ(ierr);
35219653cdaSPeter Brune 
3539f425c49SPeter Brune     /* differences for selection and restart */
35413a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) {
35518aa0c0cSPeter Brune       if (ngmres->singlereduction) {
35618aa0c0cSPeter Brune         dminnorm = -1.0;
357f109b39eSPeter Brune         ierr=VecCopy(XA, D);CHKERRQ(ierr);
35818aa0c0cSPeter Brune         ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr);
35918aa0c0cSPeter Brune         for (i=0;i<l;i++) {
36018aa0c0cSPeter Brune           ierr=VecAXPY(Xdot[i],-1.0,XA);CHKERRQ(ierr);
36118aa0c0cSPeter Brune         }
36218aa0c0cSPeter Brune         ierr = VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
36318aa0c0cSPeter Brune         ierr = VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr);
36418aa0c0cSPeter Brune         for (i=0;i<l;i++) {
36518aa0c0cSPeter Brune           ierr = VecNormBegin(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr);
36618aa0c0cSPeter Brune         }
36718aa0c0cSPeter Brune         ierr = VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
36818aa0c0cSPeter Brune         ierr = VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr);
36918aa0c0cSPeter Brune         for (i=0;i<l;i++) {
37018aa0c0cSPeter Brune           ierr = VecNormEnd(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr);
37118aa0c0cSPeter Brune         }
37218aa0c0cSPeter Brune         for (i=0;i<l;i++) {
37318aa0c0cSPeter Brune           dcurnorm = ngmres->xnorms[i];
37418aa0c0cSPeter Brune           if ((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm;
37518aa0c0cSPeter Brune           ierr=VecAXPY(Xdot[i],1.0,XA);CHKERRQ(ierr);
37618aa0c0cSPeter Brune         }
37718aa0c0cSPeter Brune       } else {
37818aa0c0cSPeter Brune         ierr=VecCopy(XA, D);CHKERRQ(ierr);
37918aa0c0cSPeter Brune         ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr);
38018aa0c0cSPeter Brune         ierr=VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr);
38118aa0c0cSPeter Brune         ierr=VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
38218aa0c0cSPeter Brune         ierr=VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr);
38318aa0c0cSPeter Brune         ierr=VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
384f109b39eSPeter Brune         dminnorm = -1.0;
38519653cdaSPeter Brune         for (i=0;i<l;i++) {
386f109b39eSPeter Brune           ierr=VecCopy(XA, D);CHKERRQ(ierr);
387f109b39eSPeter Brune           ierr=VecAXPY(D, -1.0, Xdot[i]);CHKERRQ(ierr);
388f109b39eSPeter Brune           ierr=VecNorm(D, NORM_2, &dcurnorm);CHKERRQ(ierr);
389f109b39eSPeter Brune           if ((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm;
39019653cdaSPeter Brune         }
39118aa0c0cSPeter Brune       }
39213a62661SPeter Brune     } else {
39313a62661SPeter Brune       ierr = VecNorm(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
39413a62661SPeter Brune     }
395b707f0f7SPeter Brune     if (PetscIsInfOrNanReal(fAnorm)) SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation");
3969f425c49SPeter Brune     /* combination (additive) or selection (multiplicative) of the N-GMRES solution */
39713a62661SPeter Brune     if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) {
3989f425c49SPeter Brune       /* X = X + \lambda(XA - X) */
3999f425c49SPeter Brune       if (ngmres->monitor) {
4009f425c49SPeter Brune         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr);
4019f425c49SPeter Brune       }
40213a62661SPeter Brune       ierr = VecCopy(FM, F);CHKERRQ(ierr);
40313a62661SPeter Brune       ierr = VecCopy(XM, X);CHKERRQ(ierr);
4049f425c49SPeter Brune       ierr = VecCopy(XA, Y);CHKERRQ(ierr);
405eb1825c3SPeter Brune       ierr = VecAYPX(Y, -1.0, X);CHKERRQ(ierr);
406d484d688SPeter Brune       fnorm = fMnorm;
407f1c6b773SPeter Brune       ierr = SNESLineSearchApply(ngmres->additive_linesearch,X,F,&fnorm,Y);CHKERRQ(ierr);
408f1c6b773SPeter Brune       ierr = SNESLineSearchGetSuccess(ngmres->additive_linesearch, &lssucceed);CHKERRQ(ierr);
4099f425c49SPeter Brune       if (!lssucceed) {
4109f425c49SPeter Brune         if (++snes->numFailures >= snes->maxFailures) {
4119f425c49SPeter Brune           snes->reason = SNES_DIVERGED_LINE_SEARCH;
4129f425c49SPeter Brune           PetscFunctionReturn(0);
4139f425c49SPeter Brune         }
4149f425c49SPeter Brune       }
4159f425c49SPeter Brune       if (ngmres->monitor) {
4169f425c49SPeter Brune         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Additive solution: ||F||_2 = %e\n", fnorm);CHKERRQ(ierr);
4179f425c49SPeter Brune       }
41813a62661SPeter Brune     } else if (ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) {
4199f425c49SPeter Brune       selectA = PETSC_TRUE;
4209f425c49SPeter Brune       /* Conditions for choosing the accelerated answer */
4219f425c49SPeter Brune       /* Criterion A -- the norm of the function isn't increased above the minimum by too much */
4229f425c49SPeter Brune       if (fAnorm >= ngmres->gammaA*fminnorm) {
4239f425c49SPeter Brune         selectA = PETSC_FALSE;
4249f425c49SPeter Brune       }
4259f425c49SPeter Brune       /* Criterion B -- the choice of x^A isn't too close to some other choice */
426cf22de31SPeter Brune       if (ngmres->epsilonB*dnorm<dminnorm || PetscSqrtReal(fnorm)<ngmres->deltaB*PetscSqrtReal(fminnorm)) {
42719653cdaSPeter Brune       } else {
42819653cdaSPeter Brune         selectA=PETSC_FALSE;
42919653cdaSPeter Brune       }
43019653cdaSPeter Brune       if (selectA) {
431dfbf837cSBarry Smith         if (ngmres->monitor) {
4329e764e56SPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_A, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr);
433dfbf837cSBarry Smith         }
43498b3e84cSPeter Brune         /* copy it over */
435f109b39eSPeter Brune         fnorm = fAnorm;
436f109b39eSPeter Brune         nu = fnorm*fnorm;
437f109b39eSPeter Brune         ierr = VecCopy(FA, F);CHKERRQ(ierr);
438f109b39eSPeter Brune         ierr = VecCopy(XA, X);CHKERRQ(ierr);
43919653cdaSPeter Brune       } else {
440dfbf837cSBarry Smith         if (ngmres->monitor) {
4415b0d26cfSPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_M, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr);
442dfbf837cSBarry Smith         }
4439f425c49SPeter Brune         fnorm = fMnorm;
4449f425c49SPeter Brune         nu = fnorm*fnorm;
445d484d688SPeter Brune         ierr = VecCopy(XM, Y);CHKERRQ(ierr);
446d484d688SPeter Brune         ierr = VecAXPY(Y,-1.0,X);CHKERRQ(ierr);
4479f425c49SPeter Brune         ierr = VecCopy(FM, F);CHKERRQ(ierr);
4489f425c49SPeter Brune         ierr = VecCopy(XM, X);CHKERRQ(ierr);
4499f425c49SPeter Brune       }
45013a62661SPeter Brune     } else { /* none */
45113a62661SPeter Brune       fnorm = fAnorm;
45213a62661SPeter Brune       nu = fnorm*fnorm;
45313a62661SPeter Brune       ierr = VecCopy(FA, F);CHKERRQ(ierr);
45413a62661SPeter Brune       ierr = VecCopy(XA, X);CHKERRQ(ierr);
45519653cdaSPeter Brune     }
456211b2d39SPeter Brune 
45719653cdaSPeter Brune     selectRestart = PETSC_FALSE;
45813a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) {
45998b3e84cSPeter Brune       /* difference stagnation restart */
460cf22de31SPeter Brune       if ((ngmres->epsilonB*dnorm > dminnorm) && (PetscSqrtReal(fAnorm) > ngmres->deltaB*PetscSqrtReal(fminnorm))) {
461dfbf837cSBarry Smith         if (ngmres->monitor) {
462f109b39eSPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "difference restart: %e > %e\n", ngmres->epsilonB*dnorm, dminnorm);CHKERRQ(ierr);
463dfbf837cSBarry Smith         }
46419653cdaSPeter Brune         selectRestart = PETSC_TRUE;
46519653cdaSPeter Brune       }
46698b3e84cSPeter Brune       /* residual stagnation restart */
467cf22de31SPeter Brune       if (PetscSqrtReal(fAnorm) > ngmres->gammaC*PetscSqrtReal(fminnorm)) {
468dfbf837cSBarry Smith         if (ngmres->monitor) {
469cf22de31SPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "residual restart: %e > %e\n", PetscSqrtReal(fAnorm), ngmres->gammaC*PetscSqrtReal(fminnorm));CHKERRQ(ierr);
470dfbf837cSBarry Smith         }
47119653cdaSPeter Brune         selectRestart = PETSC_TRUE;
47219653cdaSPeter Brune       }
47328ed4a04SPeter Brune       /* if the restart conditions persist for more than restart_it iterations, restart. */
47419653cdaSPeter Brune       if (selectRestart) {
47528ed4a04SPeter Brune         restart_count++;
47628ed4a04SPeter Brune       } else {
47728ed4a04SPeter Brune         restart_count = 0;
47828ed4a04SPeter Brune       }
47913a62661SPeter Brune     } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) {
48013a62661SPeter Brune       if (k_restart > ngmres->restart_periodic) {
48113a62661SPeter Brune         if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor, "periodic restart after %D iterations\n", k_restart);CHKERRQ(ierr);
48213a62661SPeter Brune         restart_count = ngmres->restart_it;
48313a62661SPeter Brune       }
48413a62661SPeter Brune     }
48528ed4a04SPeter Brune     /* restart after restart conditions have persisted for a fixed number of iterations */
48628ed4a04SPeter Brune     if (restart_count >= ngmres->restart_it) {
487dfbf837cSBarry Smith       if (ngmres->monitor) {
488dfbf837cSBarry Smith         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Restarted at iteration %d\n", k_restart);CHKERRQ(ierr);
489dfbf837cSBarry Smith       }
49028ed4a04SPeter Brune       restart_count = 0;
49119653cdaSPeter Brune       k_restart = 1;
49219653cdaSPeter Brune       l = 1;
49398b3e84cSPeter Brune       /* q_{00} = nu */
494d2e16ddcSPeter Brune       if (ngmres->anderson) {
495d2e16ddcSPeter Brune         ngmres->fnorms[0] = fMnorm;
496d2e16ddcSPeter Brune         nu = fMnorm*fMnorm;
497d2e16ddcSPeter Brune         Q(0,0) = nu;
498d2e16ddcSPeter Brune         /* Fdot[0] = F */
499d2e16ddcSPeter Brune         ierr = VecCopy(XM, Xdot[0]);CHKERRQ(ierr);
500d2e16ddcSPeter Brune         ierr = VecCopy(FM, Fdot[0]);CHKERRQ(ierr);
501d2e16ddcSPeter Brune       } else {
502f109b39eSPeter Brune         ngmres->fnorms[0] = fnorm;
503f109b39eSPeter Brune         nu = fnorm*fnorm;
50419653cdaSPeter Brune         Q(0,0) = nu;
505f109b39eSPeter Brune         /* Fdot[0] = F */
506f109b39eSPeter Brune         ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr);
507f109b39eSPeter Brune         ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr);
508d2e16ddcSPeter Brune       }
50919653cdaSPeter Brune     } else {
51098b3e84cSPeter Brune       /* select the current size of the subspace */
5111e633543SBarry Smith       if (l < ngmres->msize) l++;
51219653cdaSPeter Brune       k_restart++;
51398b3e84cSPeter Brune       /* place the current entry in the list of previous entries */
514d2e16ddcSPeter Brune       if (ngmres->anderson) {
515d2e16ddcSPeter Brune         ierr = VecCopy(FM, Fdot[ivec]);CHKERRQ(ierr);
516d2e16ddcSPeter Brune         ierr = VecCopy(XM, Xdot[ivec]);CHKERRQ(ierr);
517d2e16ddcSPeter Brune         ngmres->fnorms[ivec] = fMnorm;
518d2e16ddcSPeter Brune         if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of FM */
51918aa0c0cSPeter Brune         xi[ivec] = fMnorm*fMnorm;
520d2e16ddcSPeter Brune         for (i = 0; i < l; i++) {
52118aa0c0cSPeter Brune           Q(i, ivec) = xi[i];
52218aa0c0cSPeter Brune           Q(ivec, i) = xi[i];
523d2e16ddcSPeter Brune         }
524d2e16ddcSPeter Brune       } else {
525f109b39eSPeter Brune         ierr = VecCopy(F, Fdot[ivec]);CHKERRQ(ierr);
526f109b39eSPeter Brune         ierr = VecCopy(X, Xdot[ivec]);CHKERRQ(ierr);
527f109b39eSPeter Brune         ngmres->fnorms[ivec] = fnorm;
528d2e16ddcSPeter Brune         if (fminnorm > fnorm) fminnorm = fnorm;  /* the minimum norm is now of FA */
52918aa0c0cSPeter Brune         ierr = VecMDot(F, l, Fdot, xi);CHKERRQ(ierr);
53019653cdaSPeter Brune         for (i = 0; i < l; i++) {
53118aa0c0cSPeter Brune           Q(i, ivec) = xi[i];
53218aa0c0cSPeter Brune           Q(ivec, i) = xi[i];
53319653cdaSPeter Brune         }
53419653cdaSPeter Brune       }
535d2e16ddcSPeter Brune     }
53619653cdaSPeter Brune 
5378409ca45SMatthew G Knepley     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
538087dfb9eSxuemin     snes->iter = k;
539f109b39eSPeter Brune     snes->norm = fnorm;
5408409ca45SMatthew G Knepley     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
5418409ca45SMatthew G Knepley     SNESLogConvHistory(snes, snes->norm, snes->iter);
5428409ca45SMatthew G Knepley     ierr = SNESMonitor(snes, snes->iter, snes->norm);CHKERRQ(ierr);
543d484d688SPeter Brune     ierr = VecNormBegin(Y,NORM_2,&ynorm);CHKERRQ(ierr);
544d484d688SPeter Brune     ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);
545d484d688SPeter Brune     ierr = VecNormEnd(Y,NORM_2,&ynorm);CHKERRQ(ierr);
546d484d688SPeter Brune     ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
547d484d688SPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
548087dfb9eSxuemin     if (snes->reason) PetscFunctionReturn(0);
549a312c225SMatthew G Knepley   }
550a312c225SMatthew G Knepley   snes->reason = SNES_DIVERGED_MAX_IT;
551a312c225SMatthew G Knepley   PetscFunctionReturn(0);
552a312c225SMatthew G Knepley }
553a312c225SMatthew G Knepley 
55413a62661SPeter Brune #undef __FUNCT__
55513a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType"
55613a62661SPeter Brune /*@
55713a62661SPeter Brune     SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES.
55813a62661SPeter Brune 
55913a62661SPeter Brune     Logically Collective on SNES
56013a62661SPeter Brune 
56113a62661SPeter Brune     Input Parameters:
56213a62661SPeter Brune +   snes - the iterative context
56313a62661SPeter Brune -   rtype - restart type
56413a62661SPeter Brune 
56513a62661SPeter Brune     Options Database:
56613a62661SPeter Brune +   -snes_ngmres_restart_type<difference,periodic,none> - set the restart type
5670c777b0cSPeter Brune -   -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic
56813a62661SPeter Brune 
56913a62661SPeter Brune     Level: intermediate
57013a62661SPeter Brune 
57113a62661SPeter Brune     SNESNGMRESRestartTypes:
57213a62661SPeter Brune +   SNES_NGMRES_RESTART_NONE - never restart
57313a62661SPeter Brune .   SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria
57413a62661SPeter Brune -   SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations
57513a62661SPeter Brune 
57613a62661SPeter Brune     Notes:
57713a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
57813a62661SPeter Brune 
57913a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch
58013a62661SPeter Brune @*/
5810adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes, SNESNGMRESRestartType rtype)
5820adebc6cSBarry Smith {
58313a62661SPeter Brune   PetscErrorCode ierr;
584*5fd66863SKarl Rupp 
58513a62661SPeter Brune   PetscFunctionBegin;
58613a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
58713a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr);
58813a62661SPeter Brune   PetscFunctionReturn(0);
58913a62661SPeter Brune }
59013a62661SPeter Brune 
59113a62661SPeter Brune #undef __FUNCT__
59213a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType"
59313a62661SPeter Brune /*@
59413a62661SPeter Brune     SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES.  This determines how the candidate solution and
59513a62661SPeter Brune     combined solution are used to create the next iterate.
59613a62661SPeter Brune 
59713a62661SPeter Brune     Logically Collective on SNES
59813a62661SPeter Brune 
59913a62661SPeter Brune     Input Parameters:
60013a62661SPeter Brune +   snes - the iterative context
60113a62661SPeter Brune -   stype - selection type
60213a62661SPeter Brune 
60313a62661SPeter Brune     Options Database:
60413a62661SPeter Brune .   -snes_ngmres_select_type<difference,none,linesearch>
60513a62661SPeter Brune 
60613a62661SPeter Brune     Level: intermediate
60713a62661SPeter Brune 
60813a62661SPeter Brune     SNESNGMRESSelectTypes:
60913a62661SPeter Brune +   SNES_NGMRES_SELECT_NONE - choose the combined solution all the time
61013a62661SPeter Brune .   SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria
61113a62661SPeter Brune -   SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination
61213a62661SPeter Brune 
61313a62661SPeter Brune     Notes:
61413a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
61513a62661SPeter Brune 
61613a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch
61713a62661SPeter Brune @*/
6180adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes, SNESNGMRESSelectType stype)
6190adebc6cSBarry Smith {
62013a62661SPeter Brune   PetscErrorCode ierr;
621*5fd66863SKarl Rupp 
62213a62661SPeter Brune   PetscFunctionBegin;
62313a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
62413a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr);
62513a62661SPeter Brune   PetscFunctionReturn(0);
62613a62661SPeter Brune }
62713a62661SPeter Brune 
62813a62661SPeter Brune EXTERN_C_BEGIN
62913a62661SPeter Brune #undef __FUNCT__
63013a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES"
6310adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes, SNESNGMRESSelectType stype)
6320adebc6cSBarry Smith {
63313a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES *)snes->data;
634*5fd66863SKarl Rupp 
63513a62661SPeter Brune   PetscFunctionBegin;
63613a62661SPeter Brune   ngmres->select_type = stype;
63713a62661SPeter Brune   PetscFunctionReturn(0);
63813a62661SPeter Brune }
63913a62661SPeter Brune 
64013a62661SPeter Brune #undef __FUNCT__
64113a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES"
6420adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes, SNESNGMRESRestartType rtype)
6430adebc6cSBarry Smith {
64413a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES *)snes->data;
645*5fd66863SKarl Rupp 
64613a62661SPeter Brune   PetscFunctionBegin;
64713a62661SPeter Brune   ngmres->restart_type = rtype;
64813a62661SPeter Brune   PetscFunctionReturn(0);
64913a62661SPeter Brune }
65013a62661SPeter Brune EXTERN_C_END
65113a62661SPeter Brune 
652dfbf837cSBarry Smith /*MC
6531867fe5bSPeter Brune   SNESNGMRES - The Nonlinear Generalized Minimum Residual method.
654a312c225SMatthew G Knepley 
655dfbf837cSBarry Smith    Level: beginner
656dfbf837cSBarry Smith 
6571867fe5bSPeter Brune    Options Database:
65813a62661SPeter Brune +  -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution
65913a62661SPeter Brune +  -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions
66013a62661SPeter Brune .  -snes_ngmres_anderson         - Use Anderson mixing NGMRES variant which combines candidate solutions instead of actual solutions
66113a62661SPeter Brune .  -snes_ngmres_m                - Number of stored previous solutions and residuals
66213a62661SPeter Brune .  -snes_ngmres_restart_it       - Number of iterations the restart conditions hold before restart
66313a62661SPeter Brune .  -snes_ngmres_gammaA           - Residual tolerance for solution select between the candidate and combination
66413a62661SPeter Brune .  -snes_ngmres_gammaC           - Residual tolerance for restart
66513a62661SPeter Brune .  -snes_ngmres_epsilonB         - Difference tolerance between subsequent solutions triggering restart
66613a62661SPeter Brune .  -snes_ngmres_deltaB           - Difference tolerance between residuals triggering restart
66713a62661SPeter Brune .  -snes_ngmres_monitor          - Prints relevant information about the ngmres iteration
66813a62661SPeter Brune .  -snes_linesearch_type <basic,basicnonorms,quadratic,critical> - Line search type used for the default smoother
66913a62661SPeter Brune -  -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type
6701867fe5bSPeter Brune 
6711867fe5bSPeter Brune    Notes:
6721867fe5bSPeter Brune 
6731867fe5bSPeter Brune    The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized
6741867fe5bSPeter Brune    optimization problem at each iteration.
6751867fe5bSPeter Brune 
6761867fe5bSPeter Brune    References:
6771867fe5bSPeter Brune 
678dfbf837cSBarry Smith    "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio,
679dfbf837cSBarry Smith    SIAM Journal on Scientific Computing, 21(5), 2000.
680dfbf837cSBarry Smith 
681dfbf837cSBarry Smith    This is also the same as the algorithm called Anderson acceleration introduced in "D. G. Anderson. Iterative procedures for nonlinear integral equations.
682dfbf837cSBarry Smith    J. Assoc. Comput. Mach., 12:547–560, 1965."
683dfbf837cSBarry Smith 
684dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types)
685dfbf837cSBarry Smith M*/
686a312c225SMatthew G Knepley 
687a312c225SMatthew G Knepley EXTERN_C_BEGIN
688a312c225SMatthew G Knepley #undef __FUNCT__
689a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES"
690a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes)
691a312c225SMatthew G Knepley {
692a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres;
693a312c225SMatthew G Knepley   PetscErrorCode ierr;
694a312c225SMatthew G Knepley 
695a312c225SMatthew G Knepley   PetscFunctionBegin;
696a312c225SMatthew G Knepley   snes->ops->destroy        = SNESDestroy_NGMRES;
697a312c225SMatthew G Knepley   snes->ops->setup          = SNESSetUp_NGMRES;
698a312c225SMatthew G Knepley   snes->ops->setfromoptions = SNESSetFromOptions_NGMRES;
699a312c225SMatthew G Knepley   snes->ops->view           = SNESView_NGMRES;
700a312c225SMatthew G Knepley   snes->ops->solve          = SNESSolve_NGMRES;
701a312c225SMatthew G Knepley   snes->ops->reset          = SNESReset_NGMRES;
702a312c225SMatthew G Knepley 
70342f4f86dSBarry Smith   snes->usespc          = PETSC_TRUE;
7042c155ee1SBarry Smith   snes->usesksp         = PETSC_FALSE;
7052c155ee1SBarry Smith 
706a312c225SMatthew G Knepley   ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr);
707a312c225SMatthew G Knepley   snes->data = (void*) ngmres;
708d2e16ddcSPeter Brune   ngmres->msize = 30;
70919653cdaSPeter Brune 
71088976e71SPeter Brune   if (!snes->tolerancesset) {
7110e444f03SPeter Brune     snes->max_funcs = 30000;
7120e444f03SPeter Brune     snes->max_its   = 10000;
71388976e71SPeter Brune   }
7140e444f03SPeter Brune 
715d2e16ddcSPeter Brune   ngmres->anderson   = PETSC_FALSE;
716d2e16ddcSPeter Brune 
717e7058c64SPeter Brune   ngmres->additive_linesearch = PETSC_NULL;
718e7058c64SPeter Brune 
71928ed4a04SPeter Brune   ngmres->restart_it = 2;
72013a62661SPeter Brune   ngmres->restart_periodic = 30;
721f109b39eSPeter Brune   ngmres->gammaA     = 2.0;
722f109b39eSPeter Brune   ngmres->gammaC     = 2.0;
723cac108bcSPeter Brune   ngmres->deltaB     = 0.9;
724cac108bcSPeter Brune   ngmres->epsilonB   = 0.1;
725e7058c64SPeter Brune 
72613a62661SPeter Brune   ngmres->restart_type   = SNES_NGMRES_RESTART_DIFFERENCE;
72713a62661SPeter Brune   ngmres->select_type    = SNES_NGMRES_SELECT_DIFFERENCE;
72813a62661SPeter Brune 
72913a62661SPeter Brune   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNGMRESSetSelectType_C","SNESNGMRESSetSelectType_NGMRES", SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr);
73013a62661SPeter Brune   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNGMRESSetRestartType_C","SNESNGMRESSetRestartType_NGMRES", SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr);
73113a62661SPeter Brune 
732a312c225SMatthew G Knepley   PetscFunctionReturn(0);
733a312c225SMatthew G Knepley }
734a312c225SMatthew G Knepley EXTERN_C_END
735