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