113a62661SPeter Brune #include <../src/snes/impls/ngmres/snesngmres.h> /*I "petscsnes.h" I*/ 219653cdaSPeter Brune #include <petscblaslapack.h> 3a312c225SMatthew G Knepley 46a6fc655SJed Brown const char *const SNESNGMRESRestartTypes[] = {"NONE","PERIODIC","DIFFERENCE","SNESNGMRESRestartType","SNES_NGMRES_RESTART_",0}; 56a6fc655SJed Brown const char *const SNESNGMRESSelectTypes[] = {"NONE","DIFFERENCE","LINESEARCH","SNESNGMRESSelectType","SNES_NGMRES_SELECT_",0}; 613a62661SPeter Brune 7a312c225SMatthew G Knepley #undef __FUNCT__ 8a312c225SMatthew G Knepley #define __FUNCT__ "SNESReset_NGMRES" 9a312c225SMatthew G Knepley PetscErrorCode SNESReset_NGMRES(SNES snes) 10a312c225SMatthew G Knepley { 11a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 12a312c225SMatthew G Knepley PetscErrorCode ierr; 13a312c225SMatthew G Knepley 14a312c225SMatthew G Knepley PetscFunctionBegin; 15f109b39eSPeter Brune ierr = VecDestroyVecs(ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr); 16f109b39eSPeter Brune ierr = VecDestroyVecs(ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr); 17f1c6b773SPeter Brune ierr = SNESLineSearchDestroy(&ngmres->additive_linesearch);CHKERRQ(ierr); 18a312c225SMatthew G Knepley PetscFunctionReturn(0); 19a312c225SMatthew G Knepley } 20a312c225SMatthew G Knepley 21a312c225SMatthew G Knepley #undef __FUNCT__ 22a312c225SMatthew G Knepley #define __FUNCT__ "SNESDestroy_NGMRES" 23a312c225SMatthew G Knepley PetscErrorCode SNESDestroy_NGMRES(SNES snes) 24a312c225SMatthew G Knepley { 25a312c225SMatthew G Knepley PetscErrorCode ierr; 2678440776SJed Brown SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 27a312c225SMatthew G Knepley 28a312c225SMatthew G Knepley PetscFunctionBegin; 29a312c225SMatthew G Knepley ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr); 30f109b39eSPeter Brune ierr = PetscFree5(ngmres->h,ngmres->beta,ngmres->xi,ngmres->fnorms,ngmres->q);CHKERRQ(ierr); 3119653cdaSPeter Brune ierr = PetscFree(ngmres->s);CHKERRQ(ierr); 3218aa0c0cSPeter Brune ierr = PetscFree(ngmres->xnorms);CHKERRQ(ierr); 3319653cdaSPeter Brune #if PETSC_USE_COMPLEX 3422d28d08SBarry Smith ierr = PetscFree(ngmres->rwork);CHKERRQ(ierr); 3519653cdaSPeter Brune #endif 3622d28d08SBarry Smith ierr = PetscFree(ngmres->work);CHKERRQ(ierr); 3722d28d08SBarry Smith ierr = PetscFree(snes->data);CHKERRQ(ierr); 38a312c225SMatthew G Knepley PetscFunctionReturn(0); 39a312c225SMatthew G Knepley } 40a312c225SMatthew G Knepley 41a312c225SMatthew G Knepley #undef __FUNCT__ 42a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetUp_NGMRES" 43a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes) 44a312c225SMatthew G Knepley { 45a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 46e7058c64SPeter Brune const char *optionsprefix; 4719653cdaSPeter Brune PetscInt msize,hsize; 48a312c225SMatthew G Knepley PetscErrorCode ierr; 49a312c225SMatthew G Knepley 50a312c225SMatthew G Knepley PetscFunctionBegin; 5178440776SJed Brown ierr = SNESDefaultGetWork(snes,5);CHKERRQ(ierr); 5278440776SJed Brown if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);} 5378440776SJed Brown if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);} 5478440776SJed Brown if (!ngmres->setup_called) { 55087dfb9eSxuemin msize = ngmres->msize; /* restart size */ 5619653cdaSPeter Brune hsize = msize * msize; 57087dfb9eSxuemin 5898b3e84cSPeter Brune /* explicit least squares minimization solve */ 5919653cdaSPeter Brune ierr = PetscMalloc5(hsize,PetscScalar,&ngmres->h, 6019653cdaSPeter Brune msize,PetscScalar,&ngmres->beta, 6119653cdaSPeter Brune msize,PetscScalar,&ngmres->xi, 62f109b39eSPeter Brune msize,PetscReal, &ngmres->fnorms, 6319653cdaSPeter Brune hsize,PetscScalar,&ngmres->q);CHKERRQ(ierr); 6418aa0c0cSPeter Brune if (ngmres->singlereduction) { 6518aa0c0cSPeter Brune ierr = PetscMalloc(msize*sizeof(PetscReal),&ngmres->xnorms);CHKERRQ(ierr); 6618aa0c0cSPeter Brune } 6719653cdaSPeter Brune ngmres->nrhs = 1; 6819653cdaSPeter Brune ngmres->lda = msize; 6919653cdaSPeter Brune ngmres->ldb = msize; 7019653cdaSPeter Brune ierr = PetscMalloc(msize*sizeof(PetscScalar),&ngmres->s);CHKERRQ(ierr); 7119653cdaSPeter Brune ierr = PetscMemzero(ngmres->h, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 7219653cdaSPeter Brune ierr = PetscMemzero(ngmres->q, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 7319653cdaSPeter Brune ierr = PetscMemzero(ngmres->xi, msize*sizeof(PetscScalar));CHKERRQ(ierr); 7419653cdaSPeter Brune ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr); 7519653cdaSPeter Brune ngmres->lwork = 12*msize; 7619653cdaSPeter Brune #if PETSC_USE_COMPLEX 7722d28d08SBarry Smith ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork);CHKERRQ(ierr); 7819653cdaSPeter Brune #endif 7922d28d08SBarry Smith ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work);CHKERRQ(ierr); 8078440776SJed Brown } 81e7058c64SPeter Brune 82e7058c64SPeter Brune /* linesearch setup */ 83e7058c64SPeter Brune ierr = SNESGetOptionsPrefix(snes,&optionsprefix);CHKERRQ(ierr); 84e7058c64SPeter Brune 8513a62661SPeter Brune if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) { 86*ce94432eSBarry Smith ierr = SNESLineSearchCreate(PetscObjectComm((PetscObject)snes),&ngmres->additive_linesearch);CHKERRQ(ierr); 87f1c6b773SPeter Brune ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch,snes);CHKERRQ(ierr); 881a4f838cSPeter Brune ierr = SNESLineSearchSetType(ngmres->additive_linesearch,SNESLINESEARCHL2);CHKERRQ(ierr); 89f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,"additive_");CHKERRQ(ierr); 90f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,optionsprefix);CHKERRQ(ierr); 91f1c6b773SPeter Brune ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr); 92e7058c64SPeter Brune } 93e7058c64SPeter Brune 9478440776SJed Brown ngmres->setup_called = PETSC_TRUE; 95a312c225SMatthew G Knepley PetscFunctionReturn(0); 96a312c225SMatthew G Knepley } 97a312c225SMatthew G Knepley 98a312c225SMatthew G Knepley #undef __FUNCT__ 99a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES" 100a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes) 101a312c225SMatthew G Knepley { 102a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 103a312c225SMatthew G Knepley PetscErrorCode ierr; 104dfbf837cSBarry Smith PetscBool debug; 105f1c6b773SPeter Brune SNESLineSearch linesearch; 1060adebc6cSBarry Smith 107a312c225SMatthew G Knepley PetscFunctionBegin; 108a312c225SMatthew G Knepley ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr); 10913a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes, 1100298fd71SBarry Smith (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,NULL);CHKERRQ(ierr); 11113a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes, 1120298fd71SBarry Smith (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,NULL);CHKERRQ(ierr); 1130298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_candidate","Use candidate storage", "SNES",ngmres->candidate,&ngmres->candidate,NULL);CHKERRQ(ierr); 1140298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_m", "Number of directions", "SNES",ngmres->msize,&ngmres->msize,NULL);CHKERRQ(ierr); 1150298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_restart", "Iterations before forced restart", "SNES",ngmres->restart_periodic,&ngmres->restart_periodic,NULL);CHKERRQ(ierr); 1160298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_restart_it","Tolerance iterations before restart","SNES",ngmres->restart_it,&ngmres->restart_it,NULL);CHKERRQ(ierr); 1170298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_monitor", "Monitor actions of NGMRES", "SNES",ngmres->monitor ? PETSC_TRUE : PETSC_FALSE,&debug,NULL);CHKERRQ(ierr); 118dfbf837cSBarry Smith if (debug) { 119*ce94432eSBarry Smith ngmres->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 120dfbf837cSBarry Smith } 1210298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_gammaA", "Residual selection constant", "SNES",ngmres->gammaA,&ngmres->gammaA,NULL);CHKERRQ(ierr); 1220298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_gammaC", " Residual restart constant", "SNES",ngmres->gammaC,&ngmres->gammaC,NULL);CHKERRQ(ierr); 1230298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES",ngmres->epsilonB,&ngmres->epsilonB,NULL);CHKERRQ(ierr); 1240298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_deltaB", "Difference residual selection constant", "SNES",ngmres->deltaB,&ngmres->deltaB,NULL);CHKERRQ(ierr); 1250298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions", "SNES",ngmres->singlereduction,&ngmres->singlereduction,NULL);CHKERRQ(ierr); 126a312c225SMatthew G Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1276a7cf640SPeter Brune if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA; 1289e764e56SPeter Brune 1299e764e56SPeter Brune /* set the default type of the line search if the user hasn't already. */ 1309e764e56SPeter Brune if (!snes->linesearch) { 131f1c6b773SPeter Brune ierr = SNESGetSNESLineSearch(snes,&linesearch);CHKERRQ(ierr); 1321a4f838cSPeter Brune ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr); 1339e764e56SPeter Brune } 134a312c225SMatthew G Knepley PetscFunctionReturn(0); 135a312c225SMatthew G Knepley } 136a312c225SMatthew G Knepley 137a312c225SMatthew G Knepley #undef __FUNCT__ 138a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES" 139a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes,PetscViewer viewer) 140a312c225SMatthew G Knepley { 141a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 142a312c225SMatthew G Knepley PetscBool iascii; 143a312c225SMatthew G Knepley PetscErrorCode ierr; 144a312c225SMatthew G Knepley 145a312c225SMatthew G Knepley PetscFunctionBegin; 146251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject) viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 147a312c225SMatthew G Knepley if (iascii) { 148f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr); 149f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Residual selection: gammaA=%1.0e, gammaC=%1.0e\n",ngmres->gammaA,ngmres->gammaC);CHKERRQ(ierr); 150f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n",ngmres->epsilonB,ngmres->deltaB);CHKERRQ(ierr); 151a312c225SMatthew G Knepley } 152a312c225SMatthew G Knepley PetscFunctionReturn(0); 153a312c225SMatthew G Knepley } 154a312c225SMatthew G Knepley 155a312c225SMatthew G Knepley #undef __FUNCT__ 156a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES" 157a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes) 158a312c225SMatthew G Knepley { 15938774f0aSPeter Brune 160087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 16198b3e84cSPeter Brune /* present solution, residual, and preconditioned residual */ 1629f425c49SPeter Brune Vec X,F,B,D,Y; 163f109b39eSPeter Brune 164f109b39eSPeter Brune /* candidate linear combination answers */ 1654b32a720SPeter Brune Vec XA,FA,XM,FM,FPC; 16619653cdaSPeter Brune 16798b3e84cSPeter Brune /* coefficients and RHS to the minimization problem */ 16818aa0c0cSPeter Brune PetscReal fnorm,fMnorm,fAnorm; 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; 174d484d688SPeter Brune PetscReal fminnorm,xnorm,ynorm; 17519653cdaSPeter Brune 1761e633543SBarry Smith SNESConvergedReason reason; 17738774f0aSPeter Brune PetscBool lssucceed; 178a312c225SMatthew G Knepley PetscErrorCode ierr; 179a312c225SMatthew G Knepley 180a312c225SMatthew G Knepley PetscFunctionBegin; 18198b3e84cSPeter Brune /* variable initialization */ 182a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 183f109b39eSPeter Brune X = snes->vec_sol; 184f109b39eSPeter Brune F = snes->vec_func; 185f109b39eSPeter Brune B = snes->vec_rhs; 186f109b39eSPeter Brune XA = snes->vec_sol_update; 187f109b39eSPeter Brune FA = snes->work[0]; 188f109b39eSPeter Brune D = snes->work[1]; 189f109b39eSPeter Brune 190f109b39eSPeter Brune /* work for the line search */ 191f109b39eSPeter Brune Y = snes->work[2]; 1929f425c49SPeter Brune XM = snes->work[3]; 1939f425c49SPeter Brune FM = snes->work[4]; 194a312c225SMatthew G Knepley 195a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 196a312c225SMatthew G Knepley snes->iter = 0; 197a312c225SMatthew G Knepley snes->norm = 0.; 198a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 19919653cdaSPeter Brune 20098b3e84cSPeter Brune /* initialization */ 20119653cdaSPeter Brune 20298b3e84cSPeter Brune /* r = F(x) */ 203e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 204f109b39eSPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 205a312c225SMatthew G Knepley if (snes->domainerror) { 206a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 207a312c225SMatthew G Knepley PetscFunctionReturn(0); 208a312c225SMatthew G Knepley } 2091aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 21019653cdaSPeter Brune 211e4ed7901SPeter Brune if (!snes->norm_init_set) { 212f109b39eSPeter Brune ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 213*ce94432eSBarry Smith if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_FP,"Infinite or not-a-number generated in function evaluation"); 214e4ed7901SPeter Brune } else { 215e4ed7901SPeter Brune fnorm = snes->norm_init; 216e4ed7901SPeter Brune snes->norm_init_set = PETSC_FALSE; 217e4ed7901SPeter Brune } 218e4ed7901SPeter Brune fminnorm = fnorm; 21919653cdaSPeter Brune 22098b3e84cSPeter Brune /* q_{00} = nu */ 22138774f0aSPeter Brune SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fnorm,X); 222087dfb9eSxuemin 223a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 224f109b39eSPeter Brune snes->norm = fnorm; 225a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 226a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); 227f109b39eSPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 228f109b39eSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 229a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 230a312c225SMatthew G Knepley 23119653cdaSPeter Brune k_restart = 1; 23219653cdaSPeter Brune l = 1; 23309c08436SPeter Brune for (k=1; k < snes->max_its+1; k++) { 23498b3e84cSPeter Brune /* select which vector of the stored subspace will be updated */ 23598b3e84cSPeter Brune ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */ 23619653cdaSPeter Brune 23798b3e84cSPeter Brune /* Computation of x^M */ 238c40d0f55SPeter Brune if (snes->pc && snes->pcside == PC_RIGHT) { 2399f425c49SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 240e4ed7901SPeter Brune ierr = SNESSetInitialFunction(snes->pc,F);CHKERRQ(ierr); 241e4ed7901SPeter Brune ierr = SNESSetInitialFunctionNorm(snes->pc,fnorm);CHKERRQ(ierr); 24263e7833aSPeter Brune 24363e7833aSPeter Brune ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); 2449f425c49SPeter Brune ierr = SNESSolve(snes->pc,B,XM);CHKERRQ(ierr); 24563e7833aSPeter Brune ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); 24663e7833aSPeter Brune 2478cc86e31SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 2488cc86e31SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2498cc86e31SPeter Brune snes->reason = SNES_DIVERGED_INNER; 2508cc86e31SPeter Brune PetscFunctionReturn(0); 2518cc86e31SPeter Brune } 2520298fd71SBarry Smith ierr = SNESGetFunction(snes->pc,&FPC,NULL,NULL);CHKERRQ(ierr); 2534b32a720SPeter Brune ierr = VecCopy(FPC,FM);CHKERRQ(ierr); 2544b32a720SPeter Brune ierr = SNESGetFunctionNorm(snes->pc,&fMnorm);CHKERRQ(ierr); 2558cc86e31SPeter Brune } else { 256f109b39eSPeter Brune /* no preconditioner -- just take gradient descent with line search */ 257f109b39eSPeter Brune ierr = VecCopy(F,Y);CHKERRQ(ierr); 258e7058c64SPeter Brune ierr = VecCopy(F,FM);CHKERRQ(ierr); 259e7058c64SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 2601aa26658SKarl Rupp 261e7058c64SPeter Brune fMnorm = fnorm; 2621aa26658SKarl Rupp 263f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr); 264f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(snes->linesearch,&lssucceed);CHKERRQ(ierr); 265f109b39eSPeter Brune if (!lssucceed) { 266f109b39eSPeter Brune if (++snes->numFailures >= snes->maxFailures) { 267f109b39eSPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 268f109b39eSPeter Brune PetscFunctionReturn(0); 269f109b39eSPeter Brune } 270f109b39eSPeter Brune } 2716634f59bSPeter Brune } 272f6408107SPeter Brune ierr = SNESNGMRESFormCombinedSolution_Private(snes,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr); 27398b3e84cSPeter Brune /* r = F(x) */ 2749f425c49SPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of F^M */ 27519653cdaSPeter Brune 2769f425c49SPeter Brune /* differences for selection and restart */ 27713a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) { 278fa8c639aSPeter Brune ierr = SNESNGMRESCalculateDifferences_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,&fAnorm);CHKERRQ(ierr); 27913a62661SPeter Brune } else { 28013a62661SPeter Brune ierr = VecNorm(FA,NORM_2,&fAnorm);CHKERRQ(ierr); 28113a62661SPeter Brune } 282*ce94432eSBarry Smith if (PetscIsInfOrNanReal(fAnorm)) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_FP,"Infinite or not-a-number generated in function evaluation"); 2831aa26658SKarl Rupp 2849f425c49SPeter Brune /* combination (additive) or selection (multiplicative) of the N-GMRES solution */ 285fa8c639aSPeter Brune ierr = SNESNGMRESSelect_Private(snes,k_restart,XM,FM,fMnorm,XA,FA,fAnorm,dnorm,fminnorm,dminnorm,X,F,Y,&fnorm);CHKERRQ(ierr); 28619653cdaSPeter Brune selectRestart = PETSC_FALSE; 28713a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) { 28821687c63SPeter Brune ierr = SNESNGMRESSelectRestart_Private(snes,l,fAnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr); 28928ed4a04SPeter Brune /* if the restart conditions persist for more than restart_it iterations, restart. */ 2901aa26658SKarl Rupp if (selectRestart) restart_count++; 2911aa26658SKarl Rupp else restart_count = 0; 29213a62661SPeter Brune } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) { 29313a62661SPeter Brune if (k_restart > ngmres->restart_periodic) { 29413a62661SPeter Brune if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr); 29513a62661SPeter Brune restart_count = ngmres->restart_it; 29613a62661SPeter Brune } 29713a62661SPeter Brune } 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; 30698b3e84cSPeter Brune /* q_{00} = nu */ 30738774f0aSPeter Brune if (ngmres->candidate) { 308fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,FM,fMnorm,XM);CHKERRQ(ierr); 309d2e16ddcSPeter Brune } else { 310fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fMnorm,X);CHKERRQ(ierr); 311d2e16ddcSPeter Brune } 31219653cdaSPeter Brune } else { 31398b3e84cSPeter Brune /* select the current size of the subspace */ 3141e633543SBarry Smith if (l < ngmres->msize) l++; 31519653cdaSPeter Brune k_restart++; 31698b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 31738774f0aSPeter Brune if (ngmres->candidate) { 31838774f0aSPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; 319fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fMnorm,XM);CHKERRQ(ierr); 320d2e16ddcSPeter Brune } else { 32138774f0aSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; 322fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,F,fnorm,X);CHKERRQ(ierr); 32319653cdaSPeter Brune } 324d2e16ddcSPeter Brune } 32519653cdaSPeter Brune 3268409ca45SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 327087dfb9eSxuemin snes->iter = k; 328f109b39eSPeter Brune snes->norm = fnorm; 3298409ca45SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 330a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr); 3318409ca45SMatthew G Knepley ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 332d484d688SPeter Brune ierr = VecNormBegin(Y,NORM_2,&ynorm);CHKERRQ(ierr); 333d484d688SPeter Brune ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); 334d484d688SPeter Brune ierr = VecNormEnd(Y,NORM_2,&ynorm);CHKERRQ(ierr); 335d484d688SPeter Brune ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 336d484d688SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 337087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 338a312c225SMatthew G Knepley } 339a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 340a312c225SMatthew G Knepley PetscFunctionReturn(0); 341a312c225SMatthew G Knepley } 342a312c225SMatthew G Knepley 34313a62661SPeter Brune #undef __FUNCT__ 34413a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType" 34513a62661SPeter Brune /*@ 34613a62661SPeter Brune SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES. 34713a62661SPeter Brune 34813a62661SPeter Brune Logically Collective on SNES 34913a62661SPeter Brune 35013a62661SPeter Brune Input Parameters: 35113a62661SPeter Brune + snes - the iterative context 35213a62661SPeter Brune - rtype - restart type 35313a62661SPeter Brune 35413a62661SPeter Brune Options Database: 35513a62661SPeter Brune + -snes_ngmres_restart_type<difference,periodic,none> - set the restart type 3560c777b0cSPeter Brune - -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic 35713a62661SPeter Brune 35813a62661SPeter Brune Level: intermediate 35913a62661SPeter Brune 36013a62661SPeter Brune SNESNGMRESRestartTypes: 36113a62661SPeter Brune + SNES_NGMRES_RESTART_NONE - never restart 36213a62661SPeter Brune . SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria 36313a62661SPeter Brune - SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations 36413a62661SPeter Brune 36513a62661SPeter Brune Notes: 36613a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 36713a62661SPeter Brune 36813a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch 36913a62661SPeter Brune @*/ 3700adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes,SNESNGMRESRestartType rtype) 3710adebc6cSBarry Smith { 37213a62661SPeter Brune PetscErrorCode ierr; 3735fd66863SKarl Rupp 37413a62661SPeter Brune PetscFunctionBegin; 37513a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 37613a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr); 37713a62661SPeter Brune PetscFunctionReturn(0); 37813a62661SPeter Brune } 37913a62661SPeter Brune 38013a62661SPeter Brune #undef __FUNCT__ 38113a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType" 38213a62661SPeter Brune /*@ 38313a62661SPeter Brune SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES. This determines how the candidate solution and 38413a62661SPeter Brune combined solution are used to create the next iterate. 38513a62661SPeter Brune 38613a62661SPeter Brune Logically Collective on SNES 38713a62661SPeter Brune 38813a62661SPeter Brune Input Parameters: 38913a62661SPeter Brune + snes - the iterative context 39013a62661SPeter Brune - stype - selection type 39113a62661SPeter Brune 39213a62661SPeter Brune Options Database: 39313a62661SPeter Brune . -snes_ngmres_select_type<difference,none,linesearch> 39413a62661SPeter Brune 39513a62661SPeter Brune Level: intermediate 39613a62661SPeter Brune 39713a62661SPeter Brune SNESNGMRESSelectTypes: 39813a62661SPeter Brune + SNES_NGMRES_SELECT_NONE - choose the combined solution all the time 39913a62661SPeter Brune . SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria 40013a62661SPeter Brune - SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination 40113a62661SPeter Brune 40213a62661SPeter Brune Notes: 40313a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 40413a62661SPeter Brune 40513a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch 40613a62661SPeter Brune @*/ 4070adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes,SNESNGMRESSelectType stype) 4080adebc6cSBarry Smith { 40913a62661SPeter Brune PetscErrorCode ierr; 4105fd66863SKarl Rupp 41113a62661SPeter Brune PetscFunctionBegin; 41213a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 41313a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr); 41413a62661SPeter Brune PetscFunctionReturn(0); 41513a62661SPeter Brune } 41613a62661SPeter Brune 41713a62661SPeter Brune EXTERN_C_BEGIN 41813a62661SPeter Brune #undef __FUNCT__ 41913a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES" 4200adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes,SNESNGMRESSelectType stype) 4210adebc6cSBarry Smith { 42213a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 4235fd66863SKarl Rupp 42413a62661SPeter Brune PetscFunctionBegin; 42513a62661SPeter Brune ngmres->select_type = stype; 42613a62661SPeter Brune PetscFunctionReturn(0); 42713a62661SPeter Brune } 42813a62661SPeter Brune 42913a62661SPeter Brune #undef __FUNCT__ 43013a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES" 4310adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes,SNESNGMRESRestartType rtype) 4320adebc6cSBarry Smith { 43313a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 4345fd66863SKarl Rupp 43513a62661SPeter Brune PetscFunctionBegin; 43613a62661SPeter Brune ngmres->restart_type = rtype; 43713a62661SPeter Brune PetscFunctionReturn(0); 43813a62661SPeter Brune } 43913a62661SPeter Brune EXTERN_C_END 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 45713a62661SPeter Brune . -snes_linesearch_type <basic,basicnonorms,quadratic,critical> - 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 EXTERN_C_BEGIN 474a312c225SMatthew G Knepley #undef __FUNCT__ 475a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 476a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes) 477a312c225SMatthew G Knepley { 478a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 479a312c225SMatthew G Knepley PetscErrorCode ierr; 480a312c225SMatthew G Knepley 481a312c225SMatthew G Knepley PetscFunctionBegin; 482a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 483a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 484a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 485a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 486a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 487a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 488a312c225SMatthew G Knepley 48942f4f86dSBarry Smith snes->usespc = PETSC_TRUE; 4902c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 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; 504e7058c64SPeter Brune 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 51513a62661SPeter Brune ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNGMRESSetSelectType_C","SNESNGMRESSetSelectType_NGMRES",SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr); 51613a62661SPeter Brune ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNGMRESSetRestartType_C","SNESNGMRESSetRestartType_NGMRES",SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr); 517a312c225SMatthew G Knepley PetscFunctionReturn(0); 518a312c225SMatthew G Knepley } 519a312c225SMatthew G Knepley EXTERN_C_END 520