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 */ 6319653cdaSPeter Brune ierr = PetscMalloc5(hsize,PetscScalar,&ngmres->h, 6419653cdaSPeter Brune msize,PetscScalar,&ngmres->beta, 6519653cdaSPeter Brune msize,PetscScalar,&ngmres->xi, 66f109b39eSPeter Brune msize,PetscReal, &ngmres->fnorms, 6719653cdaSPeter Brune hsize,PetscScalar,&ngmres->q);CHKERRQ(ierr); 6818aa0c0cSPeter Brune ierr = PetscMalloc(msize*sizeof(PetscReal),&ngmres->xnorms);CHKERRQ(ierr); 6919653cdaSPeter Brune ngmres->nrhs = 1; 7019653cdaSPeter Brune ngmres->lda = msize; 7119653cdaSPeter Brune ngmres->ldb = msize; 7219653cdaSPeter Brune ierr = PetscMalloc(msize*sizeof(PetscScalar),&ngmres->s);CHKERRQ(ierr); 7319653cdaSPeter Brune ierr = PetscMemzero(ngmres->h, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 7419653cdaSPeter Brune ierr = PetscMemzero(ngmres->q, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 7519653cdaSPeter Brune ierr = PetscMemzero(ngmres->xi, msize*sizeof(PetscScalar));CHKERRQ(ierr); 7619653cdaSPeter Brune ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr); 7719653cdaSPeter Brune ngmres->lwork = 12*msize; 7819653cdaSPeter Brune #if PETSC_USE_COMPLEX 7922d28d08SBarry Smith ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork);CHKERRQ(ierr); 8019653cdaSPeter Brune #endif 8122d28d08SBarry Smith ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work);CHKERRQ(ierr); 8278440776SJed Brown } 83e7058c64SPeter Brune 84e7058c64SPeter Brune /* linesearch setup */ 85e7058c64SPeter Brune ierr = SNESGetOptionsPrefix(snes,&optionsprefix);CHKERRQ(ierr); 86e7058c64SPeter Brune 8713a62661SPeter Brune if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) { 88ce94432eSBarry Smith ierr = SNESLineSearchCreate(PetscObjectComm((PetscObject)snes),&ngmres->additive_linesearch);CHKERRQ(ierr); 89f1c6b773SPeter Brune ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch,snes);CHKERRQ(ierr); 901a4f838cSPeter Brune ierr = SNESLineSearchSetType(ngmres->additive_linesearch,SNESLINESEARCHL2);CHKERRQ(ierr); 91f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,"additive_");CHKERRQ(ierr); 92f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,optionsprefix);CHKERRQ(ierr); 93f1c6b773SPeter Brune ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr); 94e7058c64SPeter Brune } 95e7058c64SPeter Brune 9678440776SJed Brown ngmres->setup_called = PETSC_TRUE; 97a312c225SMatthew G Knepley PetscFunctionReturn(0); 98a312c225SMatthew G Knepley } 99a312c225SMatthew G Knepley 100a312c225SMatthew G Knepley #undef __FUNCT__ 101a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES" 102a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes) 103a312c225SMatthew G Knepley { 104a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 105a312c225SMatthew G Knepley PetscErrorCode ierr; 106dfbf837cSBarry Smith PetscBool debug; 107f1c6b773SPeter Brune SNESLineSearch linesearch; 1080adebc6cSBarry Smith 109a312c225SMatthew G Knepley PetscFunctionBegin; 110a312c225SMatthew G Knepley ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr); 11113a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes, 1120298fd71SBarry Smith (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,NULL);CHKERRQ(ierr); 11313a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes, 1140298fd71SBarry Smith (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,NULL);CHKERRQ(ierr); 1150298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_candidate", "Use candidate storage", "SNES",ngmres->candidate,&ngmres->candidate,NULL);CHKERRQ(ierr); 116077c4231SPeter Brune ierr = PetscOptionsBool("-snes_ngmres_approxfunc","Linearly approximate the function", "SNES",ngmres->approxfunc,&ngmres->approxfunc,NULL);CHKERRQ(ierr); 1170298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_m", "Number of directions", "SNES",ngmres->msize,&ngmres->msize,NULL);CHKERRQ(ierr); 1180298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_restart", "Iterations before forced restart", "SNES",ngmres->restart_periodic,&ngmres->restart_periodic,NULL);CHKERRQ(ierr); 1190298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_restart_it", "Tolerance iterations before restart","SNES",ngmres->restart_it,&ngmres->restart_it,NULL);CHKERRQ(ierr); 1200298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_monitor", "Monitor actions of NGMRES", "SNES",ngmres->monitor ? PETSC_TRUE : PETSC_FALSE,&debug,NULL);CHKERRQ(ierr); 121dfbf837cSBarry Smith if (debug) { 122ce94432eSBarry Smith ngmres->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 123dfbf837cSBarry Smith } 1240298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_gammaA", "Residual selection constant", "SNES",ngmres->gammaA,&ngmres->gammaA,NULL);CHKERRQ(ierr); 1250298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_gammaC", "Residual restart constant", "SNES",ngmres->gammaC,&ngmres->gammaC,NULL);CHKERRQ(ierr); 1260298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES",ngmres->epsilonB,&ngmres->epsilonB,NULL);CHKERRQ(ierr); 1270298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_deltaB", "Difference residual selection constant", "SNES",ngmres->deltaB,&ngmres->deltaB,NULL);CHKERRQ(ierr); 1280298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions", "SNES",ngmres->singlereduction,&ngmres->singlereduction,NULL);CHKERRQ(ierr); 129a312c225SMatthew G Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1306a7cf640SPeter Brune if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA; 1319e764e56SPeter Brune 1329e764e56SPeter Brune /* set the default type of the line search if the user hasn't already. */ 1339e764e56SPeter Brune if (!snes->linesearch) { 1347601faf0SJed Brown ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 1351a4f838cSPeter Brune ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr); 1369e764e56SPeter Brune } 137a312c225SMatthew G Knepley PetscFunctionReturn(0); 138a312c225SMatthew G Knepley } 139a312c225SMatthew G Knepley 140a312c225SMatthew G Knepley #undef __FUNCT__ 141a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES" 142a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes,PetscViewer viewer) 143a312c225SMatthew G Knepley { 144a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 145a312c225SMatthew G Knepley PetscBool iascii; 146a312c225SMatthew G Knepley PetscErrorCode ierr; 147a312c225SMatthew G Knepley 148a312c225SMatthew G Knepley PetscFunctionBegin; 149251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject) viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 150a312c225SMatthew G Knepley if (iascii) { 151f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr); 152f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Residual selection: gammaA=%1.0e, gammaC=%1.0e\n",ngmres->gammaA,ngmres->gammaC);CHKERRQ(ierr); 153f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n",ngmres->epsilonB,ngmres->deltaB);CHKERRQ(ierr); 154a312c225SMatthew G Knepley } 155a312c225SMatthew G Knepley PetscFunctionReturn(0); 156a312c225SMatthew G Knepley } 157a312c225SMatthew G Knepley 158a312c225SMatthew G Knepley #undef __FUNCT__ 159a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES" 160a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes) 161a312c225SMatthew G Knepley { 16238774f0aSPeter Brune 163087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 16498b3e84cSPeter Brune /* present solution, residual, and preconditioned residual */ 1659f425c49SPeter Brune Vec X,F,B,D,Y; 166f109b39eSPeter Brune 167f109b39eSPeter Brune /* candidate linear combination answers */ 168ddd40ce5SPeter Brune Vec XA,FA,XM,FM; 16919653cdaSPeter Brune 17098b3e84cSPeter Brune /* coefficients and RHS to the minimization problem */ 17118aa0c0cSPeter Brune PetscReal fnorm,fMnorm,fAnorm; 172b3c6a99cSPeter Brune PetscReal xnorm,xMnorm,xAnorm; 173b3c6a99cSPeter Brune PetscReal ynorm,yMnorm,yAnorm; 17438774f0aSPeter Brune PetscInt k,k_restart,l,ivec,restart_count = 0; 17519653cdaSPeter Brune 17698b3e84cSPeter Brune /* solution selection data */ 17738774f0aSPeter Brune PetscBool selectRestart; 17838774f0aSPeter Brune PetscReal dnorm,dminnorm = 0.0; 179b3c6a99cSPeter Brune PetscReal fminnorm; 18019653cdaSPeter Brune 1811e633543SBarry Smith SNESConvergedReason reason; 18238774f0aSPeter Brune PetscBool lssucceed; 183a312c225SMatthew G Knepley PetscErrorCode ierr; 184a312c225SMatthew G Knepley 185a312c225SMatthew G Knepley PetscFunctionBegin; 18698b3e84cSPeter Brune /* variable initialization */ 187a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 188f109b39eSPeter Brune X = snes->vec_sol; 189f109b39eSPeter Brune F = snes->vec_func; 190f109b39eSPeter Brune B = snes->vec_rhs; 191f109b39eSPeter Brune XA = snes->vec_sol_update; 192f109b39eSPeter Brune FA = snes->work[0]; 193f109b39eSPeter Brune D = snes->work[1]; 194f109b39eSPeter Brune 195f109b39eSPeter Brune /* work for the line search */ 196f109b39eSPeter Brune Y = snes->work[2]; 1979f425c49SPeter Brune XM = snes->work[3]; 1989f425c49SPeter Brune FM = snes->work[4]; 199a312c225SMatthew G Knepley 200ce8c27fbSBarry Smith ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 201a312c225SMatthew G Knepley snes->iter = 0; 202a312c225SMatthew G Knepley snes->norm = 0.; 203ce8c27fbSBarry Smith ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 20419653cdaSPeter Brune 20598b3e84cSPeter Brune /* initialization */ 20619653cdaSPeter Brune 2073a2ae377SPeter Brune if (snes->pc && snes->pcside == PC_LEFT) { 2083a2ae377SPeter Brune ierr = SNESApplyPC(snes,X,NULL,NULL,F);CHKERRQ(ierr); 2093a2ae377SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 2103a2ae377SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2113a2ae377SPeter Brune snes->reason = SNES_DIVERGED_INNER; 2123a2ae377SPeter Brune PetscFunctionReturn(0); 2133a2ae377SPeter Brune } 2143a2ae377SPeter Brune ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 2153a2ae377SPeter Brune } else { 216e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 217f109b39eSPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 218a312c225SMatthew G Knepley if (snes->domainerror) { 219a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 220a312c225SMatthew G Knepley PetscFunctionReturn(0); 221a312c225SMatthew G Knepley } 2221aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 223*c1c75074SPeter Brune 224f109b39eSPeter Brune ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 225189a9710SBarry Smith if (PetscIsInfOrNanReal(fnorm)) { 226189a9710SBarry Smith snes->reason = SNES_DIVERGED_FNORM_NAN; 227189a9710SBarry Smith PetscFunctionReturn(0); 228189a9710SBarry Smith } 2293a2ae377SPeter Brune } 230e4ed7901SPeter Brune fminnorm = fnorm; 23119653cdaSPeter Brune 232ce8c27fbSBarry Smith ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 233f109b39eSPeter Brune snes->norm = fnorm; 234ce8c27fbSBarry Smith ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 235a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); 236f109b39eSPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 237f109b39eSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 238a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 239b3c6a99cSPeter Brune SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fnorm,X); 240a312c225SMatthew G Knepley 24119653cdaSPeter Brune k_restart = 1; 24219653cdaSPeter Brune l = 1; 243b3c6a99cSPeter Brune ivec = 0; 24409c08436SPeter Brune for (k=1; k < snes->max_its+1; k++) { 24598b3e84cSPeter Brune /* Computation of x^M */ 246c40d0f55SPeter Brune if (snes->pc && snes->pcside == PC_RIGHT) { 2479f425c49SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 248e4ed7901SPeter Brune ierr = SNESSetInitialFunction(snes->pc,F);CHKERRQ(ierr); 24963e7833aSPeter Brune 25063e7833aSPeter Brune ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); 2519f425c49SPeter Brune ierr = SNESSolve(snes->pc,B,XM);CHKERRQ(ierr); 25263e7833aSPeter Brune ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); 25363e7833aSPeter Brune 2548cc86e31SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 2558cc86e31SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2568cc86e31SPeter Brune snes->reason = SNES_DIVERGED_INNER; 2578cc86e31SPeter Brune PetscFunctionReturn(0); 2588cc86e31SPeter Brune } 259ddd40ce5SPeter Brune ierr = SNESGetPCFunction(snes,FM,&fMnorm);CHKERRQ(ierr); 2608cc86e31SPeter Brune } else { 261f109b39eSPeter Brune /* no preconditioner -- just take gradient descent with line search */ 262f109b39eSPeter Brune ierr = VecCopy(F,Y);CHKERRQ(ierr); 263e7058c64SPeter Brune ierr = VecCopy(F,FM);CHKERRQ(ierr); 264e7058c64SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 2651aa26658SKarl Rupp 266e7058c64SPeter Brune fMnorm = fnorm; 2671aa26658SKarl Rupp 268f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr); 269f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(snes->linesearch,&lssucceed);CHKERRQ(ierr); 270f109b39eSPeter Brune if (!lssucceed) { 271f109b39eSPeter Brune if (++snes->numFailures >= snes->maxFailures) { 272f109b39eSPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 273f109b39eSPeter Brune PetscFunctionReturn(0); 274f109b39eSPeter Brune } 275f109b39eSPeter Brune } 2766634f59bSPeter Brune } 277b3c6a99cSPeter Brune ierr = SNESNGMRESFormCombinedSolution_Private(snes,ivec,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr); 27898b3e84cSPeter Brune /* r = F(x) */ 2799f425c49SPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of F^M */ 28019653cdaSPeter Brune 2819f425c49SPeter Brune /* differences for selection and restart */ 28213a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) { 283b3c6a99cSPeter Brune ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr); 28413a62661SPeter Brune } else { 285b3c6a99cSPeter Brune ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,NULL,NULL,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr); 28613a62661SPeter Brune } 287189a9710SBarry Smith if (PetscIsInfOrNanReal(fAnorm)) { 288189a9710SBarry Smith snes->reason = SNES_DIVERGED_FNORM_NAN; 289189a9710SBarry Smith PetscFunctionReturn(0); 290189a9710SBarry Smith } 2911aa26658SKarl Rupp 2929f425c49SPeter Brune /* combination (additive) or selection (multiplicative) of the N-GMRES solution */ 293b3c6a99cSPeter 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); 29419653cdaSPeter Brune selectRestart = PETSC_FALSE; 29513a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) { 29621687c63SPeter Brune ierr = SNESNGMRESSelectRestart_Private(snes,l,fAnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr); 29728ed4a04SPeter Brune /* if the restart conditions persist for more than restart_it iterations, restart. */ 2981aa26658SKarl Rupp if (selectRestart) restart_count++; 2991aa26658SKarl Rupp else restart_count = 0; 30013a62661SPeter Brune } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) { 30113a62661SPeter Brune if (k_restart > ngmres->restart_periodic) { 30213a62661SPeter Brune if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr); 30313a62661SPeter Brune restart_count = ngmres->restart_it; 30413a62661SPeter Brune } 30513a62661SPeter Brune } 306b3c6a99cSPeter Brune ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */ 30728ed4a04SPeter Brune /* restart after restart conditions have persisted for a fixed number of iterations */ 30828ed4a04SPeter Brune if (restart_count >= ngmres->restart_it) { 309dfbf837cSBarry Smith if (ngmres->monitor) { 310dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor,"Restarted at iteration %d\n",k_restart);CHKERRQ(ierr); 311dfbf837cSBarry Smith } 31228ed4a04SPeter Brune restart_count = 0; 31319653cdaSPeter Brune k_restart = 1; 31419653cdaSPeter Brune l = 1; 315b3c6a99cSPeter Brune ivec = 0; 31698b3e84cSPeter Brune /* q_{00} = nu */ 317fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,FM,fMnorm,XM);CHKERRQ(ierr); 318d2e16ddcSPeter Brune } else { 31998b3e84cSPeter Brune /* select the current size of the subspace */ 3201e633543SBarry Smith if (l < ngmres->msize) l++; 32119653cdaSPeter Brune k_restart++; 32298b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 32338774f0aSPeter Brune if (ngmres->candidate) { 32438774f0aSPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; 325fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fMnorm,XM);CHKERRQ(ierr); 326d2e16ddcSPeter Brune } else { 32738774f0aSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; 328fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,F,fnorm,X);CHKERRQ(ierr); 32919653cdaSPeter Brune } 330d2e16ddcSPeter Brune } 33119653cdaSPeter Brune 332ce8c27fbSBarry Smith ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 333087dfb9eSxuemin snes->iter = k; 334f109b39eSPeter Brune snes->norm = fnorm; 335ce8c27fbSBarry Smith ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 336a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr); 3378409ca45SMatthew G Knepley ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 338b3c6a99cSPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0,0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 339087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 340a312c225SMatthew G Knepley } 341a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 342a312c225SMatthew G Knepley PetscFunctionReturn(0); 343a312c225SMatthew G Knepley } 344a312c225SMatthew G Knepley 34513a62661SPeter Brune #undef __FUNCT__ 34613a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType" 34713a62661SPeter Brune /*@ 34813a62661SPeter Brune SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES. 34913a62661SPeter Brune 35013a62661SPeter Brune Logically Collective on SNES 35113a62661SPeter Brune 35213a62661SPeter Brune Input Parameters: 35313a62661SPeter Brune + snes - the iterative context 35413a62661SPeter Brune - rtype - restart type 35513a62661SPeter Brune 35613a62661SPeter Brune Options Database: 35713a62661SPeter Brune + -snes_ngmres_restart_type<difference,periodic,none> - set the restart type 3580c777b0cSPeter Brune - -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic 35913a62661SPeter Brune 36013a62661SPeter Brune Level: intermediate 36113a62661SPeter Brune 36213a62661SPeter Brune SNESNGMRESRestartTypes: 36313a62661SPeter Brune + SNES_NGMRES_RESTART_NONE - never restart 36413a62661SPeter Brune . SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria 36513a62661SPeter Brune - SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations 36613a62661SPeter Brune 36713a62661SPeter Brune Notes: 36813a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 36913a62661SPeter Brune 37013a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch 37113a62661SPeter Brune @*/ 3720adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes,SNESNGMRESRestartType rtype) 3730adebc6cSBarry Smith { 37413a62661SPeter Brune PetscErrorCode ierr; 3755fd66863SKarl Rupp 37613a62661SPeter Brune PetscFunctionBegin; 37713a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 37813a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr); 37913a62661SPeter Brune PetscFunctionReturn(0); 38013a62661SPeter Brune } 38113a62661SPeter Brune 38213a62661SPeter Brune #undef __FUNCT__ 38313a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType" 38413a62661SPeter Brune /*@ 38513a62661SPeter Brune SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES. This determines how the candidate solution and 38613a62661SPeter Brune combined solution are used to create the next iterate. 38713a62661SPeter Brune 38813a62661SPeter Brune Logically Collective on SNES 38913a62661SPeter Brune 39013a62661SPeter Brune Input Parameters: 39113a62661SPeter Brune + snes - the iterative context 39213a62661SPeter Brune - stype - selection type 39313a62661SPeter Brune 39413a62661SPeter Brune Options Database: 39513a62661SPeter Brune . -snes_ngmres_select_type<difference,none,linesearch> 39613a62661SPeter Brune 39713a62661SPeter Brune Level: intermediate 39813a62661SPeter Brune 39913a62661SPeter Brune SNESNGMRESSelectTypes: 40013a62661SPeter Brune + SNES_NGMRES_SELECT_NONE - choose the combined solution all the time 40113a62661SPeter Brune . SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria 40213a62661SPeter Brune - SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination 40313a62661SPeter Brune 40413a62661SPeter Brune Notes: 40513a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 40613a62661SPeter Brune 40713a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch 40813a62661SPeter Brune @*/ 4090adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes,SNESNGMRESSelectType stype) 4100adebc6cSBarry Smith { 41113a62661SPeter Brune PetscErrorCode ierr; 4125fd66863SKarl Rupp 41313a62661SPeter Brune PetscFunctionBegin; 41413a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 41513a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr); 41613a62661SPeter Brune PetscFunctionReturn(0); 41713a62661SPeter Brune } 41813a62661SPeter Brune 41913a62661SPeter Brune #undef __FUNCT__ 42013a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES" 4210adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes,SNESNGMRESSelectType stype) 4220adebc6cSBarry Smith { 42313a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 4245fd66863SKarl Rupp 42513a62661SPeter Brune PetscFunctionBegin; 42613a62661SPeter Brune ngmres->select_type = stype; 42713a62661SPeter Brune PetscFunctionReturn(0); 42813a62661SPeter Brune } 42913a62661SPeter Brune 43013a62661SPeter Brune #undef __FUNCT__ 43113a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES" 4320adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes,SNESNGMRESRestartType rtype) 4330adebc6cSBarry Smith { 43413a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 4355fd66863SKarl Rupp 43613a62661SPeter Brune PetscFunctionBegin; 43713a62661SPeter Brune ngmres->restart_type = rtype; 43813a62661SPeter Brune PetscFunctionReturn(0); 43913a62661SPeter Brune } 44013a62661SPeter Brune 441dfbf837cSBarry Smith /*MC 4421867fe5bSPeter Brune SNESNGMRES - The Nonlinear Generalized Minimum Residual method. 443a312c225SMatthew G Knepley 444dfbf837cSBarry Smith Level: beginner 445dfbf837cSBarry Smith 4461867fe5bSPeter Brune Options Database: 44713a62661SPeter Brune + -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution 44838774f0aSPeter Brune . -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions 44938774f0aSPeter Brune . -snes_ngmres_candidate - Use NGMRES variant which combines candidate solutions instead of actual solutions 45013a62661SPeter Brune . -snes_ngmres_m - Number of stored previous solutions and residuals 45113a62661SPeter Brune . -snes_ngmres_restart_it - Number of iterations the restart conditions hold before restart 45213a62661SPeter Brune . -snes_ngmres_gammaA - Residual tolerance for solution select between the candidate and combination 45313a62661SPeter Brune . -snes_ngmres_gammaC - Residual tolerance for restart 45413a62661SPeter Brune . -snes_ngmres_epsilonB - Difference tolerance between subsequent solutions triggering restart 45513a62661SPeter Brune . -snes_ngmres_deltaB - Difference tolerance between residuals triggering restart 45613a62661SPeter Brune . -snes_ngmres_monitor - Prints relevant information about the ngmres iteration 4575c3e6ab7SPeter Brune . -snes_linesearch_type <basic,l2,cp> - Line search type used for the default smoother 45813a62661SPeter Brune - -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type 4591867fe5bSPeter Brune 4601867fe5bSPeter Brune Notes: 4611867fe5bSPeter Brune 4621867fe5bSPeter Brune The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized 4631867fe5bSPeter Brune optimization problem at each iteration. 4641867fe5bSPeter Brune 4651867fe5bSPeter Brune References: 4661867fe5bSPeter Brune 467dfbf837cSBarry Smith "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 468dfbf837cSBarry Smith SIAM Journal on Scientific Computing, 21(5), 2000. 469dfbf837cSBarry Smith 470dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 471dfbf837cSBarry Smith M*/ 472a312c225SMatthew G Knepley 473a312c225SMatthew G Knepley #undef __FUNCT__ 474a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 4758cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NGMRES(SNES snes) 476a312c225SMatthew G Knepley { 477a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 478a312c225SMatthew G Knepley PetscErrorCode ierr; 479a312c225SMatthew G Knepley 480a312c225SMatthew G Knepley PetscFunctionBegin; 481a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 482a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 483a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 484a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 485a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 486a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 487a312c225SMatthew G Knepley 48842f4f86dSBarry Smith snes->usespc = PETSC_TRUE; 4892c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 49046159c86SPeter Brune snes->pcside = PC_RIGHT; 4912c155ee1SBarry Smith 492a312c225SMatthew G Knepley ierr = PetscNewLog(snes,SNES_NGMRES,&ngmres);CHKERRQ(ierr); 493a312c225SMatthew G Knepley snes->data = (void*) ngmres; 494d2e16ddcSPeter Brune ngmres->msize = 30; 49519653cdaSPeter Brune 49688976e71SPeter Brune if (!snes->tolerancesset) { 4970e444f03SPeter Brune snes->max_funcs = 30000; 4980e444f03SPeter Brune snes->max_its = 10000; 49988976e71SPeter Brune } 5000e444f03SPeter Brune 50138774f0aSPeter Brune ngmres->candidate = PETSC_FALSE; 502d2e16ddcSPeter Brune 5030298fd71SBarry Smith ngmres->additive_linesearch = NULL; 504077c4231SPeter Brune ngmres->approxfunc = PETSC_FALSE; 50528ed4a04SPeter Brune ngmres->restart_it = 2; 50613a62661SPeter Brune ngmres->restart_periodic = 30; 507f109b39eSPeter Brune ngmres->gammaA = 2.0; 508f109b39eSPeter Brune ngmres->gammaC = 2.0; 509cac108bcSPeter Brune ngmres->deltaB = 0.9; 510cac108bcSPeter Brune ngmres->epsilonB = 0.1; 511e7058c64SPeter Brune 51213a62661SPeter Brune ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE; 51313a62661SPeter Brune ngmres->select_type = SNES_NGMRES_SELECT_DIFFERENCE; 51413a62661SPeter Brune 515bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetSelectType_C",SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr); 516bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartType_C",SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr); 517a312c225SMatthew G Knepley PetscFunctionReturn(0); 518a312c225SMatthew G Knepley } 51999e0435eSBarry Smith 520