xref: /petsc/src/snes/impls/ngmres/snesngmres.c (revision 18aa0c0c4d4a20077b9dc4c1e40ad8cc0dcb2298)
119653cdaSPeter Brune #include <../src/snes/impls/ngmres/snesngmres.h>
219653cdaSPeter Brune #include <petscblaslapack.h>
3a312c225SMatthew G Knepley 
4a312c225SMatthew G Knepley #undef __FUNCT__
5a312c225SMatthew G Knepley #define __FUNCT__ "SNESReset_NGMRES"
6a312c225SMatthew G Knepley PetscErrorCode SNESReset_NGMRES(SNES snes)
7a312c225SMatthew G Knepley {
8a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres = (SNES_NGMRES*) snes->data;
9a312c225SMatthew G Knepley   PetscErrorCode ierr;
10a312c225SMatthew G Knepley 
11a312c225SMatthew G Knepley   PetscFunctionBegin;
12f109b39eSPeter Brune   ierr = VecDestroyVecs(ngmres->msize, &ngmres->Fdot);CHKERRQ(ierr);
13f109b39eSPeter Brune   ierr = VecDestroyVecs(ngmres->msize, &ngmres->Xdot);CHKERRQ(ierr);
14f1c6b773SPeter Brune   ierr = SNESLineSearchDestroy(&ngmres->additive_linesearch);CHKERRQ(ierr);
159e764e56SPeter Brune 
16a312c225SMatthew G Knepley   PetscFunctionReturn(0);
17a312c225SMatthew G Knepley }
18a312c225SMatthew G Knepley 
19a312c225SMatthew G Knepley #undef __FUNCT__
20a312c225SMatthew G Knepley #define __FUNCT__ "SNESDestroy_NGMRES"
21a312c225SMatthew G Knepley PetscErrorCode SNESDestroy_NGMRES(SNES snes)
22a312c225SMatthew G Knepley {
23a312c225SMatthew G Knepley   PetscErrorCode ierr;
2478440776SJed Brown   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
25a312c225SMatthew G Knepley 
26a312c225SMatthew G Knepley   PetscFunctionBegin;
27a312c225SMatthew G Knepley   ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr);
28f109b39eSPeter Brune   ierr = PetscFree5(ngmres->h, ngmres->beta, ngmres->xi, ngmres->fnorms, ngmres->q);CHKERRQ(ierr);
2919653cdaSPeter Brune   ierr = PetscFree(ngmres->s);CHKERRQ(ierr);
30*18aa0c0cSPeter Brune   ierr = PetscFree(ngmres->xnorms);CHKERRQ(ierr);
3119653cdaSPeter Brune #if PETSC_USE_COMPLEX
3219653cdaSPeter Brune   ierr = PetscFree(ngmres->rwork);
3319653cdaSPeter Brune #endif
3419653cdaSPeter Brune   ierr = PetscFree(ngmres->work);
3519653cdaSPeter Brune   ierr = PetscFree(snes->data);
36a312c225SMatthew G Knepley   PetscFunctionReturn(0);
37a312c225SMatthew G Knepley }
38a312c225SMatthew G Knepley 
39a312c225SMatthew G Knepley #undef __FUNCT__
40a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetUp_NGMRES"
41a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes)
42a312c225SMatthew G Knepley {
43a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES *) snes->data;
44e7058c64SPeter Brune   const char     *optionsprefix;
4519653cdaSPeter Brune   PetscInt       msize,hsize;
46a312c225SMatthew G Knepley   PetscErrorCode ierr;
47a312c225SMatthew G Knepley 
48a312c225SMatthew G Knepley   PetscFunctionBegin;
4978440776SJed Brown   ierr = SNESDefaultGetWork(snes,5);CHKERRQ(ierr);
5078440776SJed Brown   if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);}
5178440776SJed Brown   if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);}
5278440776SJed Brown   if (!ngmres->setup_called) {
53087dfb9eSxuemin     msize         = ngmres->msize;  /* restart size */
5419653cdaSPeter Brune     hsize         = msize * msize;
55087dfb9eSxuemin 
5698b3e84cSPeter Brune     /* explicit least squares minimization solve */
5719653cdaSPeter Brune     ierr = PetscMalloc5(hsize,PetscScalar,&ngmres->h,
5819653cdaSPeter Brune                         msize,PetscScalar,&ngmres->beta,
5919653cdaSPeter Brune                         msize,PetscScalar,&ngmres->xi,
60f109b39eSPeter Brune                         msize,PetscReal,  &ngmres->fnorms,
6119653cdaSPeter Brune                         hsize,PetscScalar,&ngmres->q);CHKERRQ(ierr);
62*18aa0c0cSPeter Brune     if (ngmres->singlereduction) {
63*18aa0c0cSPeter Brune       ierr = PetscMalloc(msize*sizeof(PetscReal),&ngmres->xnorms);CHKERRQ(ierr);
64*18aa0c0cSPeter Brune     }
6519653cdaSPeter Brune     ngmres->nrhs = 1;
6619653cdaSPeter Brune     ngmres->lda = msize;
6719653cdaSPeter Brune     ngmres->ldb = msize;
6819653cdaSPeter Brune     ierr = PetscMalloc(msize*sizeof(PetscScalar),&ngmres->s);CHKERRQ(ierr);
6919653cdaSPeter Brune     ierr = PetscMemzero(ngmres->h,   hsize*sizeof(PetscScalar));CHKERRQ(ierr);
7019653cdaSPeter Brune     ierr = PetscMemzero(ngmres->q,   hsize*sizeof(PetscScalar));CHKERRQ(ierr);
7119653cdaSPeter Brune     ierr = PetscMemzero(ngmres->xi,  msize*sizeof(PetscScalar));CHKERRQ(ierr);
7219653cdaSPeter Brune     ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr);
7319653cdaSPeter Brune     ngmres->lwork = 12*msize;
7419653cdaSPeter Brune #if PETSC_USE_COMPLEX
7519653cdaSPeter Brune     ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork);
7619653cdaSPeter Brune #endif
7719653cdaSPeter Brune     ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work);
7878440776SJed Brown   }
79e7058c64SPeter Brune 
80e7058c64SPeter Brune   /* linesearch setup */
81e7058c64SPeter Brune   ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr);
82e7058c64SPeter Brune 
83e7058c64SPeter Brune   if (ngmres->additive) {
84f1c6b773SPeter Brune     ierr = SNESLineSearchCreate(((PetscObject)snes)->comm, &ngmres->additive_linesearch);CHKERRQ(ierr);
85f1c6b773SPeter Brune     ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch, snes);CHKERRQ(ierr);
861a4f838cSPeter Brune     ierr = SNESLineSearchSetType(ngmres->additive_linesearch, SNESLINESEARCHL2);CHKERRQ(ierr);
87f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch, "additive_");CHKERRQ(ierr);
88f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch, optionsprefix);CHKERRQ(ierr);
89f1c6b773SPeter Brune     ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr);
90e7058c64SPeter Brune   }
91e7058c64SPeter Brune 
9278440776SJed Brown   ngmres->setup_called = PETSC_TRUE;
93a312c225SMatthew G Knepley   PetscFunctionReturn(0);
94a312c225SMatthew G Knepley }
95a312c225SMatthew G Knepley 
96a312c225SMatthew G Knepley #undef __FUNCT__
97a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES"
98a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes)
99a312c225SMatthew G Knepley {
100a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres = (SNES_NGMRES *) snes->data;
101a312c225SMatthew G Knepley   PetscErrorCode ierr;
102dfbf837cSBarry Smith   PetscBool      debug;
103f1c6b773SPeter Brune   SNESLineSearch linesearch;
104a312c225SMatthew G Knepley   PetscFunctionBegin;
105a312c225SMatthew G Knepley   ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr);
1069f425c49SPeter Brune   ierr = PetscOptionsBool("-snes_ngmres_additive", "Use additive variant vs. choice",    "SNES", ngmres->additive,  &ngmres->additive, PETSC_NULL);CHKERRQ(ierr);
107d2e16ddcSPeter Brune   ierr = PetscOptionsBool("-snes_ngmres_anderson", "Use Anderson mixing storage",        "SNES", ngmres->anderson,  &ngmres->anderson, PETSC_NULL);CHKERRQ(ierr);
10819653cdaSPeter Brune   ierr = PetscOptionsInt("-snes_ngmres_m",         "Number of directions",               "SNES", ngmres->msize,  &ngmres->msize, PETSC_NULL);CHKERRQ(ierr);
10928ed4a04SPeter Brune   ierr = PetscOptionsInt("-snes_ngmres_restart_it","Tolerance iterations before restart","SNES", ngmres->restart_it,  &ngmres->restart_it, PETSC_NULL);CHKERRQ(ierr);
110dfbf837cSBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_monitor",  "Monitor actions of NGMRES",          "SNES", ngmres->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);CHKERRQ(ierr);
111dfbf837cSBarry Smith   if (debug) {
112dfbf837cSBarry Smith     ngmres->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr);
113dfbf837cSBarry Smith   }
1146a7cf640SPeter Brune   ierr = PetscOptionsReal("-snes_ngmres_gammaA",   "Residual selection constant",   "SNES", ngmres->gammaA, &ngmres->gammaA, PETSC_NULL);CHKERRQ(ierr);
1156a7cf640SPeter Brune   ierr = PetscOptionsReal("-snes_ngmres_gammaC", "  Residual restart constant",     "SNES", ngmres->gammaC, &ngmres->gammaC, PETSC_NULL);CHKERRQ(ierr);
1166a7cf640SPeter Brune   ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES", ngmres->epsilonB, &ngmres->epsilonB, PETSC_NULL);CHKERRQ(ierr);
1176a7cf640SPeter Brune   ierr = PetscOptionsReal("-snes_ngmres_deltaB",   "Difference residual selection constant", "SNES", ngmres->deltaB, &ngmres->deltaB, PETSC_NULL);CHKERRQ(ierr);
118*18aa0c0cSPeter Brune   ierr = PetscOptionsBool("-snes_ngmres_singlereduction", "Aggregate reductions",       "SNES", ngmres->singlereduction, &ngmres->singlereduction, PETSC_NULL);CHKERRQ(ierr);
119a312c225SMatthew G Knepley   ierr = PetscOptionsTail();CHKERRQ(ierr);
1206a7cf640SPeter Brune   if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA;
1219e764e56SPeter Brune 
1229e764e56SPeter Brune   /* set the default type of the line search if the user hasn't already. */
1239e764e56SPeter Brune   if (!snes->linesearch) {
124f1c6b773SPeter Brune     ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
1251a4f838cSPeter Brune     ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC);CHKERRQ(ierr);
1269e764e56SPeter Brune   }
127a312c225SMatthew G Knepley   PetscFunctionReturn(0);
128a312c225SMatthew G Knepley }
129a312c225SMatthew G Knepley 
130a312c225SMatthew G Knepley #undef __FUNCT__
131a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES"
132a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes, PetscViewer viewer)
133a312c225SMatthew G Knepley {
134a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres = (SNES_NGMRES *) snes->data;
135a312c225SMatthew G Knepley   PetscBool      iascii;
136a312c225SMatthew G Knepley   PetscErrorCode ierr;
137a312c225SMatthew G Knepley 
138a312c225SMatthew G Knepley   PetscFunctionBegin;
139a312c225SMatthew G Knepley   ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
140a312c225SMatthew G Knepley   if (iascii) {
1419e764e56SPeter Brune 
142f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer, "  Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr);
143f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer, "  Residual selection: gammaA=%1.0e, gammaC=%1.0e\n", ngmres->gammaA, ngmres->gammaC);CHKERRQ(ierr);
144f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer, "  Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n", ngmres->epsilonB, ngmres->deltaB);CHKERRQ(ierr);
145a312c225SMatthew G Knepley   }
146a312c225SMatthew G Knepley   PetscFunctionReturn(0);
147a312c225SMatthew G Knepley }
148a312c225SMatthew G Knepley 
149a312c225SMatthew G Knepley #undef __FUNCT__
150a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES"
151211b2d39SPeter Brune 
152a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes)
153a312c225SMatthew G Knepley {
154087dfb9eSxuemin   SNES_NGMRES        *ngmres = (SNES_NGMRES *) snes->data;
15598b3e84cSPeter Brune   /* present solution, residual, and preconditioned residual */
1569f425c49SPeter Brune   Vec                 X, F, B, D, Y;
157f109b39eSPeter Brune 
158f109b39eSPeter Brune   /* candidate linear combination answers */
1594b32a720SPeter Brune   Vec                 XA, FA, XM, FM, FPC;
16019653cdaSPeter Brune 
16198b3e84cSPeter Brune   /* previous iterations to construct the subspace */
162f109b39eSPeter Brune   Vec                 *Fdot = ngmres->Fdot;
163f109b39eSPeter Brune   Vec                 *Xdot = ngmres->Xdot;
16419653cdaSPeter Brune 
16598b3e84cSPeter Brune   /* coefficients and RHS to the minimization problem */
16619653cdaSPeter Brune   PetscScalar         *beta = ngmres->beta;
16719653cdaSPeter Brune   PetscScalar         *xi   = ngmres->xi;
168*18aa0c0cSPeter Brune   PetscReal           fnorm, fMnorm, fAnorm;
16919653cdaSPeter Brune   PetscReal           nu;
17019653cdaSPeter Brune   PetscScalar         alph_total = 0.;
17128ed4a04SPeter Brune   PetscInt            i, j, k, k_restart, l, ivec, restart_count = 0;
17219653cdaSPeter Brune 
17398b3e84cSPeter Brune   /* solution selection data */
17419653cdaSPeter Brune   PetscBool           selectA, selectRestart;
175f109b39eSPeter Brune   PetscReal           dnorm, dminnorm, dcurnorm;
176f109b39eSPeter Brune   PetscReal           fminnorm;
17719653cdaSPeter Brune 
1781e633543SBarry Smith   SNESConvergedReason reason;
179f109b39eSPeter Brune   PetscBool           lssucceed;
180a312c225SMatthew G Knepley   PetscErrorCode      ierr;
181a312c225SMatthew G Knepley 
182a312c225SMatthew G Knepley   PetscFunctionBegin;
18398b3e84cSPeter Brune   /* variable initialization */
184a312c225SMatthew G Knepley   snes->reason  = SNES_CONVERGED_ITERATING;
185f109b39eSPeter Brune   X             = snes->vec_sol;
186f109b39eSPeter Brune   F             = snes->vec_func;
187f109b39eSPeter Brune   B             = snes->vec_rhs;
188f109b39eSPeter Brune   XA            = snes->vec_sol_update;
189f109b39eSPeter Brune   FA            = snes->work[0];
190f109b39eSPeter Brune   D             = snes->work[1];
191f109b39eSPeter Brune 
192f109b39eSPeter Brune   /* work for the line search */
193f109b39eSPeter Brune   Y             = snes->work[2];
1949f425c49SPeter Brune   XM            = snes->work[3];
1959f425c49SPeter Brune   FM            = snes->work[4];
196a312c225SMatthew G Knepley 
197a312c225SMatthew G Knepley   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
198a312c225SMatthew G Knepley   snes->iter = 0;
199a312c225SMatthew G Knepley   snes->norm = 0.;
200a312c225SMatthew G Knepley   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
20119653cdaSPeter Brune 
20298b3e84cSPeter Brune   /* initialization */
20319653cdaSPeter Brune 
20498b3e84cSPeter Brune   /* r = F(x) */
205e4ed7901SPeter Brune   if (!snes->vec_func_init_set) {
206f109b39eSPeter Brune     ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr);
207a312c225SMatthew G Knepley     if (snes->domainerror) {
208a312c225SMatthew G Knepley       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
209a312c225SMatthew G Knepley       PetscFunctionReturn(0);
210a312c225SMatthew G Knepley     }
211e4ed7901SPeter Brune   } else {
212e4ed7901SPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
213e4ed7901SPeter Brune   }
21419653cdaSPeter Brune 
215e4ed7901SPeter Brune   if (!snes->norm_init_set) {
216f109b39eSPeter Brune     ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr);
217f109b39eSPeter Brune     if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation");
218e4ed7901SPeter Brune   } else {
219e4ed7901SPeter Brune     fnorm = snes->norm_init;
220e4ed7901SPeter Brune     snes->norm_init_set = PETSC_FALSE;
221e4ed7901SPeter Brune   }
222e4ed7901SPeter Brune   fminnorm = fnorm;
223e4ed7901SPeter Brune   /* nu = (r, r) */
224e4ed7901SPeter Brune   nu = fnorm*fnorm;
22519653cdaSPeter Brune 
22698b3e84cSPeter Brune   /* q_{00} = nu  */
22719653cdaSPeter Brune   Q(0,0) = nu;
228f109b39eSPeter Brune   ngmres->fnorms[0] = fnorm;
229f109b39eSPeter Brune   /* Fdot[0] = F */
230f109b39eSPeter Brune   ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr);
231f109b39eSPeter Brune   ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr);
232087dfb9eSxuemin 
233a312c225SMatthew G Knepley   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
234f109b39eSPeter Brune   snes->norm = fnorm;
235a312c225SMatthew G Knepley   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
236f109b39eSPeter Brune   SNESLogConvHistory(snes, fnorm, 0);
237f109b39eSPeter Brune   ierr = SNESMonitor(snes, 0, fnorm);CHKERRQ(ierr);
238f109b39eSPeter Brune   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
239a312c225SMatthew G Knepley   if (snes->reason) PetscFunctionReturn(0);
240a312c225SMatthew G Knepley 
24119653cdaSPeter Brune   k_restart = 1;
24219653cdaSPeter Brune   l = 1;
24309c08436SPeter Brune   for (k=1; k < snes->max_its+1; k++) {
24498b3e84cSPeter Brune     /* select which vector of the stored subspace will be updated */
24598b3e84cSPeter Brune     ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */
24619653cdaSPeter Brune 
24798b3e84cSPeter Brune     /* Computation of x^M */
2488cc86e31SPeter Brune     if (snes->pc) {
2499f425c49SPeter Brune       ierr = VecCopy(X, XM);CHKERRQ(ierr);
250e4ed7901SPeter Brune       ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr);
251e4ed7901SPeter Brune       ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr);
2529f425c49SPeter Brune       ierr = SNESSolve(snes->pc, B, XM);CHKERRQ(ierr);
2538cc86e31SPeter Brune       ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
2548cc86e31SPeter Brune       if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
2558cc86e31SPeter Brune         snes->reason = SNES_DIVERGED_INNER;
2568cc86e31SPeter Brune         PetscFunctionReturn(0);
2578cc86e31SPeter Brune       }
2584b32a720SPeter Brune       ierr = SNESGetFunction(snes->pc, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr);
2594b32a720SPeter Brune       ierr = VecCopy(FPC, FM);CHKERRQ(ierr);
2604b32a720SPeter Brune       ierr = SNESGetFunctionNorm(snes->pc, &fMnorm);CHKERRQ(ierr);
2618cc86e31SPeter Brune     } else {
262f109b39eSPeter Brune       /* no preconditioner -- just take gradient descent with line search */
263f109b39eSPeter Brune       ierr = VecCopy(F, Y);CHKERRQ(ierr);
264e7058c64SPeter Brune       ierr = VecCopy(F, FM);CHKERRQ(ierr);
265e7058c64SPeter Brune       ierr = VecCopy(X, XM);CHKERRQ(ierr);
266e7058c64SPeter Brune       fMnorm = fnorm;
267f1c6b773SPeter Brune       ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr);
268f1c6b773SPeter Brune       ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssucceed);CHKERRQ(ierr);
269f109b39eSPeter Brune       if (!lssucceed) {
270f109b39eSPeter Brune         if (++snes->numFailures >= snes->maxFailures) {
271f109b39eSPeter Brune           snes->reason = SNES_DIVERGED_LINE_SEARCH;
272f109b39eSPeter Brune           PetscFunctionReturn(0);
273f109b39eSPeter Brune         }
274f109b39eSPeter Brune       }
2756634f59bSPeter Brune     }
2761e633543SBarry Smith 
27798b3e84cSPeter Brune     /* r = F(x) */
2789f425c49SPeter Brune     nu = fMnorm*fMnorm;
2799f425c49SPeter Brune     if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of F^M */
28019653cdaSPeter Brune 
28198b3e84cSPeter Brune     /* construct the right hand side and xi factors */
2828c09b6b7SPeter Brune     ierr = VecMDot(FM, l, Fdot, xi);CHKERRQ(ierr);
2838c09b6b7SPeter Brune 
28419653cdaSPeter Brune     for (i = 0; i < l; i++) {
28519653cdaSPeter Brune       beta[i] = nu - xi[i];
28619653cdaSPeter Brune     }
28719653cdaSPeter Brune 
28898b3e84cSPeter Brune     /* construct h */
28919653cdaSPeter Brune     for (j = 0; j < l; j++) {
29019653cdaSPeter Brune       for (i = 0; i < l; i++) {
29119653cdaSPeter Brune         H(i, j) = Q(i, j) - xi[i] - xi[j] + nu;
29219653cdaSPeter Brune       }
29319653cdaSPeter Brune     }
294f109b39eSPeter Brune 
295f109b39eSPeter Brune     if(l == 1) {
296f109b39eSPeter Brune       /* simply set alpha[0] = beta[0] / H[0, 0] */
297f109b39eSPeter Brune       beta[0] = beta[0] / H(0, 0);
298f109b39eSPeter Brune     } else {
29919653cdaSPeter Brune #ifdef PETSC_MISSING_LAPACK_GELSS
30019653cdaSPeter Brune     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "NGMRES with LS requires the LAPACK GELSS routine.");
3014a0c5b0cSMatthew G Knepley #else
30219653cdaSPeter Brune     ngmres->m = PetscBLASIntCast(l);
30319653cdaSPeter Brune     ngmres->n = PetscBLASIntCast(l);
30419653cdaSPeter Brune     ngmres->info = PetscBLASIntCast(0);
30519653cdaSPeter Brune     ngmres->rcond = -1.;
3068e57ea43SSatish Balay     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
30719653cdaSPeter Brune #ifdef PETSC_USE_COMPLEX
30819653cdaSPeter Brune     LAPACKgelss_(&ngmres->m,
30919653cdaSPeter Brune                  &ngmres->n,
31019653cdaSPeter Brune                  &ngmres->nrhs,
31119653cdaSPeter Brune                  ngmres->h,
31219653cdaSPeter Brune                  &ngmres->lda,
31319653cdaSPeter Brune                  ngmres->beta,
31419653cdaSPeter Brune                  &ngmres->ldb,
31519653cdaSPeter Brune                  ngmres->s,
31619653cdaSPeter Brune                  &ngmres->rcond,
31719653cdaSPeter Brune                  &ngmres->rank,
31819653cdaSPeter Brune                  ngmres->work,
31919653cdaSPeter Brune                  &ngmres->lwork,
32019653cdaSPeter Brune                  ngmres->rwork,
32119653cdaSPeter Brune                  &ngmres->info);
32219653cdaSPeter Brune #else
32319653cdaSPeter Brune     LAPACKgelss_(&ngmres->m,
32419653cdaSPeter Brune                  &ngmres->n,
32519653cdaSPeter Brune                  &ngmres->nrhs,
32619653cdaSPeter Brune                  ngmres->h,
32719653cdaSPeter Brune                  &ngmres->lda,
32819653cdaSPeter Brune                  ngmres->beta,
32919653cdaSPeter Brune                  &ngmres->ldb,
33019653cdaSPeter Brune                  ngmres->s,
33119653cdaSPeter Brune                  &ngmres->rcond,
33219653cdaSPeter Brune                  &ngmres->rank,
33319653cdaSPeter Brune                  ngmres->work,
33419653cdaSPeter Brune                  &ngmres->lwork,
33519653cdaSPeter Brune                  &ngmres->info);
33619653cdaSPeter Brune #endif
3378e57ea43SSatish Balay     ierr = PetscFPTrapPop();CHKERRQ(ierr);
33819653cdaSPeter Brune     if (ngmres->info < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to GELSS");
33919653cdaSPeter Brune     if (ngmres->info > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SVD failed to converge");
340a312c225SMatthew G Knepley #endif
341f109b39eSPeter Brune     }
342a312c225SMatthew G Knepley 
34319653cdaSPeter Brune     alph_total = 0.;
34419653cdaSPeter Brune     for (i = 0; i < l; i++) {
34519653cdaSPeter Brune       alph_total += beta[i];
346c0bbabecSxuemin     }
347f109b39eSPeter Brune 
3489f425c49SPeter Brune     ierr = VecCopy(XM, XA);CHKERRQ(ierr);
349f109b39eSPeter Brune     ierr = VecScale(XA, 1. - alph_total);CHKERRQ(ierr);
350087dfb9eSxuemin 
3518c09b6b7SPeter Brune     ierr = VecMAXPY(XA, l, beta, Xdot);CHKERRQ(ierr);
352f109b39eSPeter Brune     ierr = SNESComputeFunction(snes, XA, FA);CHKERRQ(ierr);
35319653cdaSPeter Brune 
3549f425c49SPeter Brune     /* differences for selection and restart */
355*18aa0c0cSPeter Brune 
356*18aa0c0cSPeter Brune     if (ngmres->singlereduction) {
357*18aa0c0cSPeter Brune       dminnorm = -1.0;
358f109b39eSPeter Brune       ierr=VecCopy(XA, D);CHKERRQ(ierr);
359*18aa0c0cSPeter Brune       ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr);
360*18aa0c0cSPeter Brune       for(i=0;i<l;i++) {
361*18aa0c0cSPeter Brune         ierr=VecAXPY(Xdot[i],-1.0,XA);CHKERRQ(ierr);
362*18aa0c0cSPeter Brune       }
363*18aa0c0cSPeter Brune       ierr = VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
364*18aa0c0cSPeter Brune       ierr = VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr);
365*18aa0c0cSPeter Brune       for (i=0;i<l;i++) {
366*18aa0c0cSPeter Brune         ierr = VecNormBegin(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr);
367*18aa0c0cSPeter Brune       }
368*18aa0c0cSPeter Brune       ierr = VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
369*18aa0c0cSPeter Brune       ierr = VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr);
370*18aa0c0cSPeter Brune       for (i=0;i<l;i++) {
371*18aa0c0cSPeter Brune         ierr = VecNormEnd(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr);
372*18aa0c0cSPeter Brune       }
373*18aa0c0cSPeter Brune       for(i=0;i<l;i++) {
374*18aa0c0cSPeter Brune         dcurnorm = ngmres->xnorms[i];
375*18aa0c0cSPeter Brune         if ((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm;
376*18aa0c0cSPeter Brune         ierr=VecAXPY(Xdot[i],1.0,XA);CHKERRQ(ierr);
377*18aa0c0cSPeter Brune       }
378*18aa0c0cSPeter Brune     } else {
379*18aa0c0cSPeter Brune       ierr=VecCopy(XA, D);CHKERRQ(ierr);
380*18aa0c0cSPeter Brune       ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr);
381*18aa0c0cSPeter Brune       ierr=VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr);
382*18aa0c0cSPeter Brune       ierr=VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
383*18aa0c0cSPeter Brune       ierr=VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr);
384*18aa0c0cSPeter Brune       ierr=VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr);
385f109b39eSPeter Brune       dminnorm = -1.0;
38619653cdaSPeter Brune       for(i=0;i<l;i++) {
387f109b39eSPeter Brune         ierr=VecCopy(XA, D);CHKERRQ(ierr);
388f109b39eSPeter Brune         ierr=VecAXPY(D, -1.0, Xdot[i]);CHKERRQ(ierr);
389f109b39eSPeter Brune         ierr=VecNorm(D, NORM_2, &dcurnorm);CHKERRQ(ierr);
390f109b39eSPeter Brune         if((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm;
39119653cdaSPeter Brune       }
392*18aa0c0cSPeter Brune     }
3939f425c49SPeter Brune 
3949f425c49SPeter Brune     /* combination (additive) or selection (multiplicative) of the N-GMRES solution */
3959f425c49SPeter Brune     if (ngmres->additive) {
3969f425c49SPeter Brune       /* X = X + \lambda(XA - X) */
3979f425c49SPeter Brune       if (ngmres->monitor) {
3989f425c49SPeter Brune         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr);
3999f425c49SPeter Brune       }
4009f425c49SPeter Brune       ierr = VecCopy(XA, Y);CHKERRQ(ierr);
401eb1825c3SPeter Brune       ierr = VecAYPX(Y, -1.0, X);CHKERRQ(ierr);
402f1c6b773SPeter Brune       ierr = SNESLineSearchApply(ngmres->additive_linesearch,X,F,&fnorm,Y);CHKERRQ(ierr);
403f1c6b773SPeter Brune       ierr = SNESLineSearchGetSuccess(ngmres->additive_linesearch, &lssucceed);CHKERRQ(ierr);
4049f425c49SPeter Brune       if (!lssucceed) {
4059f425c49SPeter Brune         if (++snes->numFailures >= snes->maxFailures) {
4069f425c49SPeter Brune           snes->reason = SNES_DIVERGED_LINE_SEARCH;
4079f425c49SPeter Brune           PetscFunctionReturn(0);
4089f425c49SPeter Brune         }
4099f425c49SPeter Brune       }
4109f425c49SPeter Brune       if (ngmres->monitor) {
4119f425c49SPeter Brune         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Additive solution: ||F||_2 = %e\n", fnorm);CHKERRQ(ierr);
4129f425c49SPeter Brune       }
4139f425c49SPeter Brune     } else {
4149f425c49SPeter Brune       selectA = PETSC_TRUE;
4159f425c49SPeter Brune       /* Conditions for choosing the accelerated answer */
4169f425c49SPeter Brune       /* Criterion A -- the norm of the function isn't increased above the minimum by too much */
4179f425c49SPeter Brune       if (fAnorm >= ngmres->gammaA*fminnorm) {
4189f425c49SPeter Brune         selectA = PETSC_FALSE;
4199f425c49SPeter Brune       }
4209f425c49SPeter Brune       /* Criterion B -- the choice of x^A isn't too close to some other choice */
421cf22de31SPeter Brune      if (ngmres->epsilonB*dnorm<dminnorm || PetscSqrtReal(fnorm)<ngmres->deltaB*PetscSqrtReal(fminnorm)) {
42219653cdaSPeter Brune       } else {
42319653cdaSPeter Brune         selectA=PETSC_FALSE;
42419653cdaSPeter Brune       }
42519653cdaSPeter Brune       if (selectA) {
426dfbf837cSBarry Smith         if (ngmres->monitor) {
4279e764e56SPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_A, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr);
428dfbf837cSBarry Smith         }
42998b3e84cSPeter Brune         /* copy it over */
430f109b39eSPeter Brune         fnorm = fAnorm;
431f109b39eSPeter Brune         nu = fnorm*fnorm;
432f109b39eSPeter Brune         ierr = VecCopy(FA, F);CHKERRQ(ierr);
433f109b39eSPeter Brune         ierr = VecCopy(XA, X);CHKERRQ(ierr);
43419653cdaSPeter Brune       } else {
435dfbf837cSBarry Smith         if (ngmres->monitor) {
436f109b39eSPeter Brune           ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_M, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fnorm);CHKERRQ(ierr);
437dfbf837cSBarry Smith         }
4389f425c49SPeter Brune         fnorm = fMnorm;
4399f425c49SPeter Brune         nu = fnorm*fnorm;
4409f425c49SPeter Brune         ierr = VecCopy(FM, F);CHKERRQ(ierr);
4419f425c49SPeter Brune         ierr = VecCopy(XM, X);CHKERRQ(ierr);
4429f425c49SPeter Brune       }
44319653cdaSPeter Brune     }
444211b2d39SPeter Brune 
44519653cdaSPeter Brune     selectRestart = PETSC_FALSE;
44619653cdaSPeter Brune 
44798b3e84cSPeter Brune     /* difference stagnation restart */
448cf22de31SPeter Brune     if((ngmres->epsilonB*dnorm > dminnorm) && (PetscSqrtReal(fAnorm) > ngmres->deltaB*PetscSqrtReal(fminnorm))) {
449dfbf837cSBarry Smith       if (ngmres->monitor) {
450f109b39eSPeter Brune         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "difference restart: %e > %e\n", ngmres->epsilonB*dnorm, dminnorm);CHKERRQ(ierr);
451dfbf837cSBarry Smith       }
45219653cdaSPeter Brune       selectRestart = PETSC_TRUE;
45319653cdaSPeter Brune     }
45498b3e84cSPeter Brune     /* residual stagnation restart */
455cf22de31SPeter Brune     if (PetscSqrtReal(fAnorm) > ngmres->gammaC*PetscSqrtReal(fminnorm)) {
456dfbf837cSBarry Smith       if (ngmres->monitor) {
457cf22de31SPeter Brune         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "residual restart: %e > %e\n", PetscSqrtReal(fAnorm), ngmres->gammaC*PetscSqrtReal(fminnorm));CHKERRQ(ierr);
458dfbf837cSBarry Smith       }
45919653cdaSPeter Brune       selectRestart = PETSC_TRUE;
46019653cdaSPeter Brune     }
46119653cdaSPeter Brune 
46228ed4a04SPeter Brune     /* if the restart conditions persist for more than restart_it iterations, restart. */
46319653cdaSPeter Brune     if (selectRestart) {
46428ed4a04SPeter Brune       restart_count++;
46528ed4a04SPeter Brune     } else {
46628ed4a04SPeter Brune       restart_count = 0;
46728ed4a04SPeter Brune     }
46828ed4a04SPeter Brune 
46928ed4a04SPeter Brune     /* restart after restart conditions have persisted for a fixed number of iterations */
47028ed4a04SPeter Brune     if (restart_count >= ngmres->restart_it) {
471dfbf837cSBarry Smith       if (ngmres->monitor){
472dfbf837cSBarry Smith         ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Restarted at iteration %d\n", k_restart);CHKERRQ(ierr);
473dfbf837cSBarry Smith       }
47428ed4a04SPeter Brune       restart_count = 0;
47519653cdaSPeter Brune       k_restart = 1;
47619653cdaSPeter Brune       l = 1;
47798b3e84cSPeter Brune       /* q_{00} = nu */
478d2e16ddcSPeter Brune       if (ngmres->anderson) {
479d2e16ddcSPeter Brune         ngmres->fnorms[0] = fMnorm;
480d2e16ddcSPeter Brune         nu = fMnorm*fMnorm;
481d2e16ddcSPeter Brune         Q(0,0) = nu;
482d2e16ddcSPeter Brune         /* Fdot[0] = F */
483d2e16ddcSPeter Brune         ierr = VecCopy(XM, Xdot[0]);CHKERRQ(ierr);
484d2e16ddcSPeter Brune         ierr = VecCopy(FM, Fdot[0]);CHKERRQ(ierr);
485d2e16ddcSPeter Brune       } else {
486f109b39eSPeter Brune         ngmres->fnorms[0] = fnorm;
487f109b39eSPeter Brune         nu = fnorm*fnorm;
48819653cdaSPeter Brune         Q(0,0) = nu;
489f109b39eSPeter Brune         /* Fdot[0] = F */
490f109b39eSPeter Brune         ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr);
491f109b39eSPeter Brune         ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr);
492d2e16ddcSPeter Brune       }
49319653cdaSPeter Brune     } else {
49498b3e84cSPeter Brune       /* select the current size of the subspace */
4951e633543SBarry Smith       if (l < ngmres->msize) l++;
49619653cdaSPeter Brune       k_restart++;
49798b3e84cSPeter Brune       /* place the current entry in the list of previous entries */
498d2e16ddcSPeter Brune       if (ngmres->anderson) {
499d2e16ddcSPeter Brune         ierr = VecCopy(FM, Fdot[ivec]);CHKERRQ(ierr);
500d2e16ddcSPeter Brune         ierr = VecCopy(XM, Xdot[ivec]);CHKERRQ(ierr);
501d2e16ddcSPeter Brune         ngmres->fnorms[ivec] = fMnorm;
502d2e16ddcSPeter Brune         if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of FM */
503*18aa0c0cSPeter Brune         xi[ivec] = fMnorm*fMnorm;
504d2e16ddcSPeter Brune         for (i = 0; i < l; i++) {
505*18aa0c0cSPeter Brune           Q(i, ivec) = xi[i];
506*18aa0c0cSPeter Brune           Q(ivec, i) = xi[i];
507d2e16ddcSPeter Brune         }
508d2e16ddcSPeter Brune       } else {
509f109b39eSPeter Brune         ierr = VecCopy(F, Fdot[ivec]);CHKERRQ(ierr);
510f109b39eSPeter Brune         ierr = VecCopy(X, Xdot[ivec]);CHKERRQ(ierr);
511f109b39eSPeter Brune         ngmres->fnorms[ivec] = fnorm;
512d2e16ddcSPeter Brune         if (fminnorm > fnorm) fminnorm = fnorm;  /* the minimum norm is now of FA */
513*18aa0c0cSPeter Brune         ierr = VecMDot(F, l, Fdot, xi);CHKERRQ(ierr);
51419653cdaSPeter Brune         for (i = 0; i < l; i++) {
515*18aa0c0cSPeter Brune           Q(i, ivec) = xi[i];
516*18aa0c0cSPeter Brune           Q(ivec, i) = xi[i];
51719653cdaSPeter Brune         }
51819653cdaSPeter Brune       }
519d2e16ddcSPeter Brune     }
52019653cdaSPeter Brune 
5218409ca45SMatthew G Knepley     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
522087dfb9eSxuemin     snes->iter = k;
523f109b39eSPeter Brune     snes->norm = fnorm;
5248409ca45SMatthew G Knepley     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
5258409ca45SMatthew G Knepley     SNESLogConvHistory(snes, snes->norm, snes->iter);
5268409ca45SMatthew G Knepley     ierr = SNESMonitor(snes, snes->iter, snes->norm);CHKERRQ(ierr);
5278409ca45SMatthew G Knepley 
528*18aa0c0cSPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
529087dfb9eSxuemin     if (snes->reason) PetscFunctionReturn(0);
530a312c225SMatthew G Knepley   }
531a312c225SMatthew G Knepley   snes->reason = SNES_DIVERGED_MAX_IT;
532a312c225SMatthew G Knepley   PetscFunctionReturn(0);
533a312c225SMatthew G Knepley }
534a312c225SMatthew G Knepley 
535dfbf837cSBarry Smith /*MC
5361867fe5bSPeter Brune   SNESNGMRES - The Nonlinear Generalized Minimum Residual method.
537a312c225SMatthew G Knepley 
538dfbf837cSBarry Smith    Level: beginner
539dfbf837cSBarry Smith 
5401867fe5bSPeter Brune    Options Database:
5411867fe5bSPeter Brune +  -snes_ngmres_additive   - Use a variant that line-searches between the candidate solution and the combined solution.
5421867fe5bSPeter Brune .  -snes_ngmres_anderson   - Use Anderson mixing NGMRES variant which combines candidate solutions instead of actual solutions.
5431867fe5bSPeter Brune .  -snes_ngmres_m          - Number of stored previous solutions and residuals.
5441867fe5bSPeter Brune .  -snes_ngmres_restart_it - Number of iterations the restart conditions hold before restart.
5451867fe5bSPeter Brune .  -snes_ngmres_gammaA     - Residual tolerance for solution selection between the candidate and combination.
5461867fe5bSPeter Brune .  -snes_ngmres_gammaC     - Residual tolerance for restart.
5471867fe5bSPeter Brune .  -snes_ngmres_epsilonB   - Difference tolerance between subsequent solutions triggering restart.
5481867fe5bSPeter Brune .  -snes_ngmres_deltaB     - Difference tolerance between residuals triggering restart.
5491867fe5bSPeter Brune .  -snes_ngmres_monitor    - Prints relevant information about the ngmres iteration.
550f3aaf736SPeter Brune -  -snes_ls <basic,basicnonorms,quadratic,critical> - Line search type.
5511867fe5bSPeter Brune 
5521867fe5bSPeter Brune    Notes:
5531867fe5bSPeter Brune 
5541867fe5bSPeter Brune    The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized
5551867fe5bSPeter Brune    optimization problem at each iteration.
5561867fe5bSPeter Brune 
5571867fe5bSPeter Brune    References:
5581867fe5bSPeter Brune 
559dfbf837cSBarry Smith    "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio,
560dfbf837cSBarry Smith    SIAM Journal on Scientific Computing, 21(5), 2000.
561dfbf837cSBarry Smith 
562dfbf837cSBarry Smith    This is also the same as the algorithm called Anderson acceleration introduced in "D. G. Anderson. Iterative procedures for nonlinear integral equations.
563dfbf837cSBarry Smith    J. Assoc. Comput. Mach., 12:547–560, 1965."
564dfbf837cSBarry Smith 
565dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types)
566dfbf837cSBarry Smith M*/
567a312c225SMatthew G Knepley 
568a312c225SMatthew G Knepley EXTERN_C_BEGIN
569a312c225SMatthew G Knepley #undef __FUNCT__
570a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES"
571a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes)
572a312c225SMatthew G Knepley {
573a312c225SMatthew G Knepley   SNES_NGMRES   *ngmres;
574a312c225SMatthew G Knepley   PetscErrorCode ierr;
575a312c225SMatthew G Knepley 
576a312c225SMatthew G Knepley   PetscFunctionBegin;
577a312c225SMatthew G Knepley   snes->ops->destroy        = SNESDestroy_NGMRES;
578a312c225SMatthew G Knepley   snes->ops->setup          = SNESSetUp_NGMRES;
579a312c225SMatthew G Knepley   snes->ops->setfromoptions = SNESSetFromOptions_NGMRES;
580a312c225SMatthew G Knepley   snes->ops->view           = SNESView_NGMRES;
581a312c225SMatthew G Knepley   snes->ops->solve          = SNESSolve_NGMRES;
582a312c225SMatthew G Knepley   snes->ops->reset          = SNESReset_NGMRES;
583a312c225SMatthew G Knepley 
58442f4f86dSBarry Smith   snes->usespc          = PETSC_TRUE;
5852c155ee1SBarry Smith   snes->usesksp         = PETSC_FALSE;
5862c155ee1SBarry Smith 
587a312c225SMatthew G Knepley   ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr);
588a312c225SMatthew G Knepley   snes->data = (void*) ngmres;
589d2e16ddcSPeter Brune   ngmres->msize = 30;
59019653cdaSPeter Brune 
59188976e71SPeter Brune   if (!snes->tolerancesset) {
5920e444f03SPeter Brune     snes->max_funcs = 30000;
5930e444f03SPeter Brune     snes->max_its   = 10000;
59488976e71SPeter Brune   }
5950e444f03SPeter Brune 
596d2e16ddcSPeter Brune   ngmres->additive   = PETSC_FALSE;
597d2e16ddcSPeter Brune   ngmres->anderson   = PETSC_FALSE;
598d2e16ddcSPeter Brune 
599e7058c64SPeter Brune   ngmres->additive_linesearch = PETSC_NULL;
600e7058c64SPeter Brune 
60128ed4a04SPeter Brune   ngmres->restart_it = 2;
602f109b39eSPeter Brune   ngmres->gammaA     = 2.0;
603f109b39eSPeter Brune   ngmres->gammaC     = 2.0;
604cac108bcSPeter Brune   ngmres->deltaB     = 0.9;
605cac108bcSPeter Brune   ngmres->epsilonB   = 0.1;
606e7058c64SPeter Brune 
607a312c225SMatthew G Knepley   PetscFunctionReturn(0);
608a312c225SMatthew G Knepley }
609a312c225SMatthew G Knepley EXTERN_C_END
610