xref: /petsc/src/snes/impls/ngmres/snesngmres.c (revision 9e5d08929599755f0fc0004c3575ee121dac326a)
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 
5*9e5d0892SLisandro Dalcin const char *const SNESNGMRESRestartTypes[] = {"NONE","PERIODIC","DIFFERENCE","SNESNGMRESRestartType","SNES_NGMRES_RESTART_",NULL};
6*9e5d0892SLisandro Dalcin const char *const SNESNGMRESSelectTypes[] = {"NONE","DIFFERENCE","LINESEARCH","SNESNGMRESSelectType","SNES_NGMRES_SELECT_",NULL};
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);
27580bdb30SBarry Smith   ierr = PetscFree4(ngmres->h,ngmres->beta,ngmres->xi,ngmres->q);CHKERRQ(ierr);
28580bdb30SBarry Smith   ierr = PetscFree3(ngmres->xnorms,ngmres->fnorms,ngmres->s);CHKERRQ(ierr);
29dd63322aSSatish Balay #if defined(PETSC_USE_COMPLEX)
3022d28d08SBarry Smith   ierr = PetscFree(ngmres->rwork);CHKERRQ(ierr);
3119653cdaSPeter Brune #endif
3222d28d08SBarry Smith   ierr = PetscFree(ngmres->work);CHKERRQ(ierr);
3322d28d08SBarry Smith   ierr = PetscFree(snes->data);CHKERRQ(ierr);
34a312c225SMatthew G Knepley   PetscFunctionReturn(0);
35a312c225SMatthew G Knepley }
36a312c225SMatthew G Knepley 
37a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes)
38a312c225SMatthew G Knepley {
39a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
40e7058c64SPeter Brune   const char     *optionsprefix;
4119653cdaSPeter Brune   PetscInt       msize,hsize;
42a312c225SMatthew G Knepley   PetscErrorCode ierr;
43fced5a79SAsbjørn Nilsen Riseth   DM             dm;
44a312c225SMatthew G Knepley 
45a312c225SMatthew G Knepley   PetscFunctionBegin;
46efd4aadfSBarry Smith   if (snes->npc && snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) {
4746159c86SPeter Brune     SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"SNESNGMRES does not support left preconditioning with unpreconditioned function");
4846159c86SPeter Brune   }
49efd4aadfSBarry Smith   if (snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_DEFAULT) snes->functype = SNES_FUNCTION_PRECONDITIONED;
50fa0ddf94SBarry Smith   ierr = SNESSetWorkVecs(snes,5);CHKERRQ(ierr);
51fced5a79SAsbjørn Nilsen Riseth 
52fced5a79SAsbjørn Nilsen Riseth   if (!snes->vec_sol) {
53fced5a79SAsbjørn Nilsen Riseth     ierr             = SNESGetDM(snes,&dm);CHKERRQ(ierr);
54fced5a79SAsbjørn Nilsen Riseth     ierr             = DMCreateGlobalVector(dm,&snes->vec_sol);CHKERRQ(ierr);
55fced5a79SAsbjørn Nilsen Riseth   }
56fced5a79SAsbjørn Nilsen Riseth 
5778440776SJed Brown   if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);}
5878440776SJed Brown   if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);}
5978440776SJed Brown   if (!ngmres->setup_called) {
60087dfb9eSxuemin     msize = ngmres->msize;          /* restart size */
6119653cdaSPeter Brune     hsize = msize * msize;
62087dfb9eSxuemin 
6398b3e84cSPeter Brune     /* explicit least squares minimization solve */
64580bdb30SBarry Smith     ierr = PetscCalloc4(hsize,&ngmres->h, msize,&ngmres->beta, msize,&ngmres->xi, hsize,&ngmres->q);CHKERRQ(ierr);
65580bdb30SBarry Smith     ierr = PetscMalloc3(msize,&ngmres->xnorms,msize,&ngmres->fnorms,msize,&ngmres->s);CHKERRQ(ierr);
6619653cdaSPeter Brune     ngmres->nrhs  = 1;
6719653cdaSPeter Brune     ngmres->lda   = msize;
6819653cdaSPeter Brune     ngmres->ldb   = msize;
6919653cdaSPeter Brune     ngmres->lwork = 12*msize;
70dd63322aSSatish Balay #if defined(PETSC_USE_COMPLEX)
71854ce69bSBarry Smith     ierr = PetscMalloc1(ngmres->lwork,&ngmres->rwork);CHKERRQ(ierr);
7219653cdaSPeter Brune #endif
73854ce69bSBarry Smith     ierr = PetscMalloc1(ngmres->lwork,&ngmres->work);CHKERRQ(ierr);
7478440776SJed Brown   }
75e7058c64SPeter Brune 
76e7058c64SPeter Brune   /* linesearch setup */
77e7058c64SPeter Brune   ierr = SNESGetOptionsPrefix(snes,&optionsprefix);CHKERRQ(ierr);
78e7058c64SPeter Brune 
7913a62661SPeter Brune   if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) {
80ce94432eSBarry Smith     ierr = SNESLineSearchCreate(PetscObjectComm((PetscObject)snes),&ngmres->additive_linesearch);CHKERRQ(ierr);
81f1c6b773SPeter Brune     ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch,snes);CHKERRQ(ierr);
82ec786807SJed Brown     if (!((PetscObject)ngmres->additive_linesearch)->type_name) {
831a4f838cSPeter Brune       ierr = SNESLineSearchSetType(ngmres->additive_linesearch,SNESLINESEARCHL2);CHKERRQ(ierr);
84ec786807SJed Brown     }
85f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,"additive_");CHKERRQ(ierr);
86f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,optionsprefix);CHKERRQ(ierr);
87f1c6b773SPeter Brune     ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr);
88e7058c64SPeter Brune   }
89e7058c64SPeter Brune 
9078440776SJed Brown   ngmres->setup_called = PETSC_TRUE;
91a312c225SMatthew G Knepley   PetscFunctionReturn(0);
92a312c225SMatthew G Knepley }
93a312c225SMatthew G Knepley 
944416b707SBarry Smith PetscErrorCode SNESSetFromOptions_NGMRES(PetscOptionItems *PetscOptionsObject,SNES snes)
95a312c225SMatthew G Knepley {
96a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
97a312c225SMatthew G Knepley   PetscErrorCode ierr;
9894ae4db5SBarry Smith   PetscBool      debug = PETSC_FALSE;
990adebc6cSBarry Smith 
100a312c225SMatthew G Knepley   PetscFunctionBegin;
101e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"SNES NGMRES options");CHKERRQ(ierr);
10213a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes,
1030298fd71SBarry Smith                           (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,NULL);CHKERRQ(ierr);
10413a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes,
1050298fd71SBarry Smith                           (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,NULL);CHKERRQ(ierr);
1060298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_candidate", "Use candidate storage",              "SNES",ngmres->candidate,&ngmres->candidate,NULL);CHKERRQ(ierr);
107077c4231SPeter Brune   ierr = PetscOptionsBool("-snes_ngmres_approxfunc","Linearly approximate the function", "SNES",ngmres->approxfunc,&ngmres->approxfunc,NULL);CHKERRQ(ierr);
1080298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_m",          "Number of directions",               "SNES",ngmres->msize,&ngmres->msize,NULL);CHKERRQ(ierr);
1090298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_restart",    "Iterations before forced restart",   "SNES",ngmres->restart_periodic,&ngmres->restart_periodic,NULL);CHKERRQ(ierr);
1100298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_restart_it", "Tolerance iterations before restart","SNES",ngmres->restart_it,&ngmres->restart_it,NULL);CHKERRQ(ierr);
1110298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_monitor",   "Monitor actions of NGMRES",          "SNES",ngmres->monitor ? PETSC_TRUE : PETSC_FALSE,&debug,NULL);CHKERRQ(ierr);
112dfbf837cSBarry Smith   if (debug) {
113ce94432eSBarry Smith     ngmres->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr);
114dfbf837cSBarry Smith   }
1150298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_gammaA",    "Residual selection constant",   "SNES",ngmres->gammaA,&ngmres->gammaA,NULL);CHKERRQ(ierr);
1160298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_gammaC",    "Residual restart constant",     "SNES",ngmres->gammaC,&ngmres->gammaC,NULL);CHKERRQ(ierr);
1170298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_epsilonB",  "Difference selection constant", "SNES",ngmres->epsilonB,&ngmres->epsilonB,NULL);CHKERRQ(ierr);
1180298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_deltaB",    "Difference residual selection constant", "SNES",ngmres->deltaB,&ngmres->deltaB,NULL);CHKERRQ(ierr);
1190298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions",  "SNES",ngmres->singlereduction,&ngmres->singlereduction,NULL);CHKERRQ(ierr);
12023b3e82cSAsbjø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);
121a312c225SMatthew G Knepley   ierr = PetscOptionsTail();CHKERRQ(ierr);
1226a7cf640SPeter Brune   if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA;
123a312c225SMatthew G Knepley   PetscFunctionReturn(0);
124a312c225SMatthew G Knepley }
125a312c225SMatthew G Knepley 
126a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes,PetscViewer viewer)
127a312c225SMatthew G Knepley {
128a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
129a312c225SMatthew G Knepley   PetscBool      iascii;
130a312c225SMatthew G Knepley   PetscErrorCode ierr;
131a312c225SMatthew G Knepley 
132a312c225SMatthew G Knepley   PetscFunctionBegin;
133251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject) viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
134a312c225SMatthew G Knepley   if (iascii) {
135f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr);
136f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Residual selection: gammaA=%1.0e, gammaC=%1.0e\n",ngmres->gammaA,ngmres->gammaC);CHKERRQ(ierr);
137f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n",ngmres->epsilonB,ngmres->deltaB);CHKERRQ(ierr);
13823b3e82cSAsbjørn Nilsen Riseth     ierr = PetscViewerASCIIPrintf(viewer,"  Restart on F_M residual increase: %s\n",ngmres->restart_fm_rise?"TRUE":"FALSE");CHKERRQ(ierr);
139a312c225SMatthew G Knepley   }
140a312c225SMatthew G Knepley   PetscFunctionReturn(0);
141a312c225SMatthew G Knepley }
142a312c225SMatthew G Knepley 
143a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes)
144a312c225SMatthew G Knepley {
145087dfb9eSxuemin   SNES_NGMRES          *ngmres = (SNES_NGMRES*) snes->data;
14698b3e84cSPeter Brune   /* present solution, residual, and preconditioned residual */
1479f425c49SPeter Brune   Vec                  X,F,B,D,Y;
148f109b39eSPeter Brune 
149f109b39eSPeter Brune   /* candidate linear combination answers */
150ddd40ce5SPeter Brune   Vec                  XA,FA,XM,FM;
15119653cdaSPeter Brune 
15298b3e84cSPeter Brune   /* coefficients and RHS to the minimization problem */
15318aa0c0cSPeter Brune   PetscReal            fnorm,fMnorm,fAnorm;
154b3c6a99cSPeter Brune   PetscReal            xnorm,xMnorm,xAnorm;
155b3c6a99cSPeter Brune   PetscReal            ynorm,yMnorm,yAnorm;
15638774f0aSPeter Brune   PetscInt             k,k_restart,l,ivec,restart_count = 0;
15719653cdaSPeter Brune 
15898b3e84cSPeter Brune   /* solution selection data */
15938774f0aSPeter Brune   PetscBool            selectRestart;
16061ba4676SBarry Smith   /*
16161ba4676SBarry Smith       These two variables are initialized to prevent compilers/analyzers from producing false warnings about these variables being passed
16261ba4676SBarry Smith       to SNESNGMRESSelect_Private() without being set when SNES_NGMRES_RESTART_DIFFERENCE, the values are not used in the subroutines in that case
16361ba4676SBarry Smith       so the code is correct as written.
16461ba4676SBarry Smith   */
16561ba4676SBarry Smith   PetscReal            dnorm = 0.0,dminnorm = 0.0;
166b3c6a99cSPeter Brune   PetscReal            fminnorm;
16719653cdaSPeter Brune 
1681e633543SBarry Smith   SNESConvergedReason  reason;
169422a814eSBarry Smith   SNESLineSearchReason lssucceed;
170a312c225SMatthew G Knepley   PetscErrorCode       ierr;
171a312c225SMatthew G Knepley 
172a312c225SMatthew G Knepley   PetscFunctionBegin;
1736c4ed002SBarry 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);
174c579b300SPatrick Farrell 
175fffbeea8SBarry Smith   ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr);
17698b3e84cSPeter Brune   /* variable initialization */
177a312c225SMatthew G Knepley   snes->reason = SNES_CONVERGED_ITERATING;
178f109b39eSPeter Brune   X            = snes->vec_sol;
179f109b39eSPeter Brune   F            = snes->vec_func;
180f109b39eSPeter Brune   B            = snes->vec_rhs;
181f109b39eSPeter Brune   XA           = snes->vec_sol_update;
182f109b39eSPeter Brune   FA           = snes->work[0];
183f109b39eSPeter Brune   D            = snes->work[1];
184f109b39eSPeter Brune 
185f109b39eSPeter Brune   /* work for the line search */
186f109b39eSPeter Brune   Y  = snes->work[2];
1879f425c49SPeter Brune   XM = snes->work[3];
1889f425c49SPeter Brune   FM = snes->work[4];
189a312c225SMatthew G Knepley 
190e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
191a312c225SMatthew G Knepley   snes->iter = 0;
192a312c225SMatthew G Knepley   snes->norm = 0.;
193e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
19419653cdaSPeter Brune 
19598b3e84cSPeter Brune   /* initialization */
19619653cdaSPeter Brune 
197efd4aadfSBarry Smith   if (snes->npc && snes->npcside== PC_LEFT) {
198be95d8f1SBarry Smith     ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr);
199efd4aadfSBarry Smith     ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr);
2003a2ae377SPeter Brune     if (reason < 0  && reason != SNES_DIVERGED_MAX_IT) {
2013a2ae377SPeter Brune       snes->reason = SNES_DIVERGED_INNER;
2023a2ae377SPeter Brune       PetscFunctionReturn(0);
2033a2ae377SPeter Brune     }
2043a2ae377SPeter Brune     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
2053a2ae377SPeter Brune   } else {
206e4ed7901SPeter Brune     if (!snes->vec_func_init_set) {
207f109b39eSPeter Brune       ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
2081aa26658SKarl Rupp     } else snes->vec_func_init_set = PETSC_FALSE;
209c1c75074SPeter Brune 
210f109b39eSPeter Brune     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
211422a814eSBarry Smith     SNESCheckFunctionNorm(snes,fnorm);
2123a2ae377SPeter Brune   }
213e4ed7901SPeter Brune   fminnorm = fnorm;
21419653cdaSPeter Brune 
215e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
216f109b39eSPeter Brune   snes->norm = fnorm;
217e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
218a71f0d7dSBarry Smith   ierr       = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr);
219f109b39eSPeter Brune   ierr       = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
220f109b39eSPeter Brune   ierr       = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
221a312c225SMatthew G Knepley   if (snes->reason) PetscFunctionReturn(0);
222b3c6a99cSPeter Brune   SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fnorm,X);
223a312c225SMatthew G Knepley 
22419653cdaSPeter Brune   k_restart = 1;
22519653cdaSPeter Brune   l         = 1;
226b3c6a99cSPeter Brune   ivec      = 0;
22709c08436SPeter Brune   for (k=1; k < snes->max_its+1; k++) {
22898b3e84cSPeter Brune     /* Computation of x^M */
229efd4aadfSBarry Smith     if (snes->npc && snes->npcside== PC_RIGHT) {
2309f425c49SPeter Brune       ierr = VecCopy(X,XM);CHKERRQ(ierr);
231efd4aadfSBarry Smith       ierr = SNESSetInitialFunction(snes->npc,F);CHKERRQ(ierr);
23263e7833aSPeter Brune 
233efd4aadfSBarry Smith       ierr = PetscLogEventBegin(SNES_NPCSolve,snes->npc,XM,B,0);CHKERRQ(ierr);
234efd4aadfSBarry Smith       ierr = SNESSolve(snes->npc,B,XM);CHKERRQ(ierr);
235efd4aadfSBarry Smith       ierr = PetscLogEventEnd(SNES_NPCSolve,snes->npc,XM,B,0);CHKERRQ(ierr);
23663e7833aSPeter Brune 
237efd4aadfSBarry Smith       ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr);
2388cc86e31SPeter Brune       if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
2398cc86e31SPeter Brune         snes->reason = SNES_DIVERGED_INNER;
2408cc86e31SPeter Brune         PetscFunctionReturn(0);
2418cc86e31SPeter Brune       }
242be95d8f1SBarry Smith       ierr = SNESGetNPCFunction(snes,FM,&fMnorm);CHKERRQ(ierr);
2438cc86e31SPeter Brune     } else {
244f109b39eSPeter Brune       /* no preconditioner -- just take gradient descent with line search */
245f109b39eSPeter Brune       ierr = VecCopy(F,Y);CHKERRQ(ierr);
246e7058c64SPeter Brune       ierr = VecCopy(F,FM);CHKERRQ(ierr);
247e7058c64SPeter Brune       ierr = VecCopy(X,XM);CHKERRQ(ierr);
2481aa26658SKarl Rupp 
249e7058c64SPeter Brune       fMnorm = fnorm;
2501aa26658SKarl Rupp 
251f1c6b773SPeter Brune       ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr);
252422a814eSBarry Smith       ierr = SNESLineSearchGetReason(snes->linesearch,&lssucceed);CHKERRQ(ierr);
253422a814eSBarry Smith       if (lssucceed) {
254f109b39eSPeter Brune         if (++snes->numFailures >= snes->maxFailures) {
255f109b39eSPeter Brune           snes->reason = SNES_DIVERGED_LINE_SEARCH;
256f109b39eSPeter Brune           PetscFunctionReturn(0);
257f109b39eSPeter Brune         }
258f109b39eSPeter Brune       }
2596634f59bSPeter Brune     }
26023b3e82cSAsbjørn Nilsen Riseth 
261b3c6a99cSPeter Brune     ierr = SNESNGMRESFormCombinedSolution_Private(snes,ivec,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr);
26298b3e84cSPeter Brune     /* r = F(x) */
2639f425c49SPeter Brune     if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of F^M */
26419653cdaSPeter Brune 
2659f425c49SPeter Brune     /* differences for selection and restart */
26613a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) {
267b3c6a99cSPeter Brune       ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr);
26813a62661SPeter Brune     } else {
269b3c6a99cSPeter Brune       ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,NULL,NULL,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr);
27013a62661SPeter Brune     }
271422a814eSBarry Smith     SNESCheckFunctionNorm(snes,fnorm);
2721aa26658SKarl Rupp 
2739f425c49SPeter Brune     /* combination (additive) or selection (multiplicative) of the N-GMRES solution */
274b3c6a99cSPeter 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);
27519653cdaSPeter Brune     selectRestart = PETSC_FALSE;
27623b3e82cSAsbjørn Nilsen Riseth 
27713a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) {
27823b3e82cSAsbjørn Nilsen Riseth       ierr = SNESNGMRESSelectRestart_Private(snes,l,fMnorm,fAnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr);
27923b3e82cSAsbjørn Nilsen Riseth 
28028ed4a04SPeter Brune       /* if the restart conditions persist for more than restart_it iterations, restart. */
2811aa26658SKarl Rupp       if (selectRestart) restart_count++;
2821aa26658SKarl Rupp       else restart_count = 0;
28313a62661SPeter Brune     } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) {
28413a62661SPeter Brune       if (k_restart > ngmres->restart_periodic) {
28513a62661SPeter Brune         if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr);
28613a62661SPeter Brune         restart_count = ngmres->restart_it;
28713a62661SPeter Brune       }
28813a62661SPeter Brune     }
28923b3e82cSAsbjørn Nilsen Riseth 
290b3c6a99cSPeter Brune     ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */
29123b3e82cSAsbjørn Nilsen Riseth 
29228ed4a04SPeter Brune     /* restart after restart conditions have persisted for a fixed number of iterations */
29328ed4a04SPeter Brune     if (restart_count >= ngmres->restart_it) {
294dfbf837cSBarry Smith       if (ngmres->monitor) {
295dfbf837cSBarry Smith         ierr = PetscViewerASCIIPrintf(ngmres->monitor,"Restarted at iteration %d\n",k_restart);CHKERRQ(ierr);
296dfbf837cSBarry Smith       }
29728ed4a04SPeter Brune       restart_count = 0;
29819653cdaSPeter Brune       k_restart     = 1;
29919653cdaSPeter Brune       l             = 1;
300b3c6a99cSPeter Brune       ivec          = 0;
30198b3e84cSPeter Brune       /* q_{00} = nu */
302fa8c639aSPeter Brune       ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,FM,fMnorm,XM);CHKERRQ(ierr);
303d2e16ddcSPeter Brune     } else {
30498b3e84cSPeter Brune       /* select the current size of the subspace */
3051e633543SBarry Smith       if (l < ngmres->msize) l++;
30619653cdaSPeter Brune       k_restart++;
30798b3e84cSPeter Brune       /* place the current entry in the list of previous entries */
30838774f0aSPeter Brune       if (ngmres->candidate) {
30938774f0aSPeter Brune         if (fminnorm > fMnorm) fminnorm = fMnorm;
310fa8c639aSPeter Brune         ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fMnorm,XM);CHKERRQ(ierr);
311d2e16ddcSPeter Brune       } else {
31238774f0aSPeter Brune         if (fminnorm > fnorm) fminnorm = fnorm;
313fa8c639aSPeter Brune         ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,F,fnorm,X);CHKERRQ(ierr);
31419653cdaSPeter Brune       }
315d2e16ddcSPeter Brune     }
31619653cdaSPeter Brune 
317e04113cfSBarry Smith     ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
318087dfb9eSxuemin     snes->iter = k;
319f109b39eSPeter Brune     snes->norm = fnorm;
320e04113cfSBarry Smith     ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
321a71f0d7dSBarry Smith     ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr);
3228409ca45SMatthew G Knepley     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
323b3c6a99cSPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,0,0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
324087dfb9eSxuemin     if (snes->reason) PetscFunctionReturn(0);
325a312c225SMatthew G Knepley   }
326a312c225SMatthew G Knepley   snes->reason = SNES_DIVERGED_MAX_IT;
327a312c225SMatthew G Knepley   PetscFunctionReturn(0);
328a312c225SMatthew G Knepley }
329a312c225SMatthew G Knepley 
33023b3e82cSAsbjørn Nilsen Riseth /*@
33123b3e82cSAsbjørn Nilsen Riseth  SNESNGMRESSetRestartFmRise - Increase the restart count if the step x_M increases the residual F_M
33223b3e82cSAsbjørn Nilsen Riseth 
33323b3e82cSAsbjørn Nilsen Riseth   Input Parameters:
33423b3e82cSAsbjørn Nilsen Riseth   +  snes - the SNES context.
33523b3e82cSAsbjørn Nilsen Riseth   -  flg  - boolean value deciding whether to use the option or not
33623b3e82cSAsbjørn Nilsen Riseth 
33723b3e82cSAsbjørn Nilsen Riseth   Options Database:
33823b3e82cSAsbjørn Nilsen Riseth   + -snes_ngmres_restart_fm_rise - Increase the restart count if the step x_M increases the residual F_M
33923b3e82cSAsbjørn Nilsen Riseth 
34023b3e82cSAsbjørn Nilsen Riseth   Level: intermediate
34123b3e82cSAsbjørn Nilsen Riseth 
34223b3e82cSAsbjørn Nilsen Riseth   Notes:
34323b3e82cSAsbjø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.
34423b3e82cSAsbjørn Nilsen Riseth   To help the solver do that, reset the Krylov subspace whenever F_M increases.
34523b3e82cSAsbjørn Nilsen Riseth 
34623b3e82cSAsbjørn Nilsen Riseth   This option must be used with SNES_NGMRES_RESTART_DIFFERENCE
34723b3e82cSAsbjørn Nilsen Riseth 
34823b3e82cSAsbjørn Nilsen Riseth   The default is FALSE.
34923b3e82cSAsbjørn Nilsen Riseth   .seealso: SNES_NGMRES_RESTART_DIFFERENCE
35023b3e82cSAsbjørn Nilsen Riseth   @*/
35123b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESSetRestartFmRise(SNES snes,PetscBool flg)
35223b3e82cSAsbjørn Nilsen Riseth {
35323b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode (*f)(SNES,PetscBool);
35423b3e82cSAsbjørn Nilsen Riseth     PetscErrorCode ierr;
35523b3e82cSAsbjørn Nilsen Riseth 
35623b3e82cSAsbjørn Nilsen Riseth     PetscFunctionBegin;
35723b3e82cSAsbjørn Nilsen Riseth     ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNGMRESSetRestartFmRise_C",&f);CHKERRQ(ierr);
35823b3e82cSAsbjørn Nilsen Riseth     if (f) {ierr = (f)(snes,flg);CHKERRQ(ierr);}
35923b3e82cSAsbjørn Nilsen Riseth     PetscFunctionReturn(0);
36023b3e82cSAsbjørn Nilsen Riseth }
36123b3e82cSAsbjørn Nilsen Riseth 
36223b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESSetRestartFmRise_NGMRES(SNES snes,PetscBool flg)
36323b3e82cSAsbjørn Nilsen Riseth {
36423b3e82cSAsbjørn Nilsen Riseth   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
36523b3e82cSAsbjørn Nilsen Riseth 
36623b3e82cSAsbjørn Nilsen Riseth   PetscFunctionBegin;
36723b3e82cSAsbjørn Nilsen Riseth   ngmres->restart_fm_rise = flg;
36823b3e82cSAsbjørn Nilsen Riseth   PetscFunctionReturn(0);
36923b3e82cSAsbjørn Nilsen Riseth }
37023b3e82cSAsbjørn Nilsen Riseth 
37123b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESGetRestartFmRise(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,"SNESNGMRESGetRestartFmRise_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 PetscErrorCode SNESNGMRESGetRestartFmRise_NGMRES(SNES snes,PetscBool *flg)
38323b3e82cSAsbjørn Nilsen Riseth {
38423b3e82cSAsbjørn Nilsen Riseth   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
38523b3e82cSAsbjørn Nilsen Riseth 
38623b3e82cSAsbjørn Nilsen Riseth   PetscFunctionBegin;
38723b3e82cSAsbjørn Nilsen Riseth   *flg = ngmres->restart_fm_rise;
38823b3e82cSAsbjørn Nilsen Riseth   PetscFunctionReturn(0);
38923b3e82cSAsbjørn Nilsen Riseth }
39023b3e82cSAsbjørn Nilsen Riseth 
39123b3e82cSAsbjørn Nilsen Riseth 
39213a62661SPeter Brune /*@
39313a62661SPeter Brune     SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES.
39413a62661SPeter Brune 
39513a62661SPeter Brune     Logically Collective on SNES
39613a62661SPeter Brune 
39713a62661SPeter Brune     Input Parameters:
39813a62661SPeter Brune +   snes - the iterative context
39913a62661SPeter Brune -   rtype - restart type
40013a62661SPeter Brune 
40113a62661SPeter Brune     Options Database:
40213a62661SPeter Brune +   -snes_ngmres_restart_type<difference,periodic,none> - set the restart type
4030c777b0cSPeter Brune -   -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic
40413a62661SPeter Brune 
40513a62661SPeter Brune     Level: intermediate
40613a62661SPeter Brune 
40713a62661SPeter Brune     SNESNGMRESRestartTypes:
40813a62661SPeter Brune +   SNES_NGMRES_RESTART_NONE - never restart
40913a62661SPeter Brune .   SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria
41013a62661SPeter Brune -   SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations
41113a62661SPeter Brune 
41213a62661SPeter Brune     Notes:
41313a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
41413a62661SPeter Brune 
41513a62661SPeter Brune @*/
4160adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes,SNESNGMRESRestartType rtype)
4170adebc6cSBarry Smith {
41813a62661SPeter Brune   PetscErrorCode ierr;
4195fd66863SKarl Rupp 
42013a62661SPeter Brune   PetscFunctionBegin;
42113a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
42213a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr);
42313a62661SPeter Brune   PetscFunctionReturn(0);
42413a62661SPeter Brune }
42513a62661SPeter Brune 
42613a62661SPeter Brune /*@
42713a62661SPeter Brune     SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES.  This determines how the candidate solution and
42813a62661SPeter Brune     combined solution are used to create the next iterate.
42913a62661SPeter Brune 
43013a62661SPeter Brune     Logically Collective on SNES
43113a62661SPeter Brune 
43213a62661SPeter Brune     Input Parameters:
43313a62661SPeter Brune +   snes - the iterative context
43413a62661SPeter Brune -   stype - selection type
43513a62661SPeter Brune 
43613a62661SPeter Brune     Options Database:
43713a62661SPeter Brune .   -snes_ngmres_select_type<difference,none,linesearch>
43813a62661SPeter Brune 
43913a62661SPeter Brune     Level: intermediate
44013a62661SPeter Brune 
44113a62661SPeter Brune     SNESNGMRESSelectTypes:
44213a62661SPeter Brune +   SNES_NGMRES_SELECT_NONE - choose the combined solution all the time
44313a62661SPeter Brune .   SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria
44413a62661SPeter Brune -   SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination
44513a62661SPeter Brune 
44613a62661SPeter Brune     Notes:
44713a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
44813a62661SPeter Brune 
44913a62661SPeter Brune @*/
4500adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes,SNESNGMRESSelectType stype)
4510adebc6cSBarry Smith {
45213a62661SPeter Brune   PetscErrorCode ierr;
4535fd66863SKarl Rupp 
45413a62661SPeter Brune   PetscFunctionBegin;
45513a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
45613a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr);
45713a62661SPeter Brune   PetscFunctionReturn(0);
45813a62661SPeter Brune }
45913a62661SPeter Brune 
4600adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes,SNESNGMRESSelectType stype)
4610adebc6cSBarry Smith {
46213a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
4635fd66863SKarl Rupp 
46413a62661SPeter Brune   PetscFunctionBegin;
46513a62661SPeter Brune   ngmres->select_type = stype;
46613a62661SPeter Brune   PetscFunctionReturn(0);
46713a62661SPeter Brune }
46813a62661SPeter Brune 
4690adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes,SNESNGMRESRestartType rtype)
4700adebc6cSBarry Smith {
47113a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
4725fd66863SKarl Rupp 
47313a62661SPeter Brune   PetscFunctionBegin;
47413a62661SPeter Brune   ngmres->restart_type = rtype;
47513a62661SPeter Brune   PetscFunctionReturn(0);
47613a62661SPeter Brune }
47713a62661SPeter Brune 
478dfbf837cSBarry Smith /*MC
4791867fe5bSPeter Brune   SNESNGMRES - The Nonlinear Generalized Minimum Residual method.
480a312c225SMatthew G Knepley 
481dfbf837cSBarry Smith    Level: beginner
482dfbf837cSBarry Smith 
4831867fe5bSPeter Brune    Options Database:
48413a62661SPeter Brune +  -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution
48538774f0aSPeter Brune .  -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions
48638774f0aSPeter Brune .  -snes_ngmres_candidate        - Use NGMRES variant which combines candidate solutions instead of actual solutions
48713a62661SPeter Brune .  -snes_ngmres_m                - Number of stored previous solutions and residuals
48813a62661SPeter Brune .  -snes_ngmres_restart_it       - Number of iterations the restart conditions hold before restart
48913a62661SPeter Brune .  -snes_ngmres_gammaA           - Residual tolerance for solution select between the candidate and combination
49013a62661SPeter Brune .  -snes_ngmres_gammaC           - Residual tolerance for restart
49113a62661SPeter Brune .  -snes_ngmres_epsilonB         - Difference tolerance between subsequent solutions triggering restart
49213a62661SPeter Brune .  -snes_ngmres_deltaB           - Difference tolerance between residuals triggering restart
49323b3e82cSAsbjørn Nilsen Riseth .  -snes_ngmres_restart_fm_rise  - Restart on residual rise from x_M step
49413a62661SPeter Brune .  -snes_ngmres_monitor          - Prints relevant information about the ngmres iteration
4955c3e6ab7SPeter Brune .  -snes_linesearch_type <basic,l2,cp> - Line search type used for the default smoother
49613a62661SPeter Brune -  -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type
4971867fe5bSPeter Brune 
4981867fe5bSPeter Brune    Notes:
4991867fe5bSPeter Brune 
5001867fe5bSPeter Brune    The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized
5011867fe5bSPeter Brune    optimization problem at each iteration.
5021867fe5bSPeter Brune 
5034f02bc6aSBarry Smith    Very similar to the SNESANDERSON algorithm.
5044f02bc6aSBarry Smith 
5051867fe5bSPeter Brune    References:
50696a0c994SBarry Smith +  1. - C. W. Oosterlee and T. Washio, "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows",
507dfbf837cSBarry Smith    SIAM Journal on Scientific Computing, 21(5), 2000.
50896a0c994SBarry Smith -  2. - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers",
5094f02bc6aSBarry Smith    SIAM Review, 57(4), 2015
5104f02bc6aSBarry Smith 
5114f02bc6aSBarry Smith 
512dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types)
513dfbf837cSBarry Smith M*/
514a312c225SMatthew G Knepley 
5158cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NGMRES(SNES snes)
516a312c225SMatthew G Knepley {
517a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres;
518a312c225SMatthew G Knepley   PetscErrorCode ierr;
519d8d34be6SBarry Smith   SNESLineSearch linesearch;
520a312c225SMatthew G Knepley 
521a312c225SMatthew G Knepley   PetscFunctionBegin;
522a312c225SMatthew G Knepley   snes->ops->destroy        = SNESDestroy_NGMRES;
523a312c225SMatthew G Knepley   snes->ops->setup          = SNESSetUp_NGMRES;
524a312c225SMatthew G Knepley   snes->ops->setfromoptions = SNESSetFromOptions_NGMRES;
525a312c225SMatthew G Knepley   snes->ops->view           = SNESView_NGMRES;
526a312c225SMatthew G Knepley   snes->ops->solve          = SNESSolve_NGMRES;
527a312c225SMatthew G Knepley   snes->ops->reset          = SNESReset_NGMRES;
528a312c225SMatthew G Knepley 
529efd4aadfSBarry Smith   snes->usesnpc  = PETSC_TRUE;
5302c155ee1SBarry Smith   snes->usesksp  = PETSC_FALSE;
531efd4aadfSBarry Smith   snes->npcside  = PC_RIGHT;
5322c155ee1SBarry Smith 
5334fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_TRUE;
5344fc747eaSLawrence Mitchell 
535b00a9115SJed Brown   ierr          = PetscNewLog(snes,&ngmres);CHKERRQ(ierr);
536a312c225SMatthew G Knepley   snes->data    = (void*) ngmres;
537d2e16ddcSPeter Brune   ngmres->msize = 30;
53819653cdaSPeter Brune 
53988976e71SPeter Brune   if (!snes->tolerancesset) {
5400e444f03SPeter Brune     snes->max_funcs = 30000;
5410e444f03SPeter Brune     snes->max_its   = 10000;
54288976e71SPeter Brune   }
5430e444f03SPeter Brune 
54438774f0aSPeter Brune   ngmres->candidate = PETSC_FALSE;
545d2e16ddcSPeter Brune 
546d8d34be6SBarry Smith   ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr);
547ec786807SJed Brown   if (!((PetscObject)linesearch)->type_name) {
548d8d34be6SBarry Smith     ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr);
549ec786807SJed Brown   }
550d8d34be6SBarry Smith 
5510298fd71SBarry Smith   ngmres->additive_linesearch = NULL;
552077c4231SPeter Brune   ngmres->approxfunc          = PETSC_FALSE;
55328ed4a04SPeter Brune   ngmres->restart_it          = 2;
55413a62661SPeter Brune   ngmres->restart_periodic    = 30;
555f109b39eSPeter Brune   ngmres->gammaA              = 2.0;
556f109b39eSPeter Brune   ngmres->gammaC              = 2.0;
557cac108bcSPeter Brune   ngmres->deltaB              = 0.9;
558cac108bcSPeter Brune   ngmres->epsilonB            = 0.1;
55923b3e82cSAsbjørn Nilsen Riseth   ngmres->restart_fm_rise     = PETSC_FALSE;
560e7058c64SPeter Brune 
56113a62661SPeter Brune   ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE;
56213a62661SPeter Brune   ngmres->select_type  = SNES_NGMRES_SELECT_DIFFERENCE;
56313a62661SPeter Brune 
564bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetSelectType_C",SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr);
565bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartType_C",SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr);
56623b3e82cSAsbjørn Nilsen Riseth   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartFmRise_C",SNESNGMRESSetRestartFmRise_NGMRES);CHKERRQ(ierr);
56723b3e82cSAsbjørn Nilsen Riseth   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESGetRestartFmRise_C",SNESNGMRESGetRestartFmRise_NGMRES);CHKERRQ(ierr);
568a312c225SMatthew G Knepley   PetscFunctionReturn(0);
569a312c225SMatthew G Knepley }
570