xref: /petsc/src/snes/impls/ngmres/snesngmres.c (revision 8cc058d9cd56c1ccb3be12a47760ddfc446aaffc)
113a62661SPeter Brune #include <../src/snes/impls/ngmres/snesngmres.h> /*I "petscsnes.h" I*/
219653cdaSPeter Brune #include <petscblaslapack.h>
3a312c225SMatthew G Knepley 
46a6fc655SJed Brown const char *const SNESNGMRESRestartTypes[] = {"NONE","PERIODIC","DIFFERENCE","SNESNGMRESRestartType","SNES_NGMRES_RESTART_",0};
56a6fc655SJed Brown const char *const SNESNGMRESSelectTypes[] = {"NONE","DIFFERENCE","LINESEARCH","SNESNGMRESSelectType","SNES_NGMRES_SELECT_",0};
613a62661SPeter 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);
18a312c225SMatthew G Knepley   PetscFunctionReturn(0);
19a312c225SMatthew G Knepley }
20a312c225SMatthew G Knepley 
21a312c225SMatthew G Knepley #undef __FUNCT__
22a312c225SMatthew G Knepley #define __FUNCT__ "SNESDestroy_NGMRES"
23a312c225SMatthew G Knepley PetscErrorCode SNESDestroy_NGMRES(SNES snes)
24a312c225SMatthew G Knepley {
25a312c225SMatthew G Knepley   PetscErrorCode ierr;
2678440776SJed Brown   SNES_NGMRES    *ngmres = (SNES_NGMRES*)snes->data;
27a312c225SMatthew G Knepley 
28a312c225SMatthew G Knepley   PetscFunctionBegin;
29a312c225SMatthew G Knepley   ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr);
30f109b39eSPeter Brune   ierr = PetscFree5(ngmres->h,ngmres->beta,ngmres->xi,ngmres->fnorms,ngmres->q);CHKERRQ(ierr);
3119653cdaSPeter Brune   ierr = PetscFree(ngmres->s);CHKERRQ(ierr);
3218aa0c0cSPeter Brune   ierr = PetscFree(ngmres->xnorms);CHKERRQ(ierr);
3319653cdaSPeter Brune #if PETSC_USE_COMPLEX
3422d28d08SBarry Smith   ierr = PetscFree(ngmres->rwork);CHKERRQ(ierr);
3519653cdaSPeter Brune #endif
3622d28d08SBarry Smith   ierr = PetscFree(ngmres->work);CHKERRQ(ierr);
3722d28d08SBarry Smith   ierr = PetscFree(snes->data);CHKERRQ(ierr);
38a312c225SMatthew G Knepley   PetscFunctionReturn(0);
39a312c225SMatthew G Knepley }
40a312c225SMatthew G Knepley 
41a312c225SMatthew G Knepley #undef __FUNCT__
42a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetUp_NGMRES"
43a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes)
44a312c225SMatthew G Knepley {
45a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
46e7058c64SPeter Brune   const char     *optionsprefix;
4719653cdaSPeter Brune   PetscInt       msize,hsize;
48a312c225SMatthew G Knepley   PetscErrorCode ierr;
49a312c225SMatthew G Knepley 
50a312c225SMatthew G Knepley   PetscFunctionBegin;
5178440776SJed Brown   ierr = SNESDefaultGetWork(snes,5);CHKERRQ(ierr);
5278440776SJed Brown   if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);}
5378440776SJed Brown   if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);}
5478440776SJed Brown   if (!ngmres->setup_called) {
55087dfb9eSxuemin     msize = ngmres->msize;          /* restart size */
5619653cdaSPeter Brune     hsize = msize * msize;
57087dfb9eSxuemin 
5898b3e84cSPeter Brune     /* explicit least squares minimization solve */
5919653cdaSPeter Brune     ierr = PetscMalloc5(hsize,PetscScalar,&ngmres->h,
6019653cdaSPeter Brune                         msize,PetscScalar,&ngmres->beta,
6119653cdaSPeter Brune                         msize,PetscScalar,&ngmres->xi,
62f109b39eSPeter Brune                         msize,PetscReal, &ngmres->fnorms,
6319653cdaSPeter Brune                         hsize,PetscScalar,&ngmres->q);CHKERRQ(ierr);
6418aa0c0cSPeter Brune     if (ngmres->singlereduction) {
6518aa0c0cSPeter Brune       ierr = PetscMalloc(msize*sizeof(PetscReal),&ngmres->xnorms);CHKERRQ(ierr);
6618aa0c0cSPeter Brune     }
6719653cdaSPeter Brune     ngmres->nrhs  = 1;
6819653cdaSPeter Brune     ngmres->lda   = msize;
6919653cdaSPeter Brune     ngmres->ldb   = msize;
7019653cdaSPeter Brune     ierr          = PetscMalloc(msize*sizeof(PetscScalar),&ngmres->s);CHKERRQ(ierr);
7119653cdaSPeter Brune     ierr          = PetscMemzero(ngmres->h,   hsize*sizeof(PetscScalar));CHKERRQ(ierr);
7219653cdaSPeter Brune     ierr          = PetscMemzero(ngmres->q,   hsize*sizeof(PetscScalar));CHKERRQ(ierr);
7319653cdaSPeter Brune     ierr          = PetscMemzero(ngmres->xi,  msize*sizeof(PetscScalar));CHKERRQ(ierr);
7419653cdaSPeter Brune     ierr          = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr);
7519653cdaSPeter Brune     ngmres->lwork = 12*msize;
7619653cdaSPeter Brune #if PETSC_USE_COMPLEX
7722d28d08SBarry Smith     ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork);CHKERRQ(ierr);
7819653cdaSPeter Brune #endif
7922d28d08SBarry Smith     ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work);CHKERRQ(ierr);
8078440776SJed Brown   }
81e7058c64SPeter Brune 
82e7058c64SPeter Brune   /* linesearch setup */
83e7058c64SPeter Brune   ierr = SNESGetOptionsPrefix(snes,&optionsprefix);CHKERRQ(ierr);
84e7058c64SPeter Brune 
8513a62661SPeter Brune   if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) {
86ce94432eSBarry Smith     ierr = SNESLineSearchCreate(PetscObjectComm((PetscObject)snes),&ngmres->additive_linesearch);CHKERRQ(ierr);
87f1c6b773SPeter Brune     ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch,snes);CHKERRQ(ierr);
881a4f838cSPeter Brune     ierr = SNESLineSearchSetType(ngmres->additive_linesearch,SNESLINESEARCHL2);CHKERRQ(ierr);
89f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,"additive_");CHKERRQ(ierr);
90f1c6b773SPeter Brune     ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,optionsprefix);CHKERRQ(ierr);
91f1c6b773SPeter Brune     ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr);
92e7058c64SPeter Brune   }
93e7058c64SPeter Brune 
9478440776SJed Brown   ngmres->setup_called = PETSC_TRUE;
95a312c225SMatthew G Knepley   PetscFunctionReturn(0);
96a312c225SMatthew G Knepley }
97a312c225SMatthew G Knepley 
98a312c225SMatthew G Knepley #undef __FUNCT__
99a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES"
100a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes)
101a312c225SMatthew G Knepley {
102a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
103a312c225SMatthew G Knepley   PetscErrorCode ierr;
104dfbf837cSBarry Smith   PetscBool      debug;
105f1c6b773SPeter Brune   SNESLineSearch linesearch;
1060adebc6cSBarry Smith 
107a312c225SMatthew G Knepley   PetscFunctionBegin;
108a312c225SMatthew G Knepley   ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr);
10913a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes,
1100298fd71SBarry Smith                           (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,NULL);CHKERRQ(ierr);
11113a62661SPeter Brune   ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes,
1120298fd71SBarry Smith                           (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,NULL);CHKERRQ(ierr);
1130298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_candidate", "Use candidate storage",              "SNES",ngmres->candidate,&ngmres->candidate,NULL);CHKERRQ(ierr);
114077c4231SPeter Brune   ierr = PetscOptionsBool("-snes_ngmres_approxfunc","Linearly approximate the function", "SNES",ngmres->approxfunc,&ngmres->approxfunc,NULL);CHKERRQ(ierr);
1150298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_m",          "Number of directions",               "SNES",ngmres->msize,&ngmres->msize,NULL);CHKERRQ(ierr);
1160298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_restart",    "Iterations before forced restart",   "SNES",ngmres->restart_periodic,&ngmres->restart_periodic,NULL);CHKERRQ(ierr);
1170298fd71SBarry Smith   ierr = PetscOptionsInt("-snes_ngmres_restart_it", "Tolerance iterations before restart","SNES",ngmres->restart_it,&ngmres->restart_it,NULL);CHKERRQ(ierr);
1180298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_monitor",   "Monitor actions of NGMRES",          "SNES",ngmres->monitor ? PETSC_TRUE : PETSC_FALSE,&debug,NULL);CHKERRQ(ierr);
119dfbf837cSBarry Smith   if (debug) {
120ce94432eSBarry Smith     ngmres->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr);
121dfbf837cSBarry Smith   }
1220298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_gammaA",    "Residual selection constant",   "SNES",ngmres->gammaA,&ngmres->gammaA,NULL);CHKERRQ(ierr);
1230298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_gammaC",    "Residual restart constant",     "SNES",ngmres->gammaC,&ngmres->gammaC,NULL);CHKERRQ(ierr);
1240298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_epsilonB",  "Difference selection constant", "SNES",ngmres->epsilonB,&ngmres->epsilonB,NULL);CHKERRQ(ierr);
1250298fd71SBarry Smith   ierr = PetscOptionsReal("-snes_ngmres_deltaB",    "Difference residual selection constant", "SNES",ngmres->deltaB,&ngmres->deltaB,NULL);CHKERRQ(ierr);
1260298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions",  "SNES",ngmres->singlereduction,&ngmres->singlereduction,NULL);CHKERRQ(ierr);
127a312c225SMatthew G Knepley   ierr = PetscOptionsTail();CHKERRQ(ierr);
1286a7cf640SPeter Brune   if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA;
1299e764e56SPeter Brune 
1309e764e56SPeter Brune   /* set the default type of the line search if the user hasn't already. */
1319e764e56SPeter Brune   if (!snes->linesearch) {
132f1c6b773SPeter Brune     ierr = SNESGetSNESLineSearch(snes,&linesearch);CHKERRQ(ierr);
1331a4f838cSPeter Brune     ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr);
1349e764e56SPeter Brune   }
135a312c225SMatthew G Knepley   PetscFunctionReturn(0);
136a312c225SMatthew G Knepley }
137a312c225SMatthew G Knepley 
138a312c225SMatthew G Knepley #undef __FUNCT__
139a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES"
140a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes,PetscViewer viewer)
141a312c225SMatthew G Knepley {
142a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres = (SNES_NGMRES*) snes->data;
143a312c225SMatthew G Knepley   PetscBool      iascii;
144a312c225SMatthew G Knepley   PetscErrorCode ierr;
145a312c225SMatthew G Knepley 
146a312c225SMatthew G Knepley   PetscFunctionBegin;
147251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject) viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
148a312c225SMatthew G Knepley   if (iascii) {
149f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr);
150f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Residual selection: gammaA=%1.0e, gammaC=%1.0e\n",ngmres->gammaA,ngmres->gammaC);CHKERRQ(ierr);
151f109b39eSPeter Brune     ierr = PetscViewerASCIIPrintf(viewer,"  Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n",ngmres->epsilonB,ngmres->deltaB);CHKERRQ(ierr);
152a312c225SMatthew G Knepley   }
153a312c225SMatthew G Knepley   PetscFunctionReturn(0);
154a312c225SMatthew G Knepley }
155a312c225SMatthew G Knepley 
156a312c225SMatthew G Knepley #undef __FUNCT__
157a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES"
158a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes)
159a312c225SMatthew G Knepley {
16038774f0aSPeter Brune 
161087dfb9eSxuemin   SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data;
16298b3e84cSPeter Brune   /* present solution, residual, and preconditioned residual */
1639f425c49SPeter Brune   Vec X,F,B,D,Y;
164f109b39eSPeter Brune 
165f109b39eSPeter Brune   /* candidate linear combination answers */
1664b32a720SPeter Brune   Vec XA,FA,XM,FM,FPC;
16719653cdaSPeter Brune 
16898b3e84cSPeter Brune   /* coefficients and RHS to the minimization problem */
16918aa0c0cSPeter Brune   PetscReal fnorm,fMnorm,fAnorm;
17038774f0aSPeter Brune   PetscInt  k,k_restart,l,ivec,restart_count = 0;
17119653cdaSPeter Brune 
17298b3e84cSPeter Brune   /* solution selection data */
17338774f0aSPeter Brune   PetscBool selectRestart;
17438774f0aSPeter Brune   PetscReal dnorm,dminnorm = 0.0;
175d484d688SPeter Brune   PetscReal fminnorm,xnorm,ynorm;
17619653cdaSPeter Brune 
1771e633543SBarry Smith   SNESConvergedReason reason;
17838774f0aSPeter Brune   PetscBool           lssucceed;
179a312c225SMatthew G Knepley   PetscErrorCode      ierr;
180a312c225SMatthew G Knepley 
181a312c225SMatthew G Knepley   PetscFunctionBegin;
18298b3e84cSPeter Brune   /* variable initialization */
183a312c225SMatthew G Knepley   snes->reason = SNES_CONVERGED_ITERATING;
184f109b39eSPeter Brune   X            = snes->vec_sol;
185f109b39eSPeter Brune   F            = snes->vec_func;
186f109b39eSPeter Brune   B            = snes->vec_rhs;
187f109b39eSPeter Brune   XA           = snes->vec_sol_update;
188f109b39eSPeter Brune   FA           = snes->work[0];
189f109b39eSPeter Brune   D            = snes->work[1];
190f109b39eSPeter Brune 
191f109b39eSPeter Brune   /* work for the line search */
192f109b39eSPeter Brune   Y  = snes->work[2];
1939f425c49SPeter Brune   XM = snes->work[3];
1949f425c49SPeter Brune   FM = snes->work[4];
195a312c225SMatthew G Knepley 
196a312c225SMatthew G Knepley   ierr       = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
197a312c225SMatthew G Knepley   snes->iter = 0;
198a312c225SMatthew G Knepley   snes->norm = 0.;
199a312c225SMatthew G Knepley   ierr       = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
20019653cdaSPeter Brune 
20198b3e84cSPeter Brune   /* initialization */
20219653cdaSPeter Brune 
20398b3e84cSPeter Brune   /* r = F(x) */
204e4ed7901SPeter Brune   if (!snes->vec_func_init_set) {
205f109b39eSPeter Brune     ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
206a312c225SMatthew G Knepley     if (snes->domainerror) {
207a312c225SMatthew G Knepley       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
208a312c225SMatthew G Knepley       PetscFunctionReturn(0);
209a312c225SMatthew G Knepley     }
2101aa26658SKarl Rupp   } else snes->vec_func_init_set = PETSC_FALSE;
21119653cdaSPeter Brune 
212e4ed7901SPeter Brune   if (!snes->norm_init_set) {
213f109b39eSPeter Brune     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
214189a9710SBarry Smith     if (PetscIsInfOrNanReal(fnorm)) {
215189a9710SBarry Smith       snes->reason = SNES_DIVERGED_FNORM_NAN;
216189a9710SBarry Smith       PetscFunctionReturn(0);
217189a9710SBarry Smith     }
218e4ed7901SPeter Brune   } else {
219e4ed7901SPeter Brune     fnorm               = snes->norm_init;
220e4ed7901SPeter Brune     snes->norm_init_set = PETSC_FALSE;
221e4ed7901SPeter Brune   }
222e4ed7901SPeter Brune   fminnorm = fnorm;
22319653cdaSPeter Brune 
22498b3e84cSPeter Brune   /* q_{00} = nu  */
22538774f0aSPeter Brune   SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fnorm,X);
226087dfb9eSxuemin 
227a312c225SMatthew G Knepley   ierr       = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
228f109b39eSPeter Brune   snes->norm = fnorm;
229a312c225SMatthew G Knepley   ierr       = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
230a71f0d7dSBarry Smith   ierr       = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr);
231f109b39eSPeter Brune   ierr       = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
232f109b39eSPeter Brune   ierr       = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
233a312c225SMatthew G Knepley   if (snes->reason) PetscFunctionReturn(0);
234a312c225SMatthew G Knepley 
23519653cdaSPeter Brune   k_restart = 1;
23619653cdaSPeter Brune   l         = 1;
23709c08436SPeter Brune   for (k=1; k < snes->max_its+1; k++) {
23898b3e84cSPeter Brune     /* select which vector of the stored subspace will be updated */
23998b3e84cSPeter Brune     ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */
24019653cdaSPeter Brune 
24198b3e84cSPeter Brune     /* Computation of x^M */
242c40d0f55SPeter Brune     if (snes->pc && snes->pcside == PC_RIGHT) {
2439f425c49SPeter Brune       ierr = VecCopy(X,XM);CHKERRQ(ierr);
244e4ed7901SPeter Brune       ierr = SNESSetInitialFunction(snes->pc,F);CHKERRQ(ierr);
245e4ed7901SPeter Brune       ierr = SNESSetInitialFunctionNorm(snes->pc,fnorm);CHKERRQ(ierr);
24663e7833aSPeter Brune 
24763e7833aSPeter Brune       ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr);
2489f425c49SPeter Brune       ierr = SNESSolve(snes->pc,B,XM);CHKERRQ(ierr);
24963e7833aSPeter Brune       ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr);
25063e7833aSPeter Brune 
2518cc86e31SPeter Brune       ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
2528cc86e31SPeter Brune       if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
2538cc86e31SPeter Brune         snes->reason = SNES_DIVERGED_INNER;
2548cc86e31SPeter Brune         PetscFunctionReturn(0);
2558cc86e31SPeter Brune       }
2560298fd71SBarry Smith       ierr = SNESGetFunction(snes->pc,&FPC,NULL,NULL);CHKERRQ(ierr);
2574b32a720SPeter Brune       ierr = VecCopy(FPC,FM);CHKERRQ(ierr);
2584b32a720SPeter Brune       ierr = SNESGetFunctionNorm(snes->pc,&fMnorm);CHKERRQ(ierr);
2598cc86e31SPeter Brune     } else {
260f109b39eSPeter Brune       /* no preconditioner -- just take gradient descent with line search */
261f109b39eSPeter Brune       ierr = VecCopy(F,Y);CHKERRQ(ierr);
262e7058c64SPeter Brune       ierr = VecCopy(F,FM);CHKERRQ(ierr);
263e7058c64SPeter Brune       ierr = VecCopy(X,XM);CHKERRQ(ierr);
2641aa26658SKarl Rupp 
265e7058c64SPeter Brune       fMnorm = fnorm;
2661aa26658SKarl Rupp 
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     }
276f6408107SPeter Brune     ierr = SNESNGMRESFormCombinedSolution_Private(snes,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr);
27798b3e84cSPeter Brune     /* r = F(x) */
2789f425c49SPeter Brune     if (fminnorm > fMnorm) fminnorm = fMnorm;  /* the minimum norm is now of F^M */
27919653cdaSPeter Brune 
2809f425c49SPeter Brune     /* differences for selection and restart */
28113a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) {
282fa8c639aSPeter Brune       ierr = SNESNGMRESCalculateDifferences_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,&fAnorm);CHKERRQ(ierr);
28313a62661SPeter Brune     } else {
28413a62661SPeter Brune       ierr = VecNorm(FA,NORM_2,&fAnorm);CHKERRQ(ierr);
28513a62661SPeter Brune     }
286189a9710SBarry Smith     if (PetscIsInfOrNanReal(fAnorm)) {
287189a9710SBarry Smith       snes->reason = SNES_DIVERGED_FNORM_NAN;
288189a9710SBarry Smith       PetscFunctionReturn(0);
289189a9710SBarry Smith     }
2901aa26658SKarl Rupp 
2919f425c49SPeter Brune     /* combination (additive) or selection (multiplicative) of the N-GMRES solution */
292fa8c639aSPeter Brune     ierr          = SNESNGMRESSelect_Private(snes,k_restart,XM,FM,fMnorm,XA,FA,fAnorm,dnorm,fminnorm,dminnorm,X,F,Y,&fnorm);CHKERRQ(ierr);
29319653cdaSPeter Brune     selectRestart = PETSC_FALSE;
29413a62661SPeter Brune     if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) {
29521687c63SPeter Brune       ierr = SNESNGMRESSelectRestart_Private(snes,l,fAnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr);
29628ed4a04SPeter Brune       /* if the restart conditions persist for more than restart_it iterations, restart. */
2971aa26658SKarl Rupp       if (selectRestart) restart_count++;
2981aa26658SKarl Rupp       else restart_count = 0;
29913a62661SPeter Brune     } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) {
30013a62661SPeter Brune       if (k_restart > ngmres->restart_periodic) {
30113a62661SPeter Brune         if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr);
30213a62661SPeter Brune         restart_count = ngmres->restart_it;
30313a62661SPeter Brune       }
30413a62661SPeter Brune     }
30528ed4a04SPeter Brune     /* restart after restart conditions have persisted for a fixed number of iterations */
30628ed4a04SPeter Brune     if (restart_count >= ngmres->restart_it) {
307dfbf837cSBarry Smith       if (ngmres->monitor) {
308dfbf837cSBarry Smith         ierr = PetscViewerASCIIPrintf(ngmres->monitor,"Restarted at iteration %d\n",k_restart);CHKERRQ(ierr);
309dfbf837cSBarry Smith       }
31028ed4a04SPeter Brune       restart_count = 0;
31119653cdaSPeter Brune       k_restart     = 1;
31219653cdaSPeter Brune       l             = 1;
31398b3e84cSPeter Brune       /* q_{00} = nu */
31438774f0aSPeter Brune       if (ngmres->candidate) {
315fa8c639aSPeter Brune         ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,FM,fMnorm,XM);CHKERRQ(ierr);
316d2e16ddcSPeter Brune       } else {
317fa8c639aSPeter Brune         ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fMnorm,X);CHKERRQ(ierr);
318d2e16ddcSPeter Brune       }
31919653cdaSPeter Brune     } else {
32098b3e84cSPeter Brune       /* select the current size of the subspace */
3211e633543SBarry Smith       if (l < ngmres->msize) l++;
32219653cdaSPeter Brune       k_restart++;
32398b3e84cSPeter Brune       /* place the current entry in the list of previous entries */
32438774f0aSPeter Brune       if (ngmres->candidate) {
32538774f0aSPeter Brune         if (fminnorm > fMnorm) fminnorm = fMnorm;
326fa8c639aSPeter Brune         ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fMnorm,XM);CHKERRQ(ierr);
327d2e16ddcSPeter Brune       } else {
32838774f0aSPeter Brune         if (fminnorm > fnorm) fminnorm = fnorm;
329fa8c639aSPeter Brune         ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,F,fnorm,X);CHKERRQ(ierr);
33019653cdaSPeter Brune       }
331d2e16ddcSPeter Brune     }
33219653cdaSPeter Brune 
3338409ca45SMatthew G Knepley     ierr       = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
334087dfb9eSxuemin     snes->iter = k;
335f109b39eSPeter Brune     snes->norm = fnorm;
3368409ca45SMatthew G Knepley     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
337a71f0d7dSBarry Smith     ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr);
3388409ca45SMatthew G Knepley     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
339d484d688SPeter Brune     ierr = VecNormBegin(Y,NORM_2,&ynorm);CHKERRQ(ierr);
340d484d688SPeter Brune     ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);
341d484d688SPeter Brune     ierr = VecNormEnd(Y,NORM_2,&ynorm);CHKERRQ(ierr);
342d484d688SPeter Brune     ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
343d484d688SPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
344087dfb9eSxuemin     if (snes->reason) PetscFunctionReturn(0);
345a312c225SMatthew G Knepley   }
346a312c225SMatthew G Knepley   snes->reason = SNES_DIVERGED_MAX_IT;
347a312c225SMatthew G Knepley   PetscFunctionReturn(0);
348a312c225SMatthew G Knepley }
349a312c225SMatthew G Knepley 
35013a62661SPeter Brune #undef __FUNCT__
35113a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType"
35213a62661SPeter Brune /*@
35313a62661SPeter Brune     SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES.
35413a62661SPeter Brune 
35513a62661SPeter Brune     Logically Collective on SNES
35613a62661SPeter Brune 
35713a62661SPeter Brune     Input Parameters:
35813a62661SPeter Brune +   snes - the iterative context
35913a62661SPeter Brune -   rtype - restart type
36013a62661SPeter Brune 
36113a62661SPeter Brune     Options Database:
36213a62661SPeter Brune +   -snes_ngmres_restart_type<difference,periodic,none> - set the restart type
3630c777b0cSPeter Brune -   -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic
36413a62661SPeter Brune 
36513a62661SPeter Brune     Level: intermediate
36613a62661SPeter Brune 
36713a62661SPeter Brune     SNESNGMRESRestartTypes:
36813a62661SPeter Brune +   SNES_NGMRES_RESTART_NONE - never restart
36913a62661SPeter Brune .   SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria
37013a62661SPeter Brune -   SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations
37113a62661SPeter Brune 
37213a62661SPeter Brune     Notes:
37313a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
37413a62661SPeter Brune 
37513a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch
37613a62661SPeter Brune @*/
3770adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes,SNESNGMRESRestartType rtype)
3780adebc6cSBarry Smith {
37913a62661SPeter Brune   PetscErrorCode ierr;
3805fd66863SKarl Rupp 
38113a62661SPeter Brune   PetscFunctionBegin;
38213a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
38313a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr);
38413a62661SPeter Brune   PetscFunctionReturn(0);
38513a62661SPeter Brune }
38613a62661SPeter Brune 
38713a62661SPeter Brune #undef __FUNCT__
38813a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType"
38913a62661SPeter Brune /*@
39013a62661SPeter Brune     SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES.  This determines how the candidate solution and
39113a62661SPeter Brune     combined solution are used to create the next iterate.
39213a62661SPeter Brune 
39313a62661SPeter Brune     Logically Collective on SNES
39413a62661SPeter Brune 
39513a62661SPeter Brune     Input Parameters:
39613a62661SPeter Brune +   snes - the iterative context
39713a62661SPeter Brune -   stype - selection type
39813a62661SPeter Brune 
39913a62661SPeter Brune     Options Database:
40013a62661SPeter Brune .   -snes_ngmres_select_type<difference,none,linesearch>
40113a62661SPeter Brune 
40213a62661SPeter Brune     Level: intermediate
40313a62661SPeter Brune 
40413a62661SPeter Brune     SNESNGMRESSelectTypes:
40513a62661SPeter Brune +   SNES_NGMRES_SELECT_NONE - choose the combined solution all the time
40613a62661SPeter Brune .   SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria
40713a62661SPeter Brune -   SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination
40813a62661SPeter Brune 
40913a62661SPeter Brune     Notes:
41013a62661SPeter Brune     The default line search used is the L2 line search and it requires two additional function evaluations.
41113a62661SPeter Brune 
41213a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch
41313a62661SPeter Brune @*/
4140adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes,SNESNGMRESSelectType stype)
4150adebc6cSBarry Smith {
41613a62661SPeter Brune   PetscErrorCode ierr;
4175fd66863SKarl Rupp 
41813a62661SPeter Brune   PetscFunctionBegin;
41913a62661SPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
42013a62661SPeter Brune   ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr);
42113a62661SPeter Brune   PetscFunctionReturn(0);
42213a62661SPeter Brune }
42313a62661SPeter Brune 
42413a62661SPeter Brune #undef __FUNCT__
42513a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES"
4260adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes,SNESNGMRESSelectType stype)
4270adebc6cSBarry Smith {
42813a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
4295fd66863SKarl Rupp 
43013a62661SPeter Brune   PetscFunctionBegin;
43113a62661SPeter Brune   ngmres->select_type = stype;
43213a62661SPeter Brune   PetscFunctionReturn(0);
43313a62661SPeter Brune }
43413a62661SPeter Brune 
43513a62661SPeter Brune #undef __FUNCT__
43613a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES"
4370adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes,SNESNGMRESRestartType rtype)
4380adebc6cSBarry Smith {
43913a62661SPeter Brune   SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data;
4405fd66863SKarl Rupp 
44113a62661SPeter Brune   PetscFunctionBegin;
44213a62661SPeter Brune   ngmres->restart_type = rtype;
44313a62661SPeter Brune   PetscFunctionReturn(0);
44413a62661SPeter Brune }
44513a62661SPeter Brune 
446dfbf837cSBarry Smith /*MC
4471867fe5bSPeter Brune   SNESNGMRES - The Nonlinear Generalized Minimum Residual method.
448a312c225SMatthew G Knepley 
449dfbf837cSBarry Smith    Level: beginner
450dfbf837cSBarry Smith 
4511867fe5bSPeter Brune    Options Database:
45213a62661SPeter Brune +  -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution
45338774f0aSPeter Brune .  -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions
45438774f0aSPeter Brune .  -snes_ngmres_candidate        - Use NGMRES variant which combines candidate solutions instead of actual solutions
45513a62661SPeter Brune .  -snes_ngmres_m                - Number of stored previous solutions and residuals
45613a62661SPeter Brune .  -snes_ngmres_restart_it       - Number of iterations the restart conditions hold before restart
45713a62661SPeter Brune .  -snes_ngmres_gammaA           - Residual tolerance for solution select between the candidate and combination
45813a62661SPeter Brune .  -snes_ngmres_gammaC           - Residual tolerance for restart
45913a62661SPeter Brune .  -snes_ngmres_epsilonB         - Difference tolerance between subsequent solutions triggering restart
46013a62661SPeter Brune .  -snes_ngmres_deltaB           - Difference tolerance between residuals triggering restart
46113a62661SPeter Brune .  -snes_ngmres_monitor          - Prints relevant information about the ngmres iteration
46213a62661SPeter Brune .  -snes_linesearch_type <basic,basicnonorms,quadratic,critical> - Line search type used for the default smoother
46313a62661SPeter Brune -  -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type
4641867fe5bSPeter Brune 
4651867fe5bSPeter Brune    Notes:
4661867fe5bSPeter Brune 
4671867fe5bSPeter Brune    The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized
4681867fe5bSPeter Brune    optimization problem at each iteration.
4691867fe5bSPeter Brune 
4701867fe5bSPeter Brune    References:
4711867fe5bSPeter Brune 
472dfbf837cSBarry Smith    "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio,
473dfbf837cSBarry Smith    SIAM Journal on Scientific Computing, 21(5), 2000.
474dfbf837cSBarry Smith 
475dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types)
476dfbf837cSBarry Smith M*/
477a312c225SMatthew G Knepley 
478a312c225SMatthew G Knepley #undef __FUNCT__
479a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES"
480*8cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NGMRES(SNES snes)
481a312c225SMatthew G Knepley {
482a312c225SMatthew G Knepley   SNES_NGMRES    *ngmres;
483a312c225SMatthew G Knepley   PetscErrorCode ierr;
484a312c225SMatthew G Knepley 
485a312c225SMatthew G Knepley   PetscFunctionBegin;
486a312c225SMatthew G Knepley   snes->ops->destroy        = SNESDestroy_NGMRES;
487a312c225SMatthew G Knepley   snes->ops->setup          = SNESSetUp_NGMRES;
488a312c225SMatthew G Knepley   snes->ops->setfromoptions = SNESSetFromOptions_NGMRES;
489a312c225SMatthew G Knepley   snes->ops->view           = SNESView_NGMRES;
490a312c225SMatthew G Knepley   snes->ops->solve          = SNESSolve_NGMRES;
491a312c225SMatthew G Knepley   snes->ops->reset          = SNESReset_NGMRES;
492a312c225SMatthew G Knepley 
49342f4f86dSBarry Smith   snes->usespc  = PETSC_TRUE;
4942c155ee1SBarry Smith   snes->usesksp = PETSC_FALSE;
4952c155ee1SBarry Smith 
496a312c225SMatthew G Knepley   ierr          = PetscNewLog(snes,SNES_NGMRES,&ngmres);CHKERRQ(ierr);
497a312c225SMatthew G Knepley   snes->data    = (void*) ngmres;
498d2e16ddcSPeter Brune   ngmres->msize = 30;
49919653cdaSPeter Brune 
50088976e71SPeter Brune   if (!snes->tolerancesset) {
5010e444f03SPeter Brune     snes->max_funcs = 30000;
5020e444f03SPeter Brune     snes->max_its   = 10000;
50388976e71SPeter Brune   }
5040e444f03SPeter Brune 
50538774f0aSPeter Brune   ngmres->candidate = PETSC_FALSE;
506d2e16ddcSPeter Brune 
5070298fd71SBarry Smith   ngmres->additive_linesearch = NULL;
508077c4231SPeter Brune   ngmres->approxfunc       = PETSC_FALSE;
50928ed4a04SPeter Brune   ngmres->restart_it       = 2;
51013a62661SPeter Brune   ngmres->restart_periodic = 30;
511f109b39eSPeter Brune   ngmres->gammaA           = 2.0;
512f109b39eSPeter Brune   ngmres->gammaC           = 2.0;
513cac108bcSPeter Brune   ngmres->deltaB           = 0.9;
514cac108bcSPeter Brune   ngmres->epsilonB         = 0.1;
515e7058c64SPeter Brune 
51613a62661SPeter Brune   ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE;
51713a62661SPeter Brune   ngmres->select_type  = SNES_NGMRES_SELECT_DIFFERENCE;
51813a62661SPeter Brune 
51900de8ff0SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetSelectType_C","SNESNGMRESSetSelectType_NGMRES",SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr);
52000de8ff0SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartType_C","SNESNGMRESSetRestartType_NGMRES",SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr);
521a312c225SMatthew G Knepley   PetscFunctionReturn(0);
522a312c225SMatthew G Knepley }
52399e0435eSBarry Smith 
524