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; 5146159c86SPeter Brune if (snes->pc && snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) { 5246159c86SPeter Brune SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"SNESNGMRES does not support left preconditioning with unpreconditioned function"); 5346159c86SPeter Brune } 546c67d002SPeter Brune if (snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_DEFAULT) snes->functype = SNES_FUNCTION_PRECONDITIONED; 55fa0ddf94SBarry Smith ierr = SNESSetWorkVecs(snes,5);CHKERRQ(ierr); 5678440776SJed Brown if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);} 5778440776SJed Brown if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);} 5878440776SJed Brown if (!ngmres->setup_called) { 59087dfb9eSxuemin msize = ngmres->msize; /* restart size */ 6019653cdaSPeter Brune hsize = msize * msize; 61087dfb9eSxuemin 6298b3e84cSPeter Brune /* explicit least squares minimization solve */ 63dcca6d9dSJed Brown ierr = PetscMalloc5(hsize,&ngmres->h, msize,&ngmres->beta, msize,&ngmres->xi, msize,&ngmres->fnorms, hsize,&ngmres->q);CHKERRQ(ierr); 64785e854fSJed Brown ierr = PetscMalloc1(msize,&ngmres->xnorms);CHKERRQ(ierr); 6519653cdaSPeter Brune ngmres->nrhs = 1; 6619653cdaSPeter Brune ngmres->lda = msize; 6719653cdaSPeter Brune ngmres->ldb = msize; 68785e854fSJed Brown ierr = PetscMalloc1(msize,&ngmres->s);CHKERRQ(ierr); 6919653cdaSPeter Brune ierr = PetscMemzero(ngmres->h, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 7019653cdaSPeter Brune ierr = PetscMemzero(ngmres->q, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 7119653cdaSPeter Brune ierr = PetscMemzero(ngmres->xi, msize*sizeof(PetscScalar));CHKERRQ(ierr); 7219653cdaSPeter Brune ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr); 7319653cdaSPeter Brune ngmres->lwork = 12*msize; 7419653cdaSPeter Brune #if PETSC_USE_COMPLEX 75854ce69bSBarry Smith ierr = PetscMalloc1(ngmres->lwork,&ngmres->rwork);CHKERRQ(ierr); 7619653cdaSPeter Brune #endif 77854ce69bSBarry Smith ierr = PetscMalloc1(ngmres->lwork,&ngmres->work);CHKERRQ(ierr); 7878440776SJed Brown } 79e7058c64SPeter Brune 80e7058c64SPeter Brune /* linesearch setup */ 81e7058c64SPeter Brune ierr = SNESGetOptionsPrefix(snes,&optionsprefix);CHKERRQ(ierr); 82e7058c64SPeter Brune 8313a62661SPeter Brune if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) { 84ce94432eSBarry Smith ierr = SNESLineSearchCreate(PetscObjectComm((PetscObject)snes),&ngmres->additive_linesearch);CHKERRQ(ierr); 85f1c6b773SPeter Brune ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch,snes);CHKERRQ(ierr); 861a4f838cSPeter Brune ierr = SNESLineSearchSetType(ngmres->additive_linesearch,SNESLINESEARCHL2);CHKERRQ(ierr); 87f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,"additive_");CHKERRQ(ierr); 88f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,optionsprefix);CHKERRQ(ierr); 89f1c6b773SPeter Brune ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr); 90e7058c64SPeter Brune } 91e7058c64SPeter Brune 9278440776SJed Brown ngmres->setup_called = PETSC_TRUE; 93a312c225SMatthew G Knepley PetscFunctionReturn(0); 94a312c225SMatthew G Knepley } 95a312c225SMatthew G Knepley 96a312c225SMatthew G Knepley #undef __FUNCT__ 97a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES" 988c34d3f5SBarry Smith PetscErrorCode SNESSetFromOptions_NGMRES(PetscOptions *PetscOptionsObject,SNES snes) 99a312c225SMatthew G Knepley { 100a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 101a312c225SMatthew G Knepley PetscErrorCode ierr; 10294ae4db5SBarry Smith PetscBool debug = PETSC_FALSE; 103f1c6b773SPeter Brune SNESLineSearch linesearch; 1040adebc6cSBarry Smith 105a312c225SMatthew G Knepley PetscFunctionBegin; 106e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"SNES NGMRES options");CHKERRQ(ierr); 10713a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes, 1080298fd71SBarry Smith (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,NULL);CHKERRQ(ierr); 10913a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes, 1100298fd71SBarry Smith (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,NULL);CHKERRQ(ierr); 1110298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_candidate", "Use candidate storage", "SNES",ngmres->candidate,&ngmres->candidate,NULL);CHKERRQ(ierr); 112077c4231SPeter Brune ierr = PetscOptionsBool("-snes_ngmres_approxfunc","Linearly approximate the function", "SNES",ngmres->approxfunc,&ngmres->approxfunc,NULL);CHKERRQ(ierr); 1130298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_m", "Number of directions", "SNES",ngmres->msize,&ngmres->msize,NULL);CHKERRQ(ierr); 1140298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_restart", "Iterations before forced restart", "SNES",ngmres->restart_periodic,&ngmres->restart_periodic,NULL);CHKERRQ(ierr); 1150298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_restart_it", "Tolerance iterations before restart","SNES",ngmres->restart_it,&ngmres->restart_it,NULL);CHKERRQ(ierr); 1160298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_monitor", "Monitor actions of NGMRES", "SNES",ngmres->monitor ? PETSC_TRUE : PETSC_FALSE,&debug,NULL);CHKERRQ(ierr); 117dfbf837cSBarry Smith if (debug) { 118ce94432eSBarry Smith ngmres->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 119dfbf837cSBarry Smith } 1200298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_gammaA", "Residual selection constant", "SNES",ngmres->gammaA,&ngmres->gammaA,NULL);CHKERRQ(ierr); 1210298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_gammaC", "Residual restart constant", "SNES",ngmres->gammaC,&ngmres->gammaC,NULL);CHKERRQ(ierr); 1220298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES",ngmres->epsilonB,&ngmres->epsilonB,NULL);CHKERRQ(ierr); 1230298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_deltaB", "Difference residual selection constant", "SNES",ngmres->deltaB,&ngmres->deltaB,NULL);CHKERRQ(ierr); 1240298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions", "SNES",ngmres->singlereduction,&ngmres->singlereduction,NULL);CHKERRQ(ierr); 125a312c225SMatthew G Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1266a7cf640SPeter Brune if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA; 1279e764e56SPeter Brune 1289e764e56SPeter Brune /* set the default type of the line search if the user hasn't already. */ 1299e764e56SPeter Brune if (!snes->linesearch) { 1307601faf0SJed Brown ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 1311a4f838cSPeter Brune ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr); 1329e764e56SPeter Brune } 133a312c225SMatthew G Knepley PetscFunctionReturn(0); 134a312c225SMatthew G Knepley } 135a312c225SMatthew G Knepley 136a312c225SMatthew G Knepley #undef __FUNCT__ 137a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES" 138a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes,PetscViewer viewer) 139a312c225SMatthew G Knepley { 140a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 141a312c225SMatthew G Knepley PetscBool iascii; 142a312c225SMatthew G Knepley PetscErrorCode ierr; 143a312c225SMatthew G Knepley 144a312c225SMatthew G Knepley PetscFunctionBegin; 145251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject) viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 146a312c225SMatthew G Knepley if (iascii) { 147f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr); 148f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Residual selection: gammaA=%1.0e, gammaC=%1.0e\n",ngmres->gammaA,ngmres->gammaC);CHKERRQ(ierr); 149f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n",ngmres->epsilonB,ngmres->deltaB);CHKERRQ(ierr); 150a312c225SMatthew G Knepley } 151a312c225SMatthew G Knepley PetscFunctionReturn(0); 152a312c225SMatthew G Knepley } 153a312c225SMatthew G Knepley 154a312c225SMatthew G Knepley #undef __FUNCT__ 155a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES" 156a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes) 157a312c225SMatthew G Knepley { 158087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 15998b3e84cSPeter Brune /* present solution, residual, and preconditioned residual */ 1609f425c49SPeter Brune Vec X,F,B,D,Y; 161f109b39eSPeter Brune 162f109b39eSPeter Brune /* candidate linear combination answers */ 163ddd40ce5SPeter Brune Vec XA,FA,XM,FM; 16419653cdaSPeter Brune 16598b3e84cSPeter Brune /* coefficients and RHS to the minimization problem */ 16618aa0c0cSPeter Brune PetscReal fnorm,fMnorm,fAnorm; 167b3c6a99cSPeter Brune PetscReal xnorm,xMnorm,xAnorm; 168b3c6a99cSPeter Brune PetscReal ynorm,yMnorm,yAnorm; 16938774f0aSPeter Brune PetscInt k,k_restart,l,ivec,restart_count = 0; 17019653cdaSPeter Brune 17198b3e84cSPeter Brune /* solution selection data */ 17238774f0aSPeter Brune PetscBool selectRestart; 17338774f0aSPeter Brune PetscReal dnorm,dminnorm = 0.0; 174b3c6a99cSPeter Brune PetscReal fminnorm; 17519653cdaSPeter Brune 1761e633543SBarry Smith SNESConvergedReason reason; 177*422a814eSBarry Smith SNESLineSearchReason lssucceed; 178a312c225SMatthew G Knepley PetscErrorCode ierr; 179a312c225SMatthew G Knepley 180a312c225SMatthew G Knepley PetscFunctionBegin; 181c579b300SPatrick Farrell 182c579b300SPatrick Farrell if (snes->xl || snes->xu || snes->ops->computevariablebounds) { 183c579b300SPatrick Farrell SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); 184c579b300SPatrick Farrell } 185c579b300SPatrick Farrell 186fffbeea8SBarry Smith ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr); 18798b3e84cSPeter Brune /* variable initialization */ 188a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 189f109b39eSPeter Brune X = snes->vec_sol; 190f109b39eSPeter Brune F = snes->vec_func; 191f109b39eSPeter Brune B = snes->vec_rhs; 192f109b39eSPeter Brune XA = snes->vec_sol_update; 193f109b39eSPeter Brune FA = snes->work[0]; 194f109b39eSPeter Brune D = snes->work[1]; 195f109b39eSPeter Brune 196f109b39eSPeter Brune /* work for the line search */ 197f109b39eSPeter Brune Y = snes->work[2]; 1989f425c49SPeter Brune XM = snes->work[3]; 1999f425c49SPeter Brune FM = snes->work[4]; 200a312c225SMatthew G Knepley 201e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 202a312c225SMatthew G Knepley snes->iter = 0; 203a312c225SMatthew G Knepley snes->norm = 0.; 204e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 20519653cdaSPeter Brune 20698b3e84cSPeter Brune /* initialization */ 20719653cdaSPeter Brune 2083a2ae377SPeter Brune if (snes->pc && snes->pcside == PC_LEFT) { 209be95d8f1SBarry Smith ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr); 2103a2ae377SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 2113a2ae377SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2123a2ae377SPeter Brune snes->reason = SNES_DIVERGED_INNER; 2133a2ae377SPeter Brune PetscFunctionReturn(0); 2143a2ae377SPeter Brune } 2153a2ae377SPeter Brune ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 2163a2ae377SPeter Brune } else { 217e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 218f109b39eSPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 2191aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 220c1c75074SPeter Brune 221f109b39eSPeter Brune ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 222*422a814eSBarry Smith SNESCheckFunctionNorm(snes,fnorm); 2233a2ae377SPeter Brune } 224e4ed7901SPeter Brune fminnorm = fnorm; 22519653cdaSPeter Brune 226e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 227f109b39eSPeter Brune snes->norm = fnorm; 228e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 229a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); 230f109b39eSPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 231f109b39eSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 232a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 233b3c6a99cSPeter Brune SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fnorm,X); 234a312c225SMatthew G Knepley 23519653cdaSPeter Brune k_restart = 1; 23619653cdaSPeter Brune l = 1; 237b3c6a99cSPeter Brune ivec = 0; 23809c08436SPeter Brune for (k=1; k < snes->max_its+1; k++) { 23998b3e84cSPeter Brune /* Computation of x^M */ 240c40d0f55SPeter Brune if (snes->pc && snes->pcside == PC_RIGHT) { 2419f425c49SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 242e4ed7901SPeter Brune ierr = SNESSetInitialFunction(snes->pc,F);CHKERRQ(ierr); 24363e7833aSPeter Brune 24463e7833aSPeter Brune ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); 2459f425c49SPeter Brune ierr = SNESSolve(snes->pc,B,XM);CHKERRQ(ierr); 24663e7833aSPeter Brune ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); 24763e7833aSPeter Brune 2488cc86e31SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 2498cc86e31SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2508cc86e31SPeter Brune snes->reason = SNES_DIVERGED_INNER; 2518cc86e31SPeter Brune PetscFunctionReturn(0); 2528cc86e31SPeter Brune } 253be95d8f1SBarry Smith ierr = SNESGetNPCFunction(snes,FM,&fMnorm);CHKERRQ(ierr); 2548cc86e31SPeter Brune } else { 255f109b39eSPeter Brune /* no preconditioner -- just take gradient descent with line search */ 256f109b39eSPeter Brune ierr = VecCopy(F,Y);CHKERRQ(ierr); 257e7058c64SPeter Brune ierr = VecCopy(F,FM);CHKERRQ(ierr); 258e7058c64SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 2591aa26658SKarl Rupp 260e7058c64SPeter Brune fMnorm = fnorm; 2611aa26658SKarl Rupp 262f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr); 263*422a814eSBarry Smith ierr = SNESLineSearchGetReason(snes->linesearch,&lssucceed);CHKERRQ(ierr); 264*422a814eSBarry Smith if (lssucceed) { 265f109b39eSPeter Brune if (++snes->numFailures >= snes->maxFailures) { 266f109b39eSPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 267f109b39eSPeter Brune PetscFunctionReturn(0); 268f109b39eSPeter Brune } 269f109b39eSPeter Brune } 2706634f59bSPeter Brune } 271b3c6a99cSPeter Brune ierr = SNESNGMRESFormCombinedSolution_Private(snes,ivec,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr); 27298b3e84cSPeter Brune /* r = F(x) */ 2739f425c49SPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of F^M */ 27419653cdaSPeter Brune 2759f425c49SPeter Brune /* differences for selection and restart */ 27613a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) { 277b3c6a99cSPeter Brune ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr); 27813a62661SPeter Brune } else { 279b3c6a99cSPeter Brune ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,NULL,NULL,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr); 28013a62661SPeter Brune } 281*422a814eSBarry Smith SNESCheckFunctionNorm(snes,fnorm); 2821aa26658SKarl Rupp 2839f425c49SPeter Brune /* combination (additive) or selection (multiplicative) of the N-GMRES solution */ 284b3c6a99cSPeter 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); 28519653cdaSPeter Brune selectRestart = PETSC_FALSE; 28613a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) { 28721687c63SPeter Brune ierr = SNESNGMRESSelectRestart_Private(snes,l,fAnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr); 28828ed4a04SPeter Brune /* if the restart conditions persist for more than restart_it iterations, restart. */ 2891aa26658SKarl Rupp if (selectRestart) restart_count++; 2901aa26658SKarl Rupp else restart_count = 0; 29113a62661SPeter Brune } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) { 29213a62661SPeter Brune if (k_restart > ngmres->restart_periodic) { 29313a62661SPeter Brune if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr); 29413a62661SPeter Brune restart_count = ngmres->restart_it; 29513a62661SPeter Brune } 29613a62661SPeter Brune } 297b3c6a99cSPeter Brune ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */ 29828ed4a04SPeter Brune /* restart after restart conditions have persisted for a fixed number of iterations */ 29928ed4a04SPeter Brune if (restart_count >= ngmres->restart_it) { 300dfbf837cSBarry Smith if (ngmres->monitor) { 301dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor,"Restarted at iteration %d\n",k_restart);CHKERRQ(ierr); 302dfbf837cSBarry Smith } 30328ed4a04SPeter Brune restart_count = 0; 30419653cdaSPeter Brune k_restart = 1; 30519653cdaSPeter Brune l = 1; 306b3c6a99cSPeter Brune ivec = 0; 30798b3e84cSPeter Brune /* q_{00} = nu */ 308fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,FM,fMnorm,XM);CHKERRQ(ierr); 309d2e16ddcSPeter Brune } else { 31098b3e84cSPeter Brune /* select the current size of the subspace */ 3111e633543SBarry Smith if (l < ngmres->msize) l++; 31219653cdaSPeter Brune k_restart++; 31398b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 31438774f0aSPeter Brune if (ngmres->candidate) { 31538774f0aSPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; 316fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fMnorm,XM);CHKERRQ(ierr); 317d2e16ddcSPeter Brune } else { 31838774f0aSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; 319fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,F,fnorm,X);CHKERRQ(ierr); 32019653cdaSPeter Brune } 321d2e16ddcSPeter Brune } 32219653cdaSPeter Brune 323e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 324087dfb9eSxuemin snes->iter = k; 325f109b39eSPeter Brune snes->norm = fnorm; 326e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 327a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr); 3288409ca45SMatthew G Knepley ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 329b3c6a99cSPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0,0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 330087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 331a312c225SMatthew G Knepley } 332a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 333a312c225SMatthew G Knepley PetscFunctionReturn(0); 334a312c225SMatthew G Knepley } 335a312c225SMatthew G Knepley 33613a62661SPeter Brune #undef __FUNCT__ 33713a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType" 33813a62661SPeter Brune /*@ 33913a62661SPeter Brune SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES. 34013a62661SPeter Brune 34113a62661SPeter Brune Logically Collective on SNES 34213a62661SPeter Brune 34313a62661SPeter Brune Input Parameters: 34413a62661SPeter Brune + snes - the iterative context 34513a62661SPeter Brune - rtype - restart type 34613a62661SPeter Brune 34713a62661SPeter Brune Options Database: 34813a62661SPeter Brune + -snes_ngmres_restart_type<difference,periodic,none> - set the restart type 3490c777b0cSPeter Brune - -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic 35013a62661SPeter Brune 35113a62661SPeter Brune Level: intermediate 35213a62661SPeter Brune 35313a62661SPeter Brune SNESNGMRESRestartTypes: 35413a62661SPeter Brune + SNES_NGMRES_RESTART_NONE - never restart 35513a62661SPeter Brune . SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria 35613a62661SPeter Brune - SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations 35713a62661SPeter Brune 35813a62661SPeter Brune Notes: 35913a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 36013a62661SPeter Brune 36113a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch 36213a62661SPeter Brune @*/ 3630adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes,SNESNGMRESRestartType rtype) 3640adebc6cSBarry Smith { 36513a62661SPeter Brune PetscErrorCode ierr; 3665fd66863SKarl Rupp 36713a62661SPeter Brune PetscFunctionBegin; 36813a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 36913a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr); 37013a62661SPeter Brune PetscFunctionReturn(0); 37113a62661SPeter Brune } 37213a62661SPeter Brune 37313a62661SPeter Brune #undef __FUNCT__ 37413a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType" 37513a62661SPeter Brune /*@ 37613a62661SPeter Brune SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES. This determines how the candidate solution and 37713a62661SPeter Brune combined solution are used to create the next iterate. 37813a62661SPeter Brune 37913a62661SPeter Brune Logically Collective on SNES 38013a62661SPeter Brune 38113a62661SPeter Brune Input Parameters: 38213a62661SPeter Brune + snes - the iterative context 38313a62661SPeter Brune - stype - selection type 38413a62661SPeter Brune 38513a62661SPeter Brune Options Database: 38613a62661SPeter Brune . -snes_ngmres_select_type<difference,none,linesearch> 38713a62661SPeter Brune 38813a62661SPeter Brune Level: intermediate 38913a62661SPeter Brune 39013a62661SPeter Brune SNESNGMRESSelectTypes: 39113a62661SPeter Brune + SNES_NGMRES_SELECT_NONE - choose the combined solution all the time 39213a62661SPeter Brune . SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria 39313a62661SPeter Brune - SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination 39413a62661SPeter Brune 39513a62661SPeter Brune Notes: 39613a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 39713a62661SPeter Brune 39813a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch 39913a62661SPeter Brune @*/ 4000adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes,SNESNGMRESSelectType stype) 4010adebc6cSBarry Smith { 40213a62661SPeter Brune PetscErrorCode ierr; 4035fd66863SKarl Rupp 40413a62661SPeter Brune PetscFunctionBegin; 40513a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 40613a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr); 40713a62661SPeter Brune PetscFunctionReturn(0); 40813a62661SPeter Brune } 40913a62661SPeter Brune 41013a62661SPeter Brune #undef __FUNCT__ 41113a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES" 4120adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes,SNESNGMRESSelectType stype) 4130adebc6cSBarry Smith { 41413a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 4155fd66863SKarl Rupp 41613a62661SPeter Brune PetscFunctionBegin; 41713a62661SPeter Brune ngmres->select_type = stype; 41813a62661SPeter Brune PetscFunctionReturn(0); 41913a62661SPeter Brune } 42013a62661SPeter Brune 42113a62661SPeter Brune #undef __FUNCT__ 42213a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES" 4230adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes,SNESNGMRESRestartType rtype) 4240adebc6cSBarry Smith { 42513a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 4265fd66863SKarl Rupp 42713a62661SPeter Brune PetscFunctionBegin; 42813a62661SPeter Brune ngmres->restart_type = rtype; 42913a62661SPeter Brune PetscFunctionReturn(0); 43013a62661SPeter Brune } 43113a62661SPeter Brune 432dfbf837cSBarry Smith /*MC 4331867fe5bSPeter Brune SNESNGMRES - The Nonlinear Generalized Minimum Residual method. 434a312c225SMatthew G Knepley 435dfbf837cSBarry Smith Level: beginner 436dfbf837cSBarry Smith 4371867fe5bSPeter Brune Options Database: 43813a62661SPeter Brune + -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution 43938774f0aSPeter Brune . -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions 44038774f0aSPeter Brune . -snes_ngmres_candidate - Use NGMRES variant which combines candidate solutions instead of actual solutions 44113a62661SPeter Brune . -snes_ngmres_m - Number of stored previous solutions and residuals 44213a62661SPeter Brune . -snes_ngmres_restart_it - Number of iterations the restart conditions hold before restart 44313a62661SPeter Brune . -snes_ngmres_gammaA - Residual tolerance for solution select between the candidate and combination 44413a62661SPeter Brune . -snes_ngmres_gammaC - Residual tolerance for restart 44513a62661SPeter Brune . -snes_ngmres_epsilonB - Difference tolerance between subsequent solutions triggering restart 44613a62661SPeter Brune . -snes_ngmres_deltaB - Difference tolerance between residuals triggering restart 44713a62661SPeter Brune . -snes_ngmres_monitor - Prints relevant information about the ngmres iteration 4485c3e6ab7SPeter Brune . -snes_linesearch_type <basic,l2,cp> - Line search type used for the default smoother 44913a62661SPeter Brune - -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type 4501867fe5bSPeter Brune 4511867fe5bSPeter Brune Notes: 4521867fe5bSPeter Brune 4531867fe5bSPeter Brune The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized 4541867fe5bSPeter Brune optimization problem at each iteration. 4551867fe5bSPeter Brune 4561867fe5bSPeter Brune References: 4571867fe5bSPeter Brune 458dfbf837cSBarry Smith "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 459dfbf837cSBarry Smith SIAM Journal on Scientific Computing, 21(5), 2000. 460dfbf837cSBarry Smith 461dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 462dfbf837cSBarry Smith M*/ 463a312c225SMatthew G Knepley 464a312c225SMatthew G Knepley #undef __FUNCT__ 465a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 4668cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NGMRES(SNES snes) 467a312c225SMatthew G Knepley { 468a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 469a312c225SMatthew G Knepley PetscErrorCode ierr; 470a312c225SMatthew G Knepley 471a312c225SMatthew G Knepley PetscFunctionBegin; 472a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 473a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 474a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 475a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 476a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 477a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 478a312c225SMatthew G Knepley 47942f4f86dSBarry Smith snes->usespc = PETSC_TRUE; 4802c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 48146159c86SPeter Brune snes->pcside = PC_RIGHT; 4822c155ee1SBarry Smith 483b00a9115SJed Brown ierr = PetscNewLog(snes,&ngmres);CHKERRQ(ierr); 484a312c225SMatthew G Knepley snes->data = (void*) ngmres; 485d2e16ddcSPeter Brune ngmres->msize = 30; 48619653cdaSPeter Brune 48788976e71SPeter Brune if (!snes->tolerancesset) { 4880e444f03SPeter Brune snes->max_funcs = 30000; 4890e444f03SPeter Brune snes->max_its = 10000; 49088976e71SPeter Brune } 4910e444f03SPeter Brune 49238774f0aSPeter Brune ngmres->candidate = PETSC_FALSE; 493d2e16ddcSPeter Brune 4940298fd71SBarry Smith ngmres->additive_linesearch = NULL; 495077c4231SPeter Brune ngmres->approxfunc = PETSC_FALSE; 49628ed4a04SPeter Brune ngmres->restart_it = 2; 49713a62661SPeter Brune ngmres->restart_periodic = 30; 498f109b39eSPeter Brune ngmres->gammaA = 2.0; 499f109b39eSPeter Brune ngmres->gammaC = 2.0; 500cac108bcSPeter Brune ngmres->deltaB = 0.9; 501cac108bcSPeter Brune ngmres->epsilonB = 0.1; 502e7058c64SPeter Brune 50313a62661SPeter Brune ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE; 50413a62661SPeter Brune ngmres->select_type = SNES_NGMRES_SELECT_DIFFERENCE; 50513a62661SPeter Brune 506bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetSelectType_C",SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr); 507bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartType_C",SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr); 508a312c225SMatthew G Knepley PetscFunctionReturn(0); 509a312c225SMatthew G Knepley } 51099e0435eSBarry Smith 511