113a62661SPeter Brune #include <../src/snes/impls/ngmres/snesngmres.h> /*I "petscsnes.h" I*/ 219653cdaSPeter Brune #include <petscblaslapack.h> 3fced5a79SAsbjørn Nilsen Riseth #include <petscdm.h> 4a312c225SMatthew G Knepley 56a6fc655SJed Brown const char *const SNESNGMRESRestartTypes[] = {"NONE","PERIODIC","DIFFERENCE","SNESNGMRESRestartType","SNES_NGMRES_RESTART_",0}; 66a6fc655SJed Brown const char *const SNESNGMRESSelectTypes[] = {"NONE","DIFFERENCE","LINESEARCH","SNESNGMRESSelectType","SNES_NGMRES_SELECT_",0}; 713a62661SPeter Brune 8a312c225SMatthew G Knepley PetscErrorCode SNESReset_NGMRES(SNES snes) 9a312c225SMatthew G Knepley { 10a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 11a312c225SMatthew G Knepley PetscErrorCode ierr; 12a312c225SMatthew G Knepley 13a312c225SMatthew G Knepley PetscFunctionBegin; 14f109b39eSPeter Brune ierr = VecDestroyVecs(ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr); 15f109b39eSPeter Brune ierr = VecDestroyVecs(ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr); 16f1c6b773SPeter Brune ierr = SNESLineSearchDestroy(&ngmres->additive_linesearch);CHKERRQ(ierr); 17a312c225SMatthew G Knepley PetscFunctionReturn(0); 18a312c225SMatthew G Knepley } 19a312c225SMatthew G Knepley 20a312c225SMatthew G Knepley PetscErrorCode SNESDestroy_NGMRES(SNES snes) 21a312c225SMatthew G Knepley { 22a312c225SMatthew G Knepley PetscErrorCode ierr; 2378440776SJed Brown SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 24a312c225SMatthew G Knepley 25a312c225SMatthew G Knepley PetscFunctionBegin; 26a312c225SMatthew G Knepley ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr); 27*580bdb30SBarry Smith ierr = PetscFree4(ngmres->h,ngmres->beta,ngmres->xi,ngmres->q);CHKERRQ(ierr); 28*580bdb30SBarry Smith ierr = PetscFree3(ngmres->xnorms,ngmres->fnorms,ngmres->s);CHKERRQ(ierr); 29dd63322aSSatish Balay #if defined(PETSC_USE_COMPLEX) 3022d28d08SBarry Smith ierr = PetscFree(ngmres->rwork);CHKERRQ(ierr); 3119653cdaSPeter Brune #endif 3222d28d08SBarry Smith ierr = PetscFree(ngmres->work);CHKERRQ(ierr); 3322d28d08SBarry Smith ierr = PetscFree(snes->data);CHKERRQ(ierr); 34a312c225SMatthew G Knepley PetscFunctionReturn(0); 35a312c225SMatthew G Knepley } 36a312c225SMatthew G Knepley 37a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes) 38a312c225SMatthew G Knepley { 39a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 40e7058c64SPeter Brune const char *optionsprefix; 4119653cdaSPeter Brune PetscInt msize,hsize; 42a312c225SMatthew G Knepley PetscErrorCode ierr; 43fced5a79SAsbjørn Nilsen Riseth DM dm; 44a312c225SMatthew G Knepley 45a312c225SMatthew G Knepley PetscFunctionBegin; 46efd4aadfSBarry Smith if (snes->npc && snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) { 4746159c86SPeter Brune SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"SNESNGMRES does not support left preconditioning with unpreconditioned function"); 4846159c86SPeter Brune } 49efd4aadfSBarry Smith if (snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_DEFAULT) snes->functype = SNES_FUNCTION_PRECONDITIONED; 50fa0ddf94SBarry Smith ierr = SNESSetWorkVecs(snes,5);CHKERRQ(ierr); 51fced5a79SAsbjørn Nilsen Riseth 52fced5a79SAsbjørn Nilsen Riseth if (!snes->vec_sol) { 53fced5a79SAsbjørn Nilsen Riseth ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 54fced5a79SAsbjørn Nilsen Riseth ierr = DMCreateGlobalVector(dm,&snes->vec_sol);CHKERRQ(ierr); 55fced5a79SAsbjørn Nilsen Riseth } 56fced5a79SAsbjørn Nilsen Riseth 5778440776SJed Brown if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);} 5878440776SJed Brown if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);} 5978440776SJed Brown if (!ngmres->setup_called) { 60087dfb9eSxuemin msize = ngmres->msize; /* restart size */ 6119653cdaSPeter Brune hsize = msize * msize; 62087dfb9eSxuemin 6398b3e84cSPeter Brune /* explicit least squares minimization solve */ 64*580bdb30SBarry Smith ierr = PetscCalloc4(hsize,&ngmres->h, msize,&ngmres->beta, msize,&ngmres->xi, hsize,&ngmres->q);CHKERRQ(ierr); 65*580bdb30SBarry Smith ierr = PetscMalloc3(msize,&ngmres->xnorms,msize,&ngmres->fnorms,msize,&ngmres->s);CHKERRQ(ierr); 6619653cdaSPeter Brune ngmres->nrhs = 1; 6719653cdaSPeter Brune ngmres->lda = msize; 6819653cdaSPeter Brune ngmres->ldb = msize; 6919653cdaSPeter Brune ngmres->lwork = 12*msize; 70dd63322aSSatish Balay #if defined(PETSC_USE_COMPLEX) 71854ce69bSBarry Smith ierr = PetscMalloc1(ngmres->lwork,&ngmres->rwork);CHKERRQ(ierr); 7219653cdaSPeter Brune #endif 73854ce69bSBarry Smith ierr = PetscMalloc1(ngmres->lwork,&ngmres->work);CHKERRQ(ierr); 7478440776SJed Brown } 75e7058c64SPeter Brune 76e7058c64SPeter Brune /* linesearch setup */ 77e7058c64SPeter Brune ierr = SNESGetOptionsPrefix(snes,&optionsprefix);CHKERRQ(ierr); 78e7058c64SPeter Brune 7913a62661SPeter Brune if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) { 80ce94432eSBarry Smith ierr = SNESLineSearchCreate(PetscObjectComm((PetscObject)snes),&ngmres->additive_linesearch);CHKERRQ(ierr); 81f1c6b773SPeter Brune ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch,snes);CHKERRQ(ierr); 821a4f838cSPeter Brune ierr = SNESLineSearchSetType(ngmres->additive_linesearch,SNESLINESEARCHL2);CHKERRQ(ierr); 83f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,"additive_");CHKERRQ(ierr); 84f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,optionsprefix);CHKERRQ(ierr); 85f1c6b773SPeter Brune ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr); 86e7058c64SPeter Brune } 87e7058c64SPeter Brune 8878440776SJed Brown ngmres->setup_called = PETSC_TRUE; 89a312c225SMatthew G Knepley PetscFunctionReturn(0); 90a312c225SMatthew G Knepley } 91a312c225SMatthew G Knepley 924416b707SBarry Smith PetscErrorCode SNESSetFromOptions_NGMRES(PetscOptionItems *PetscOptionsObject,SNES snes) 93a312c225SMatthew G Knepley { 94a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 95a312c225SMatthew G Knepley PetscErrorCode ierr; 9694ae4db5SBarry Smith PetscBool debug = PETSC_FALSE; 970adebc6cSBarry Smith 98a312c225SMatthew G Knepley PetscFunctionBegin; 99e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"SNES NGMRES options");CHKERRQ(ierr); 10013a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes, 1010298fd71SBarry Smith (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,NULL);CHKERRQ(ierr); 10213a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes, 1030298fd71SBarry Smith (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,NULL);CHKERRQ(ierr); 1040298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_candidate", "Use candidate storage", "SNES",ngmres->candidate,&ngmres->candidate,NULL);CHKERRQ(ierr); 105077c4231SPeter Brune ierr = PetscOptionsBool("-snes_ngmres_approxfunc","Linearly approximate the function", "SNES",ngmres->approxfunc,&ngmres->approxfunc,NULL);CHKERRQ(ierr); 1060298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_m", "Number of directions", "SNES",ngmres->msize,&ngmres->msize,NULL);CHKERRQ(ierr); 1070298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_restart", "Iterations before forced restart", "SNES",ngmres->restart_periodic,&ngmres->restart_periodic,NULL);CHKERRQ(ierr); 1080298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_restart_it", "Tolerance iterations before restart","SNES",ngmres->restart_it,&ngmres->restart_it,NULL);CHKERRQ(ierr); 1090298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_monitor", "Monitor actions of NGMRES", "SNES",ngmres->monitor ? PETSC_TRUE : PETSC_FALSE,&debug,NULL);CHKERRQ(ierr); 110dfbf837cSBarry Smith if (debug) { 111ce94432eSBarry Smith ngmres->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 112dfbf837cSBarry Smith } 1130298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_gammaA", "Residual selection constant", "SNES",ngmres->gammaA,&ngmres->gammaA,NULL);CHKERRQ(ierr); 1140298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_gammaC", "Residual restart constant", "SNES",ngmres->gammaC,&ngmres->gammaC,NULL);CHKERRQ(ierr); 1150298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES",ngmres->epsilonB,&ngmres->epsilonB,NULL);CHKERRQ(ierr); 1160298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_deltaB", "Difference residual selection constant", "SNES",ngmres->deltaB,&ngmres->deltaB,NULL);CHKERRQ(ierr); 1170298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions", "SNES",ngmres->singlereduction,&ngmres->singlereduction,NULL);CHKERRQ(ierr); 11823b3e82cSAsbjørn Nilsen Riseth ierr = PetscOptionsBool("-snes_ngmres_restart_fm_rise", "Restart on F_M residual rise", "SNESNGMRESSetRestartFmRise",ngmres->restart_fm_rise,&ngmres->restart_fm_rise,NULL);CHKERRQ(ierr); 119a312c225SMatthew G Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1206a7cf640SPeter Brune if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA; 121a312c225SMatthew G Knepley PetscFunctionReturn(0); 122a312c225SMatthew G Knepley } 123a312c225SMatthew G Knepley 124a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes,PetscViewer viewer) 125a312c225SMatthew G Knepley { 126a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 127a312c225SMatthew G Knepley PetscBool iascii; 128a312c225SMatthew G Knepley PetscErrorCode ierr; 129a312c225SMatthew G Knepley 130a312c225SMatthew G Knepley PetscFunctionBegin; 131251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject) viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 132a312c225SMatthew G Knepley if (iascii) { 133f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr); 134f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Residual selection: gammaA=%1.0e, gammaC=%1.0e\n",ngmres->gammaA,ngmres->gammaC);CHKERRQ(ierr); 135f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n",ngmres->epsilonB,ngmres->deltaB);CHKERRQ(ierr); 13623b3e82cSAsbjørn Nilsen Riseth ierr = PetscViewerASCIIPrintf(viewer," Restart on F_M residual increase: %s\n",ngmres->restart_fm_rise?"TRUE":"FALSE");CHKERRQ(ierr); 137a312c225SMatthew G Knepley } 138a312c225SMatthew G Knepley PetscFunctionReturn(0); 139a312c225SMatthew G Knepley } 140a312c225SMatthew G Knepley 141a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes) 142a312c225SMatthew G Knepley { 143087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 14498b3e84cSPeter Brune /* present solution, residual, and preconditioned residual */ 1459f425c49SPeter Brune Vec X,F,B,D,Y; 146f109b39eSPeter Brune 147f109b39eSPeter Brune /* candidate linear combination answers */ 148ddd40ce5SPeter Brune Vec XA,FA,XM,FM; 14919653cdaSPeter Brune 15098b3e84cSPeter Brune /* coefficients and RHS to the minimization problem */ 15118aa0c0cSPeter Brune PetscReal fnorm,fMnorm,fAnorm; 152b3c6a99cSPeter Brune PetscReal xnorm,xMnorm,xAnorm; 153b3c6a99cSPeter Brune PetscReal ynorm,yMnorm,yAnorm; 15438774f0aSPeter Brune PetscInt k,k_restart,l,ivec,restart_count = 0; 15519653cdaSPeter Brune 15698b3e84cSPeter Brune /* solution selection data */ 15738774f0aSPeter Brune PetscBool selectRestart; 15861ba4676SBarry Smith /* 15961ba4676SBarry Smith These two variables are initialized to prevent compilers/analyzers from producing false warnings about these variables being passed 16061ba4676SBarry Smith to SNESNGMRESSelect_Private() without being set when SNES_NGMRES_RESTART_DIFFERENCE, the values are not used in the subroutines in that case 16161ba4676SBarry Smith so the code is correct as written. 16261ba4676SBarry Smith */ 16361ba4676SBarry Smith PetscReal dnorm = 0.0,dminnorm = 0.0; 164b3c6a99cSPeter Brune PetscReal fminnorm; 16519653cdaSPeter Brune 1661e633543SBarry Smith SNESConvergedReason reason; 167422a814eSBarry Smith SNESLineSearchReason lssucceed; 168a312c225SMatthew G Knepley PetscErrorCode ierr; 169a312c225SMatthew G Knepley 170a312c225SMatthew G Knepley PetscFunctionBegin; 1716c4ed002SBarry Smith if (snes->xl || snes->xu || snes->ops->computevariablebounds) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); 172c579b300SPatrick Farrell 173fffbeea8SBarry Smith ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr); 17498b3e84cSPeter Brune /* variable initialization */ 175a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 176f109b39eSPeter Brune X = snes->vec_sol; 177f109b39eSPeter Brune F = snes->vec_func; 178f109b39eSPeter Brune B = snes->vec_rhs; 179f109b39eSPeter Brune XA = snes->vec_sol_update; 180f109b39eSPeter Brune FA = snes->work[0]; 181f109b39eSPeter Brune D = snes->work[1]; 182f109b39eSPeter Brune 183f109b39eSPeter Brune /* work for the line search */ 184f109b39eSPeter Brune Y = snes->work[2]; 1859f425c49SPeter Brune XM = snes->work[3]; 1869f425c49SPeter Brune FM = snes->work[4]; 187a312c225SMatthew G Knepley 188e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 189a312c225SMatthew G Knepley snes->iter = 0; 190a312c225SMatthew G Knepley snes->norm = 0.; 191e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 19219653cdaSPeter Brune 19398b3e84cSPeter Brune /* initialization */ 19419653cdaSPeter Brune 195efd4aadfSBarry Smith if (snes->npc && snes->npcside== PC_LEFT) { 196be95d8f1SBarry Smith ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr); 197efd4aadfSBarry Smith ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr); 1983a2ae377SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 1993a2ae377SPeter Brune snes->reason = SNES_DIVERGED_INNER; 2003a2ae377SPeter Brune PetscFunctionReturn(0); 2013a2ae377SPeter Brune } 2023a2ae377SPeter Brune ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 2033a2ae377SPeter Brune } else { 204e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 205f109b39eSPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 2061aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 207c1c75074SPeter Brune 208f109b39eSPeter Brune ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 209422a814eSBarry Smith SNESCheckFunctionNorm(snes,fnorm); 2103a2ae377SPeter Brune } 211e4ed7901SPeter Brune fminnorm = fnorm; 21219653cdaSPeter Brune 213e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 214f109b39eSPeter Brune snes->norm = fnorm; 215e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 216a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); 217f109b39eSPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 218f109b39eSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 219a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 220b3c6a99cSPeter Brune SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fnorm,X); 221a312c225SMatthew G Knepley 22219653cdaSPeter Brune k_restart = 1; 22319653cdaSPeter Brune l = 1; 224b3c6a99cSPeter Brune ivec = 0; 22509c08436SPeter Brune for (k=1; k < snes->max_its+1; k++) { 22698b3e84cSPeter Brune /* Computation of x^M */ 227efd4aadfSBarry Smith if (snes->npc && snes->npcside== PC_RIGHT) { 2289f425c49SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 229efd4aadfSBarry Smith ierr = SNESSetInitialFunction(snes->npc,F);CHKERRQ(ierr); 23063e7833aSPeter Brune 231efd4aadfSBarry Smith ierr = PetscLogEventBegin(SNES_NPCSolve,snes->npc,XM,B,0);CHKERRQ(ierr); 232efd4aadfSBarry Smith ierr = SNESSolve(snes->npc,B,XM);CHKERRQ(ierr); 233efd4aadfSBarry Smith ierr = PetscLogEventEnd(SNES_NPCSolve,snes->npc,XM,B,0);CHKERRQ(ierr); 23463e7833aSPeter Brune 235efd4aadfSBarry Smith ierr = SNESGetConvergedReason(snes->npc,&reason);CHKERRQ(ierr); 2368cc86e31SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2378cc86e31SPeter Brune snes->reason = SNES_DIVERGED_INNER; 2388cc86e31SPeter Brune PetscFunctionReturn(0); 2398cc86e31SPeter Brune } 240be95d8f1SBarry Smith ierr = SNESGetNPCFunction(snes,FM,&fMnorm);CHKERRQ(ierr); 2418cc86e31SPeter Brune } else { 242f109b39eSPeter Brune /* no preconditioner -- just take gradient descent with line search */ 243f109b39eSPeter Brune ierr = VecCopy(F,Y);CHKERRQ(ierr); 244e7058c64SPeter Brune ierr = VecCopy(F,FM);CHKERRQ(ierr); 245e7058c64SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 2461aa26658SKarl Rupp 247e7058c64SPeter Brune fMnorm = fnorm; 2481aa26658SKarl Rupp 249f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr); 250422a814eSBarry Smith ierr = SNESLineSearchGetReason(snes->linesearch,&lssucceed);CHKERRQ(ierr); 251422a814eSBarry Smith if (lssucceed) { 252f109b39eSPeter Brune if (++snes->numFailures >= snes->maxFailures) { 253f109b39eSPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 254f109b39eSPeter Brune PetscFunctionReturn(0); 255f109b39eSPeter Brune } 256f109b39eSPeter Brune } 2576634f59bSPeter Brune } 25823b3e82cSAsbjørn Nilsen Riseth 259b3c6a99cSPeter Brune ierr = SNESNGMRESFormCombinedSolution_Private(snes,ivec,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr); 26098b3e84cSPeter Brune /* r = F(x) */ 2619f425c49SPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of F^M */ 26219653cdaSPeter Brune 2639f425c49SPeter Brune /* differences for selection and restart */ 26413a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) { 265b3c6a99cSPeter Brune ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr); 26613a62661SPeter Brune } else { 267b3c6a99cSPeter Brune ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,NULL,NULL,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr); 26813a62661SPeter Brune } 269422a814eSBarry Smith SNESCheckFunctionNorm(snes,fnorm); 2701aa26658SKarl Rupp 2719f425c49SPeter Brune /* combination (additive) or selection (multiplicative) of the N-GMRES solution */ 272b3c6a99cSPeter Brune ierr = SNESNGMRESSelect_Private(snes,k_restart,XM,FM,xMnorm,fMnorm,yMnorm,XA,FA,xAnorm,fAnorm,yAnorm,dnorm,fminnorm,dminnorm,X,F,Y,&xnorm,&fnorm,&ynorm);CHKERRQ(ierr); 27319653cdaSPeter Brune selectRestart = PETSC_FALSE; 27423b3e82cSAsbjørn Nilsen Riseth 27513a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) { 27623b3e82cSAsbjørn Nilsen Riseth ierr = SNESNGMRESSelectRestart_Private(snes,l,fMnorm,fAnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr); 27723b3e82cSAsbjørn Nilsen Riseth 27828ed4a04SPeter Brune /* if the restart conditions persist for more than restart_it iterations, restart. */ 2791aa26658SKarl Rupp if (selectRestart) restart_count++; 2801aa26658SKarl Rupp else restart_count = 0; 28113a62661SPeter Brune } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) { 28213a62661SPeter Brune if (k_restart > ngmres->restart_periodic) { 28313a62661SPeter Brune if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr); 28413a62661SPeter Brune restart_count = ngmres->restart_it; 28513a62661SPeter Brune } 28613a62661SPeter Brune } 28723b3e82cSAsbjørn Nilsen Riseth 288b3c6a99cSPeter Brune ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */ 28923b3e82cSAsbjørn Nilsen Riseth 29028ed4a04SPeter Brune /* restart after restart conditions have persisted for a fixed number of iterations */ 29128ed4a04SPeter Brune if (restart_count >= ngmres->restart_it) { 292dfbf837cSBarry Smith if (ngmres->monitor) { 293dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor,"Restarted at iteration %d\n",k_restart);CHKERRQ(ierr); 294dfbf837cSBarry Smith } 29528ed4a04SPeter Brune restart_count = 0; 29619653cdaSPeter Brune k_restart = 1; 29719653cdaSPeter Brune l = 1; 298b3c6a99cSPeter Brune ivec = 0; 29998b3e84cSPeter Brune /* q_{00} = nu */ 300fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,FM,fMnorm,XM);CHKERRQ(ierr); 301d2e16ddcSPeter Brune } else { 30298b3e84cSPeter Brune /* select the current size of the subspace */ 3031e633543SBarry Smith if (l < ngmres->msize) l++; 30419653cdaSPeter Brune k_restart++; 30598b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 30638774f0aSPeter Brune if (ngmres->candidate) { 30738774f0aSPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; 308fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fMnorm,XM);CHKERRQ(ierr); 309d2e16ddcSPeter Brune } else { 31038774f0aSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; 311fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,F,fnorm,X);CHKERRQ(ierr); 31219653cdaSPeter Brune } 313d2e16ddcSPeter Brune } 31419653cdaSPeter Brune 315e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 316087dfb9eSxuemin snes->iter = k; 317f109b39eSPeter Brune snes->norm = fnorm; 318e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 319a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr); 3208409ca45SMatthew G Knepley ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 321b3c6a99cSPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0,0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 322087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 323a312c225SMatthew G Knepley } 324a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 325a312c225SMatthew G Knepley PetscFunctionReturn(0); 326a312c225SMatthew G Knepley } 327a312c225SMatthew G Knepley 32823b3e82cSAsbjørn Nilsen Riseth /*@ 32923b3e82cSAsbjørn Nilsen Riseth SNESNGMRESSetRestartFmRise - Increase the restart count if the step x_M increases the residual F_M 33023b3e82cSAsbjørn Nilsen Riseth 33123b3e82cSAsbjørn Nilsen Riseth Input Parameters: 33223b3e82cSAsbjørn Nilsen Riseth + snes - the SNES context. 33323b3e82cSAsbjørn Nilsen Riseth - flg - boolean value deciding whether to use the option or not 33423b3e82cSAsbjørn Nilsen Riseth 33523b3e82cSAsbjørn Nilsen Riseth Options Database: 33623b3e82cSAsbjørn Nilsen Riseth + -snes_ngmres_restart_fm_rise - Increase the restart count if the step x_M increases the residual F_M 33723b3e82cSAsbjørn Nilsen Riseth 33823b3e82cSAsbjørn Nilsen Riseth Level: intermediate 33923b3e82cSAsbjørn Nilsen Riseth 34023b3e82cSAsbjørn Nilsen Riseth Notes: 34123b3e82cSAsbjørn Nilsen Riseth If the proposed step x_M increases the residual F_M, it might be trying to get out of a stagnation area. 34223b3e82cSAsbjørn Nilsen Riseth To help the solver do that, reset the Krylov subspace whenever F_M increases. 34323b3e82cSAsbjørn Nilsen Riseth 34423b3e82cSAsbjørn Nilsen Riseth This option must be used with SNES_NGMRES_RESTART_DIFFERENCE 34523b3e82cSAsbjørn Nilsen Riseth 34623b3e82cSAsbjørn Nilsen Riseth The default is FALSE. 34723b3e82cSAsbjørn Nilsen Riseth .seealso: SNES_NGMRES_RESTART_DIFFERENCE 34823b3e82cSAsbjørn Nilsen Riseth @*/ 34923b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESSetRestartFmRise(SNES snes,PetscBool flg) 35023b3e82cSAsbjørn Nilsen Riseth { 35123b3e82cSAsbjørn Nilsen Riseth PetscErrorCode (*f)(SNES,PetscBool); 35223b3e82cSAsbjørn Nilsen Riseth PetscErrorCode ierr; 35323b3e82cSAsbjørn Nilsen Riseth 35423b3e82cSAsbjørn Nilsen Riseth PetscFunctionBegin; 35523b3e82cSAsbjørn Nilsen Riseth ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNGMRESSetRestartFmRise_C",&f);CHKERRQ(ierr); 35623b3e82cSAsbjørn Nilsen Riseth if (f) {ierr = (f)(snes,flg);CHKERRQ(ierr);} 35723b3e82cSAsbjørn Nilsen Riseth PetscFunctionReturn(0); 35823b3e82cSAsbjørn Nilsen Riseth } 35923b3e82cSAsbjørn Nilsen Riseth 36023b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESSetRestartFmRise_NGMRES(SNES snes,PetscBool flg) 36123b3e82cSAsbjørn Nilsen Riseth { 36223b3e82cSAsbjørn Nilsen Riseth SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 36323b3e82cSAsbjørn Nilsen Riseth 36423b3e82cSAsbjørn Nilsen Riseth PetscFunctionBegin; 36523b3e82cSAsbjørn Nilsen Riseth ngmres->restart_fm_rise = flg; 36623b3e82cSAsbjørn Nilsen Riseth PetscFunctionReturn(0); 36723b3e82cSAsbjørn Nilsen Riseth } 36823b3e82cSAsbjørn Nilsen Riseth 36923b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESGetRestartFmRise(SNES snes,PetscBool *flg) 37023b3e82cSAsbjørn Nilsen Riseth { 37123b3e82cSAsbjørn Nilsen Riseth PetscErrorCode (*f)(SNES,PetscBool*); 37223b3e82cSAsbjørn Nilsen Riseth PetscErrorCode ierr; 37323b3e82cSAsbjørn Nilsen Riseth 37423b3e82cSAsbjørn Nilsen Riseth PetscFunctionBegin; 37523b3e82cSAsbjørn Nilsen Riseth ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESNGMRESGetRestartFmRise_C",&f);CHKERRQ(ierr); 37623b3e82cSAsbjørn Nilsen Riseth if (f) {ierr = (f)(snes,flg);CHKERRQ(ierr);} 37723b3e82cSAsbjørn Nilsen Riseth PetscFunctionReturn(0); 37823b3e82cSAsbjørn Nilsen Riseth } 37923b3e82cSAsbjørn Nilsen Riseth 38023b3e82cSAsbjørn Nilsen Riseth PetscErrorCode SNESNGMRESGetRestartFmRise_NGMRES(SNES snes,PetscBool *flg) 38123b3e82cSAsbjørn Nilsen Riseth { 38223b3e82cSAsbjørn Nilsen Riseth SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 38323b3e82cSAsbjørn Nilsen Riseth 38423b3e82cSAsbjørn Nilsen Riseth PetscFunctionBegin; 38523b3e82cSAsbjørn Nilsen Riseth *flg = ngmres->restart_fm_rise; 38623b3e82cSAsbjørn Nilsen Riseth PetscFunctionReturn(0); 38723b3e82cSAsbjørn Nilsen Riseth } 38823b3e82cSAsbjørn Nilsen Riseth 38923b3e82cSAsbjørn Nilsen Riseth 39013a62661SPeter Brune /*@ 39113a62661SPeter Brune SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES. 39213a62661SPeter Brune 39313a62661SPeter Brune Logically Collective on SNES 39413a62661SPeter Brune 39513a62661SPeter Brune Input Parameters: 39613a62661SPeter Brune + snes - the iterative context 39713a62661SPeter Brune - rtype - restart type 39813a62661SPeter Brune 39913a62661SPeter Brune Options Database: 40013a62661SPeter Brune + -snes_ngmres_restart_type<difference,periodic,none> - set the restart type 4010c777b0cSPeter Brune - -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic 40213a62661SPeter Brune 40313a62661SPeter Brune Level: intermediate 40413a62661SPeter Brune 40513a62661SPeter Brune SNESNGMRESRestartTypes: 40613a62661SPeter Brune + SNES_NGMRES_RESTART_NONE - never restart 40713a62661SPeter Brune . SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria 40813a62661SPeter Brune - SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations 40913a62661SPeter Brune 41013a62661SPeter Brune Notes: 41113a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 41213a62661SPeter Brune 41313a62661SPeter Brune @*/ 4140adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes,SNESNGMRESRestartType rtype) 4150adebc6cSBarry Smith { 41613a62661SPeter Brune PetscErrorCode ierr; 4175fd66863SKarl Rupp 41813a62661SPeter Brune PetscFunctionBegin; 41913a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 42013a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr); 42113a62661SPeter Brune PetscFunctionReturn(0); 42213a62661SPeter Brune } 42313a62661SPeter Brune 42413a62661SPeter Brune /*@ 42513a62661SPeter Brune SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES. This determines how the candidate solution and 42613a62661SPeter Brune combined solution are used to create the next iterate. 42713a62661SPeter Brune 42813a62661SPeter Brune Logically Collective on SNES 42913a62661SPeter Brune 43013a62661SPeter Brune Input Parameters: 43113a62661SPeter Brune + snes - the iterative context 43213a62661SPeter Brune - stype - selection type 43313a62661SPeter Brune 43413a62661SPeter Brune Options Database: 43513a62661SPeter Brune . -snes_ngmres_select_type<difference,none,linesearch> 43613a62661SPeter Brune 43713a62661SPeter Brune Level: intermediate 43813a62661SPeter Brune 43913a62661SPeter Brune SNESNGMRESSelectTypes: 44013a62661SPeter Brune + SNES_NGMRES_SELECT_NONE - choose the combined solution all the time 44113a62661SPeter Brune . SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria 44213a62661SPeter Brune - SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination 44313a62661SPeter Brune 44413a62661SPeter Brune Notes: 44513a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 44613a62661SPeter Brune 44713a62661SPeter Brune @*/ 4480adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes,SNESNGMRESSelectType stype) 4490adebc6cSBarry Smith { 45013a62661SPeter Brune PetscErrorCode ierr; 4515fd66863SKarl Rupp 45213a62661SPeter Brune PetscFunctionBegin; 45313a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 45413a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr); 45513a62661SPeter Brune PetscFunctionReturn(0); 45613a62661SPeter Brune } 45713a62661SPeter Brune 4580adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes,SNESNGMRESSelectType stype) 4590adebc6cSBarry Smith { 46013a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 4615fd66863SKarl Rupp 46213a62661SPeter Brune PetscFunctionBegin; 46313a62661SPeter Brune ngmres->select_type = stype; 46413a62661SPeter Brune PetscFunctionReturn(0); 46513a62661SPeter Brune } 46613a62661SPeter Brune 4670adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes,SNESNGMRESRestartType rtype) 4680adebc6cSBarry Smith { 46913a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 4705fd66863SKarl Rupp 47113a62661SPeter Brune PetscFunctionBegin; 47213a62661SPeter Brune ngmres->restart_type = rtype; 47313a62661SPeter Brune PetscFunctionReturn(0); 47413a62661SPeter Brune } 47513a62661SPeter Brune 476dfbf837cSBarry Smith /*MC 4771867fe5bSPeter Brune SNESNGMRES - The Nonlinear Generalized Minimum Residual method. 478a312c225SMatthew G Knepley 479dfbf837cSBarry Smith Level: beginner 480dfbf837cSBarry Smith 4811867fe5bSPeter Brune Options Database: 48213a62661SPeter Brune + -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution 48338774f0aSPeter Brune . -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions 48438774f0aSPeter Brune . -snes_ngmres_candidate - Use NGMRES variant which combines candidate solutions instead of actual solutions 48513a62661SPeter Brune . -snes_ngmres_m - Number of stored previous solutions and residuals 48613a62661SPeter Brune . -snes_ngmres_restart_it - Number of iterations the restart conditions hold before restart 48713a62661SPeter Brune . -snes_ngmres_gammaA - Residual tolerance for solution select between the candidate and combination 48813a62661SPeter Brune . -snes_ngmres_gammaC - Residual tolerance for restart 48913a62661SPeter Brune . -snes_ngmres_epsilonB - Difference tolerance between subsequent solutions triggering restart 49013a62661SPeter Brune . -snes_ngmres_deltaB - Difference tolerance between residuals triggering restart 49123b3e82cSAsbjørn Nilsen Riseth . -snes_ngmres_restart_fm_rise - Restart on residual rise from x_M step 49213a62661SPeter Brune . -snes_ngmres_monitor - Prints relevant information about the ngmres iteration 4935c3e6ab7SPeter Brune . -snes_linesearch_type <basic,l2,cp> - Line search type used for the default smoother 49413a62661SPeter Brune - -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type 4951867fe5bSPeter Brune 4961867fe5bSPeter Brune Notes: 4971867fe5bSPeter Brune 4981867fe5bSPeter Brune The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized 4991867fe5bSPeter Brune optimization problem at each iteration. 5001867fe5bSPeter Brune 5014f02bc6aSBarry Smith Very similar to the SNESANDERSON algorithm. 5024f02bc6aSBarry Smith 5031867fe5bSPeter Brune References: 50496a0c994SBarry Smith + 1. - C. W. Oosterlee and T. Washio, "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", 505dfbf837cSBarry Smith SIAM Journal on Scientific Computing, 21(5), 2000. 50696a0c994SBarry Smith - 2. - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", 5074f02bc6aSBarry Smith SIAM Review, 57(4), 2015 5084f02bc6aSBarry Smith 5094f02bc6aSBarry Smith 510dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 511dfbf837cSBarry Smith M*/ 512a312c225SMatthew G Knepley 5138cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NGMRES(SNES snes) 514a312c225SMatthew G Knepley { 515a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 516a312c225SMatthew G Knepley PetscErrorCode ierr; 517d8d34be6SBarry Smith SNESLineSearch linesearch; 518a312c225SMatthew G Knepley 519a312c225SMatthew G Knepley PetscFunctionBegin; 520a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 521a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 522a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 523a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 524a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 525a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 526a312c225SMatthew G Knepley 527efd4aadfSBarry Smith snes->usesnpc = PETSC_TRUE; 5282c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 529efd4aadfSBarry Smith snes->npcside = PC_RIGHT; 5302c155ee1SBarry Smith 5314fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_TRUE; 5324fc747eaSLawrence Mitchell 533b00a9115SJed Brown ierr = PetscNewLog(snes,&ngmres);CHKERRQ(ierr); 534a312c225SMatthew G Knepley snes->data = (void*) ngmres; 535d2e16ddcSPeter Brune ngmres->msize = 30; 53619653cdaSPeter Brune 53788976e71SPeter Brune if (!snes->tolerancesset) { 5380e444f03SPeter Brune snes->max_funcs = 30000; 5390e444f03SPeter Brune snes->max_its = 10000; 54088976e71SPeter Brune } 5410e444f03SPeter Brune 54238774f0aSPeter Brune ngmres->candidate = PETSC_FALSE; 543d2e16ddcSPeter Brune 544d8d34be6SBarry Smith ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 545d8d34be6SBarry Smith ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr); 546d8d34be6SBarry Smith 5470298fd71SBarry Smith ngmres->additive_linesearch = NULL; 548077c4231SPeter Brune ngmres->approxfunc = PETSC_FALSE; 54928ed4a04SPeter Brune ngmres->restart_it = 2; 55013a62661SPeter Brune ngmres->restart_periodic = 30; 551f109b39eSPeter Brune ngmres->gammaA = 2.0; 552f109b39eSPeter Brune ngmres->gammaC = 2.0; 553cac108bcSPeter Brune ngmres->deltaB = 0.9; 554cac108bcSPeter Brune ngmres->epsilonB = 0.1; 55523b3e82cSAsbjørn Nilsen Riseth ngmres->restart_fm_rise = PETSC_FALSE; 556e7058c64SPeter Brune 55713a62661SPeter Brune ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE; 55813a62661SPeter Brune ngmres->select_type = SNES_NGMRES_SELECT_DIFFERENCE; 55913a62661SPeter Brune 560bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetSelectType_C",SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr); 561bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartType_C",SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr); 56223b3e82cSAsbjørn Nilsen Riseth ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartFmRise_C",SNESNGMRESSetRestartFmRise_NGMRES);CHKERRQ(ierr); 56323b3e82cSAsbjørn Nilsen Riseth ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESGetRestartFmRise_C",SNESNGMRESGetRestartFmRise_NGMRES);CHKERRQ(ierr); 564a312c225SMatthew G Knepley PetscFunctionReturn(0); 565a312c225SMatthew G Knepley } 566