xref: /petsc/src/snes/impls/ngmres/snesngmres.c (revision efd4aadf157bf1ba2d80c2be092fcf4247860003)
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 PetscErrorCode SNESReset_NGMRES(SNES snes)
9a312c225SMatthew G Knepley {
10a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
11a312c225SMatthew G Knepley   PetscErrorCode ierr;
12a312c225SMatthew G Knepley 
13a312c225SMatthew G Knepley   PetscFunctionBegin;
14f109b39eSPeter Brune   ierr = VecDestroyVecs(ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);
15f109b39eSPeter Brune   ierr = VecDestroyVecs(ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);
16f1c6b773SPeter Brune   ierr = SNESLineSearchDestroy(&ngmres->additive_linesearch);CHKERRQ(ierr);
17a312c225SMatthew G Knepley   PetscFunctionReturn(0);
18a312c225SMatthew G Knepley }
19a312c225SMatthew G Knepley 
20a312c225SMatthew G Knepley PetscErrorCode SNESDestroy_NGMRES(SNES snes)
21a312c225SMatthew G Knepley {
22a312c225SMatthew G Knepley   PetscErrorCode ierr;
2378440776SJed Brown   SNES_NGMRES    *ngmres = (SNES_NGMRES*)snes->data;
24a312c225SMatthew G Knepley 
25a312c225SMatthew G Knepley   PetscFunctionBegin;
26a312c225SMatthew G Knepley   ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr);
27f109b39eSPeter Brune   ierr = PetscFree5(ngmres->h,ngmres->beta,ngmres->xi,ngmres->fnorms,ngmres->q);CHKERRQ(ierr);
2819653cdaSPeter Brune   ierr = PetscFree(ngmres->s);CHKERRQ(ierr);
2918aa0c0cSPeter Brune   ierr = PetscFree(ngmres->xnorms);CHKERRQ(ierr);
30dd63322aSSatish Balay #if defined(PETSC_USE_COMPLEX)
3122d28d08SBarry Smith   ierr = PetscFree(ngmres->rwork);CHKERRQ(ierr);
3219653cdaSPeter Brune #endif
3322d28d08SBarry Smith   ierr = PetscFree(ngmres->work);CHKERRQ(ierr);
3422d28d08SBarry Smith   ierr = PetscFree(snes->data);CHKERRQ(ierr);
35a312c225SMatthew G Knepley   PetscFunctionReturn(0);
36a312c225SMatthew G Knepley }
37a312c225SMatthew G Knepley 
38a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes)
39a312c225SMatthew G Knepley {
40a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
41e7058c64SPeter Brune   const char     *optionsprefix;
4219653cdaSPeter Brune   PetscInt       msize,hsize;
43a312c225SMatthew G Knepley   PetscErrorCode ierr;
44fced5a79SAsbjørn Nilsen Riseth   DM             dm;
45a312c225SMatthew G Knepley 
46a312c225SMatthew G Knepley   PetscFunctionBegin;
47*efd4aadfSBarry Smith   if (snes->npc && snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) {
4846159c86SPeter Brune     SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"SNESNGMRES does not support left preconditioning with unpreconditioned function");
4946159c86SPeter Brune   }
50*efd4aadfSBarry Smith   if (snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_DEFAULT) snes->functype = SNES_FUNCTION_PRECONDITIONED;
51fa0ddf94SBarry Smith   ierr = SNESSetWorkVecs(snes,5);CHKERRQ(ierr);
52fced5a79SAsbjørn Nilsen Riseth 
53fced5a79SAsbjørn Nilsen Riseth   if (!snes->vec_sol) {
54fced5a79SAsbjørn Nilsen Riseth     ierr             = SNESGetDM(snes,&dm);CHKERRQ(ierr);
55fced5a79SAsbjørn Nilsen Riseth     ierr             = DMCreateGlobalVector(dm,&snes->vec_sol);CHKERRQ(ierr);
56fced5a79SAsbjørn Nilsen Riseth   }
57fced5a79SAsbjørn Nilsen Riseth 
5878440776SJed Brown   if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);}
5978440776SJed Brown   if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);}
6078440776SJed Brown   if (!ngmres->setup_called) {
61087dfb9eSxuemin     msize = ngmres->msize;          /* restart size */
6219653cdaSPeter Brune     hsize = msize * msize;
63087dfb9eSxuemin 
6498b3e84cSPeter Brune     /* explicit least squares minimization solve */
65dcca6d9dSJed Brown     ierr = PetscMalloc5(hsize,&ngmres->h, msize,&ngmres->beta, msize,&ngmres->xi, msize,&ngmres->fnorms, hsize,&ngmres->q);CHKERRQ(ierr);
66785e854fSJed Brown     ierr = PetscMalloc1(msize,&ngmres->xnorms);CHKERRQ(ierr);
6719653cdaSPeter Brune     ngmres->nrhs  = 1;
6819653cdaSPeter Brune     ngmres->lda   = msize;
6919653cdaSPeter Brune     ngmres->ldb   = msize;
70785e854fSJed Brown     ierr          = PetscMalloc1(msize,&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;
76dd63322aSSatish Balay #if defined(PETSC_USE_COMPLEX)
77854ce69bSBarry Smith     ierr = PetscMalloc1(ngmres->lwork,&ngmres->rwork);CHKERRQ(ierr);
7819653cdaSPeter Brune #endif
79854ce69bSBarry Smith     ierr = PetscMalloc1(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) {
86ce94432eSBarry Smith     ierr = SNESLineSearchCreate(PetscObjectComm((PetscObject)snes),&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 
984416b707SBarry Smith PetscErrorCode SNESSetFromOptions_NGMRES(PetscOptionItems *PetscOptionsObject,SNES snes)
99a312c225SMatthew G Knepley {
100a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
101a312c225SMatthew G Knepley   PetscErrorCode ierr;
10294ae4db5SBarry Smith   PetscBool      debug = PETSC_FALSE;
103f1c6b773SPeter Brune   SNESLineSearch linesearch;
1040adebc6cSBarry Smith 
105a312c225SMatthew G Knepley   PetscFunctionBegin;
106e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"SNES NGMRES options");CHKERRQ(ierr);
10713a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes,
1080298fd71SBarry Smith                           (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,NULL);CHKERRQ(ierr);
10913a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes,
1100298fd71SBarry Smith                           (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,NULL);CHKERRQ(ierr);
1110298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_candidate", "Use candidate storage",              "SNES",ngmres->candidate,&ngmres->candidate,NULL);CHKERRQ(ierr);
112077c4231SPeter Brune   ierr = PetscOptionsBool("-snes_ngmres_approxfunc","Linearly approximate the function", "SNES",ngmres->approxfunc,&ngmres->approxfunc,NULL);CHKERRQ(ierr);
1130298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_m",          "Number of directions",               "SNES",ngmres->msize,&ngmres->msize,NULL);CHKERRQ(ierr);
1140298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_restart",    "Iterations before forced restart",   "SNES",ngmres->restart_periodic,&ngmres->restart_periodic,NULL);CHKERRQ(ierr);
1150298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_restart_it", "Tolerance iterations before restart","SNES",ngmres->restart_it,&ngmres->restart_it,NULL);CHKERRQ(ierr);
1160298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_monitor",   "Monitor actions of NGMRES",          "SNES",ngmres->monitor ? PETSC_TRUE : PETSC_FALSE,&debug,NULL);CHKERRQ(ierr);
117dfbf837cSBarry Smith   if (debug) {
118ce94432eSBarry Smith     ngmres->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr);
119dfbf837cSBarry Smith   }
1200298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_gammaA",    "Residual selection constant",   "SNES",ngmres->gammaA,&ngmres->gammaA,NULL);CHKERRQ(ierr);
1210298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_gammaC",    "Residual restart constant",     "SNES",ngmres->gammaC,&ngmres->gammaC,NULL);CHKERRQ(ierr);
1220298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_epsilonB",  "Difference selection constant", "SNES",ngmres->epsilonB,&ngmres->epsilonB,NULL);CHKERRQ(ierr);
1230298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_deltaB",    "Difference residual selection constant", "SNES",ngmres->deltaB,&ngmres->deltaB,NULL);CHKERRQ(ierr);
1240298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions",  "SNES",ngmres->singlereduction,&ngmres->singlereduction,NULL);CHKERRQ(ierr);
12523b3e82cSAsbjø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);
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) {
1317601faf0SJed Brown     ierr = SNESGetLineSearch(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 PetscErrorCode SNESView_NGMRES(SNES snes,PetscViewer viewer)
138a312c225SMatthew G Knepley {
139a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
140a312c225SMatthew G Knepley   PetscBool      iascii;
141a312c225SMatthew G Knepley   PetscErrorCode ierr;
142a312c225SMatthew G Knepley 
143a312c225SMatthew G Knepley   PetscFunctionBegin;
144251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject) viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
145a312c225SMatthew G Knepley   if (iascii) {
146f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr);
147f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Residual selection: gammaA=%1.0e, gammaC=%1.0e\n",ngmres->gammaA,ngmres->gammaC);CHKERRQ(ierr);
148f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n",ngmres->epsilonB,ngmres->deltaB);CHKERRQ(ierr);
14923b3e82cSAsbjørn Nilsen Riseth     ierr = PetscViewerASCIIPrintf(viewer,"  Restart on F_M residual increase: %s\n",ngmres->restart_fm_rise?"TRUE":"FALSE");CHKERRQ(ierr);
150a312c225SMatthew G Knepley   }
151a312c225SMatthew G Knepley   PetscFunctionReturn(0);
152a312c225SMatthew G Knepley }
153a312c225SMatthew G Knepley 
154a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes)
155a312c225SMatthew G Knepley {
156087dfb9eSxuemin   SNES_NGMRES          *ngmres = (SNES_NGMRES*) snes->data;
15798b3e84cSPeter Brune   /* present solution, residual, and preconditioned residual */
1589f425c49SPeter Brune   Vec                  X,F,B,D,Y;
159f109b39eSPeter Brune 
160f109b39eSPeter Brune   /* candidate linear combination answers */
161ddd40ce5SPeter Brune   Vec                  XA,FA,XM,FM;
16219653cdaSPeter Brune 
16398b3e84cSPeter Brune   /* coefficients and RHS to the minimization problem */
16418aa0c0cSPeter Brune   PetscReal            fnorm,fMnorm,fAnorm;
165b3c6a99cSPeter Brune   PetscReal            xnorm,xMnorm,xAnorm;
166b3c6a99cSPeter Brune   PetscReal            ynorm,yMnorm,yAnorm;
16738774f0aSPeter Brune   PetscInt             k,k_restart,l,ivec,restart_count = 0;
16819653cdaSPeter Brune 
16998b3e84cSPeter Brune   /* solution selection data */
17038774f0aSPeter Brune   PetscBool            selectRestart;
17161ba4676SBarry Smith   /*
17261ba4676SBarry Smith       These two variables are initialized to prevent compilers/analyzers from producing false warnings about these variables being passed
17361ba4676SBarry Smith       to SNESNGMRESSelect_Private() without being set when SNES_NGMRES_RESTART_DIFFERENCE, the values are not used in the subroutines in that case
17461ba4676SBarry Smith       so the code is correct as written.
17561ba4676SBarry Smith   */
17661ba4676SBarry Smith   PetscReal            dnorm = 0.0,dminnorm = 0.0;
177b3c6a99cSPeter Brune   PetscReal            fminnorm;
17819653cdaSPeter Brune 
1791e633543SBarry Smith   SNESConvergedReason  reason;
180422a814eSBarry Smith   SNESLineSearchReason lssucceed;
181a312c225SMatthew G Knepley   PetscErrorCode       ierr;
182a312c225SMatthew G Knepley 
183a312c225SMatthew G Knepley   PetscFunctionBegin;
1846c4ed002SBarry 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);
185c579b300SPatrick Farrell 
186fffbeea8SBarry Smith   ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr);
18798b3e84cSPeter Brune   /* variable initialization */
188a312c225SMatthew G Knepley   snes->reason = SNES_CONVERGED_ITERATING;
189f109b39eSPeter Brune   X            = snes->vec_sol;
190f109b39eSPeter Brune   F            = snes->vec_func;
191f109b39eSPeter Brune   B            = snes->vec_rhs;
192f109b39eSPeter Brune   XA           = snes->vec_sol_update;
193f109b39eSPeter Brune   FA           = snes->work[0];
194f109b39eSPeter Brune   D            = snes->work[1];
195f109b39eSPeter Brune 
196f109b39eSPeter Brune   /* work for the line search */
197f109b39eSPeter Brune   Y  = snes->work[2];
1989f425c49SPeter Brune   XM = snes->work[3];
1999f425c49SPeter Brune   FM = snes->work[4];
200a312c225SMatthew G Knepley 
201e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
202a312c225SMatthew G Knepley   snes->iter = 0;
203a312c225SMatthew G Knepley   snes->norm = 0.;
204e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
20519653cdaSPeter Brune 
20698b3e84cSPeter Brune   /* initialization */
20719653cdaSPeter Brune 
208*efd4aadfSBarry Smith   if (snes->npc && snes->npcside== PC_LEFT) {
209be95d8f1SBarry Smith     ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr);
210*efd4aadfSBarry Smith     ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr);
2113a2ae377SPeter Brune     if (reason < 0  && reason != SNES_DIVERGED_MAX_IT) {
2123a2ae377SPeter Brune       snes->reason = SNES_DIVERGED_INNER;
2133a2ae377SPeter Brune       PetscFunctionReturn(0);
2143a2ae377SPeter Brune     }
2153a2ae377SPeter Brune     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
2163a2ae377SPeter Brune   } else {
217e4ed7901SPeter Brune     if (!snes->vec_func_init_set) {
218f109b39eSPeter Brune       ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
2191aa26658SKarl Rupp     } else snes->vec_func_init_set = PETSC_FALSE;
220c1c75074SPeter Brune 
221f109b39eSPeter Brune     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
222422a814eSBarry Smith     SNESCheckFunctionNorm(snes,fnorm);
2233a2ae377SPeter Brune   }
224e4ed7901SPeter Brune   fminnorm = fnorm;
22519653cdaSPeter Brune 
226e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
227f109b39eSPeter Brune   snes->norm = fnorm;
228e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
229a71f0d7dSBarry Smith   ierr       = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr);
230f109b39eSPeter Brune   ierr       = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
231f109b39eSPeter Brune   ierr       = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
232a312c225SMatthew G Knepley   if (snes->reason) PetscFunctionReturn(0);
233b3c6a99cSPeter Brune   SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fnorm,X);
234a312c225SMatthew G Knepley 
23519653cdaSPeter Brune   k_restart = 1;
23619653cdaSPeter Brune   l         = 1;
237b3c6a99cSPeter Brune   ivec      = 0;
23809c08436SPeter Brune   for (k=1; k < snes->max_its+1; k++) {
23998b3e84cSPeter Brune     /* Computation of x^M */
240*efd4aadfSBarry Smith     if (snes->npc && snes->npcside== PC_RIGHT) {
2419f425c49SPeter Brune       ierr = VecCopy(X,XM);CHKERRQ(ierr);
242*efd4aadfSBarry Smith       ierr = SNESSetInitialFunction(snes->npc,F);CHKERRQ(ierr);
24363e7833aSPeter Brune 
244*efd4aadfSBarry Smith       ierr = PetscLogEventBegin(SNES_NPCSolve,snes->npc,XM,B,0);CHKERRQ(ierr);
245*efd4aadfSBarry Smith       ierr = SNESSolve(snes->npc,B,XM);CHKERRQ(ierr);
246*efd4aadfSBarry Smith       ierr = PetscLogEventEnd(SNES_NPCSolve,snes->npc,XM,B,0);CHKERRQ(ierr);
24763e7833aSPeter Brune 
248*efd4aadfSBarry Smith       ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr);
2498cc86e31SPeter Brune       if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
2508cc86e31SPeter Brune         snes->reason = SNES_DIVERGED_INNER;
2518cc86e31SPeter Brune         PetscFunctionReturn(0);
2528cc86e31SPeter Brune       }
253be95d8f1SBarry Smith       ierr = SNESGetNPCFunction(snes,FM,&fMnorm);CHKERRQ(ierr);
2548cc86e31SPeter Brune     } else {
255f109b39eSPeter Brune       /* no preconditioner -- just take gradient descent with line search */
256f109b39eSPeter Brune       ierr = VecCopy(F,Y);CHKERRQ(ierr);
257e7058c64SPeter Brune       ierr = VecCopy(F,FM);CHKERRQ(ierr);
258e7058c64SPeter Brune       ierr = VecCopy(X,XM);CHKERRQ(ierr);
2591aa26658SKarl Rupp 
260e7058c64SPeter Brune       fMnorm = fnorm;
2611aa26658SKarl Rupp 
262f1c6b773SPeter Brune       ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr);
263422a814eSBarry Smith       ierr = SNESLineSearchGetReason(snes->linesearch,&lssucceed);CHKERRQ(ierr);
264422a814eSBarry Smith       if (lssucceed) {
265f109b39eSPeter Brune         if (++snes->numFailures >= snes->maxFailures) {
266f109b39eSPeter Brune           snes->reason = SNES_DIVERGED_LINE_SEARCH;
267f109b39eSPeter Brune           PetscFunctionReturn(0);
268f109b39eSPeter Brune         }
269f109b39eSPeter Brune       }
2706634f59bSPeter Brune     }
27123b3e82cSAsbjørn Nilsen Riseth 
272b3c6a99cSPeter Brune     ierr = SNESNGMRESFormCombinedSolution_Private(snes,ivec,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr);
27398b3e84cSPeter Brune     /* r = F(x) */
2749f425c49SPeter Brune     if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of F^M */
27519653cdaSPeter Brune 
2769f425c49SPeter Brune     /* differences for selection and restart */
27713a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) {
278b3c6a99cSPeter Brune       ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr);
27913a62661SPeter Brune     } else {
280b3c6a99cSPeter Brune       ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,NULL,NULL,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr);
28113a62661SPeter Brune     }
282422a814eSBarry Smith     SNESCheckFunctionNorm(snes,fnorm);
2831aa26658SKarl Rupp 
2849f425c49SPeter Brune     /* combination (additive) or selection (multiplicative) of the N-GMRES solution */
285b3c6a99cSPeter 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);
28619653cdaSPeter Brune     selectRestart = PETSC_FALSE;
28723b3e82cSAsbjørn Nilsen Riseth 
28813a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) {
28923b3e82cSAsbjørn Nilsen Riseth       ierr = SNESNGMRESSelectRestart_Private(snes,l,fMnorm,fAnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr);
29023b3e82cSAsbjørn Nilsen Riseth 
29128ed4a04SPeter Brune       /* if the restart conditions persist for more than restart_it iterations, restart. */
2921aa26658SKarl Rupp       if (selectRestart) restart_count++;
2931aa26658SKarl Rupp       else restart_count = 0;
29413a62661SPeter Brune     } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) {
29513a62661SPeter Brune       if (k_restart > ngmres->restart_periodic) {
29613a62661SPeter Brune         if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr);
29713a62661SPeter Brune         restart_count = ngmres->restart_it;
29813a62661SPeter Brune       }
29913a62661SPeter Brune     }
30023b3e82cSAsbjørn Nilsen Riseth 
301b3c6a99cSPeter Brune     ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */
30223b3e82cSAsbjørn Nilsen Riseth 
30328ed4a04SPeter Brune     /* restart after restart conditions have persisted for a fixed number of iterations */
30428ed4a04SPeter Brune     if (restart_count >= ngmres->restart_it) {
305dfbf837cSBarry Smith       if (ngmres->monitor) {
306dfbf837cSBarry Smith         ierr = PetscViewerASCIIPrintf(ngmres->monitor,"Restarted at iteration %d\n",k_restart);CHKERRQ(ierr);
307dfbf837cSBarry Smith       }
30828ed4a04SPeter Brune       restart_count = 0;
30919653cdaSPeter Brune       k_restart     = 1;
31019653cdaSPeter Brune       l             = 1;
311b3c6a99cSPeter Brune       ivec          = 0;
31298b3e84cSPeter Brune       /* q_{00} = nu */
313fa8c639aSPeter Brune       ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,FM,fMnorm,XM);CHKERRQ(ierr);
314d2e16ddcSPeter Brune     } else {
31598b3e84cSPeter Brune       /* select the current size of the subspace */
3161e633543SBarry Smith       if (l < ngmres->msize) l++;
31719653cdaSPeter Brune       k_restart++;
31898b3e84cSPeter Brune       /* place the current entry in the list of previous entries */
31938774f0aSPeter Brune       if (ngmres->candidate) {
32038774f0aSPeter Brune         if (fminnorm > fMnorm) fminnorm = fMnorm;
321fa8c639aSPeter Brune         ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fMnorm,XM);CHKERRQ(ierr);
322d2e16ddcSPeter Brune       } else {
32338774f0aSPeter Brune         if (fminnorm > fnorm) fminnorm = fnorm;
324fa8c639aSPeter Brune         ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,F,fnorm,X);CHKERRQ(ierr);
32519653cdaSPeter Brune       }
326d2e16ddcSPeter Brune     }
32719653cdaSPeter Brune 
328e04113cfSBarry Smith     ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
329087dfb9eSxuemin     snes->iter = k;
330f109b39eSPeter Brune     snes->norm = fnorm;
331e04113cfSBarry Smith     ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
332a71f0d7dSBarry Smith     ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr);
3338409ca45SMatthew G Knepley     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
334b3c6a99cSPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,0,0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
335087dfb9eSxuemin     if (snes->reason) PetscFunctionReturn(0);
336a312c225SMatthew G Knepley   }
337a312c225SMatthew G Knepley   snes->reason = SNES_DIVERGED_MAX_IT;
338a312c225SMatthew G Knepley   PetscFunctionReturn(0);
339a312c225SMatthew G Knepley }
340a312c225SMatthew G Knepley 
34123b3e82cSAsbjørn Nilsen Riseth /*@
34223b3e82cSAsbjørn Nilsen Riseth  SNESNGMRESSetRestartFmRise - Increase the restart count if the step x_M increases the residual F_M
34323b3e82cSAsbjørn Nilsen Riseth 
34423b3e82cSAsbjørn Nilsen Riseth   Input Parameters:
34523b3e82cSAsbjørn Nilsen Riseth   +  snes - the SNES context.
34623b3e82cSAsbjørn Nilsen Riseth   -  flg  - boolean value deciding whether to use the option or not
34723b3e82cSAsbjørn Nilsen Riseth 
34823b3e82cSAsbjørn Nilsen Riseth   Options Database:
34923b3e82cSAsbjørn Nilsen Riseth   + -snes_ngmres_restart_fm_rise - Increase the restart count if the step x_M increases the residual F_M
35023b3e82cSAsbjørn Nilsen Riseth 
35123b3e82cSAsbjørn Nilsen Riseth   Level: intermediate
35223b3e82cSAsbjørn Nilsen Riseth 
35323b3e82cSAsbjørn Nilsen Riseth   Notes:
35423b3e82cSAsbjø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.
35523b3e82cSAsbjørn Nilsen Riseth   To help the solver do that, reset the Krylov subspace whenever F_M increases.
35623b3e82cSAsbjørn Nilsen Riseth 
35723b3e82cSAsbjørn Nilsen Riseth   This option must be used with SNES_NGMRES_RESTART_DIFFERENCE
35823b3e82cSAsbjørn Nilsen Riseth 
35923b3e82cSAsbjørn Nilsen Riseth   The default is FALSE.
36023b3e82cSAsbjørn Nilsen Riseth   .seealso: SNES_NGMRES_RESTART_DIFFERENCE
36123b3e82cSAsbjørn Nilsen Riseth   @*/
36223b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESSetRestartFmRise(SNES snes,PetscBool flg)
36323b3e82cSAsbjørn Nilsen Riseth {
36423b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode (*f)(SNES,PetscBool);
36523b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode ierr;
36623b3e82cSAsbjørn Nilsen Riseth 
36723b3e82cSAsbjørn Nilsen Riseth     PetscFunctionBegin;
36823b3e82cSAsbjørn Nilsen Riseth     ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNGMRESSetRestartFmRise_C",&f);CHKERRQ(ierr);
36923b3e82cSAsbjørn Nilsen Riseth     if (f) {ierr = (f)(snes,flg);CHKERRQ(ierr);}
37023b3e82cSAsbjørn Nilsen Riseth     PetscFunctionReturn(0);
37123b3e82cSAsbjørn Nilsen Riseth }
37223b3e82cSAsbjørn Nilsen Riseth 
37323b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESSetRestartFmRise_NGMRES(SNES snes,PetscBool flg)
37423b3e82cSAsbjørn Nilsen Riseth {
37523b3e82cSAsbjørn Nilsen Riseth   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
37623b3e82cSAsbjørn Nilsen Riseth 
37723b3e82cSAsbjørn Nilsen Riseth   PetscFunctionBegin;
37823b3e82cSAsbjørn Nilsen Riseth   ngmres->restart_fm_rise = flg;
37923b3e82cSAsbjørn Nilsen Riseth   PetscFunctionReturn(0);
38023b3e82cSAsbjørn Nilsen Riseth }
38123b3e82cSAsbjørn Nilsen Riseth 
38223b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESGetRestartFmRise(SNES snes,PetscBool *flg)
38323b3e82cSAsbjørn Nilsen Riseth {
38423b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode (*f)(SNES,PetscBool*);
38523b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode ierr;
38623b3e82cSAsbjørn Nilsen Riseth 
38723b3e82cSAsbjørn Nilsen Riseth     PetscFunctionBegin;
38823b3e82cSAsbjørn Nilsen Riseth     ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNGMRESGetRestartFmRise_C",&f);CHKERRQ(ierr);
38923b3e82cSAsbjørn Nilsen Riseth     if (f) {ierr = (f)(snes,flg);CHKERRQ(ierr);}
39023b3e82cSAsbjørn Nilsen Riseth     PetscFunctionReturn(0);
39123b3e82cSAsbjørn Nilsen Riseth }
39223b3e82cSAsbjørn Nilsen Riseth 
39323b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESGetRestartFmRise_NGMRES(SNES snes,PetscBool *flg)
39423b3e82cSAsbjørn Nilsen Riseth {
39523b3e82cSAsbjørn Nilsen Riseth   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
39623b3e82cSAsbjørn Nilsen Riseth 
39723b3e82cSAsbjørn Nilsen Riseth   PetscFunctionBegin;
39823b3e82cSAsbjørn Nilsen Riseth   *flg = ngmres->restart_fm_rise;
39923b3e82cSAsbjørn Nilsen Riseth   PetscFunctionReturn(0);
40023b3e82cSAsbjørn Nilsen Riseth }
40123b3e82cSAsbjørn Nilsen Riseth 
40223b3e82cSAsbjørn Nilsen Riseth 
40313a62661SPeter Brune /*@
40413a62661SPeter Brune     SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES.
40513a62661SPeter Brune 
40613a62661SPeter Brune     Logically Collective on SNES
40713a62661SPeter Brune 
40813a62661SPeter Brune     Input Parameters:
40913a62661SPeter Brune +   snes - the iterative context
41013a62661SPeter Brune -   rtype - restart type
41113a62661SPeter Brune 
41213a62661SPeter Brune     Options Database:
41313a62661SPeter Brune +   -snes_ngmres_restart_type<difference,periodic,none> - set the restart type
4140c777b0cSPeter Brune -   -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic
41513a62661SPeter Brune 
41613a62661SPeter Brune     Level: intermediate
41713a62661SPeter Brune 
41813a62661SPeter Brune     SNESNGMRESRestartTypes:
41913a62661SPeter Brune +   SNES_NGMRES_RESTART_NONE - never restart
42013a62661SPeter Brune .   SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria
42113a62661SPeter Brune -   SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations
42213a62661SPeter Brune 
42313a62661SPeter Brune     Notes:
42413a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
42513a62661SPeter Brune 
42613a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch
42713a62661SPeter Brune @*/
4280adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes,SNESNGMRESRestartType rtype)
4290adebc6cSBarry Smith {
43013a62661SPeter Brune   PetscErrorCode ierr;
4315fd66863SKarl Rupp 
43213a62661SPeter Brune   PetscFunctionBegin;
43313a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
43413a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr);
43513a62661SPeter Brune   PetscFunctionReturn(0);
43613a62661SPeter Brune }
43713a62661SPeter Brune 
43813a62661SPeter Brune /*@
43913a62661SPeter Brune     SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES.  This determines how the candidate solution and
44013a62661SPeter Brune     combined solution are used to create the next iterate.
44113a62661SPeter Brune 
44213a62661SPeter Brune     Logically Collective on SNES
44313a62661SPeter Brune 
44413a62661SPeter Brune     Input Parameters:
44513a62661SPeter Brune +   snes - the iterative context
44613a62661SPeter Brune -   stype - selection type
44713a62661SPeter Brune 
44813a62661SPeter Brune     Options Database:
44913a62661SPeter Brune .   -snes_ngmres_select_type<difference,none,linesearch>
45013a62661SPeter Brune 
45113a62661SPeter Brune     Level: intermediate
45213a62661SPeter Brune 
45313a62661SPeter Brune     SNESNGMRESSelectTypes:
45413a62661SPeter Brune +   SNES_NGMRES_SELECT_NONE - choose the combined solution all the time
45513a62661SPeter Brune .   SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria
45613a62661SPeter Brune -   SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination
45713a62661SPeter Brune 
45813a62661SPeter Brune     Notes:
45913a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
46013a62661SPeter Brune 
46113a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch
46213a62661SPeter Brune @*/
4630adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes,SNESNGMRESSelectType stype)
4640adebc6cSBarry Smith {
46513a62661SPeter Brune   PetscErrorCode ierr;
4665fd66863SKarl Rupp 
46713a62661SPeter Brune   PetscFunctionBegin;
46813a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
46913a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr);
47013a62661SPeter Brune   PetscFunctionReturn(0);
47113a62661SPeter Brune }
47213a62661SPeter Brune 
4730adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes,SNESNGMRESSelectType stype)
4740adebc6cSBarry Smith {
47513a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
4765fd66863SKarl Rupp 
47713a62661SPeter Brune   PetscFunctionBegin;
47813a62661SPeter Brune   ngmres->select_type = stype;
47913a62661SPeter Brune   PetscFunctionReturn(0);
48013a62661SPeter Brune }
48113a62661SPeter Brune 
4820adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes,SNESNGMRESRestartType rtype)
4830adebc6cSBarry Smith {
48413a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
4855fd66863SKarl Rupp 
48613a62661SPeter Brune   PetscFunctionBegin;
48713a62661SPeter Brune   ngmres->restart_type = rtype;
48813a62661SPeter Brune   PetscFunctionReturn(0);
48913a62661SPeter Brune }
49013a62661SPeter Brune 
491dfbf837cSBarry Smith /*MC
4921867fe5bSPeter Brune   SNESNGMRES - The Nonlinear Generalized Minimum Residual method.
493a312c225SMatthew G Knepley 
494dfbf837cSBarry Smith    Level: beginner
495dfbf837cSBarry Smith 
4961867fe5bSPeter Brune    Options Database:
49713a62661SPeter Brune +  -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution
49838774f0aSPeter Brune .  -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions
49938774f0aSPeter Brune .  -snes_ngmres_candidate        - Use NGMRES variant which combines candidate solutions instead of actual solutions
50013a62661SPeter Brune .  -snes_ngmres_m                - Number of stored previous solutions and residuals
50113a62661SPeter Brune .  -snes_ngmres_restart_it       - Number of iterations the restart conditions hold before restart
50213a62661SPeter Brune .  -snes_ngmres_gammaA           - Residual tolerance for solution select between the candidate and combination
50313a62661SPeter Brune .  -snes_ngmres_gammaC           - Residual tolerance for restart
50413a62661SPeter Brune .  -snes_ngmres_epsilonB         - Difference tolerance between subsequent solutions triggering restart
50513a62661SPeter Brune .  -snes_ngmres_deltaB           - Difference tolerance between residuals triggering restart
50623b3e82cSAsbjørn Nilsen Riseth .  -snes_ngmres_restart_fm_rise  - Restart on residual rise from x_M step
50713a62661SPeter Brune .  -snes_ngmres_monitor          - Prints relevant information about the ngmres iteration
5085c3e6ab7SPeter Brune .  -snes_linesearch_type <basic,l2,cp> - Line search type used for the default smoother
50913a62661SPeter Brune -  -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type
5101867fe5bSPeter Brune 
5111867fe5bSPeter Brune    Notes:
5121867fe5bSPeter Brune 
5131867fe5bSPeter Brune    The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized
5141867fe5bSPeter Brune    optimization problem at each iteration.
5151867fe5bSPeter Brune 
5164f02bc6aSBarry Smith    Very similar to the SNESANDERSON algorithm.
5174f02bc6aSBarry Smith 
5181867fe5bSPeter Brune    References:
51996a0c994SBarry Smith +  1. - C. W. Oosterlee and T. Washio, "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows",
520dfbf837cSBarry Smith    SIAM Journal on Scientific Computing, 21(5), 2000.
52196a0c994SBarry Smith -  2. - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers",
5224f02bc6aSBarry Smith    SIAM Review, 57(4), 2015
5234f02bc6aSBarry Smith 
5244f02bc6aSBarry Smith 
525dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types)
526dfbf837cSBarry Smith M*/
527a312c225SMatthew G Knepley 
5288cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NGMRES(SNES snes)
529a312c225SMatthew G Knepley {
530a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres;
531a312c225SMatthew G Knepley   PetscErrorCode ierr;
532a312c225SMatthew G Knepley 
533a312c225SMatthew G Knepley   PetscFunctionBegin;
534a312c225SMatthew G Knepley   snes->ops->destroy        = SNESDestroy_NGMRES;
535a312c225SMatthew G Knepley   snes->ops->setup          = SNESSetUp_NGMRES;
536a312c225SMatthew G Knepley   snes->ops->setfromoptions = SNESSetFromOptions_NGMRES;
537a312c225SMatthew G Knepley   snes->ops->view           = SNESView_NGMRES;
538a312c225SMatthew G Knepley   snes->ops->solve          = SNESSolve_NGMRES;
539a312c225SMatthew G Knepley   snes->ops->reset          = SNESReset_NGMRES;
540a312c225SMatthew G Knepley 
541*efd4aadfSBarry Smith   snes->usesnpc  = PETSC_TRUE;
5422c155ee1SBarry Smith   snes->usesksp  = PETSC_FALSE;
543*efd4aadfSBarry Smith   snes->npcside  = PC_RIGHT;
5442c155ee1SBarry Smith 
5454fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_TRUE;
5464fc747eaSLawrence Mitchell 
547b00a9115SJed Brown   ierr          = PetscNewLog(snes,&ngmres);CHKERRQ(ierr);
548a312c225SMatthew G Knepley   snes->data    = (void*) ngmres;
549d2e16ddcSPeter Brune   ngmres->msize = 30;
55019653cdaSPeter Brune 
55188976e71SPeter Brune   if (!snes->tolerancesset) {
5520e444f03SPeter Brune     snes->max_funcs = 30000;
5530e444f03SPeter Brune     snes->max_its   = 10000;
55488976e71SPeter Brune   }
5550e444f03SPeter Brune 
55638774f0aSPeter Brune   ngmres->candidate = PETSC_FALSE;
557d2e16ddcSPeter Brune 
5580298fd71SBarry Smith   ngmres->additive_linesearch = NULL;
559077c4231SPeter Brune   ngmres->approxfunc          = PETSC_FALSE;
56028ed4a04SPeter Brune   ngmres->restart_it          = 2;
56113a62661SPeter Brune   ngmres->restart_periodic    = 30;
562f109b39eSPeter Brune   ngmres->gammaA              = 2.0;
563f109b39eSPeter Brune   ngmres->gammaC              = 2.0;
564cac108bcSPeter Brune   ngmres->deltaB              = 0.9;
565cac108bcSPeter Brune   ngmres->epsilonB            = 0.1;
56623b3e82cSAsbjørn Nilsen Riseth   ngmres->restart_fm_rise     = PETSC_FALSE;
567e7058c64SPeter Brune 
56813a62661SPeter Brune   ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE;
56913a62661SPeter Brune   ngmres->select_type  = SNES_NGMRES_SELECT_DIFFERENCE;
57013a62661SPeter Brune 
571bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetSelectType_C",SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr);
572bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartType_C",SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr);
57323b3e82cSAsbjørn Nilsen Riseth   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartFmRise_C",SNESNGMRESSetRestartFmRise_NGMRES);CHKERRQ(ierr);
57423b3e82cSAsbjørn Nilsen Riseth   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESGetRestartFmRise_C",SNESNGMRESGetRestartFmRise_NGMRES);CHKERRQ(ierr);
575a312c225SMatthew G Knepley   PetscFunctionReturn(0);
576a312c225SMatthew G Knepley }
577