xref: /petsc/src/snes/impls/ngmres/snesngmres.c (revision d8d34be668443a492f25d109cf196c1d22336895)
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;
47efd4aadfSBarry 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   }
50efd4aadfSBarry 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;
1030adebc6cSBarry Smith 
104a312c225SMatthew G Knepley   PetscFunctionBegin;
105e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"SNES NGMRES options");CHKERRQ(ierr);
10613a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes,
1070298fd71SBarry Smith                           (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,NULL);CHKERRQ(ierr);
10813a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes,
1090298fd71SBarry Smith                           (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,NULL);CHKERRQ(ierr);
1100298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_candidate", "Use candidate storage",              "SNES",ngmres->candidate,&ngmres->candidate,NULL);CHKERRQ(ierr);
111077c4231SPeter Brune   ierr = PetscOptionsBool("-snes_ngmres_approxfunc","Linearly approximate the function", "SNES",ngmres->approxfunc,&ngmres->approxfunc,NULL);CHKERRQ(ierr);
1120298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_m",          "Number of directions",               "SNES",ngmres->msize,&ngmres->msize,NULL);CHKERRQ(ierr);
1130298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_restart",    "Iterations before forced restart",   "SNES",ngmres->restart_periodic,&ngmres->restart_periodic,NULL);CHKERRQ(ierr);
1140298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_restart_it", "Tolerance iterations before restart","SNES",ngmres->restart_it,&ngmres->restart_it,NULL);CHKERRQ(ierr);
1150298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_monitor",   "Monitor actions of NGMRES",          "SNES",ngmres->monitor ? PETSC_TRUE : PETSC_FALSE,&debug,NULL);CHKERRQ(ierr);
116dfbf837cSBarry Smith   if (debug) {
117ce94432eSBarry Smith     ngmres->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr);
118dfbf837cSBarry Smith   }
1190298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_gammaA",    "Residual selection constant",   "SNES",ngmres->gammaA,&ngmres->gammaA,NULL);CHKERRQ(ierr);
1200298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_gammaC",    "Residual restart constant",     "SNES",ngmres->gammaC,&ngmres->gammaC,NULL);CHKERRQ(ierr);
1210298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_epsilonB",  "Difference selection constant", "SNES",ngmres->epsilonB,&ngmres->epsilonB,NULL);CHKERRQ(ierr);
1220298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_deltaB",    "Difference residual selection constant", "SNES",ngmres->deltaB,&ngmres->deltaB,NULL);CHKERRQ(ierr);
1230298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions",  "SNES",ngmres->singlereduction,&ngmres->singlereduction,NULL);CHKERRQ(ierr);
12423b3e82cSAsbjø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);
125a312c225SMatthew G Knepley   ierr = PetscOptionsTail();CHKERRQ(ierr);
1266a7cf640SPeter Brune   if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA;
127a312c225SMatthew G Knepley   PetscFunctionReturn(0);
128a312c225SMatthew G Knepley }
129a312c225SMatthew G Knepley 
130a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes,PetscViewer viewer)
131a312c225SMatthew G Knepley {
132a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
133a312c225SMatthew G Knepley   PetscBool      iascii;
134a312c225SMatthew G Knepley   PetscErrorCode ierr;
135a312c225SMatthew G Knepley 
136a312c225SMatthew G Knepley   PetscFunctionBegin;
137251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject) viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
138a312c225SMatthew G Knepley   if (iascii) {
139f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr);
140f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Residual selection: gammaA=%1.0e, gammaC=%1.0e\n",ngmres->gammaA,ngmres->gammaC);CHKERRQ(ierr);
141f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n",ngmres->epsilonB,ngmres->deltaB);CHKERRQ(ierr);
14223b3e82cSAsbjørn Nilsen Riseth     ierr = PetscViewerASCIIPrintf(viewer,"  Restart on F_M residual increase: %s\n",ngmres->restart_fm_rise?"TRUE":"FALSE");CHKERRQ(ierr);
143a312c225SMatthew G Knepley   }
144a312c225SMatthew G Knepley   PetscFunctionReturn(0);
145a312c225SMatthew G Knepley }
146a312c225SMatthew G Knepley 
147a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes)
148a312c225SMatthew G Knepley {
149087dfb9eSxuemin   SNES_NGMRES          *ngmres = (SNES_NGMRES*) snes->data;
15098b3e84cSPeter Brune   /* present solution, residual, and preconditioned residual */
1519f425c49SPeter Brune   Vec                  X,F,B,D,Y;
152f109b39eSPeter Brune 
153f109b39eSPeter Brune   /* candidate linear combination answers */
154ddd40ce5SPeter Brune   Vec                  XA,FA,XM,FM;
15519653cdaSPeter Brune 
15698b3e84cSPeter Brune   /* coefficients and RHS to the minimization problem */
15718aa0c0cSPeter Brune   PetscReal            fnorm,fMnorm,fAnorm;
158b3c6a99cSPeter Brune   PetscReal            xnorm,xMnorm,xAnorm;
159b3c6a99cSPeter Brune   PetscReal            ynorm,yMnorm,yAnorm;
16038774f0aSPeter Brune   PetscInt             k,k_restart,l,ivec,restart_count = 0;
16119653cdaSPeter Brune 
16298b3e84cSPeter Brune   /* solution selection data */
16338774f0aSPeter Brune   PetscBool            selectRestart;
16461ba4676SBarry Smith   /*
16561ba4676SBarry Smith       These two variables are initialized to prevent compilers/analyzers from producing false warnings about these variables being passed
16661ba4676SBarry Smith       to SNESNGMRESSelect_Private() without being set when SNES_NGMRES_RESTART_DIFFERENCE, the values are not used in the subroutines in that case
16761ba4676SBarry Smith       so the code is correct as written.
16861ba4676SBarry Smith   */
16961ba4676SBarry Smith   PetscReal            dnorm = 0.0,dminnorm = 0.0;
170b3c6a99cSPeter Brune   PetscReal            fminnorm;
17119653cdaSPeter Brune 
1721e633543SBarry Smith   SNESConvergedReason  reason;
173422a814eSBarry Smith   SNESLineSearchReason lssucceed;
174a312c225SMatthew G Knepley   PetscErrorCode       ierr;
175a312c225SMatthew G Knepley 
176a312c225SMatthew G Knepley   PetscFunctionBegin;
1776c4ed002SBarry 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);
178c579b300SPatrick Farrell 
179fffbeea8SBarry Smith   ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr);
18098b3e84cSPeter Brune   /* variable initialization */
181a312c225SMatthew G Knepley   snes->reason = SNES_CONVERGED_ITERATING;
182f109b39eSPeter Brune   X            = snes->vec_sol;
183f109b39eSPeter Brune   F            = snes->vec_func;
184f109b39eSPeter Brune   B            = snes->vec_rhs;
185f109b39eSPeter Brune   XA           = snes->vec_sol_update;
186f109b39eSPeter Brune   FA           = snes->work[0];
187f109b39eSPeter Brune   D            = snes->work[1];
188f109b39eSPeter Brune 
189f109b39eSPeter Brune   /* work for the line search */
190f109b39eSPeter Brune   Y  = snes->work[2];
1919f425c49SPeter Brune   XM = snes->work[3];
1929f425c49SPeter Brune   FM = snes->work[4];
193a312c225SMatthew G Knepley 
194e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
195a312c225SMatthew G Knepley   snes->iter = 0;
196a312c225SMatthew G Knepley   snes->norm = 0.;
197e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
19819653cdaSPeter Brune 
19998b3e84cSPeter Brune   /* initialization */
20019653cdaSPeter Brune 
201efd4aadfSBarry Smith   if (snes->npc && snes->npcside== PC_LEFT) {
202be95d8f1SBarry Smith     ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr);
203efd4aadfSBarry Smith     ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr);
2043a2ae377SPeter Brune     if (reason < 0  && reason != SNES_DIVERGED_MAX_IT) {
2053a2ae377SPeter Brune       snes->reason = SNES_DIVERGED_INNER;
2063a2ae377SPeter Brune       PetscFunctionReturn(0);
2073a2ae377SPeter Brune     }
2083a2ae377SPeter Brune     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
2093a2ae377SPeter Brune   } else {
210e4ed7901SPeter Brune     if (!snes->vec_func_init_set) {
211f109b39eSPeter Brune       ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
2121aa26658SKarl Rupp     } else snes->vec_func_init_set = PETSC_FALSE;
213c1c75074SPeter Brune 
214f109b39eSPeter Brune     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
215422a814eSBarry Smith     SNESCheckFunctionNorm(snes,fnorm);
2163a2ae377SPeter Brune   }
217e4ed7901SPeter Brune   fminnorm = fnorm;
21819653cdaSPeter Brune 
219e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
220f109b39eSPeter Brune   snes->norm = fnorm;
221e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
222a71f0d7dSBarry Smith   ierr       = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr);
223f109b39eSPeter Brune   ierr       = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
224f109b39eSPeter Brune   ierr       = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
225a312c225SMatthew G Knepley   if (snes->reason) PetscFunctionReturn(0);
226b3c6a99cSPeter Brune   SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fnorm,X);
227a312c225SMatthew G Knepley 
22819653cdaSPeter Brune   k_restart = 1;
22919653cdaSPeter Brune   l         = 1;
230b3c6a99cSPeter Brune   ivec      = 0;
23109c08436SPeter Brune   for (k=1; k < snes->max_its+1; k++) {
23298b3e84cSPeter Brune     /* Computation of x^M */
233efd4aadfSBarry Smith     if (snes->npc && snes->npcside== PC_RIGHT) {
2349f425c49SPeter Brune       ierr = VecCopy(X,XM);CHKERRQ(ierr);
235efd4aadfSBarry Smith       ierr = SNESSetInitialFunction(snes->npc,F);CHKERRQ(ierr);
23663e7833aSPeter Brune 
237efd4aadfSBarry Smith       ierr = PetscLogEventBegin(SNES_NPCSolve,snes->npc,XM,B,0);CHKERRQ(ierr);
238efd4aadfSBarry Smith       ierr = SNESSolve(snes->npc,B,XM);CHKERRQ(ierr);
239efd4aadfSBarry Smith       ierr = PetscLogEventEnd(SNES_NPCSolve,snes->npc,XM,B,0);CHKERRQ(ierr);
24063e7833aSPeter Brune 
241efd4aadfSBarry Smith       ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr);
2428cc86e31SPeter Brune       if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
2438cc86e31SPeter Brune         snes->reason = SNES_DIVERGED_INNER;
2448cc86e31SPeter Brune         PetscFunctionReturn(0);
2458cc86e31SPeter Brune       }
246be95d8f1SBarry Smith       ierr = SNESGetNPCFunction(snes,FM,&fMnorm);CHKERRQ(ierr);
2478cc86e31SPeter Brune     } else {
248f109b39eSPeter Brune       /* no preconditioner -- just take gradient descent with line search */
249f109b39eSPeter Brune       ierr = VecCopy(F,Y);CHKERRQ(ierr);
250e7058c64SPeter Brune       ierr = VecCopy(F,FM);CHKERRQ(ierr);
251e7058c64SPeter Brune       ierr = VecCopy(X,XM);CHKERRQ(ierr);
2521aa26658SKarl Rupp 
253e7058c64SPeter Brune       fMnorm = fnorm;
2541aa26658SKarl Rupp 
255f1c6b773SPeter Brune       ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr);
256422a814eSBarry Smith       ierr = SNESLineSearchGetReason(snes->linesearch,&lssucceed);CHKERRQ(ierr);
257422a814eSBarry Smith       if (lssucceed) {
258f109b39eSPeter Brune         if (++snes->numFailures >= snes->maxFailures) {
259f109b39eSPeter Brune           snes->reason = SNES_DIVERGED_LINE_SEARCH;
260f109b39eSPeter Brune           PetscFunctionReturn(0);
261f109b39eSPeter Brune         }
262f109b39eSPeter Brune       }
2636634f59bSPeter Brune     }
26423b3e82cSAsbjørn Nilsen Riseth 
265b3c6a99cSPeter Brune     ierr = SNESNGMRESFormCombinedSolution_Private(snes,ivec,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr);
26698b3e84cSPeter Brune     /* r = F(x) */
2679f425c49SPeter Brune     if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of F^M */
26819653cdaSPeter Brune 
2699f425c49SPeter Brune     /* differences for selection and restart */
27013a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) {
271b3c6a99cSPeter Brune       ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr);
27213a62661SPeter Brune     } else {
273b3c6a99cSPeter Brune       ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,NULL,NULL,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr);
27413a62661SPeter Brune     }
275422a814eSBarry Smith     SNESCheckFunctionNorm(snes,fnorm);
2761aa26658SKarl Rupp 
2779f425c49SPeter Brune     /* combination (additive) or selection (multiplicative) of the N-GMRES solution */
278b3c6a99cSPeter 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);
27919653cdaSPeter Brune     selectRestart = PETSC_FALSE;
28023b3e82cSAsbjørn Nilsen Riseth 
28113a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) {
28223b3e82cSAsbjørn Nilsen Riseth       ierr = SNESNGMRESSelectRestart_Private(snes,l,fMnorm,fAnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr);
28323b3e82cSAsbjørn Nilsen Riseth 
28428ed4a04SPeter Brune       /* if the restart conditions persist for more than restart_it iterations, restart. */
2851aa26658SKarl Rupp       if (selectRestart) restart_count++;
2861aa26658SKarl Rupp       else restart_count = 0;
28713a62661SPeter Brune     } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) {
28813a62661SPeter Brune       if (k_restart > ngmres->restart_periodic) {
28913a62661SPeter Brune         if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr);
29013a62661SPeter Brune         restart_count = ngmres->restart_it;
29113a62661SPeter Brune       }
29213a62661SPeter Brune     }
29323b3e82cSAsbjørn Nilsen Riseth 
294b3c6a99cSPeter Brune     ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */
29523b3e82cSAsbjørn Nilsen Riseth 
29628ed4a04SPeter Brune     /* restart after restart conditions have persisted for a fixed number of iterations */
29728ed4a04SPeter Brune     if (restart_count >= ngmres->restart_it) {
298dfbf837cSBarry Smith       if (ngmres->monitor) {
299dfbf837cSBarry Smith         ierr = PetscViewerASCIIPrintf(ngmres->monitor,"Restarted at iteration %d\n",k_restart);CHKERRQ(ierr);
300dfbf837cSBarry Smith       }
30128ed4a04SPeter Brune       restart_count = 0;
30219653cdaSPeter Brune       k_restart     = 1;
30319653cdaSPeter Brune       l             = 1;
304b3c6a99cSPeter Brune       ivec          = 0;
30598b3e84cSPeter Brune       /* q_{00} = nu */
306fa8c639aSPeter Brune       ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,FM,fMnorm,XM);CHKERRQ(ierr);
307d2e16ddcSPeter Brune     } else {
30898b3e84cSPeter Brune       /* select the current size of the subspace */
3091e633543SBarry Smith       if (l < ngmres->msize) l++;
31019653cdaSPeter Brune       k_restart++;
31198b3e84cSPeter Brune       /* place the current entry in the list of previous entries */
31238774f0aSPeter Brune       if (ngmres->candidate) {
31338774f0aSPeter Brune         if (fminnorm > fMnorm) fminnorm = fMnorm;
314fa8c639aSPeter Brune         ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fMnorm,XM);CHKERRQ(ierr);
315d2e16ddcSPeter Brune       } else {
31638774f0aSPeter Brune         if (fminnorm > fnorm) fminnorm = fnorm;
317fa8c639aSPeter Brune         ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,F,fnorm,X);CHKERRQ(ierr);
31819653cdaSPeter Brune       }
319d2e16ddcSPeter Brune     }
32019653cdaSPeter Brune 
321e04113cfSBarry Smith     ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
322087dfb9eSxuemin     snes->iter = k;
323f109b39eSPeter Brune     snes->norm = fnorm;
324e04113cfSBarry Smith     ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
325a71f0d7dSBarry Smith     ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr);
3268409ca45SMatthew G Knepley     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
327b3c6a99cSPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,0,0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
328087dfb9eSxuemin     if (snes->reason) PetscFunctionReturn(0);
329a312c225SMatthew G Knepley   }
330a312c225SMatthew G Knepley   snes->reason = SNES_DIVERGED_MAX_IT;
331a312c225SMatthew G Knepley   PetscFunctionReturn(0);
332a312c225SMatthew G Knepley }
333a312c225SMatthew G Knepley 
33423b3e82cSAsbjørn Nilsen Riseth /*@
33523b3e82cSAsbjørn Nilsen Riseth  SNESNGMRESSetRestartFmRise - Increase the restart count if the step x_M increases the residual F_M
33623b3e82cSAsbjørn Nilsen Riseth 
33723b3e82cSAsbjørn Nilsen Riseth   Input Parameters:
33823b3e82cSAsbjørn Nilsen Riseth   +  snes - the SNES context.
33923b3e82cSAsbjørn Nilsen Riseth   -  flg  - boolean value deciding whether to use the option or not
34023b3e82cSAsbjørn Nilsen Riseth 
34123b3e82cSAsbjørn Nilsen Riseth   Options Database:
34223b3e82cSAsbjørn Nilsen Riseth   + -snes_ngmres_restart_fm_rise - Increase the restart count if the step x_M increases the residual F_M
34323b3e82cSAsbjørn Nilsen Riseth 
34423b3e82cSAsbjørn Nilsen Riseth   Level: intermediate
34523b3e82cSAsbjørn Nilsen Riseth 
34623b3e82cSAsbjørn Nilsen Riseth   Notes:
34723b3e82cSAsbjø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.
34823b3e82cSAsbjørn Nilsen Riseth   To help the solver do that, reset the Krylov subspace whenever F_M increases.
34923b3e82cSAsbjørn Nilsen Riseth 
35023b3e82cSAsbjørn Nilsen Riseth   This option must be used with SNES_NGMRES_RESTART_DIFFERENCE
35123b3e82cSAsbjørn Nilsen Riseth 
35223b3e82cSAsbjørn Nilsen Riseth   The default is FALSE.
35323b3e82cSAsbjørn Nilsen Riseth   .seealso: SNES_NGMRES_RESTART_DIFFERENCE
35423b3e82cSAsbjørn Nilsen Riseth   @*/
35523b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESSetRestartFmRise(SNES snes,PetscBool flg)
35623b3e82cSAsbjørn Nilsen Riseth {
35723b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode (*f)(SNES,PetscBool);
35823b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode ierr;
35923b3e82cSAsbjørn Nilsen Riseth 
36023b3e82cSAsbjørn Nilsen Riseth     PetscFunctionBegin;
36123b3e82cSAsbjørn Nilsen Riseth     ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNGMRESSetRestartFmRise_C",&f);CHKERRQ(ierr);
36223b3e82cSAsbjørn Nilsen Riseth     if (f) {ierr = (f)(snes,flg);CHKERRQ(ierr);}
36323b3e82cSAsbjørn Nilsen Riseth     PetscFunctionReturn(0);
36423b3e82cSAsbjørn Nilsen Riseth }
36523b3e82cSAsbjørn Nilsen Riseth 
36623b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESSetRestartFmRise_NGMRES(SNES snes,PetscBool flg)
36723b3e82cSAsbjørn Nilsen Riseth {
36823b3e82cSAsbjørn Nilsen Riseth   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
36923b3e82cSAsbjørn Nilsen Riseth 
37023b3e82cSAsbjørn Nilsen Riseth   PetscFunctionBegin;
37123b3e82cSAsbjørn Nilsen Riseth   ngmres->restart_fm_rise = flg;
37223b3e82cSAsbjørn Nilsen Riseth   PetscFunctionReturn(0);
37323b3e82cSAsbjørn Nilsen Riseth }
37423b3e82cSAsbjørn Nilsen Riseth 
37523b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESGetRestartFmRise(SNES snes,PetscBool *flg)
37623b3e82cSAsbjørn Nilsen Riseth {
37723b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode (*f)(SNES,PetscBool*);
37823b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode ierr;
37923b3e82cSAsbjørn Nilsen Riseth 
38023b3e82cSAsbjørn Nilsen Riseth     PetscFunctionBegin;
38123b3e82cSAsbjørn Nilsen Riseth     ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNGMRESGetRestartFmRise_C",&f);CHKERRQ(ierr);
38223b3e82cSAsbjørn Nilsen Riseth     if (f) {ierr = (f)(snes,flg);CHKERRQ(ierr);}
38323b3e82cSAsbjørn Nilsen Riseth     PetscFunctionReturn(0);
38423b3e82cSAsbjørn Nilsen Riseth }
38523b3e82cSAsbjørn Nilsen Riseth 
38623b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESGetRestartFmRise_NGMRES(SNES snes,PetscBool *flg)
38723b3e82cSAsbjørn Nilsen Riseth {
38823b3e82cSAsbjørn Nilsen Riseth   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
38923b3e82cSAsbjørn Nilsen Riseth 
39023b3e82cSAsbjørn Nilsen Riseth   PetscFunctionBegin;
39123b3e82cSAsbjørn Nilsen Riseth   *flg = ngmres->restart_fm_rise;
39223b3e82cSAsbjørn Nilsen Riseth   PetscFunctionReturn(0);
39323b3e82cSAsbjørn Nilsen Riseth }
39423b3e82cSAsbjørn Nilsen Riseth 
39523b3e82cSAsbjørn Nilsen Riseth 
39613a62661SPeter Brune /*@
39713a62661SPeter Brune     SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES.
39813a62661SPeter Brune 
39913a62661SPeter Brune     Logically Collective on SNES
40013a62661SPeter Brune 
40113a62661SPeter Brune     Input Parameters:
40213a62661SPeter Brune +   snes - the iterative context
40313a62661SPeter Brune -   rtype - restart type
40413a62661SPeter Brune 
40513a62661SPeter Brune     Options Database:
40613a62661SPeter Brune +   -snes_ngmres_restart_type<difference,periodic,none> - set the restart type
4070c777b0cSPeter Brune -   -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic
40813a62661SPeter Brune 
40913a62661SPeter Brune     Level: intermediate
41013a62661SPeter Brune 
41113a62661SPeter Brune     SNESNGMRESRestartTypes:
41213a62661SPeter Brune +   SNES_NGMRES_RESTART_NONE - never restart
41313a62661SPeter Brune .   SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria
41413a62661SPeter Brune -   SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations
41513a62661SPeter Brune 
41613a62661SPeter Brune     Notes:
41713a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
41813a62661SPeter Brune 
41913a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch
42013a62661SPeter Brune @*/
4210adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes,SNESNGMRESRestartType rtype)
4220adebc6cSBarry Smith {
42313a62661SPeter Brune   PetscErrorCode ierr;
4245fd66863SKarl Rupp 
42513a62661SPeter Brune   PetscFunctionBegin;
42613a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
42713a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr);
42813a62661SPeter Brune   PetscFunctionReturn(0);
42913a62661SPeter Brune }
43013a62661SPeter Brune 
43113a62661SPeter Brune /*@
43213a62661SPeter Brune     SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES.  This determines how the candidate solution and
43313a62661SPeter Brune     combined solution are used to create the next iterate.
43413a62661SPeter Brune 
43513a62661SPeter Brune     Logically Collective on SNES
43613a62661SPeter Brune 
43713a62661SPeter Brune     Input Parameters:
43813a62661SPeter Brune +   snes - the iterative context
43913a62661SPeter Brune -   stype - selection type
44013a62661SPeter Brune 
44113a62661SPeter Brune     Options Database:
44213a62661SPeter Brune .   -snes_ngmres_select_type<difference,none,linesearch>
44313a62661SPeter Brune 
44413a62661SPeter Brune     Level: intermediate
44513a62661SPeter Brune 
44613a62661SPeter Brune     SNESNGMRESSelectTypes:
44713a62661SPeter Brune +   SNES_NGMRES_SELECT_NONE - choose the combined solution all the time
44813a62661SPeter Brune .   SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria
44913a62661SPeter Brune -   SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination
45013a62661SPeter Brune 
45113a62661SPeter Brune     Notes:
45213a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
45313a62661SPeter Brune 
45413a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch
45513a62661SPeter Brune @*/
4560adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes,SNESNGMRESSelectType stype)
4570adebc6cSBarry Smith {
45813a62661SPeter Brune   PetscErrorCode ierr;
4595fd66863SKarl Rupp 
46013a62661SPeter Brune   PetscFunctionBegin;
46113a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
46213a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr);
46313a62661SPeter Brune   PetscFunctionReturn(0);
46413a62661SPeter Brune }
46513a62661SPeter Brune 
4660adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes,SNESNGMRESSelectType stype)
4670adebc6cSBarry Smith {
46813a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
4695fd66863SKarl Rupp 
47013a62661SPeter Brune   PetscFunctionBegin;
47113a62661SPeter Brune   ngmres->select_type = stype;
47213a62661SPeter Brune   PetscFunctionReturn(0);
47313a62661SPeter Brune }
47413a62661SPeter Brune 
4750adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes,SNESNGMRESRestartType rtype)
4760adebc6cSBarry Smith {
47713a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
4785fd66863SKarl Rupp 
47913a62661SPeter Brune   PetscFunctionBegin;
48013a62661SPeter Brune   ngmres->restart_type = rtype;
48113a62661SPeter Brune   PetscFunctionReturn(0);
48213a62661SPeter Brune }
48313a62661SPeter Brune 
484dfbf837cSBarry Smith /*MC
4851867fe5bSPeter Brune   SNESNGMRES - The Nonlinear Generalized Minimum Residual method.
486a312c225SMatthew G Knepley 
487dfbf837cSBarry Smith    Level: beginner
488dfbf837cSBarry Smith 
4891867fe5bSPeter Brune    Options Database:
49013a62661SPeter Brune +  -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution
49138774f0aSPeter Brune .  -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions
49238774f0aSPeter Brune .  -snes_ngmres_candidate        - Use NGMRES variant which combines candidate solutions instead of actual solutions
49313a62661SPeter Brune .  -snes_ngmres_m                - Number of stored previous solutions and residuals
49413a62661SPeter Brune .  -snes_ngmres_restart_it       - Number of iterations the restart conditions hold before restart
49513a62661SPeter Brune .  -snes_ngmres_gammaA           - Residual tolerance for solution select between the candidate and combination
49613a62661SPeter Brune .  -snes_ngmres_gammaC           - Residual tolerance for restart
49713a62661SPeter Brune .  -snes_ngmres_epsilonB         - Difference tolerance between subsequent solutions triggering restart
49813a62661SPeter Brune .  -snes_ngmres_deltaB           - Difference tolerance between residuals triggering restart
49923b3e82cSAsbjørn Nilsen Riseth .  -snes_ngmres_restart_fm_rise  - Restart on residual rise from x_M step
50013a62661SPeter Brune .  -snes_ngmres_monitor          - Prints relevant information about the ngmres iteration
5015c3e6ab7SPeter Brune .  -snes_linesearch_type <basic,l2,cp> - Line search type used for the default smoother
50213a62661SPeter Brune -  -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type
5031867fe5bSPeter Brune 
5041867fe5bSPeter Brune    Notes:
5051867fe5bSPeter Brune 
5061867fe5bSPeter Brune    The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized
5071867fe5bSPeter Brune    optimization problem at each iteration.
5081867fe5bSPeter Brune 
5094f02bc6aSBarry Smith    Very similar to the SNESANDERSON algorithm.
5104f02bc6aSBarry Smith 
5111867fe5bSPeter Brune    References:
51296a0c994SBarry Smith +  1. - C. W. Oosterlee and T. Washio, "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows",
513dfbf837cSBarry Smith    SIAM Journal on Scientific Computing, 21(5), 2000.
51496a0c994SBarry Smith -  2. - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers",
5154f02bc6aSBarry Smith    SIAM Review, 57(4), 2015
5164f02bc6aSBarry Smith 
5174f02bc6aSBarry Smith 
518dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types)
519dfbf837cSBarry Smith M*/
520a312c225SMatthew G Knepley 
5218cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NGMRES(SNES snes)
522a312c225SMatthew G Knepley {
523a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres;
524a312c225SMatthew G Knepley   PetscErrorCode ierr;
525*d8d34be6SBarry Smith   SNESLineSearch linesearch;
526a312c225SMatthew G Knepley 
527a312c225SMatthew G Knepley   PetscFunctionBegin;
528a312c225SMatthew G Knepley   snes->ops->destroy        = SNESDestroy_NGMRES;
529a312c225SMatthew G Knepley   snes->ops->setup          = SNESSetUp_NGMRES;
530a312c225SMatthew G Knepley   snes->ops->setfromoptions = SNESSetFromOptions_NGMRES;
531a312c225SMatthew G Knepley   snes->ops->view           = SNESView_NGMRES;
532a312c225SMatthew G Knepley   snes->ops->solve          = SNESSolve_NGMRES;
533a312c225SMatthew G Knepley   snes->ops->reset          = SNESReset_NGMRES;
534a312c225SMatthew G Knepley 
535efd4aadfSBarry Smith   snes->usesnpc  = PETSC_TRUE;
5362c155ee1SBarry Smith   snes->usesksp  = PETSC_FALSE;
537efd4aadfSBarry Smith   snes->npcside  = PC_RIGHT;
5382c155ee1SBarry Smith 
5394fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_TRUE;
5404fc747eaSLawrence Mitchell 
541b00a9115SJed Brown   ierr          = PetscNewLog(snes,&ngmres);CHKERRQ(ierr);
542a312c225SMatthew G Knepley   snes->data    = (void*) ngmres;
543d2e16ddcSPeter Brune   ngmres->msize = 30;
54419653cdaSPeter Brune 
54588976e71SPeter Brune   if (!snes->tolerancesset) {
5460e444f03SPeter Brune     snes->max_funcs = 30000;
5470e444f03SPeter Brune     snes->max_its   = 10000;
54888976e71SPeter Brune   }
5490e444f03SPeter Brune 
55038774f0aSPeter Brune   ngmres->candidate = PETSC_FALSE;
551d2e16ddcSPeter Brune 
552*d8d34be6SBarry Smith  ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr);
553*d8d34be6SBarry Smith  ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr);
554*d8d34be6SBarry Smith 
5550298fd71SBarry Smith   ngmres->additive_linesearch = NULL;
556077c4231SPeter Brune   ngmres->approxfunc          = PETSC_FALSE;
55728ed4a04SPeter Brune   ngmres->restart_it          = 2;
55813a62661SPeter Brune   ngmres->restart_periodic    = 30;
559f109b39eSPeter Brune   ngmres->gammaA              = 2.0;
560f109b39eSPeter Brune   ngmres->gammaC              = 2.0;
561cac108bcSPeter Brune   ngmres->deltaB              = 0.9;
562cac108bcSPeter Brune   ngmres->epsilonB            = 0.1;
56323b3e82cSAsbjørn Nilsen Riseth   ngmres->restart_fm_rise     = PETSC_FALSE;
564e7058c64SPeter Brune 
56513a62661SPeter Brune   ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE;
56613a62661SPeter Brune   ngmres->select_type  = SNES_NGMRES_SELECT_DIFFERENCE;
56713a62661SPeter Brune 
568bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetSelectType_C",SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr);
569bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartType_C",SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr);
57023b3e82cSAsbjørn Nilsen Riseth   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartFmRise_C",SNESNGMRESSetRestartFmRise_NGMRES);CHKERRQ(ierr);
57123b3e82cSAsbjørn Nilsen Riseth   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESGetRestartFmRise_C",SNESNGMRESGetRestartFmRise_NGMRES);CHKERRQ(ierr);
572a312c225SMatthew G Knepley   PetscFunctionReturn(0);
573a312c225SMatthew G Knepley }
574