xref: /petsc/src/snes/impls/ngmres/snesngmres.c (revision 13a62661d0525ff64d8b6ff69405cd2b20448c7e)
1*13a62661SPeter Brune #include <../src/snes/impls/ngmres/snesngmres.h> /*I "petscsnes.h" I*/
219653cdaSPeter Brune #include <petscblaslapack.h>
3a312c225SMatthew G Knepley 
4*13a62661SPeter Brune const char *SNESNGMRESRestartTypes[] = {"NONE","PERIODIC","DIFFERENCE","SNESNGMRESRestartType","SNES_NGMRES_RESTART_",0};
5*13a62661SPeter Brune const char *SNESNGMRESSelectTypes[] = {"NONE","DIFFERENCE","LINESEARCH","SNESNGMRESSelectType","SNES_NGMRES_SELECT_",0};
6*13a62661SPeter Brune 
7a312c225SMatthew G Knepley #undef __FUNCT__
8a312c225SMatthew G Knepley #define __FUNCT__ "SNESReset_NGMRES"
9a312c225SMatthew G Knepley PetscErrorCode SNESReset_NGMRES(SNES snes)
10a312c225SMatthew G Knepley {
11a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres = (SNES_NGMRES*) snes->data;
12a312c225SMatthew G Knepley   PetscErrorCode ierr;
13a312c225SMatthew G Knepley 
14a312c225SMatthew G Knepley   PetscFunctionBegin;
15f109b39eSPeter Brune   ierr = VecDestroyVecs(ngmres->msize, &ngmres->Fdot);CHKERRQ(ierr);
16f109b39eSPeter Brune   ierr = VecDestroyVecs(ngmres->msize, &ngmres->Xdot);CHKERRQ(ierr);
17f1c6b773SPeter Brune   ierr = SNESLineSearchDestroy(&ngmres->additive_linesearch);CHKERRQ(ierr);
189e764e56SPeter Brune 
19a312c225SMatthew G Knepley   PetscFunctionReturn(0);
20a312c225SMatthew G Knepley }
21a312c225SMatthew G Knepley 
22a312c225SMatthew G Knepley #undef __FUNCT__
23a312c225SMatthew G Knepley #define __FUNCT__ "SNESDestroy_NGMRES"
24a312c225SMatthew G Knepley PetscErrorCode SNESDestroy_NGMRES(SNES snes)
25a312c225SMatthew G Knepley {
26a312c225SMatthew G Knepley   PetscErrorCode ierr;
2778440776SJed Brown   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
28a312c225SMatthew G Knepley 
29a312c225SMatthew G Knepley   PetscFunctionBegin;
30a312c225SMatthew G Knepley   ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr);
31f109b39eSPeter Brune   ierr = PetscFree5(ngmres->h, ngmres->beta, ngmres->xi, ngmres->fnorms, ngmres->q);CHKERRQ(ierr);
3219653cdaSPeter Brune   ierr = PetscFree(ngmres->s);CHKERRQ(ierr);
3318aa0c0cSPeter Brune   ierr = PetscFree(ngmres->xnorms);CHKERRQ(ierr);
3419653cdaSPeter Brune #if PETSC_USE_COMPLEX
3519653cdaSPeter Brune   ierr = PetscFree(ngmres->rwork);
3619653cdaSPeter Brune #endif
3719653cdaSPeter Brune   ierr = PetscFree(ngmres->work);
3819653cdaSPeter Brune   ierr = PetscFree(snes->data);
39a312c225SMatthew G Knepley   PetscFunctionReturn(0);
40a312c225SMatthew G Knepley }
41a312c225SMatthew G Knepley 
42a312c225SMatthew G Knepley #undef __FUNCT__
43a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetUp_NGMRES"
44a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes)
45a312c225SMatthew G Knepley {
46a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES *) snes->data;
47e7058c64SPeter Brune   const char     *optionsprefix;
4819653cdaSPeter Brune   PetscInt       msize,hsize;
49a312c225SMatthew G Knepley   PetscErrorCode ierr;
50a312c225SMatthew G Knepley 
51a312c225SMatthew G Knepley   PetscFunctionBegin;
5278440776SJed Brown   ierr = SNESDefaultGetWork(snes,5);CHKERRQ(ierr);
5378440776SJed Brown   if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);}
5478440776SJed Brown   if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);}
5578440776SJed Brown   if (!ngmres->setup_called) {
56087dfb9eSxuemin     msize         = ngmres->msize;  /* restart size */
5719653cdaSPeter Brune     hsize         = msize * msize;
58087dfb9eSxuemin 
5998b3e84cSPeter Brune     /* explicit least squares minimization solve */
6019653cdaSPeter Brune     ierr = PetscMalloc5(hsize,PetscScalar,&ngmres->h,
6119653cdaSPeter Brune                         msize,PetscScalar,&ngmres->beta,
6219653cdaSPeter Brune                         msize,PetscScalar,&ngmres->xi,
63f109b39eSPeter Brune                         msize,PetscReal,  &ngmres->fnorms,
6419653cdaSPeter Brune                         hsize,PetscScalar,&ngmres->q);CHKERRQ(ierr);
6518aa0c0cSPeter Brune     if (ngmres->singlereduction) {
6618aa0c0cSPeter Brune       ierr = PetscMalloc(msize*sizeof(PetscReal),&ngmres->xnorms);CHKERRQ(ierr);
6718aa0c0cSPeter Brune     }
6819653cdaSPeter Brune     ngmres->nrhs = 1;
6919653cdaSPeter Brune     ngmres->lda = msize;
7019653cdaSPeter Brune     ngmres->ldb = msize;
7119653cdaSPeter Brune     ierr = PetscMalloc(msize*sizeof(PetscScalar),&ngmres->s);CHKERRQ(ierr);
7219653cdaSPeter Brune     ierr = PetscMemzero(ngmres->h,   hsize*sizeof(PetscScalar));CHKERRQ(ierr);
7319653cdaSPeter Brune     ierr = PetscMemzero(ngmres->q,   hsize*sizeof(PetscScalar));CHKERRQ(ierr);
7419653cdaSPeter Brune     ierr = PetscMemzero(ngmres->xi,  msize*sizeof(PetscScalar));CHKERRQ(ierr);
7519653cdaSPeter Brune     ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr);
7619653cdaSPeter Brune     ngmres->lwork = 12*msize;
7719653cdaSPeter Brune #if PETSC_USE_COMPLEX
7819653cdaSPeter Brune     ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork);
7919653cdaSPeter Brune #endif
8019653cdaSPeter Brune     ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work);
8178440776SJed Brown   }
82e7058c64SPeter Brune 
83e7058c64SPeter Brune   /* linesearch setup */
84e7058c64SPeter Brune   ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr);
85e7058c64SPeter Brune 
86*13a62661SPeter Brune   if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) {
87f1c6b773SPeter Brune     ierr = SNESLineSearchCreate(((PetscObject)snes)->comm, &ngmres->additive_linesearch);CHKERRQ(ierr);
88f1c6b773SPeter Brune     ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch, snes);CHKERRQ(ierr);
891a4f838cSPeter Brune     ierr = SNESLineSearchSetType(ngmres->additive_linesearch, SNESLINESEARCHL2);CHKERRQ(ierr);
90f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch, "additive_");CHKERRQ(ierr);
91f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch, optionsprefix);CHKERRQ(ierr);
92f1c6b773SPeter Brune     ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr);
93e7058c64SPeter Brune   }
94e7058c64SPeter Brune 
9578440776SJed Brown   ngmres->setup_called = PETSC_TRUE;
96a312c225SMatthew G Knepley   PetscFunctionReturn(0);
97a312c225SMatthew G Knepley }
98a312c225SMatthew G Knepley 
99a312c225SMatthew G Knepley #undef __FUNCT__
100a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES"
101a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes)
102a312c225SMatthew G Knepley {
103a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres = (SNES_NGMRES *) snes->data;
104a312c225SMatthew G Knepley   PetscErrorCode ierr;
105dfbf837cSBarry Smith   PetscBool      debug;
106f1c6b773SPeter Brune   SNESLineSearch linesearch;
107a312c225SMatthew G Knepley   PetscFunctionBegin;
108a312c225SMatthew G Knepley   ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr);
109*13a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes,
110*13a62661SPeter Brune                           (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,PETSC_NULL);CHKERRQ(ierr);
111*13a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes,
112*13a62661SPeter Brune                           (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,PETSC_NULL);CHKERRQ(ierr);
113d2e16ddcSPeter Brune   ierr = PetscOptionsBool("-snes_ngmres_anderson", "Use Anderson mixing storage",        "SNES", ngmres->anderson,  &ngmres->anderson, PETSC_NULL);CHKERRQ(ierr);
11419653cdaSPeter Brune   ierr = PetscOptionsInt("-snes_ngmres_m",         "Number of directions",               "SNES", ngmres->msize,  &ngmres->msize, PETSC_NULL);CHKERRQ(ierr);
11528ed4a04SPeter Brune   ierr = PetscOptionsInt("-snes_ngmres_restart_it","Tolerance iterations before restart","SNES", ngmres->restart_it,  &ngmres->restart_it, PETSC_NULL);CHKERRQ(ierr);
116dfbf837cSBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_monitor",  "Monitor actions of NGMRES",          "SNES", ngmres->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);CHKERRQ(ierr);
117dfbf837cSBarry Smith   if (debug) {
118dfbf837cSBarry Smith     ngmres->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr);
119dfbf837cSBarry Smith   }
1206a7cf640SPeter Brune   ierr = PetscOptionsReal("-snes_ngmres_gammaA",   "Residual selection constant",   "SNES", ngmres->gammaA, &ngmres->gammaA, PETSC_NULL);CHKERRQ(ierr);
1216a7cf640SPeter Brune   ierr = PetscOptionsReal("-snes_ngmres_gammaC", "  Residual restart constant",     "SNES", ngmres->gammaC, &ngmres->gammaC, PETSC_NULL);CHKERRQ(ierr);
1226a7cf640SPeter Brune   ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES", ngmres->epsilonB, &ngmres->epsilonB, PETSC_NULL);CHKERRQ(ierr);
1236a7cf640SPeter Brune   ierr = PetscOptionsReal("-snes_ngmres_deltaB",   "Difference residual selection constant", "SNES", ngmres->deltaB, &ngmres->deltaB, PETSC_NULL);CHKERRQ(ierr);
1244d116c7dSPeter Brune   ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions",  "SNES", ngmres->singlereduction, &ngmres->singlereduction, PETSC_NULL);CHKERRQ(ierr);
125a312c225SMatthew G Knepley   ierr = PetscOptionsTail();CHKERRQ(ierr);
1266a7cf640SPeter Brune   if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA;
1279e764e56SPeter Brune 
1289e764e56SPeter Brune   /* set the default type of the line search if the user hasn't already. */
1299e764e56SPeter Brune   if (!snes->linesearch) {
130f1c6b773SPeter Brune     ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
1311a4f838cSPeter Brune     ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC);CHKERRQ(ierr);
1329e764e56SPeter Brune   }
133a312c225SMatthew G Knepley   PetscFunctionReturn(0);
134a312c225SMatthew G Knepley }
135a312c225SMatthew G Knepley 
136a312c225SMatthew G Knepley #undef __FUNCT__
137a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES"
138a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes, PetscViewer viewer)
139a312c225SMatthew G Knepley {
140a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres = (SNES_NGMRES *) snes->data;
141a312c225SMatthew G Knepley   PetscBool      iascii;
142a312c225SMatthew G Knepley   PetscErrorCode ierr;
143a312c225SMatthew G Knepley 
144a312c225SMatthew G Knepley   PetscFunctionBegin;
145a312c225SMatthew G Knepley   ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
146a312c225SMatthew G Knepley   if (iascii) {
1479e764e56SPeter Brune 
148f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer, "  Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr);
149f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer, "  Residual selection: gammaA=%1.0e, gammaC=%1.0e\n", ngmres->gammaA, ngmres->gammaC);CHKERRQ(ierr);
150f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer, "  Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n", ngmres->epsilonB, ngmres->deltaB);CHKERRQ(ierr);
151a312c225SMatthew G Knepley   }
152a312c225SMatthew G Knepley   PetscFunctionReturn(0);
153a312c225SMatthew G Knepley }
154a312c225SMatthew G Knepley 
155a312c225SMatthew G Knepley #undef __FUNCT__
156a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES"
157211b2d39SPeter Brune 
158a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes)
159a312c225SMatthew G Knepley {
160087dfb9eSxuemin   SNES_NGMRES        *ngmres = (SNES_NGMRES *) snes->data;
16198b3e84cSPeter Brune   /* present solution, residual, and preconditioned residual */
1629f425c49SPeter Brune   Vec                 X, F, B, D, Y;
163f109b39eSPeter Brune 
164f109b39eSPeter Brune   /* candidate linear combination answers */
1654b32a720SPeter Brune   Vec                 XA, FA, XM, FM, FPC;
16619653cdaSPeter Brune 
16798b3e84cSPeter Brune   /* previous iterations to construct the subspace */
168f109b39eSPeter Brune   Vec                 *Fdot = ngmres->Fdot;
169f109b39eSPeter Brune   Vec                 *Xdot = ngmres->Xdot;
17019653cdaSPeter Brune 
17198b3e84cSPeter Brune   /* coefficients and RHS to the minimization problem */
17219653cdaSPeter Brune   PetscScalar         *beta = ngmres->beta;
17319653cdaSPeter Brune   PetscScalar         *xi   = ngmres->xi;
17418aa0c0cSPeter Brune   PetscReal           fnorm, fMnorm, fAnorm;
17519653cdaSPeter Brune   PetscReal           nu;
17619653cdaSPeter Brune   PetscScalar         alph_total = 0.;
17728ed4a04SPeter Brune   PetscInt            i, j, k, k_restart, l, ivec, restart_count = 0;
17819653cdaSPeter Brune 
17998b3e84cSPeter Brune   /* solution selection data */
18019653cdaSPeter Brune   PetscBool           selectA, selectRestart;
181f109b39eSPeter Brune   PetscReal           dnorm, dminnorm, dcurnorm;
182f109b39eSPeter Brune   PetscReal           fminnorm;
18319653cdaSPeter Brune 
1841e633543SBarry Smith   SNESConvergedReason reason;
185f109b39eSPeter Brune   PetscBool           lssucceed;
186a312c225SMatthew G Knepley   PetscErrorCode      ierr;
187a312c225SMatthew G Knepley 
188a312c225SMatthew G Knepley   PetscFunctionBegin;
18998b3e84cSPeter Brune   /* variable initialization */
190a312c225SMatthew G Knepley   snes->reason  = SNES_CONVERGED_ITERATING;
191f109b39eSPeter Brune   X             = snes->vec_sol;
192f109b39eSPeter Brune   F             = snes->vec_func;
193f109b39eSPeter Brune   B             = snes->vec_rhs;
194f109b39eSPeter Brune   XA            = snes->vec_sol_update;
195f109b39eSPeter Brune   FA            = snes->work[0];
196f109b39eSPeter Brune   D             = snes->work[1];
197f109b39eSPeter Brune 
198f109b39eSPeter Brune   /* work for the line search */
199f109b39eSPeter Brune   Y             = snes->work[2];
2009f425c49SPeter Brune   XM            = snes->work[3];
2019f425c49SPeter Brune   FM            = snes->work[4];
202a312c225SMatthew G Knepley 
203a312c225SMatthew G Knepley   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
204a312c225SMatthew G Knepley   snes->iter = 0;
205a312c225SMatthew G Knepley   snes->norm = 0.;
206a312c225SMatthew G Knepley   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
20719653cdaSPeter Brune 
20898b3e84cSPeter Brune   /* initialization */
20919653cdaSPeter Brune 
21098b3e84cSPeter Brune   /* r = F(x) */
211e4ed7901SPeter Brune   if (!snes->vec_func_init_set) {
212f109b39eSPeter Brune     ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr);
213a312c225SMatthew G Knepley     if (snes->domainerror) {
214a312c225SMatthew G Knepley       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
215a312c225SMatthew G Knepley       PetscFunctionReturn(0);
216a312c225SMatthew G Knepley     }
217e4ed7901SPeter Brune   } else {
218e4ed7901SPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
219e4ed7901SPeter Brune   }
22019653cdaSPeter Brune 
221e4ed7901SPeter Brune   if (!snes->norm_init_set) {
222f109b39eSPeter Brune     ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr);
223f109b39eSPeter Brune     if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation");
224e4ed7901SPeter Brune   } else {
225e4ed7901SPeter Brune     fnorm = snes->norm_init;
226e4ed7901SPeter Brune     snes->norm_init_set = PETSC_FALSE;
227e4ed7901SPeter Brune   }
228e4ed7901SPeter Brune   fminnorm = fnorm;
229e4ed7901SPeter Brune   /* nu = (r, r) */
230e4ed7901SPeter Brune   nu = fnorm*fnorm;
23119653cdaSPeter Brune 
23298b3e84cSPeter Brune   /* q_{00} = nu  */
23319653cdaSPeter Brune   Q(0,0) = nu;
234f109b39eSPeter Brune   ngmres->fnorms[0] = fnorm;
235f109b39eSPeter Brune   /* Fdot[0] = F */
236f109b39eSPeter Brune   ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr);
237f109b39eSPeter Brune   ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr);
238087dfb9eSxuemin 
239a312c225SMatthew G Knepley   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
240f109b39eSPeter Brune   snes->norm = fnorm;
241a312c225SMatthew G Knepley   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
242f109b39eSPeter Brune   SNESLogConvHistory(snes, fnorm, 0);
243f109b39eSPeter Brune   ierr = SNESMonitor(snes, 0, fnorm);CHKERRQ(ierr);
244f109b39eSPeter Brune   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
245a312c225SMatthew G Knepley   if (snes->reason) PetscFunctionReturn(0);
246a312c225SMatthew G Knepley 
24719653cdaSPeter Brune   k_restart = 1;
24819653cdaSPeter Brune   l = 1;
24909c08436SPeter Brune   for (k=1; k < snes->max_its+1; k++) {
25098b3e84cSPeter Brune     /* select which vector of the stored subspace will be updated */
25198b3e84cSPeter Brune     ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */
25219653cdaSPeter Brune 
25398b3e84cSPeter Brune     /* Computation of x^M */
2548cc86e31SPeter Brune     if (snes->pc) {
2559f425c49SPeter Brune       ierr = VecCopy(X, XM);CHKERRQ(ierr);
256e4ed7901SPeter Brune       ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr);
257e4ed7901SPeter Brune       ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr);
2589f425c49SPeter Brune       ierr = SNESSolve(snes->pc, B, XM);CHKERRQ(ierr);
2598cc86e31SPeter Brune       ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
2608cc86e31SPeter Brune       if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
2618cc86e31SPeter Brune         snes->reason = SNES_DIVERGED_INNER;
2628cc86e31SPeter Brune         PetscFunctionReturn(0);
2638cc86e31SPeter Brune       }
2644b32a720SPeter Brune       ierr = SNESGetFunction(snes->pc, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr);
2654b32a720SPeter Brune       ierr = VecCopy(FPC, FM);CHKERRQ(ierr);
2664b32a720SPeter Brune       ierr = SNESGetFunctionNorm(snes->pc, &fMnorm);CHKERRQ(ierr);
2678cc86e31SPeter Brune     } else {
268f109b39eSPeter Brune       /* no preconditioner -- just take gradient descent with line search */
269f109b39eSPeter Brune       ierr = VecCopy(F, Y);CHKERRQ(ierr);
270e7058c64SPeter Brune       ierr = VecCopy(F, FM);CHKERRQ(ierr);
271e7058c64SPeter Brune       ierr = VecCopy(X, XM);CHKERRQ(ierr);
272e7058c64SPeter Brune       fMnorm = fnorm;
273f1c6b773SPeter Brune       ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr);
274f1c6b773SPeter Brune       ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssucceed);CHKERRQ(ierr);
275f109b39eSPeter Brune       if (!lssucceed) {
276f109b39eSPeter Brune         if (++snes->numFailures >= snes->maxFailures) {
277f109b39eSPeter Brune           snes->reason = SNES_DIVERGED_LINE_SEARCH;
278f109b39eSPeter Brune           PetscFunctionReturn(0);
279f109b39eSPeter Brune         }
280f109b39eSPeter Brune       }
2816634f59bSPeter Brune     }
2821e633543SBarry Smith 
28398b3e84cSPeter Brune     /* r = F(x) */
2849f425c49SPeter Brune     nu = fMnorm*fMnorm;
2859f425c49SPeter Brune     if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of F^M */
28619653cdaSPeter Brune 
28798b3e84cSPeter Brune     /* construct the right hand side and xi factors */
2888c09b6b7SPeter Brune     ierr = VecMDot(FM, l, Fdot, xi);CHKERRQ(ierr);
2898c09b6b7SPeter Brune 
29019653cdaSPeter Brune     for (i = 0; i < l; i++) {
29119653cdaSPeter Brune       beta[i] = nu - xi[i];
29219653cdaSPeter Brune     }
29319653cdaSPeter Brune 
29498b3e84cSPeter Brune     /* construct h */
29519653cdaSPeter Brune     for (j = 0; j < l; j++) {
29619653cdaSPeter Brune       for (i = 0; i < l; i++) {
29719653cdaSPeter Brune         H(i, j) = Q(i, j) - xi[i] - xi[j] + nu;
29819653cdaSPeter Brune       }
29919653cdaSPeter Brune     }
300f109b39eSPeter Brune 
301f109b39eSPeter Brune     if(l == 1) {
302f109b39eSPeter Brune       /* simply set alpha[0] = beta[0] / H[0, 0] */
303f109b39eSPeter Brune       beta[0] = beta[0] / H(0, 0);
304f109b39eSPeter Brune     } else {
30519653cdaSPeter Brune #ifdef PETSC_MISSING_LAPACK_GELSS
30619653cdaSPeter Brune     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "NGMRES with LS requires the LAPACK GELSS routine.");
3074a0c5b0cSMatthew G Knepley #else
30819653cdaSPeter Brune     ngmres->m = PetscBLASIntCast(l);
30919653cdaSPeter Brune     ngmres->n = PetscBLASIntCast(l);
31019653cdaSPeter Brune     ngmres->info = PetscBLASIntCast(0);
31119653cdaSPeter Brune     ngmres->rcond = -1.;
3128e57ea43SSatish Balay     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
31319653cdaSPeter Brune #ifdef PETSC_USE_COMPLEX
31419653cdaSPeter Brune     LAPACKgelss_(&ngmres->m,
31519653cdaSPeter Brune                  &ngmres->n,
31619653cdaSPeter Brune                  &ngmres->nrhs,
31719653cdaSPeter Brune                  ngmres->h,
31819653cdaSPeter Brune                  &ngmres->lda,
31919653cdaSPeter Brune                  ngmres->beta,
32019653cdaSPeter Brune                  &ngmres->ldb,
32119653cdaSPeter Brune                  ngmres->s,
32219653cdaSPeter Brune                  &ngmres->rcond,
32319653cdaSPeter Brune                  &ngmres->rank,
32419653cdaSPeter Brune                  ngmres->work,
32519653cdaSPeter Brune                  &ngmres->lwork,
32619653cdaSPeter Brune                  ngmres->rwork,
32719653cdaSPeter Brune                  &ngmres->info);
32819653cdaSPeter Brune #else
32919653cdaSPeter Brune     LAPACKgelss_(&ngmres->m,
33019653cdaSPeter Brune                  &ngmres->n,
33119653cdaSPeter Brune                  &ngmres->nrhs,
33219653cdaSPeter Brune                  ngmres->h,
33319653cdaSPeter Brune                  &ngmres->lda,
33419653cdaSPeter Brune                  ngmres->beta,
33519653cdaSPeter Brune                  &ngmres->ldb,
33619653cdaSPeter Brune                  ngmres->s,
33719653cdaSPeter Brune                  &ngmres->rcond,
33819653cdaSPeter Brune                  &ngmres->rank,
33919653cdaSPeter Brune                  ngmres->work,
34019653cdaSPeter Brune                  &ngmres->lwork,
34119653cdaSPeter Brune                  &ngmres->info);
34219653cdaSPeter Brune #endif
3438e57ea43SSatish Balay     ierr = PetscFPTrapPop();CHKERRQ(ierr);
34419653cdaSPeter Brune     if (ngmres->info < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to GELSS");
34519653cdaSPeter Brune     if (ngmres->info > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SVD failed to converge");
346a312c225SMatthew G Knepley #endif
347f109b39eSPeter Brune     }
348a312c225SMatthew G Knepley 
34919653cdaSPeter Brune     alph_total = 0.;
35019653cdaSPeter Brune     for (i = 0; i < l; i++) {
35119653cdaSPeter Brune       alph_total += beta[i];
352c0bbabecSxuemin     }
353f109b39eSPeter Brune 
3549f425c49SPeter Brune     ierr = VecCopy(XM, XA);CHKERRQ(ierr);
355f109b39eSPeter Brune     ierr = VecScale(XA, 1. - alph_total);CHKERRQ(ierr);
356087dfb9eSxuemin 
3578c09b6b7SPeter Brune     ierr = VecMAXPY(XA, l, beta, Xdot);CHKERRQ(ierr);
358f109b39eSPeter Brune     ierr = SNESComputeFunction(snes, XA, FA);CHKERRQ(ierr);
35919653cdaSPeter Brune 
3609f425c49SPeter Brune     /* differences for selection and restart */
361*13a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) {
36218aa0c0cSPeter Brune       if (ngmres->singlereduction) {
36318aa0c0cSPeter Brune         dminnorm = -1.0;
364f109b39eSPeter Brune         ierr=VecCopy(XA, D);CHKERRQ(ierr);
36518aa0c0cSPeter Brune         ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr);
36618aa0c0cSPeter Brune         for(i=0;i<l;i++) {
36718aa0c0cSPeter Brune           ierr=VecAXPY(Xdot[i],-1.0,XA);CHKERRQ(ierr);
36818aa0c0cSPeter Brune         }
36918aa0c0cSPeter Brune         ierr = VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
37018aa0c0cSPeter Brune         ierr = VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr);
37118aa0c0cSPeter Brune         for (i=0;i<l;i++) {
37218aa0c0cSPeter Brune           ierr = VecNormBegin(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr);
37318aa0c0cSPeter Brune         }
37418aa0c0cSPeter Brune         ierr = VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
37518aa0c0cSPeter Brune         ierr = VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr);
37618aa0c0cSPeter Brune         for (i=0;i<l;i++) {
37718aa0c0cSPeter Brune           ierr = VecNormEnd(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr);
37818aa0c0cSPeter Brune         }
37918aa0c0cSPeter Brune         for(i=0;i<l;i++) {
38018aa0c0cSPeter Brune           dcurnorm = ngmres->xnorms[i];
38118aa0c0cSPeter Brune           if ((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm;
38218aa0c0cSPeter Brune           ierr=VecAXPY(Xdot[i],1.0,XA);CHKERRQ(ierr);
38318aa0c0cSPeter Brune         }
38418aa0c0cSPeter Brune       } else {
38518aa0c0cSPeter Brune         ierr=VecCopy(XA, D);CHKERRQ(ierr);
38618aa0c0cSPeter Brune         ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr);
38718aa0c0cSPeter Brune         ierr=VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr);
38818aa0c0cSPeter Brune         ierr=VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
38918aa0c0cSPeter Brune         ierr=VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr);
39018aa0c0cSPeter Brune         ierr=VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
391f109b39eSPeter Brune         dminnorm = -1.0;
39219653cdaSPeter Brune         for(i=0;i<l;i++) {
393f109b39eSPeter Brune           ierr=VecCopy(XA, D);CHKERRQ(ierr);
394f109b39eSPeter Brune           ierr=VecAXPY(D, -1.0, Xdot[i]);CHKERRQ(ierr);
395f109b39eSPeter Brune           ierr=VecNorm(D, NORM_2, &dcurnorm);CHKERRQ(ierr);
396f109b39eSPeter Brune           if((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm;
39719653cdaSPeter Brune         }
39818aa0c0cSPeter Brune       }
399*13a62661SPeter Brune     } else {
400*13a62661SPeter Brune       ierr = VecNorm(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
401*13a62661SPeter Brune     }
4029f425c49SPeter Brune     /* combination (additive) or selection (multiplicative) of the N-GMRES solution */
403*13a62661SPeter Brune     if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) {
4049f425c49SPeter Brune       /* X = X + \lambda(XA - X) */
4059f425c49SPeter Brune       if (ngmres->monitor) {
4069f425c49SPeter Brune         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr);
4079f425c49SPeter Brune       }
408*13a62661SPeter Brune       ierr = VecCopy(FM, F);CHKERRQ(ierr);
409*13a62661SPeter Brune       ierr = VecCopy(XM, X);CHKERRQ(ierr);
4109f425c49SPeter Brune       ierr = VecCopy(XA, Y);CHKERRQ(ierr);
411*13a62661SPeter Brune       fnorm = fMnorm;
412eb1825c3SPeter Brune       ierr = VecAYPX(Y, -1.0, X);CHKERRQ(ierr);
413f1c6b773SPeter Brune       ierr = SNESLineSearchApply(ngmres->additive_linesearch,X,F,&fnorm,Y);CHKERRQ(ierr);
414f1c6b773SPeter Brune       ierr = SNESLineSearchGetSuccess(ngmres->additive_linesearch, &lssucceed);CHKERRQ(ierr);
4159f425c49SPeter Brune       if (!lssucceed) {
4169f425c49SPeter Brune         if (++snes->numFailures >= snes->maxFailures) {
4179f425c49SPeter Brune           snes->reason = SNES_DIVERGED_LINE_SEARCH;
4189f425c49SPeter Brune           PetscFunctionReturn(0);
4199f425c49SPeter Brune         }
4209f425c49SPeter Brune       }
4219f425c49SPeter Brune       if (ngmres->monitor) {
4229f425c49SPeter Brune         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Additive solution: ||F||_2 = %e\n", fnorm);CHKERRQ(ierr);
4239f425c49SPeter Brune       }
424*13a62661SPeter Brune     } else if (ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) {
4259f425c49SPeter Brune       selectA = PETSC_TRUE;
4269f425c49SPeter Brune       /* Conditions for choosing the accelerated answer */
4279f425c49SPeter Brune       /* Criterion A -- the norm of the function isn't increased above the minimum by too much */
4289f425c49SPeter Brune       if (fAnorm >= ngmres->gammaA*fminnorm) {
4299f425c49SPeter Brune         selectA = PETSC_FALSE;
4309f425c49SPeter Brune       }
4319f425c49SPeter Brune       /* Criterion B -- the choice of x^A isn't too close to some other choice */
432cf22de31SPeter Brune       if (ngmres->epsilonB*dnorm<dminnorm || PetscSqrtReal(fnorm)<ngmres->deltaB*PetscSqrtReal(fminnorm)) {
43319653cdaSPeter Brune       } else {
43419653cdaSPeter Brune         selectA=PETSC_FALSE;
43519653cdaSPeter Brune       }
43619653cdaSPeter Brune       if (selectA) {
437dfbf837cSBarry Smith         if (ngmres->monitor) {
4389e764e56SPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_A, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr);
439dfbf837cSBarry Smith         }
44098b3e84cSPeter Brune         /* copy it over */
441f109b39eSPeter Brune         fnorm = fAnorm;
442f109b39eSPeter Brune         nu = fnorm*fnorm;
443f109b39eSPeter Brune         ierr = VecCopy(FA, F);CHKERRQ(ierr);
444f109b39eSPeter Brune         ierr = VecCopy(XA, X);CHKERRQ(ierr);
44519653cdaSPeter Brune       } else {
446dfbf837cSBarry Smith         if (ngmres->monitor) {
447f109b39eSPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_M, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fnorm);CHKERRQ(ierr);
448dfbf837cSBarry Smith         }
4499f425c49SPeter Brune         fnorm = fMnorm;
4509f425c49SPeter Brune         nu = fnorm*fnorm;
4519f425c49SPeter Brune         ierr = VecCopy(FM, F);CHKERRQ(ierr);
4529f425c49SPeter Brune         ierr = VecCopy(XM, X);CHKERRQ(ierr);
4539f425c49SPeter Brune       }
454*13a62661SPeter Brune     } else { /* none */
455*13a62661SPeter Brune       fnorm = fAnorm;
456*13a62661SPeter Brune       nu = fnorm*fnorm;
457*13a62661SPeter Brune       ierr = VecCopy(FA, F);CHKERRQ(ierr);
458*13a62661SPeter Brune       ierr = VecCopy(XA, X);CHKERRQ(ierr);
45919653cdaSPeter Brune     }
460211b2d39SPeter Brune 
46119653cdaSPeter Brune     selectRestart = PETSC_FALSE;
462*13a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) {
46398b3e84cSPeter Brune       /* difference stagnation restart */
464cf22de31SPeter Brune       if((ngmres->epsilonB*dnorm > dminnorm) && (PetscSqrtReal(fAnorm) > ngmres->deltaB*PetscSqrtReal(fminnorm))) {
465dfbf837cSBarry Smith         if (ngmres->monitor) {
466f109b39eSPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "difference restart: %e > %e\n", ngmres->epsilonB*dnorm, dminnorm);CHKERRQ(ierr);
467dfbf837cSBarry Smith         }
46819653cdaSPeter Brune         selectRestart = PETSC_TRUE;
46919653cdaSPeter Brune       }
47098b3e84cSPeter Brune       /* residual stagnation restart */
471cf22de31SPeter Brune       if (PetscSqrtReal(fAnorm) > ngmres->gammaC*PetscSqrtReal(fminnorm)) {
472dfbf837cSBarry Smith         if (ngmres->monitor) {
473cf22de31SPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "residual restart: %e > %e\n", PetscSqrtReal(fAnorm), ngmres->gammaC*PetscSqrtReal(fminnorm));CHKERRQ(ierr);
474dfbf837cSBarry Smith         }
47519653cdaSPeter Brune         selectRestart = PETSC_TRUE;
47619653cdaSPeter Brune       }
47728ed4a04SPeter Brune       /* if the restart conditions persist for more than restart_it iterations, restart. */
47819653cdaSPeter Brune       if (selectRestart) {
47928ed4a04SPeter Brune         restart_count++;
48028ed4a04SPeter Brune       } else {
48128ed4a04SPeter Brune         restart_count = 0;
48228ed4a04SPeter Brune       }
483*13a62661SPeter Brune     } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) {
484*13a62661SPeter Brune       if (k_restart > ngmres->restart_periodic) {
485*13a62661SPeter Brune         if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor, "periodic restart after %D iterations\n", k_restart);CHKERRQ(ierr);
486*13a62661SPeter Brune         restart_count = ngmres->restart_it;
487*13a62661SPeter Brune       }
488*13a62661SPeter Brune     }
48928ed4a04SPeter Brune     /* restart after restart conditions have persisted for a fixed number of iterations */
49028ed4a04SPeter Brune     if (restart_count >= ngmres->restart_it) {
491dfbf837cSBarry Smith       if (ngmres->monitor){
492dfbf837cSBarry Smith         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Restarted at iteration %d\n", k_restart);CHKERRQ(ierr);
493dfbf837cSBarry Smith       }
49428ed4a04SPeter Brune       restart_count = 0;
49519653cdaSPeter Brune       k_restart = 1;
49619653cdaSPeter Brune       l = 1;
49798b3e84cSPeter Brune       /* q_{00} = nu */
498d2e16ddcSPeter Brune       if (ngmres->anderson) {
499d2e16ddcSPeter Brune         ngmres->fnorms[0] = fMnorm;
500d2e16ddcSPeter Brune         nu = fMnorm*fMnorm;
501d2e16ddcSPeter Brune         Q(0,0) = nu;
502d2e16ddcSPeter Brune         /* Fdot[0] = F */
503d2e16ddcSPeter Brune         ierr = VecCopy(XM, Xdot[0]);CHKERRQ(ierr);
504d2e16ddcSPeter Brune         ierr = VecCopy(FM, Fdot[0]);CHKERRQ(ierr);
505d2e16ddcSPeter Brune       } else {
506f109b39eSPeter Brune         ngmres->fnorms[0] = fnorm;
507f109b39eSPeter Brune         nu = fnorm*fnorm;
50819653cdaSPeter Brune         Q(0,0) = nu;
509f109b39eSPeter Brune         /* Fdot[0] = F */
510f109b39eSPeter Brune         ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr);
511f109b39eSPeter Brune         ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr);
512d2e16ddcSPeter Brune       }
51319653cdaSPeter Brune     } else {
51498b3e84cSPeter Brune       /* select the current size of the subspace */
5151e633543SBarry Smith       if (l < ngmres->msize) l++;
51619653cdaSPeter Brune       k_restart++;
51798b3e84cSPeter Brune       /* place the current entry in the list of previous entries */
518d2e16ddcSPeter Brune       if (ngmres->anderson) {
519d2e16ddcSPeter Brune         ierr = VecCopy(FM, Fdot[ivec]);CHKERRQ(ierr);
520d2e16ddcSPeter Brune         ierr = VecCopy(XM, Xdot[ivec]);CHKERRQ(ierr);
521d2e16ddcSPeter Brune         ngmres->fnorms[ivec] = fMnorm;
522d2e16ddcSPeter Brune         if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of FM */
52318aa0c0cSPeter Brune         xi[ivec] = fMnorm*fMnorm;
524d2e16ddcSPeter Brune         for (i = 0; i < l; i++) {
52518aa0c0cSPeter Brune           Q(i, ivec) = xi[i];
52618aa0c0cSPeter Brune           Q(ivec, i) = xi[i];
527d2e16ddcSPeter Brune         }
528d2e16ddcSPeter Brune       } else {
529f109b39eSPeter Brune         ierr = VecCopy(F, Fdot[ivec]);CHKERRQ(ierr);
530f109b39eSPeter Brune         ierr = VecCopy(X, Xdot[ivec]);CHKERRQ(ierr);
531f109b39eSPeter Brune         ngmres->fnorms[ivec] = fnorm;
532d2e16ddcSPeter Brune         if (fminnorm > fnorm) fminnorm = fnorm;  /* the minimum norm is now of FA */
53318aa0c0cSPeter Brune         ierr = VecMDot(F, l, Fdot, xi);CHKERRQ(ierr);
53419653cdaSPeter Brune         for (i = 0; i < l; i++) {
53518aa0c0cSPeter Brune           Q(i, ivec) = xi[i];
53618aa0c0cSPeter Brune           Q(ivec, i) = xi[i];
53719653cdaSPeter Brune         }
53819653cdaSPeter Brune       }
539d2e16ddcSPeter Brune     }
54019653cdaSPeter Brune 
5418409ca45SMatthew G Knepley     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
542087dfb9eSxuemin     snes->iter = k;
543f109b39eSPeter Brune     snes->norm = fnorm;
5448409ca45SMatthew G Knepley     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
5458409ca45SMatthew G Knepley     SNESLogConvHistory(snes, snes->norm, snes->iter);
5468409ca45SMatthew G Knepley     ierr = SNESMonitor(snes, snes->iter, snes->norm);CHKERRQ(ierr);
5478409ca45SMatthew G Knepley 
54818aa0c0cSPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
549087dfb9eSxuemin     if (snes->reason) PetscFunctionReturn(0);
550a312c225SMatthew G Knepley   }
551a312c225SMatthew G Knepley   snes->reason = SNES_DIVERGED_MAX_IT;
552a312c225SMatthew G Knepley   PetscFunctionReturn(0);
553a312c225SMatthew G Knepley }
554a312c225SMatthew G Knepley 
555*13a62661SPeter Brune #undef __FUNCT__
556*13a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType"
557*13a62661SPeter Brune /*@
558*13a62661SPeter Brune     SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES.
559*13a62661SPeter Brune 
560*13a62661SPeter Brune     Logically Collective on SNES
561*13a62661SPeter Brune 
562*13a62661SPeter Brune     Input Parameters:
563*13a62661SPeter Brune +   snes - the iterative context
564*13a62661SPeter Brune -   rtype - restart type
565*13a62661SPeter Brune 
566*13a62661SPeter Brune     Options Database:
567*13a62661SPeter Brune +   -snes_ngmres_restart_type<difference,periodic,none> - set the restart type
568*13a62661SPeter Brune -   -snes_ngmres_restart_periodic[30] - sets the number of iterations before restart for periodic
569*13a62661SPeter Brune 
570*13a62661SPeter Brune     Level: intermediate
571*13a62661SPeter Brune 
572*13a62661SPeter Brune     SNESNGMRESRestartTypes:
573*13a62661SPeter Brune +   SNES_NGMRES_RESTART_NONE - never restart
574*13a62661SPeter Brune .   SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria
575*13a62661SPeter Brune -   SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations
576*13a62661SPeter Brune 
577*13a62661SPeter Brune     Notes:
578*13a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
579*13a62661SPeter Brune 
580*13a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch
581*13a62661SPeter Brune @*/
582*13a62661SPeter Brune PetscErrorCode SNESNGMRESSetRestartType(SNES snes, SNESNGMRESRestartType rtype) {
583*13a62661SPeter Brune   PetscErrorCode ierr;
584*13a62661SPeter Brune   PetscFunctionBegin;
585*13a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
586*13a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr);
587*13a62661SPeter Brune   PetscFunctionReturn(0);
588*13a62661SPeter Brune }
589*13a62661SPeter Brune 
590*13a62661SPeter Brune #undef __FUNCT__
591*13a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType"
592*13a62661SPeter Brune /*@
593*13a62661SPeter Brune     SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES.  This determines how the candidate solution and
594*13a62661SPeter Brune     combined solution are used to create the next iterate.
595*13a62661SPeter Brune 
596*13a62661SPeter Brune     Logically Collective on SNES
597*13a62661SPeter Brune 
598*13a62661SPeter Brune     Input Parameters:
599*13a62661SPeter Brune +   snes - the iterative context
600*13a62661SPeter Brune -   stype - selection type
601*13a62661SPeter Brune 
602*13a62661SPeter Brune     Options Database:
603*13a62661SPeter Brune .   -snes_ngmres_select_type<difference,none,linesearch>
604*13a62661SPeter Brune 
605*13a62661SPeter Brune     Level: intermediate
606*13a62661SPeter Brune 
607*13a62661SPeter Brune     SNESNGMRESSelectTypes:
608*13a62661SPeter Brune +   SNES_NGMRES_SELECT_NONE - choose the combined solution all the time
609*13a62661SPeter Brune .   SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria
610*13a62661SPeter Brune -   SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination
611*13a62661SPeter Brune 
612*13a62661SPeter Brune     Notes:
613*13a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
614*13a62661SPeter Brune 
615*13a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch
616*13a62661SPeter Brune @*/
617*13a62661SPeter Brune 
618*13a62661SPeter Brune PetscErrorCode SNESNGMRESSetSelectType(SNES snes, SNESNGMRESSelectType stype) {
619*13a62661SPeter Brune   PetscErrorCode ierr;
620*13a62661SPeter Brune   PetscFunctionBegin;
621*13a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
622*13a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr);
623*13a62661SPeter Brune   PetscFunctionReturn(0);
624*13a62661SPeter Brune }
625*13a62661SPeter Brune 
626*13a62661SPeter Brune 
627*13a62661SPeter Brune EXTERN_C_BEGIN
628*13a62661SPeter Brune #undef __FUNCT__
629*13a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES"
630*13a62661SPeter Brune 
631*13a62661SPeter Brune PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes, SNESNGMRESSelectType stype) {
632*13a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES *)snes->data;
633*13a62661SPeter Brune   PetscFunctionBegin;
634*13a62661SPeter Brune   ngmres->select_type = stype;
635*13a62661SPeter Brune   PetscFunctionReturn(0);
636*13a62661SPeter Brune }
637*13a62661SPeter Brune 
638*13a62661SPeter Brune #undef __FUNCT__
639*13a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES"
640*13a62661SPeter Brune 
641*13a62661SPeter Brune PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes, SNESNGMRESRestartType rtype) {
642*13a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES *)snes->data;
643*13a62661SPeter Brune   PetscFunctionBegin;
644*13a62661SPeter Brune   ngmres->restart_type = rtype;
645*13a62661SPeter Brune   PetscFunctionReturn(0);
646*13a62661SPeter Brune }
647*13a62661SPeter Brune EXTERN_C_END
648*13a62661SPeter Brune 
649*13a62661SPeter Brune 
650dfbf837cSBarry Smith /*MC
6511867fe5bSPeter Brune   SNESNGMRES - The Nonlinear Generalized Minimum Residual method.
652a312c225SMatthew G Knepley 
653dfbf837cSBarry Smith    Level: beginner
654dfbf837cSBarry Smith 
6551867fe5bSPeter Brune    Options Database:
656*13a62661SPeter Brune +  -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution
657*13a62661SPeter Brune +  -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions
658*13a62661SPeter Brune .  -snes_ngmres_anderson         - Use Anderson mixing NGMRES variant which combines candidate solutions instead of actual solutions
659*13a62661SPeter Brune .  -snes_ngmres_m                - Number of stored previous solutions and residuals
660*13a62661SPeter Brune .  -snes_ngmres_restart_it       - Number of iterations the restart conditions hold before restart
661*13a62661SPeter Brune .  -snes_ngmres_gammaA           - Residual tolerance for solution select between the candidate and combination
662*13a62661SPeter Brune .  -snes_ngmres_gammaC           - Residual tolerance for restart
663*13a62661SPeter Brune .  -snes_ngmres_epsilonB         - Difference tolerance between subsequent solutions triggering restart
664*13a62661SPeter Brune .  -snes_ngmres_deltaB           - Difference tolerance between residuals triggering restart
665*13a62661SPeter Brune .  -snes_ngmres_monitor          - Prints relevant information about the ngmres iteration
666*13a62661SPeter Brune .  -snes_linesearch_type <basic,basicnonorms,quadratic,critical> - Line search type used for the default smoother
667*13a62661SPeter Brune -  -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type
6681867fe5bSPeter Brune 
6691867fe5bSPeter Brune    Notes:
6701867fe5bSPeter Brune 
6711867fe5bSPeter Brune    The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized
6721867fe5bSPeter Brune    optimization problem at each iteration.
6731867fe5bSPeter Brune 
6741867fe5bSPeter Brune    References:
6751867fe5bSPeter Brune 
676dfbf837cSBarry Smith    "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio,
677dfbf837cSBarry Smith    SIAM Journal on Scientific Computing, 21(5), 2000.
678dfbf837cSBarry Smith 
679dfbf837cSBarry Smith    This is also the same as the algorithm called Anderson acceleration introduced in "D. G. Anderson. Iterative procedures for nonlinear integral equations.
680dfbf837cSBarry Smith    J. Assoc. Comput. Mach., 12:547–560, 1965."
681dfbf837cSBarry Smith 
682dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types)
683dfbf837cSBarry Smith M*/
684a312c225SMatthew G Knepley 
685a312c225SMatthew G Knepley EXTERN_C_BEGIN
686a312c225SMatthew G Knepley #undef __FUNCT__
687a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES"
688a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes)
689a312c225SMatthew G Knepley {
690a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres;
691a312c225SMatthew G Knepley   PetscErrorCode ierr;
692a312c225SMatthew G Knepley 
693a312c225SMatthew G Knepley   PetscFunctionBegin;
694a312c225SMatthew G Knepley   snes->ops->destroy        = SNESDestroy_NGMRES;
695a312c225SMatthew G Knepley   snes->ops->setup          = SNESSetUp_NGMRES;
696a312c225SMatthew G Knepley   snes->ops->setfromoptions = SNESSetFromOptions_NGMRES;
697a312c225SMatthew G Knepley   snes->ops->view           = SNESView_NGMRES;
698a312c225SMatthew G Knepley   snes->ops->solve          = SNESSolve_NGMRES;
699a312c225SMatthew G Knepley   snes->ops->reset          = SNESReset_NGMRES;
700a312c225SMatthew G Knepley 
70142f4f86dSBarry Smith   snes->usespc          = PETSC_TRUE;
7022c155ee1SBarry Smith   snes->usesksp         = PETSC_FALSE;
7032c155ee1SBarry Smith 
704a312c225SMatthew G Knepley   ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr);
705a312c225SMatthew G Knepley   snes->data = (void*) ngmres;
706d2e16ddcSPeter Brune   ngmres->msize = 30;
70719653cdaSPeter Brune 
70888976e71SPeter Brune   if (!snes->tolerancesset) {
7090e444f03SPeter Brune     snes->max_funcs = 30000;
7100e444f03SPeter Brune     snes->max_its   = 10000;
71188976e71SPeter Brune   }
7120e444f03SPeter Brune 
713d2e16ddcSPeter Brune   ngmres->anderson   = PETSC_FALSE;
714d2e16ddcSPeter Brune 
715e7058c64SPeter Brune   ngmres->additive_linesearch = PETSC_NULL;
716e7058c64SPeter Brune 
71728ed4a04SPeter Brune   ngmres->restart_it = 2;
718*13a62661SPeter Brune   ngmres->restart_periodic = 30;
719f109b39eSPeter Brune   ngmres->gammaA     = 2.0;
720f109b39eSPeter Brune   ngmres->gammaC     = 2.0;
721cac108bcSPeter Brune   ngmres->deltaB     = 0.9;
722cac108bcSPeter Brune   ngmres->epsilonB   = 0.1;
723e7058c64SPeter Brune 
724*13a62661SPeter Brune   ngmres->restart_type   = SNES_NGMRES_RESTART_DIFFERENCE;
725*13a62661SPeter Brune   ngmres->select_type    = SNES_NGMRES_SELECT_DIFFERENCE;
726*13a62661SPeter Brune 
727*13a62661SPeter Brune   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNGMRESSetSelectType_C","SNESNGMRESSetSelectType_NGMRES", SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr);
728*13a62661SPeter Brune   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNGMRESSetRestartType_C","SNESNGMRESSetRestartType_NGMRES", SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr);
729*13a62661SPeter Brune 
730a312c225SMatthew G Knepley   PetscFunctionReturn(0);
731a312c225SMatthew G Knepley }
732a312c225SMatthew G Knepley EXTERN_C_END
733