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; 51*46159c86SPeter Brune if (snes->pc && snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) { 52*46159c86SPeter Brune SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"SNESNGMRES does not support left preconditioning with unpreconditioned function"); 53*46159c86SPeter Brune } 54fa0ddf94SBarry Smith ierr = SNESSetWorkVecs(snes,5);CHKERRQ(ierr); 5578440776SJed Brown if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);} 5678440776SJed Brown if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);} 5778440776SJed Brown if (!ngmres->setup_called) { 58087dfb9eSxuemin msize = ngmres->msize; /* restart size */ 5919653cdaSPeter Brune hsize = msize * msize; 60087dfb9eSxuemin 6198b3e84cSPeter Brune /* explicit least squares minimization solve */ 6219653cdaSPeter Brune ierr = PetscMalloc5(hsize,PetscScalar,&ngmres->h, 6319653cdaSPeter Brune msize,PetscScalar,&ngmres->beta, 6419653cdaSPeter Brune msize,PetscScalar,&ngmres->xi, 65f109b39eSPeter Brune msize,PetscReal, &ngmres->fnorms, 6619653cdaSPeter Brune hsize,PetscScalar,&ngmres->q);CHKERRQ(ierr); 6718aa0c0cSPeter Brune if (ngmres->singlereduction) { 6818aa0c0cSPeter Brune ierr = PetscMalloc(msize*sizeof(PetscReal),&ngmres->xnorms);CHKERRQ(ierr); 6918aa0c0cSPeter Brune } 7019653cdaSPeter Brune ngmres->nrhs = 1; 7119653cdaSPeter Brune ngmres->lda = msize; 7219653cdaSPeter Brune ngmres->ldb = msize; 7319653cdaSPeter Brune ierr = PetscMalloc(msize*sizeof(PetscScalar),&ngmres->s);CHKERRQ(ierr); 7419653cdaSPeter Brune ierr = PetscMemzero(ngmres->h, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 7519653cdaSPeter Brune ierr = PetscMemzero(ngmres->q, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 7619653cdaSPeter Brune ierr = PetscMemzero(ngmres->xi, msize*sizeof(PetscScalar));CHKERRQ(ierr); 7719653cdaSPeter Brune ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr); 7819653cdaSPeter Brune ngmres->lwork = 12*msize; 7919653cdaSPeter Brune #if PETSC_USE_COMPLEX 8022d28d08SBarry Smith ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork);CHKERRQ(ierr); 8119653cdaSPeter Brune #endif 8222d28d08SBarry Smith ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work);CHKERRQ(ierr); 8378440776SJed Brown } 84e7058c64SPeter Brune 85e7058c64SPeter Brune /* linesearch setup */ 86e7058c64SPeter Brune ierr = SNESGetOptionsPrefix(snes,&optionsprefix);CHKERRQ(ierr); 87e7058c64SPeter Brune 8813a62661SPeter Brune if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) { 89ce94432eSBarry Smith ierr = SNESLineSearchCreate(PetscObjectComm((PetscObject)snes),&ngmres->additive_linesearch);CHKERRQ(ierr); 90f1c6b773SPeter Brune ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch,snes);CHKERRQ(ierr); 911a4f838cSPeter Brune ierr = SNESLineSearchSetType(ngmres->additive_linesearch,SNESLINESEARCHL2);CHKERRQ(ierr); 92f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,"additive_");CHKERRQ(ierr); 93f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,optionsprefix);CHKERRQ(ierr); 94f1c6b773SPeter Brune ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr); 95e7058c64SPeter Brune } 96e7058c64SPeter Brune 9778440776SJed Brown ngmres->setup_called = PETSC_TRUE; 98a312c225SMatthew G Knepley PetscFunctionReturn(0); 99a312c225SMatthew G Knepley } 100a312c225SMatthew G Knepley 101a312c225SMatthew G Knepley #undef __FUNCT__ 102a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES" 103a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes) 104a312c225SMatthew G Knepley { 105a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 106a312c225SMatthew G Knepley PetscErrorCode ierr; 107dfbf837cSBarry Smith PetscBool debug; 108f1c6b773SPeter Brune SNESLineSearch linesearch; 1090adebc6cSBarry Smith 110a312c225SMatthew G Knepley PetscFunctionBegin; 111a312c225SMatthew G Knepley ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr); 11213a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes, 1130298fd71SBarry Smith (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,NULL);CHKERRQ(ierr); 11413a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes, 1150298fd71SBarry Smith (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,NULL);CHKERRQ(ierr); 1160298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_candidate", "Use candidate storage", "SNES",ngmres->candidate,&ngmres->candidate,NULL);CHKERRQ(ierr); 117077c4231SPeter Brune ierr = PetscOptionsBool("-snes_ngmres_approxfunc","Linearly approximate the function", "SNES",ngmres->approxfunc,&ngmres->approxfunc,NULL);CHKERRQ(ierr); 1180298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_m", "Number of directions", "SNES",ngmres->msize,&ngmres->msize,NULL);CHKERRQ(ierr); 1190298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_restart", "Iterations before forced restart", "SNES",ngmres->restart_periodic,&ngmres->restart_periodic,NULL);CHKERRQ(ierr); 1200298fd71SBarry Smith ierr = PetscOptionsInt("-snes_ngmres_restart_it", "Tolerance iterations before restart","SNES",ngmres->restart_it,&ngmres->restart_it,NULL);CHKERRQ(ierr); 1210298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_monitor", "Monitor actions of NGMRES", "SNES",ngmres->monitor ? PETSC_TRUE : PETSC_FALSE,&debug,NULL);CHKERRQ(ierr); 122dfbf837cSBarry Smith if (debug) { 123ce94432eSBarry Smith ngmres->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 124dfbf837cSBarry Smith } 1250298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_gammaA", "Residual selection constant", "SNES",ngmres->gammaA,&ngmres->gammaA,NULL);CHKERRQ(ierr); 1260298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_gammaC", "Residual restart constant", "SNES",ngmres->gammaC,&ngmres->gammaC,NULL);CHKERRQ(ierr); 1270298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES",ngmres->epsilonB,&ngmres->epsilonB,NULL);CHKERRQ(ierr); 1280298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ngmres_deltaB", "Difference residual selection constant", "SNES",ngmres->deltaB,&ngmres->deltaB,NULL);CHKERRQ(ierr); 1290298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions", "SNES",ngmres->singlereduction,&ngmres->singlereduction,NULL);CHKERRQ(ierr); 130a312c225SMatthew G Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1316a7cf640SPeter Brune if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA; 1329e764e56SPeter Brune 1339e764e56SPeter Brune /* set the default type of the line search if the user hasn't already. */ 1349e764e56SPeter Brune if (!snes->linesearch) { 1357601faf0SJed Brown ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 1361a4f838cSPeter Brune ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr); 1379e764e56SPeter Brune } 138a312c225SMatthew G Knepley PetscFunctionReturn(0); 139a312c225SMatthew G Knepley } 140a312c225SMatthew G Knepley 141a312c225SMatthew G Knepley #undef __FUNCT__ 142a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES" 143a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes,PetscViewer viewer) 144a312c225SMatthew G Knepley { 145a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 146a312c225SMatthew G Knepley PetscBool iascii; 147a312c225SMatthew G Knepley PetscErrorCode ierr; 148a312c225SMatthew G Knepley 149a312c225SMatthew G Knepley PetscFunctionBegin; 150251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject) viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 151a312c225SMatthew G Knepley if (iascii) { 152f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr); 153f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Residual selection: gammaA=%1.0e, gammaC=%1.0e\n",ngmres->gammaA,ngmres->gammaC);CHKERRQ(ierr); 154f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n",ngmres->epsilonB,ngmres->deltaB);CHKERRQ(ierr); 155a312c225SMatthew G Knepley } 156a312c225SMatthew G Knepley PetscFunctionReturn(0); 157a312c225SMatthew G Knepley } 158a312c225SMatthew G Knepley 159a312c225SMatthew G Knepley #undef __FUNCT__ 160a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES" 161a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes) 162a312c225SMatthew G Knepley { 16338774f0aSPeter Brune 164087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 16598b3e84cSPeter Brune /* present solution, residual, and preconditioned residual */ 1669f425c49SPeter Brune Vec X,F,B,D,Y; 167f109b39eSPeter Brune 168f109b39eSPeter Brune /* candidate linear combination answers */ 1694b32a720SPeter Brune Vec XA,FA,XM,FM,FPC; 17019653cdaSPeter Brune 17198b3e84cSPeter Brune /* coefficients and RHS to the minimization problem */ 17218aa0c0cSPeter Brune PetscReal fnorm,fMnorm,fAnorm; 17338774f0aSPeter Brune PetscInt k,k_restart,l,ivec,restart_count = 0; 17419653cdaSPeter Brune 17598b3e84cSPeter Brune /* solution selection data */ 17638774f0aSPeter Brune PetscBool selectRestart; 17738774f0aSPeter Brune PetscReal dnorm,dminnorm = 0.0; 178d484d688SPeter Brune PetscReal fminnorm,xnorm,ynorm; 17919653cdaSPeter Brune 1801e633543SBarry Smith SNESConvergedReason reason; 18138774f0aSPeter Brune PetscBool lssucceed; 182a312c225SMatthew G Knepley PetscErrorCode ierr; 183a312c225SMatthew G Knepley 184a312c225SMatthew G Knepley PetscFunctionBegin; 18598b3e84cSPeter Brune /* variable initialization */ 186a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 187f109b39eSPeter Brune X = snes->vec_sol; 188f109b39eSPeter Brune F = snes->vec_func; 189f109b39eSPeter Brune B = snes->vec_rhs; 190f109b39eSPeter Brune XA = snes->vec_sol_update; 191f109b39eSPeter Brune FA = snes->work[0]; 192f109b39eSPeter Brune D = snes->work[1]; 193f109b39eSPeter Brune 194f109b39eSPeter Brune /* work for the line search */ 195f109b39eSPeter Brune Y = snes->work[2]; 1969f425c49SPeter Brune XM = snes->work[3]; 1979f425c49SPeter Brune FM = snes->work[4]; 198a312c225SMatthew G Knepley 199ce8c27fbSBarry Smith ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 200a312c225SMatthew G Knepley snes->iter = 0; 201a312c225SMatthew G Knepley snes->norm = 0.; 202ce8c27fbSBarry Smith ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 20319653cdaSPeter Brune 20498b3e84cSPeter Brune /* initialization */ 20519653cdaSPeter Brune 20698b3e84cSPeter Brune /* r = F(x) */ 207e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 208f109b39eSPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 209a312c225SMatthew G Knepley if (snes->domainerror) { 210a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 211a312c225SMatthew G Knepley PetscFunctionReturn(0); 212a312c225SMatthew G Knepley } 2131aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 21419653cdaSPeter Brune 215e4ed7901SPeter Brune if (!snes->norm_init_set) { 216f109b39eSPeter Brune ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 217189a9710SBarry Smith if (PetscIsInfOrNanReal(fnorm)) { 218189a9710SBarry Smith snes->reason = SNES_DIVERGED_FNORM_NAN; 219189a9710SBarry Smith PetscFunctionReturn(0); 220189a9710SBarry Smith } 221e4ed7901SPeter Brune } else { 222e4ed7901SPeter Brune fnorm = snes->norm_init; 223e4ed7901SPeter Brune snes->norm_init_set = PETSC_FALSE; 224e4ed7901SPeter Brune } 225e4ed7901SPeter Brune fminnorm = fnorm; 22619653cdaSPeter Brune 22798b3e84cSPeter Brune /* q_{00} = nu */ 22838774f0aSPeter Brune SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fnorm,X); 229087dfb9eSxuemin 230ce8c27fbSBarry Smith ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 231f109b39eSPeter Brune snes->norm = fnorm; 232ce8c27fbSBarry Smith ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 233a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); 234f109b39eSPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 235f109b39eSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 236a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 237a312c225SMatthew G Knepley 23819653cdaSPeter Brune k_restart = 1; 23919653cdaSPeter Brune l = 1; 24009c08436SPeter Brune for (k=1; k < snes->max_its+1; k++) { 24198b3e84cSPeter Brune /* select which vector of the stored subspace will be updated */ 24298b3e84cSPeter Brune ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */ 24319653cdaSPeter Brune 24498b3e84cSPeter Brune /* Computation of x^M */ 245c40d0f55SPeter Brune if (snes->pc && snes->pcside == PC_RIGHT) { 2469f425c49SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 247e4ed7901SPeter Brune ierr = SNESSetInitialFunction(snes->pc,F);CHKERRQ(ierr); 248e4ed7901SPeter Brune ierr = SNESSetInitialFunctionNorm(snes->pc,fnorm);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 } 2590298fd71SBarry Smith ierr = SNESGetFunction(snes->pc,&FPC,NULL,NULL);CHKERRQ(ierr); 2604b32a720SPeter Brune ierr = VecCopy(FPC,FM);CHKERRQ(ierr); 2614b32a720SPeter Brune ierr = SNESGetFunctionNorm(snes->pc,&fMnorm);CHKERRQ(ierr); 2628cc86e31SPeter Brune } else { 263f109b39eSPeter Brune /* no preconditioner -- just take gradient descent with line search */ 264f109b39eSPeter Brune ierr = VecCopy(F,Y);CHKERRQ(ierr); 265e7058c64SPeter Brune ierr = VecCopy(F,FM);CHKERRQ(ierr); 266e7058c64SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 2671aa26658SKarl Rupp 268e7058c64SPeter Brune fMnorm = fnorm; 2691aa26658SKarl Rupp 270f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr); 271f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(snes->linesearch,&lssucceed);CHKERRQ(ierr); 272f109b39eSPeter Brune if (!lssucceed) { 273f109b39eSPeter Brune if (++snes->numFailures >= snes->maxFailures) { 274f109b39eSPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 275f109b39eSPeter Brune PetscFunctionReturn(0); 276f109b39eSPeter Brune } 277f109b39eSPeter Brune } 2786634f59bSPeter Brune } 279f6408107SPeter Brune ierr = SNESNGMRESFormCombinedSolution_Private(snes,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr); 28098b3e84cSPeter Brune /* r = F(x) */ 2819f425c49SPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of F^M */ 28219653cdaSPeter Brune 2839f425c49SPeter Brune /* differences for selection and restart */ 28413a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) { 285fa8c639aSPeter Brune ierr = SNESNGMRESCalculateDifferences_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,&fAnorm);CHKERRQ(ierr); 28613a62661SPeter Brune } else { 28713a62661SPeter Brune ierr = VecNorm(FA,NORM_2,&fAnorm);CHKERRQ(ierr); 28813a62661SPeter Brune } 289189a9710SBarry Smith if (PetscIsInfOrNanReal(fAnorm)) { 290189a9710SBarry Smith snes->reason = SNES_DIVERGED_FNORM_NAN; 291189a9710SBarry Smith PetscFunctionReturn(0); 292189a9710SBarry Smith } 2931aa26658SKarl Rupp 2949f425c49SPeter Brune /* combination (additive) or selection (multiplicative) of the N-GMRES solution */ 295fa8c639aSPeter Brune ierr = SNESNGMRESSelect_Private(snes,k_restart,XM,FM,fMnorm,XA,FA,fAnorm,dnorm,fminnorm,dminnorm,X,F,Y,&fnorm);CHKERRQ(ierr); 29619653cdaSPeter Brune selectRestart = PETSC_FALSE; 29713a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) { 29821687c63SPeter Brune ierr = SNESNGMRESSelectRestart_Private(snes,l,fAnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr); 29928ed4a04SPeter Brune /* if the restart conditions persist for more than restart_it iterations, restart. */ 3001aa26658SKarl Rupp if (selectRestart) restart_count++; 3011aa26658SKarl Rupp else restart_count = 0; 30213a62661SPeter Brune } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) { 30313a62661SPeter Brune if (k_restart > ngmres->restart_periodic) { 30413a62661SPeter Brune if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr); 30513a62661SPeter Brune restart_count = ngmres->restart_it; 30613a62661SPeter Brune } 30713a62661SPeter Brune } 30828ed4a04SPeter Brune /* restart after restart conditions have persisted for a fixed number of iterations */ 30928ed4a04SPeter Brune if (restart_count >= ngmres->restart_it) { 310dfbf837cSBarry Smith if (ngmres->monitor) { 311dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor,"Restarted at iteration %d\n",k_restart);CHKERRQ(ierr); 312dfbf837cSBarry Smith } 31328ed4a04SPeter Brune restart_count = 0; 31419653cdaSPeter Brune k_restart = 1; 31519653cdaSPeter Brune l = 1; 31698b3e84cSPeter Brune /* q_{00} = nu */ 31738774f0aSPeter Brune if (ngmres->candidate) { 318fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,FM,fMnorm,XM);CHKERRQ(ierr); 319d2e16ddcSPeter Brune } else { 320fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fMnorm,X);CHKERRQ(ierr); 321d2e16ddcSPeter Brune } 32219653cdaSPeter Brune } else { 32398b3e84cSPeter Brune /* select the current size of the subspace */ 3241e633543SBarry Smith if (l < ngmres->msize) l++; 32519653cdaSPeter Brune k_restart++; 32698b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 32738774f0aSPeter Brune if (ngmres->candidate) { 32838774f0aSPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; 329fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fMnorm,XM);CHKERRQ(ierr); 330d2e16ddcSPeter Brune } else { 33138774f0aSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; 332fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,F,fnorm,X);CHKERRQ(ierr); 33319653cdaSPeter Brune } 334d2e16ddcSPeter Brune } 33519653cdaSPeter Brune 336ce8c27fbSBarry Smith ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 337087dfb9eSxuemin snes->iter = k; 338f109b39eSPeter Brune snes->norm = fnorm; 339ce8c27fbSBarry Smith ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 340a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr); 3418409ca45SMatthew G Knepley ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 342d484d688SPeter Brune ierr = VecNormBegin(Y,NORM_2,&ynorm);CHKERRQ(ierr); 343d484d688SPeter Brune ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); 344d484d688SPeter Brune ierr = VecNormEnd(Y,NORM_2,&ynorm);CHKERRQ(ierr); 345d484d688SPeter Brune ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 346d484d688SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 347087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 348a312c225SMatthew G Knepley } 349a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 350a312c225SMatthew G Knepley PetscFunctionReturn(0); 351a312c225SMatthew G Knepley } 352a312c225SMatthew G Knepley 35313a62661SPeter Brune #undef __FUNCT__ 35413a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType" 35513a62661SPeter Brune /*@ 35613a62661SPeter Brune SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES. 35713a62661SPeter Brune 35813a62661SPeter Brune Logically Collective on SNES 35913a62661SPeter Brune 36013a62661SPeter Brune Input Parameters: 36113a62661SPeter Brune + snes - the iterative context 36213a62661SPeter Brune - rtype - restart type 36313a62661SPeter Brune 36413a62661SPeter Brune Options Database: 36513a62661SPeter Brune + -snes_ngmres_restart_type<difference,periodic,none> - set the restart type 3660c777b0cSPeter Brune - -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic 36713a62661SPeter Brune 36813a62661SPeter Brune Level: intermediate 36913a62661SPeter Brune 37013a62661SPeter Brune SNESNGMRESRestartTypes: 37113a62661SPeter Brune + SNES_NGMRES_RESTART_NONE - never restart 37213a62661SPeter Brune . SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria 37313a62661SPeter Brune - SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations 37413a62661SPeter Brune 37513a62661SPeter Brune Notes: 37613a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 37713a62661SPeter Brune 37813a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch 37913a62661SPeter Brune @*/ 3800adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes,SNESNGMRESRestartType rtype) 3810adebc6cSBarry Smith { 38213a62661SPeter Brune PetscErrorCode ierr; 3835fd66863SKarl Rupp 38413a62661SPeter Brune PetscFunctionBegin; 38513a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 38613a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr); 38713a62661SPeter Brune PetscFunctionReturn(0); 38813a62661SPeter Brune } 38913a62661SPeter Brune 39013a62661SPeter Brune #undef __FUNCT__ 39113a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType" 39213a62661SPeter Brune /*@ 39313a62661SPeter Brune SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES. This determines how the candidate solution and 39413a62661SPeter Brune combined solution are used to create the next iterate. 39513a62661SPeter Brune 39613a62661SPeter Brune Logically Collective on SNES 39713a62661SPeter Brune 39813a62661SPeter Brune Input Parameters: 39913a62661SPeter Brune + snes - the iterative context 40013a62661SPeter Brune - stype - selection type 40113a62661SPeter Brune 40213a62661SPeter Brune Options Database: 40313a62661SPeter Brune . -snes_ngmres_select_type<difference,none,linesearch> 40413a62661SPeter Brune 40513a62661SPeter Brune Level: intermediate 40613a62661SPeter Brune 40713a62661SPeter Brune SNESNGMRESSelectTypes: 40813a62661SPeter Brune + SNES_NGMRES_SELECT_NONE - choose the combined solution all the time 40913a62661SPeter Brune . SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria 41013a62661SPeter Brune - SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination 41113a62661SPeter Brune 41213a62661SPeter Brune Notes: 41313a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 41413a62661SPeter Brune 41513a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch 41613a62661SPeter Brune @*/ 4170adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes,SNESNGMRESSelectType stype) 4180adebc6cSBarry Smith { 41913a62661SPeter Brune PetscErrorCode ierr; 4205fd66863SKarl Rupp 42113a62661SPeter Brune PetscFunctionBegin; 42213a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 42313a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr); 42413a62661SPeter Brune PetscFunctionReturn(0); 42513a62661SPeter Brune } 42613a62661SPeter Brune 42713a62661SPeter Brune #undef __FUNCT__ 42813a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES" 4290adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes,SNESNGMRESSelectType stype) 4300adebc6cSBarry Smith { 43113a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 4325fd66863SKarl Rupp 43313a62661SPeter Brune PetscFunctionBegin; 43413a62661SPeter Brune ngmres->select_type = stype; 43513a62661SPeter Brune PetscFunctionReturn(0); 43613a62661SPeter Brune } 43713a62661SPeter Brune 43813a62661SPeter Brune #undef __FUNCT__ 43913a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES" 4400adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes,SNESNGMRESRestartType rtype) 4410adebc6cSBarry Smith { 44213a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 4435fd66863SKarl Rupp 44413a62661SPeter Brune PetscFunctionBegin; 44513a62661SPeter Brune ngmres->restart_type = rtype; 44613a62661SPeter Brune PetscFunctionReturn(0); 44713a62661SPeter Brune } 44813a62661SPeter Brune 449dfbf837cSBarry Smith /*MC 4501867fe5bSPeter Brune SNESNGMRES - The Nonlinear Generalized Minimum Residual method. 451a312c225SMatthew G Knepley 452dfbf837cSBarry Smith Level: beginner 453dfbf837cSBarry Smith 4541867fe5bSPeter Brune Options Database: 45513a62661SPeter Brune + -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution 45638774f0aSPeter Brune . -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions 45738774f0aSPeter Brune . -snes_ngmres_candidate - Use NGMRES variant which combines candidate solutions instead of actual solutions 45813a62661SPeter Brune . -snes_ngmres_m - Number of stored previous solutions and residuals 45913a62661SPeter Brune . -snes_ngmres_restart_it - Number of iterations the restart conditions hold before restart 46013a62661SPeter Brune . -snes_ngmres_gammaA - Residual tolerance for solution select between the candidate and combination 46113a62661SPeter Brune . -snes_ngmres_gammaC - Residual tolerance for restart 46213a62661SPeter Brune . -snes_ngmres_epsilonB - Difference tolerance between subsequent solutions triggering restart 46313a62661SPeter Brune . -snes_ngmres_deltaB - Difference tolerance between residuals triggering restart 46413a62661SPeter Brune . -snes_ngmres_monitor - Prints relevant information about the ngmres iteration 4655c3e6ab7SPeter Brune . -snes_linesearch_type <basic,l2,cp> - Line search type used for the default smoother 46613a62661SPeter Brune - -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type 4671867fe5bSPeter Brune 4681867fe5bSPeter Brune Notes: 4691867fe5bSPeter Brune 4701867fe5bSPeter Brune The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized 4711867fe5bSPeter Brune optimization problem at each iteration. 4721867fe5bSPeter Brune 4731867fe5bSPeter Brune References: 4741867fe5bSPeter Brune 475dfbf837cSBarry Smith "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 476dfbf837cSBarry Smith SIAM Journal on Scientific Computing, 21(5), 2000. 477dfbf837cSBarry Smith 478dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 479dfbf837cSBarry Smith M*/ 480a312c225SMatthew G Knepley 481a312c225SMatthew G Knepley #undef __FUNCT__ 482a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 4838cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NGMRES(SNES snes) 484a312c225SMatthew G Knepley { 485a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 486a312c225SMatthew G Knepley PetscErrorCode ierr; 487a312c225SMatthew G Knepley 488a312c225SMatthew G Knepley PetscFunctionBegin; 489a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 490a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 491a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 492a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 493a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 494a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 495a312c225SMatthew G Knepley 49642f4f86dSBarry Smith snes->usespc = PETSC_TRUE; 4972c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 498*46159c86SPeter Brune snes->pcside = PC_RIGHT; 499*46159c86SPeter Brune snes->functype = SNES_FUNCTION_PRECONDITIONED; 5002c155ee1SBarry Smith 501a312c225SMatthew G Knepley ierr = PetscNewLog(snes,SNES_NGMRES,&ngmres);CHKERRQ(ierr); 502a312c225SMatthew G Knepley snes->data = (void*) ngmres; 503d2e16ddcSPeter Brune ngmres->msize = 30; 50419653cdaSPeter Brune 50588976e71SPeter Brune if (!snes->tolerancesset) { 5060e444f03SPeter Brune snes->max_funcs = 30000; 5070e444f03SPeter Brune snes->max_its = 10000; 50888976e71SPeter Brune } 5090e444f03SPeter Brune 51038774f0aSPeter Brune ngmres->candidate = PETSC_FALSE; 511d2e16ddcSPeter Brune 5120298fd71SBarry Smith ngmres->additive_linesearch = NULL; 513077c4231SPeter Brune ngmres->approxfunc = PETSC_FALSE; 51428ed4a04SPeter Brune ngmres->restart_it = 2; 51513a62661SPeter Brune ngmres->restart_periodic = 30; 516f109b39eSPeter Brune ngmres->gammaA = 2.0; 517f109b39eSPeter Brune ngmres->gammaC = 2.0; 518cac108bcSPeter Brune ngmres->deltaB = 0.9; 519cac108bcSPeter Brune ngmres->epsilonB = 0.1; 520e7058c64SPeter Brune 52113a62661SPeter Brune ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE; 52213a62661SPeter Brune ngmres->select_type = SNES_NGMRES_SELECT_DIFFERENCE; 52313a62661SPeter Brune 524bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetSelectType_C",SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr); 525bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartType_C",SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr); 526a312c225SMatthew G Knepley PetscFunctionReturn(0); 527a312c225SMatthew G Knepley } 52899e0435eSBarry Smith 529