xref: /petsc/src/snes/impls/ngmres/snesngmres.c (revision 4f02bc6a7df4e4b03c783003a8e0899ee35fcb05)
113a62661SPeter Brune #include <../src/snes/impls/ngmres/snesngmres.h> /*I "petscsnes.h" I*/
219653cdaSPeter Brune #include <petscblaslapack.h>
3fced5a79SAsbjørn Nilsen Riseth #include <petscdm.h>
4a312c225SMatthew G Knepley 
56a6fc655SJed Brown const char *const SNESNGMRESRestartTypes[] = {"NONE","PERIODIC","DIFFERENCE","SNESNGMRESRestartType","SNES_NGMRES_RESTART_",0};
66a6fc655SJed Brown const char *const SNESNGMRESSelectTypes[] = {"NONE","DIFFERENCE","LINESEARCH","SNESNGMRESSelectType","SNES_NGMRES_SELECT_",0};
713a62661SPeter Brune 
8a312c225SMatthew G Knepley #undef __FUNCT__
9a312c225SMatthew G Knepley #define __FUNCT__ "SNESReset_NGMRES"
10a312c225SMatthew G Knepley PetscErrorCode SNESReset_NGMRES(SNES snes)
11a312c225SMatthew G Knepley {
12a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
13a312c225SMatthew G Knepley   PetscErrorCode ierr;
14a312c225SMatthew G Knepley 
15a312c225SMatthew G Knepley   PetscFunctionBegin;
16f109b39eSPeter Brune   ierr = VecDestroyVecs(ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);
17f109b39eSPeter Brune   ierr = VecDestroyVecs(ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);
18f1c6b773SPeter Brune   ierr = SNESLineSearchDestroy(&ngmres->additive_linesearch);CHKERRQ(ierr);
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
3522d28d08SBarry Smith   ierr = PetscFree(ngmres->rwork);CHKERRQ(ierr);
3619653cdaSPeter Brune #endif
3722d28d08SBarry Smith   ierr = PetscFree(ngmres->work);CHKERRQ(ierr);
3822d28d08SBarry Smith   ierr = PetscFree(snes->data);CHKERRQ(ierr);
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;
50fced5a79SAsbjørn Nilsen Riseth   DM             dm;
51a312c225SMatthew G Knepley 
52a312c225SMatthew G Knepley   PetscFunctionBegin;
5346159c86SPeter Brune   if (snes->pc && snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) {
5446159c86SPeter Brune     SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"SNESNGMRES does not support left preconditioning with unpreconditioned function");
5546159c86SPeter Brune   }
566c67d002SPeter Brune   if (snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_DEFAULT) snes->functype = SNES_FUNCTION_PRECONDITIONED;
57fa0ddf94SBarry Smith   ierr = SNESSetWorkVecs(snes,5);CHKERRQ(ierr);
58fced5a79SAsbjørn Nilsen Riseth 
59fced5a79SAsbjørn Nilsen Riseth   if (!snes->vec_sol) {
60fced5a79SAsbjørn Nilsen Riseth     ierr             = SNESGetDM(snes,&dm);CHKERRQ(ierr);
61fced5a79SAsbjørn Nilsen Riseth     ierr             = DMCreateGlobalVector(dm,&snes->vec_sol);CHKERRQ(ierr);
62fced5a79SAsbjørn Nilsen Riseth   }
63fced5a79SAsbjørn Nilsen Riseth 
6478440776SJed Brown   if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);}
6578440776SJed Brown   if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);}
6678440776SJed Brown   if (!ngmres->setup_called) {
67087dfb9eSxuemin     msize = ngmres->msize;          /* restart size */
6819653cdaSPeter Brune     hsize = msize * msize;
69087dfb9eSxuemin 
7098b3e84cSPeter Brune     /* explicit least squares minimization solve */
71dcca6d9dSJed Brown     ierr = PetscMalloc5(hsize,&ngmres->h, msize,&ngmres->beta, msize,&ngmres->xi, msize,&ngmres->fnorms, hsize,&ngmres->q);CHKERRQ(ierr);
72785e854fSJed Brown     ierr = PetscMalloc1(msize,&ngmres->xnorms);CHKERRQ(ierr);
7319653cdaSPeter Brune     ngmres->nrhs  = 1;
7419653cdaSPeter Brune     ngmres->lda   = msize;
7519653cdaSPeter Brune     ngmres->ldb   = msize;
76785e854fSJed Brown     ierr          = PetscMalloc1(msize,&ngmres->s);CHKERRQ(ierr);
7719653cdaSPeter Brune     ierr          = PetscMemzero(ngmres->h,   hsize*sizeof(PetscScalar));CHKERRQ(ierr);
7819653cdaSPeter Brune     ierr          = PetscMemzero(ngmres->q,   hsize*sizeof(PetscScalar));CHKERRQ(ierr);
7919653cdaSPeter Brune     ierr          = PetscMemzero(ngmres->xi,  msize*sizeof(PetscScalar));CHKERRQ(ierr);
8019653cdaSPeter Brune     ierr          = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr);
8119653cdaSPeter Brune     ngmres->lwork = 12*msize;
8219653cdaSPeter Brune #if PETSC_USE_COMPLEX
83854ce69bSBarry Smith     ierr = PetscMalloc1(ngmres->lwork,&ngmres->rwork);CHKERRQ(ierr);
8419653cdaSPeter Brune #endif
85854ce69bSBarry Smith     ierr = PetscMalloc1(ngmres->lwork,&ngmres->work);CHKERRQ(ierr);
8678440776SJed Brown   }
87e7058c64SPeter Brune 
88e7058c64SPeter Brune   /* linesearch setup */
89e7058c64SPeter Brune   ierr = SNESGetOptionsPrefix(snes,&optionsprefix);CHKERRQ(ierr);
90e7058c64SPeter Brune 
9113a62661SPeter Brune   if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) {
92ce94432eSBarry Smith     ierr = SNESLineSearchCreate(PetscObjectComm((PetscObject)snes),&ngmres->additive_linesearch);CHKERRQ(ierr);
93f1c6b773SPeter Brune     ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch,snes);CHKERRQ(ierr);
941a4f838cSPeter Brune     ierr = SNESLineSearchSetType(ngmres->additive_linesearch,SNESLINESEARCHL2);CHKERRQ(ierr);
95f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,"additive_");CHKERRQ(ierr);
96f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,optionsprefix);CHKERRQ(ierr);
97f1c6b773SPeter Brune     ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr);
98e7058c64SPeter Brune   }
99e7058c64SPeter Brune 
10078440776SJed Brown   ngmres->setup_called = PETSC_TRUE;
101a312c225SMatthew G Knepley   PetscFunctionReturn(0);
102a312c225SMatthew G Knepley }
103a312c225SMatthew G Knepley 
104a312c225SMatthew G Knepley #undef __FUNCT__
105a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES"
1064416b707SBarry Smith PetscErrorCode SNESSetFromOptions_NGMRES(PetscOptionItems *PetscOptionsObject,SNES snes)
107a312c225SMatthew G Knepley {
108a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
109a312c225SMatthew G Knepley   PetscErrorCode ierr;
11094ae4db5SBarry Smith   PetscBool      debug = PETSC_FALSE;
111f1c6b773SPeter Brune   SNESLineSearch linesearch;
1120adebc6cSBarry Smith 
113a312c225SMatthew G Knepley   PetscFunctionBegin;
114e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"SNES NGMRES options");CHKERRQ(ierr);
11513a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes,
1160298fd71SBarry Smith                           (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,NULL);CHKERRQ(ierr);
11713a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes,
1180298fd71SBarry Smith                           (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,NULL);CHKERRQ(ierr);
1190298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_candidate", "Use candidate storage",              "SNES",ngmres->candidate,&ngmres->candidate,NULL);CHKERRQ(ierr);
120077c4231SPeter Brune   ierr = PetscOptionsBool("-snes_ngmres_approxfunc","Linearly approximate the function", "SNES",ngmres->approxfunc,&ngmres->approxfunc,NULL);CHKERRQ(ierr);
1210298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_m",          "Number of directions",               "SNES",ngmres->msize,&ngmres->msize,NULL);CHKERRQ(ierr);
1220298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_restart",    "Iterations before forced restart",   "SNES",ngmres->restart_periodic,&ngmres->restart_periodic,NULL);CHKERRQ(ierr);
1230298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_restart_it", "Tolerance iterations before restart","SNES",ngmres->restart_it,&ngmres->restart_it,NULL);CHKERRQ(ierr);
1240298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_monitor",   "Monitor actions of NGMRES",          "SNES",ngmres->monitor ? PETSC_TRUE : PETSC_FALSE,&debug,NULL);CHKERRQ(ierr);
125dfbf837cSBarry Smith   if (debug) {
126ce94432eSBarry Smith     ngmres->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr);
127dfbf837cSBarry Smith   }
1280298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_gammaA",    "Residual selection constant",   "SNES",ngmres->gammaA,&ngmres->gammaA,NULL);CHKERRQ(ierr);
1290298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_gammaC",    "Residual restart constant",     "SNES",ngmres->gammaC,&ngmres->gammaC,NULL);CHKERRQ(ierr);
1300298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_epsilonB",  "Difference selection constant", "SNES",ngmres->epsilonB,&ngmres->epsilonB,NULL);CHKERRQ(ierr);
1310298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_deltaB",    "Difference residual selection constant", "SNES",ngmres->deltaB,&ngmres->deltaB,NULL);CHKERRQ(ierr);
1320298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions",  "SNES",ngmres->singlereduction,&ngmres->singlereduction,NULL);CHKERRQ(ierr);
13323b3e82cSAsbjørn Nilsen Riseth   ierr = PetscOptionsBool("-snes_ngmres_restart_fm_rise", "Restart on F_M residual rise",  "SNESNGMRESSetRestartFmRise",ngmres->restart_fm_rise,&ngmres->restart_fm_rise,NULL);CHKERRQ(ierr);
134a312c225SMatthew G Knepley   ierr = PetscOptionsTail();CHKERRQ(ierr);
1356a7cf640SPeter Brune   if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA;
1369e764e56SPeter Brune 
1379e764e56SPeter Brune   /* set the default type of the line search if the user hasn't already. */
1389e764e56SPeter Brune   if (!snes->linesearch) {
1397601faf0SJed Brown     ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr);
1401a4f838cSPeter Brune     ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr);
1419e764e56SPeter Brune   }
142a312c225SMatthew G Knepley   PetscFunctionReturn(0);
143a312c225SMatthew G Knepley }
144a312c225SMatthew G Knepley 
145a312c225SMatthew G Knepley #undef __FUNCT__
146a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES"
147a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes,PetscViewer viewer)
148a312c225SMatthew G Knepley {
149a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
150a312c225SMatthew G Knepley   PetscBool      iascii;
151a312c225SMatthew G Knepley   PetscErrorCode ierr;
152a312c225SMatthew G Knepley 
153a312c225SMatthew G Knepley   PetscFunctionBegin;
154251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject) viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
155a312c225SMatthew G Knepley   if (iascii) {
156f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr);
157f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Residual selection: gammaA=%1.0e, gammaC=%1.0e\n",ngmres->gammaA,ngmres->gammaC);CHKERRQ(ierr);
158f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n",ngmres->epsilonB,ngmres->deltaB);CHKERRQ(ierr);
15923b3e82cSAsbjørn Nilsen Riseth     ierr = PetscViewerASCIIPrintf(viewer,"  Restart on F_M residual increase: %s\n",ngmres->restart_fm_rise?"TRUE":"FALSE");CHKERRQ(ierr);
160a312c225SMatthew G Knepley   }
161a312c225SMatthew G Knepley   PetscFunctionReturn(0);
162a312c225SMatthew G Knepley }
163a312c225SMatthew G Knepley 
164a312c225SMatthew G Knepley #undef __FUNCT__
165a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES"
166a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes)
167a312c225SMatthew G Knepley {
168087dfb9eSxuemin   SNES_NGMRES          *ngmres = (SNES_NGMRES*) snes->data;
16998b3e84cSPeter Brune   /* present solution, residual, and preconditioned residual */
1709f425c49SPeter Brune   Vec                  X,F,B,D,Y;
171f109b39eSPeter Brune 
172f109b39eSPeter Brune   /* candidate linear combination answers */
173ddd40ce5SPeter Brune   Vec                  XA,FA,XM,FM;
17419653cdaSPeter Brune 
17598b3e84cSPeter Brune   /* coefficients and RHS to the minimization problem */
17618aa0c0cSPeter Brune   PetscReal            fnorm,fMnorm,fAnorm;
177b3c6a99cSPeter Brune   PetscReal            xnorm,xMnorm,xAnorm;
178b3c6a99cSPeter Brune   PetscReal            ynorm,yMnorm,yAnorm;
17938774f0aSPeter Brune   PetscInt             k,k_restart,l,ivec,restart_count = 0;
18019653cdaSPeter Brune 
18198b3e84cSPeter Brune   /* solution selection data */
18238774f0aSPeter Brune   PetscBool            selectRestart;
18338774f0aSPeter Brune   PetscReal            dnorm,dminnorm = 0.0;
184b3c6a99cSPeter Brune   PetscReal            fminnorm;
18519653cdaSPeter Brune 
1861e633543SBarry Smith   SNESConvergedReason  reason;
187422a814eSBarry Smith   SNESLineSearchReason lssucceed;
188a312c225SMatthew G Knepley   PetscErrorCode       ierr;
189a312c225SMatthew G Knepley 
190a312c225SMatthew G Knepley   PetscFunctionBegin;
1916c4ed002SBarry Smith   if (snes->xl || snes->xu || snes->ops->computevariablebounds) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name);
192c579b300SPatrick Farrell 
193fffbeea8SBarry Smith   ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr);
19498b3e84cSPeter Brune   /* variable initialization */
195a312c225SMatthew G Knepley   snes->reason = SNES_CONVERGED_ITERATING;
196f109b39eSPeter Brune   X            = snes->vec_sol;
197f109b39eSPeter Brune   F            = snes->vec_func;
198f109b39eSPeter Brune   B            = snes->vec_rhs;
199f109b39eSPeter Brune   XA           = snes->vec_sol_update;
200f109b39eSPeter Brune   FA           = snes->work[0];
201f109b39eSPeter Brune   D            = snes->work[1];
202f109b39eSPeter Brune 
203f109b39eSPeter Brune   /* work for the line search */
204f109b39eSPeter Brune   Y  = snes->work[2];
2059f425c49SPeter Brune   XM = snes->work[3];
2069f425c49SPeter Brune   FM = snes->work[4];
207a312c225SMatthew G Knepley 
208e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
209a312c225SMatthew G Knepley   snes->iter = 0;
210a312c225SMatthew G Knepley   snes->norm = 0.;
211e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
21219653cdaSPeter Brune 
21398b3e84cSPeter Brune   /* initialization */
21419653cdaSPeter Brune 
2153a2ae377SPeter Brune   if (snes->pc && snes->pcside == PC_LEFT) {
216be95d8f1SBarry Smith     ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr);
2173a2ae377SPeter Brune     ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
2183a2ae377SPeter Brune     if (reason < 0  && reason != SNES_DIVERGED_MAX_IT) {
2193a2ae377SPeter Brune       snes->reason = SNES_DIVERGED_INNER;
2203a2ae377SPeter Brune       PetscFunctionReturn(0);
2213a2ae377SPeter Brune     }
2223a2ae377SPeter Brune     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
2233a2ae377SPeter Brune   } else {
224e4ed7901SPeter Brune     if (!snes->vec_func_init_set) {
225f109b39eSPeter Brune       ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
2261aa26658SKarl Rupp     } else snes->vec_func_init_set = PETSC_FALSE;
227c1c75074SPeter Brune 
228f109b39eSPeter Brune     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
229422a814eSBarry Smith     SNESCheckFunctionNorm(snes,fnorm);
2303a2ae377SPeter Brune   }
231e4ed7901SPeter Brune   fminnorm = fnorm;
23219653cdaSPeter Brune 
233e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
234f109b39eSPeter Brune   snes->norm = fnorm;
235e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
236a71f0d7dSBarry Smith   ierr       = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr);
237f109b39eSPeter Brune   ierr       = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
238f109b39eSPeter Brune   ierr       = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
239a312c225SMatthew G Knepley   if (snes->reason) PetscFunctionReturn(0);
240b3c6a99cSPeter Brune   SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fnorm,X);
241a312c225SMatthew G Knepley 
24219653cdaSPeter Brune   k_restart = 1;
24319653cdaSPeter Brune   l         = 1;
244b3c6a99cSPeter Brune   ivec      = 0;
24509c08436SPeter Brune   for (k=1; k < snes->max_its+1; k++) {
24698b3e84cSPeter Brune     /* Computation of x^M */
247c40d0f55SPeter Brune     if (snes->pc && snes->pcside == PC_RIGHT) {
2489f425c49SPeter Brune       ierr = VecCopy(X,XM);CHKERRQ(ierr);
249e4ed7901SPeter Brune       ierr = SNESSetInitialFunction(snes->pc,F);CHKERRQ(ierr);
25063e7833aSPeter Brune 
25163e7833aSPeter Brune       ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr);
2529f425c49SPeter Brune       ierr = SNESSolve(snes->pc,B,XM);CHKERRQ(ierr);
25363e7833aSPeter Brune       ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr);
25463e7833aSPeter Brune 
2558cc86e31SPeter Brune       ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
2568cc86e31SPeter Brune       if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
2578cc86e31SPeter Brune         snes->reason = SNES_DIVERGED_INNER;
2588cc86e31SPeter Brune         PetscFunctionReturn(0);
2598cc86e31SPeter Brune       }
260be95d8f1SBarry Smith       ierr = SNESGetNPCFunction(snes,FM,&fMnorm);CHKERRQ(ierr);
2618cc86e31SPeter Brune     } else {
262f109b39eSPeter Brune       /* no preconditioner -- just take gradient descent with line search */
263f109b39eSPeter Brune       ierr = VecCopy(F,Y);CHKERRQ(ierr);
264e7058c64SPeter Brune       ierr = VecCopy(F,FM);CHKERRQ(ierr);
265e7058c64SPeter Brune       ierr = VecCopy(X,XM);CHKERRQ(ierr);
2661aa26658SKarl Rupp 
267e7058c64SPeter Brune       fMnorm = fnorm;
2681aa26658SKarl Rupp 
269f1c6b773SPeter Brune       ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr);
270422a814eSBarry Smith       ierr = SNESLineSearchGetReason(snes->linesearch,&lssucceed);CHKERRQ(ierr);
271422a814eSBarry Smith       if (lssucceed) {
272f109b39eSPeter Brune         if (++snes->numFailures >= snes->maxFailures) {
273f109b39eSPeter Brune           snes->reason = SNES_DIVERGED_LINE_SEARCH;
274f109b39eSPeter Brune           PetscFunctionReturn(0);
275f109b39eSPeter Brune         }
276f109b39eSPeter Brune       }
2776634f59bSPeter Brune     }
27823b3e82cSAsbjørn Nilsen Riseth 
279b3c6a99cSPeter Brune     ierr = SNESNGMRESFormCombinedSolution_Private(snes,ivec,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr);
28098b3e84cSPeter Brune     /* r = F(x) */
2819f425c49SPeter Brune     if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of F^M */
28219653cdaSPeter Brune 
2839f425c49SPeter Brune     /* differences for selection and restart */
28413a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) {
285b3c6a99cSPeter Brune       ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr);
28613a62661SPeter Brune     } else {
287b3c6a99cSPeter Brune       ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,NULL,NULL,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr);
28813a62661SPeter Brune     }
289422a814eSBarry Smith     SNESCheckFunctionNorm(snes,fnorm);
2901aa26658SKarl Rupp 
2919f425c49SPeter Brune     /* combination (additive) or selection (multiplicative) of the N-GMRES solution */
292b3c6a99cSPeter Brune     ierr          = SNESNGMRESSelect_Private(snes,k_restart,XM,FM,xMnorm,fMnorm,yMnorm,XA,FA,xAnorm,fAnorm,yAnorm,dnorm,fminnorm,dminnorm,X,F,Y,&xnorm,&fnorm,&ynorm);CHKERRQ(ierr);
29319653cdaSPeter Brune     selectRestart = PETSC_FALSE;
29423b3e82cSAsbjørn Nilsen Riseth 
29513a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) {
29623b3e82cSAsbjørn Nilsen Riseth       ierr = SNESNGMRESSelectRestart_Private(snes,l,fMnorm,fAnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr);
29723b3e82cSAsbjørn Nilsen Riseth 
29828ed4a04SPeter Brune       /* if the restart conditions persist for more than restart_it iterations, restart. */
2991aa26658SKarl Rupp       if (selectRestart) restart_count++;
3001aa26658SKarl Rupp       else restart_count = 0;
30113a62661SPeter Brune     } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) {
30213a62661SPeter Brune       if (k_restart > ngmres->restart_periodic) {
30313a62661SPeter Brune         if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr);
30413a62661SPeter Brune         restart_count = ngmres->restart_it;
30513a62661SPeter Brune       }
30613a62661SPeter Brune     }
30723b3e82cSAsbjørn Nilsen Riseth 
308b3c6a99cSPeter Brune     ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */
30923b3e82cSAsbjørn Nilsen Riseth 
31028ed4a04SPeter Brune     /* restart after restart conditions have persisted for a fixed number of iterations */
31128ed4a04SPeter Brune     if (restart_count >= ngmres->restart_it) {
312dfbf837cSBarry Smith       if (ngmres->monitor) {
313dfbf837cSBarry Smith         ierr = PetscViewerASCIIPrintf(ngmres->monitor,"Restarted at iteration %d\n",k_restart);CHKERRQ(ierr);
314dfbf837cSBarry Smith       }
31528ed4a04SPeter Brune       restart_count = 0;
31619653cdaSPeter Brune       k_restart     = 1;
31719653cdaSPeter Brune       l             = 1;
318b3c6a99cSPeter Brune       ivec          = 0;
31998b3e84cSPeter Brune       /* q_{00} = nu */
320fa8c639aSPeter Brune       ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,FM,fMnorm,XM);CHKERRQ(ierr);
321d2e16ddcSPeter Brune     } else {
32298b3e84cSPeter Brune       /* select the current size of the subspace */
3231e633543SBarry Smith       if (l < ngmres->msize) l++;
32419653cdaSPeter Brune       k_restart++;
32598b3e84cSPeter Brune       /* place the current entry in the list of previous entries */
32638774f0aSPeter Brune       if (ngmres->candidate) {
32738774f0aSPeter Brune         if (fminnorm > fMnorm) fminnorm = fMnorm;
328fa8c639aSPeter Brune         ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fMnorm,XM);CHKERRQ(ierr);
329d2e16ddcSPeter Brune       } else {
33038774f0aSPeter Brune         if (fminnorm > fnorm) fminnorm = fnorm;
331fa8c639aSPeter Brune         ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,F,fnorm,X);CHKERRQ(ierr);
33219653cdaSPeter Brune       }
333d2e16ddcSPeter Brune     }
33419653cdaSPeter Brune 
335e04113cfSBarry Smith     ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
336087dfb9eSxuemin     snes->iter = k;
337f109b39eSPeter Brune     snes->norm = fnorm;
338e04113cfSBarry Smith     ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
339a71f0d7dSBarry Smith     ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr);
3408409ca45SMatthew G Knepley     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
341b3c6a99cSPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,0,0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
342087dfb9eSxuemin     if (snes->reason) PetscFunctionReturn(0);
343a312c225SMatthew G Knepley   }
344a312c225SMatthew G Knepley   snes->reason = SNES_DIVERGED_MAX_IT;
345a312c225SMatthew G Knepley   PetscFunctionReturn(0);
346a312c225SMatthew G Knepley }
347a312c225SMatthew G Knepley 
34813a62661SPeter Brune #undef __FUNCT__
34923b3e82cSAsbjørn Nilsen Riseth #define __FUNCT__ "SNESNGMRESSetRestartFmRise"
35023b3e82cSAsbjørn Nilsen Riseth /*@
35123b3e82cSAsbjørn Nilsen Riseth  SNESNGMRESSetRestartFmRise - Increase the restart count if the step x_M increases the residual F_M
35223b3e82cSAsbjørn Nilsen Riseth 
35323b3e82cSAsbjørn Nilsen Riseth   Input Parameters:
35423b3e82cSAsbjørn Nilsen Riseth   +  snes - the SNES context.
35523b3e82cSAsbjørn Nilsen Riseth   -  flg  - boolean value deciding whether to use the option or not
35623b3e82cSAsbjørn Nilsen Riseth 
35723b3e82cSAsbjørn Nilsen Riseth   Options Database:
35823b3e82cSAsbjørn Nilsen Riseth   + -snes_ngmres_restart_fm_rise - Increase the restart count if the step x_M increases the residual F_M
35923b3e82cSAsbjørn Nilsen Riseth 
36023b3e82cSAsbjørn Nilsen Riseth   Level: intermediate
36123b3e82cSAsbjørn Nilsen Riseth 
36223b3e82cSAsbjørn Nilsen Riseth   Notes:
36323b3e82cSAsbjørn Nilsen Riseth   If the proposed step x_M increases the residual F_M, it might be trying to get out of a stagnation area.
36423b3e82cSAsbjørn Nilsen Riseth   To help the solver do that, reset the Krylov subspace whenever F_M increases.
36523b3e82cSAsbjørn Nilsen Riseth 
36623b3e82cSAsbjørn Nilsen Riseth   This option must be used with SNES_NGMRES_RESTART_DIFFERENCE
36723b3e82cSAsbjørn Nilsen Riseth 
36823b3e82cSAsbjørn Nilsen Riseth   The default is FALSE.
36923b3e82cSAsbjørn Nilsen Riseth   .seealso: SNES_NGMRES_RESTART_DIFFERENCE
37023b3e82cSAsbjørn Nilsen Riseth   @*/
37123b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESSetRestartFmRise(SNES snes,PetscBool flg)
37223b3e82cSAsbjørn Nilsen Riseth {
37323b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode (*f)(SNES,PetscBool);
37423b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode ierr;
37523b3e82cSAsbjørn Nilsen Riseth 
37623b3e82cSAsbjørn Nilsen Riseth     PetscFunctionBegin;
37723b3e82cSAsbjørn Nilsen Riseth     ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNGMRESSetRestartFmRise_C",&f);CHKERRQ(ierr);
37823b3e82cSAsbjørn Nilsen Riseth     if (f) {ierr = (f)(snes,flg);CHKERRQ(ierr);}
37923b3e82cSAsbjørn Nilsen Riseth     PetscFunctionReturn(0);
38023b3e82cSAsbjørn Nilsen Riseth }
38123b3e82cSAsbjørn Nilsen Riseth 
38223b3e82cSAsbjørn Nilsen Riseth #undef __FUNCT__
38323b3e82cSAsbjørn Nilsen Riseth #define __FUNCT__ "SNESNGMRESSetRestartFmRise_NGMRES"
38423b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESSetRestartFmRise_NGMRES(SNES snes,PetscBool flg)
38523b3e82cSAsbjørn Nilsen Riseth {
38623b3e82cSAsbjørn Nilsen Riseth   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
38723b3e82cSAsbjørn Nilsen Riseth 
38823b3e82cSAsbjørn Nilsen Riseth   PetscFunctionBegin;
38923b3e82cSAsbjørn Nilsen Riseth   ngmres->restart_fm_rise = flg;
39023b3e82cSAsbjørn Nilsen Riseth   PetscFunctionReturn(0);
39123b3e82cSAsbjørn Nilsen Riseth }
39223b3e82cSAsbjørn Nilsen Riseth 
39323b3e82cSAsbjørn Nilsen Riseth #undef __FUNCT__
39423b3e82cSAsbjørn Nilsen Riseth #define __FUNCT__ "SNESNGMRESGetRestartFmRise"
39523b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESGetRestartFmRise(SNES snes,PetscBool *flg)
39623b3e82cSAsbjørn Nilsen Riseth {
39723b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode (*f)(SNES,PetscBool*);
39823b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode ierr;
39923b3e82cSAsbjørn Nilsen Riseth 
40023b3e82cSAsbjørn Nilsen Riseth     PetscFunctionBegin;
40123b3e82cSAsbjørn Nilsen Riseth     ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNGMRESGetRestartFmRise_C",&f);CHKERRQ(ierr);
40223b3e82cSAsbjørn Nilsen Riseth     if (f) {ierr = (f)(snes,flg);CHKERRQ(ierr);}
40323b3e82cSAsbjørn Nilsen Riseth     PetscFunctionReturn(0);
40423b3e82cSAsbjørn Nilsen Riseth }
40523b3e82cSAsbjørn Nilsen Riseth 
40623b3e82cSAsbjørn Nilsen Riseth #undef __FUNCT__
40723b3e82cSAsbjørn Nilsen Riseth #define __FUNCT__ "SNESNGMRESGetRestartFmRise_NGMRES"
40823b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESGetRestartFmRise_NGMRES(SNES snes,PetscBool *flg)
40923b3e82cSAsbjørn Nilsen Riseth {
41023b3e82cSAsbjørn Nilsen Riseth   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
41123b3e82cSAsbjørn Nilsen Riseth 
41223b3e82cSAsbjørn Nilsen Riseth   PetscFunctionBegin;
41323b3e82cSAsbjørn Nilsen Riseth   *flg = ngmres->restart_fm_rise;
41423b3e82cSAsbjørn Nilsen Riseth   PetscFunctionReturn(0);
41523b3e82cSAsbjørn Nilsen Riseth }
41623b3e82cSAsbjørn Nilsen Riseth 
41723b3e82cSAsbjørn Nilsen Riseth 
41823b3e82cSAsbjørn Nilsen Riseth #undef __FUNCT__
41913a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType"
42013a62661SPeter Brune /*@
42113a62661SPeter Brune     SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES.
42213a62661SPeter Brune 
42313a62661SPeter Brune     Logically Collective on SNES
42413a62661SPeter Brune 
42513a62661SPeter Brune     Input Parameters:
42613a62661SPeter Brune +   snes - the iterative context
42713a62661SPeter Brune -   rtype - restart type
42813a62661SPeter Brune 
42913a62661SPeter Brune     Options Database:
43013a62661SPeter Brune +   -snes_ngmres_restart_type<difference,periodic,none> - set the restart type
4310c777b0cSPeter Brune -   -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic
43213a62661SPeter Brune 
43313a62661SPeter Brune     Level: intermediate
43413a62661SPeter Brune 
43513a62661SPeter Brune     SNESNGMRESRestartTypes:
43613a62661SPeter Brune +   SNES_NGMRES_RESTART_NONE - never restart
43713a62661SPeter Brune .   SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria
43813a62661SPeter Brune -   SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations
43913a62661SPeter Brune 
44013a62661SPeter Brune     Notes:
44113a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
44213a62661SPeter Brune 
44313a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch
44413a62661SPeter Brune @*/
4450adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes,SNESNGMRESRestartType rtype)
4460adebc6cSBarry Smith {
44713a62661SPeter Brune   PetscErrorCode ierr;
4485fd66863SKarl Rupp 
44913a62661SPeter Brune   PetscFunctionBegin;
45013a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
45113a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr);
45213a62661SPeter Brune   PetscFunctionReturn(0);
45313a62661SPeter Brune }
45413a62661SPeter Brune 
45513a62661SPeter Brune #undef __FUNCT__
45613a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType"
45713a62661SPeter Brune /*@
45813a62661SPeter Brune     SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES.  This determines how the candidate solution and
45913a62661SPeter Brune     combined solution are used to create the next iterate.
46013a62661SPeter Brune 
46113a62661SPeter Brune     Logically Collective on SNES
46213a62661SPeter Brune 
46313a62661SPeter Brune     Input Parameters:
46413a62661SPeter Brune +   snes - the iterative context
46513a62661SPeter Brune -   stype - selection type
46613a62661SPeter Brune 
46713a62661SPeter Brune     Options Database:
46813a62661SPeter Brune .   -snes_ngmres_select_type<difference,none,linesearch>
46913a62661SPeter Brune 
47013a62661SPeter Brune     Level: intermediate
47113a62661SPeter Brune 
47213a62661SPeter Brune     SNESNGMRESSelectTypes:
47313a62661SPeter Brune +   SNES_NGMRES_SELECT_NONE - choose the combined solution all the time
47413a62661SPeter Brune .   SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria
47513a62661SPeter Brune -   SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination
47613a62661SPeter Brune 
47713a62661SPeter Brune     Notes:
47813a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
47913a62661SPeter Brune 
48013a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch
48113a62661SPeter Brune @*/
4820adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes,SNESNGMRESSelectType stype)
4830adebc6cSBarry Smith {
48413a62661SPeter Brune   PetscErrorCode ierr;
4855fd66863SKarl Rupp 
48613a62661SPeter Brune   PetscFunctionBegin;
48713a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
48813a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr);
48913a62661SPeter Brune   PetscFunctionReturn(0);
49013a62661SPeter Brune }
49113a62661SPeter Brune 
49213a62661SPeter Brune #undef __FUNCT__
49313a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES"
4940adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes,SNESNGMRESSelectType stype)
4950adebc6cSBarry Smith {
49613a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
4975fd66863SKarl Rupp 
49813a62661SPeter Brune   PetscFunctionBegin;
49913a62661SPeter Brune   ngmres->select_type = stype;
50013a62661SPeter Brune   PetscFunctionReturn(0);
50113a62661SPeter Brune }
50213a62661SPeter Brune 
50313a62661SPeter Brune #undef __FUNCT__
50413a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES"
5050adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes,SNESNGMRESRestartType rtype)
5060adebc6cSBarry Smith {
50713a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
5085fd66863SKarl Rupp 
50913a62661SPeter Brune   PetscFunctionBegin;
51013a62661SPeter Brune   ngmres->restart_type = rtype;
51113a62661SPeter Brune   PetscFunctionReturn(0);
51213a62661SPeter Brune }
51313a62661SPeter Brune 
514dfbf837cSBarry Smith /*MC
5151867fe5bSPeter Brune   SNESNGMRES - The Nonlinear Generalized Minimum Residual method.
516a312c225SMatthew G Knepley 
517dfbf837cSBarry Smith    Level: beginner
518dfbf837cSBarry Smith 
5191867fe5bSPeter Brune    Options Database:
52013a62661SPeter Brune +  -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution
52138774f0aSPeter Brune .  -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions
52238774f0aSPeter Brune .  -snes_ngmres_candidate        - Use NGMRES variant which combines candidate solutions instead of actual solutions
52313a62661SPeter Brune .  -snes_ngmres_m                - Number of stored previous solutions and residuals
52413a62661SPeter Brune .  -snes_ngmres_restart_it       - Number of iterations the restart conditions hold before restart
52513a62661SPeter Brune .  -snes_ngmres_gammaA           - Residual tolerance for solution select between the candidate and combination
52613a62661SPeter Brune .  -snes_ngmres_gammaC           - Residual tolerance for restart
52713a62661SPeter Brune .  -snes_ngmres_epsilonB         - Difference tolerance between subsequent solutions triggering restart
52813a62661SPeter Brune .  -snes_ngmres_deltaB           - Difference tolerance between residuals triggering restart
52923b3e82cSAsbjørn Nilsen Riseth .  -snes_ngmres_restart_fm_rise  - Restart on residual rise from x_M step
53013a62661SPeter Brune .  -snes_ngmres_monitor          - Prints relevant information about the ngmres iteration
5315c3e6ab7SPeter Brune .  -snes_linesearch_type <basic,l2,cp> - Line search type used for the default smoother
53213a62661SPeter Brune -  -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type
5331867fe5bSPeter Brune 
5341867fe5bSPeter Brune    Notes:
5351867fe5bSPeter Brune 
5361867fe5bSPeter Brune    The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized
5371867fe5bSPeter Brune    optimization problem at each iteration.
5381867fe5bSPeter Brune 
539*4f02bc6aSBarry Smith    Very similar to the SNESANDERSON algorithm.
540*4f02bc6aSBarry Smith 
5411867fe5bSPeter Brune    References:
5421867fe5bSPeter Brune 
543*4f02bc6aSBarry Smith    C. W. Oosterlee and T. Washio, "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows",
544dfbf837cSBarry Smith    SIAM Journal on Scientific Computing, 21(5), 2000.
545dfbf837cSBarry Smith 
546*4f02bc6aSBarry Smith    Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers",
547*4f02bc6aSBarry Smith    SIAM Review, 57(4), 2015
548*4f02bc6aSBarry Smith 
549*4f02bc6aSBarry Smith 
550dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types)
551dfbf837cSBarry Smith M*/
552a312c225SMatthew G Knepley 
553a312c225SMatthew G Knepley #undef __FUNCT__
554a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES"
5558cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NGMRES(SNES snes)
556a312c225SMatthew G Knepley {
557a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres;
558a312c225SMatthew G Knepley   PetscErrorCode ierr;
559a312c225SMatthew G Knepley 
560a312c225SMatthew G Knepley   PetscFunctionBegin;
561a312c225SMatthew G Knepley   snes->ops->destroy        = SNESDestroy_NGMRES;
562a312c225SMatthew G Knepley   snes->ops->setup          = SNESSetUp_NGMRES;
563a312c225SMatthew G Knepley   snes->ops->setfromoptions = SNESSetFromOptions_NGMRES;
564a312c225SMatthew G Knepley   snes->ops->view           = SNESView_NGMRES;
565a312c225SMatthew G Knepley   snes->ops->solve          = SNESSolve_NGMRES;
566a312c225SMatthew G Knepley   snes->ops->reset          = SNESReset_NGMRES;
567a312c225SMatthew G Knepley 
56842f4f86dSBarry Smith   snes->usespc   = PETSC_TRUE;
5692c155ee1SBarry Smith   snes->usesksp  = PETSC_FALSE;
57046159c86SPeter Brune   snes->pcside   = PC_RIGHT;
5712c155ee1SBarry Smith 
572b00a9115SJed Brown   ierr          = PetscNewLog(snes,&ngmres);CHKERRQ(ierr);
573a312c225SMatthew G Knepley   snes->data    = (void*) ngmres;
574d2e16ddcSPeter Brune   ngmres->msize = 30;
57519653cdaSPeter Brune 
57688976e71SPeter Brune   if (!snes->tolerancesset) {
5770e444f03SPeter Brune     snes->max_funcs = 30000;
5780e444f03SPeter Brune     snes->max_its   = 10000;
57988976e71SPeter Brune   }
5800e444f03SPeter Brune 
58138774f0aSPeter Brune   ngmres->candidate = PETSC_FALSE;
582d2e16ddcSPeter Brune 
5830298fd71SBarry Smith   ngmres->additive_linesearch = NULL;
584077c4231SPeter Brune   ngmres->approxfunc          = PETSC_FALSE;
58528ed4a04SPeter Brune   ngmres->restart_it          = 2;
58613a62661SPeter Brune   ngmres->restart_periodic    = 30;
587f109b39eSPeter Brune   ngmres->gammaA              = 2.0;
588f109b39eSPeter Brune   ngmres->gammaC              = 2.0;
589cac108bcSPeter Brune   ngmres->deltaB              = 0.9;
590cac108bcSPeter Brune   ngmres->epsilonB            = 0.1;
59123b3e82cSAsbjørn Nilsen Riseth   ngmres->restart_fm_rise     = PETSC_FALSE;
592e7058c64SPeter Brune 
59313a62661SPeter Brune   ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE;
59413a62661SPeter Brune   ngmres->select_type  = SNES_NGMRES_SELECT_DIFFERENCE;
59513a62661SPeter Brune 
596bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetSelectType_C",SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr);
597bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartType_C",SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr);
59823b3e82cSAsbjørn Nilsen Riseth   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartFmRise_C",SNESNGMRESSetRestartFmRise_NGMRES);CHKERRQ(ierr);
59923b3e82cSAsbjørn Nilsen Riseth   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESGetRestartFmRise_C",SNESNGMRESGetRestartFmRise_NGMRES);CHKERRQ(ierr);
600a312c225SMatthew G Knepley   PetscFunctionReturn(0);
601a312c225SMatthew G Knepley }
602