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 } 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 */ 169*ddd40ce5SPeter Brune Vec XA,FA,XM,FM; 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 2063a2ae377SPeter Brune if (snes->pc && snes->pcside == PC_LEFT) { 2073a2ae377SPeter Brune ierr = SNESApplyPC(snes,X,NULL,NULL,F);CHKERRQ(ierr); 2083a2ae377SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 2093a2ae377SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2103a2ae377SPeter Brune snes->reason = SNES_DIVERGED_INNER; 2113a2ae377SPeter Brune PetscFunctionReturn(0); 2123a2ae377SPeter Brune } 2133a2ae377SPeter Brune ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 2143a2ae377SPeter Brune } else { 215e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 216f109b39eSPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 217a312c225SMatthew G Knepley if (snes->domainerror) { 218a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 219a312c225SMatthew G Knepley PetscFunctionReturn(0); 220a312c225SMatthew G Knepley } 2211aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 222e4ed7901SPeter Brune if (!snes->norm_init_set) { 2233a2ae377SPeter Brune /* convergence test */ 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 } 229e4ed7901SPeter Brune } else { 230e4ed7901SPeter Brune fnorm = snes->norm_init; 231e4ed7901SPeter Brune snes->norm_init_set = PETSC_FALSE; 232e4ed7901SPeter Brune } 2333a2ae377SPeter Brune } 234e4ed7901SPeter Brune fminnorm = fnorm; 23519653cdaSPeter Brune 23698b3e84cSPeter Brune /* q_{00} = nu */ 23738774f0aSPeter Brune SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fnorm,X); 238087dfb9eSxuemin 239ce8c27fbSBarry Smith ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 240f109b39eSPeter Brune snes->norm = fnorm; 241ce8c27fbSBarry Smith ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 242a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); 243f109b39eSPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 244f109b39eSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 245a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 246a312c225SMatthew G Knepley 24719653cdaSPeter Brune k_restart = 1; 24819653cdaSPeter Brune l = 1; 24909c08436SPeter Brune for (k=1; k < snes->max_its+1; k++) { 25098b3e84cSPeter Brune /* select which vector of the stored subspace will be updated */ 25198b3e84cSPeter Brune ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */ 25219653cdaSPeter Brune 25398b3e84cSPeter Brune /* Computation of x^M */ 254c40d0f55SPeter Brune if (snes->pc && snes->pcside == PC_RIGHT) { 2559f425c49SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 256e4ed7901SPeter Brune ierr = SNESSetInitialFunction(snes->pc,F);CHKERRQ(ierr); 257e4ed7901SPeter Brune ierr = SNESSetInitialFunctionNorm(snes->pc,fnorm);CHKERRQ(ierr); 25863e7833aSPeter Brune 25963e7833aSPeter Brune ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); 2609f425c49SPeter Brune ierr = SNESSolve(snes->pc,B,XM);CHKERRQ(ierr); 26163e7833aSPeter Brune ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); 26263e7833aSPeter Brune 2638cc86e31SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 2648cc86e31SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2658cc86e31SPeter Brune snes->reason = SNES_DIVERGED_INNER; 2668cc86e31SPeter Brune PetscFunctionReturn(0); 2678cc86e31SPeter Brune } 268*ddd40ce5SPeter Brune ierr = SNESGetPCFunction(snes,FM,&fMnorm);CHKERRQ(ierr); 2698cc86e31SPeter Brune } else { 270f109b39eSPeter Brune /* no preconditioner -- just take gradient descent with line search */ 271f109b39eSPeter Brune ierr = VecCopy(F,Y);CHKERRQ(ierr); 272e7058c64SPeter Brune ierr = VecCopy(F,FM);CHKERRQ(ierr); 273e7058c64SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 2741aa26658SKarl Rupp 275e7058c64SPeter Brune fMnorm = fnorm; 2761aa26658SKarl Rupp 277f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr); 278f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(snes->linesearch,&lssucceed);CHKERRQ(ierr); 279f109b39eSPeter Brune if (!lssucceed) { 280f109b39eSPeter Brune if (++snes->numFailures >= snes->maxFailures) { 281f109b39eSPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 282f109b39eSPeter Brune PetscFunctionReturn(0); 283f109b39eSPeter Brune } 284f109b39eSPeter Brune } 2856634f59bSPeter Brune } 286f6408107SPeter Brune ierr = SNESNGMRESFormCombinedSolution_Private(snes,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr); 28798b3e84cSPeter Brune /* r = F(x) */ 2889f425c49SPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of F^M */ 28919653cdaSPeter Brune 2909f425c49SPeter Brune /* differences for selection and restart */ 29113a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) { 292fa8c639aSPeter Brune ierr = SNESNGMRESCalculateDifferences_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,&fAnorm);CHKERRQ(ierr); 29313a62661SPeter Brune } else { 29413a62661SPeter Brune ierr = VecNorm(FA,NORM_2,&fAnorm);CHKERRQ(ierr); 29513a62661SPeter Brune } 296189a9710SBarry Smith if (PetscIsInfOrNanReal(fAnorm)) { 297189a9710SBarry Smith snes->reason = SNES_DIVERGED_FNORM_NAN; 298189a9710SBarry Smith PetscFunctionReturn(0); 299189a9710SBarry Smith } 3001aa26658SKarl Rupp 3019f425c49SPeter Brune /* combination (additive) or selection (multiplicative) of the N-GMRES solution */ 302fa8c639aSPeter Brune ierr = SNESNGMRESSelect_Private(snes,k_restart,XM,FM,fMnorm,XA,FA,fAnorm,dnorm,fminnorm,dminnorm,X,F,Y,&fnorm);CHKERRQ(ierr); 30319653cdaSPeter Brune selectRestart = PETSC_FALSE; 30413a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) { 30521687c63SPeter Brune ierr = SNESNGMRESSelectRestart_Private(snes,l,fAnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr); 30628ed4a04SPeter Brune /* if the restart conditions persist for more than restart_it iterations, restart. */ 3071aa26658SKarl Rupp if (selectRestart) restart_count++; 3081aa26658SKarl Rupp else restart_count = 0; 30913a62661SPeter Brune } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) { 31013a62661SPeter Brune if (k_restart > ngmres->restart_periodic) { 31113a62661SPeter Brune if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr); 31213a62661SPeter Brune restart_count = ngmres->restart_it; 31313a62661SPeter Brune } 31413a62661SPeter Brune } 31528ed4a04SPeter Brune /* restart after restart conditions have persisted for a fixed number of iterations */ 31628ed4a04SPeter Brune if (restart_count >= ngmres->restart_it) { 317dfbf837cSBarry Smith if (ngmres->monitor) { 318dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor,"Restarted at iteration %d\n",k_restart);CHKERRQ(ierr); 319dfbf837cSBarry Smith } 32028ed4a04SPeter Brune restart_count = 0; 32119653cdaSPeter Brune k_restart = 1; 32219653cdaSPeter Brune l = 1; 32398b3e84cSPeter Brune /* q_{00} = nu */ 32438774f0aSPeter Brune if (ngmres->candidate) { 325fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,FM,fMnorm,XM);CHKERRQ(ierr); 326d2e16ddcSPeter Brune } else { 327fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fMnorm,X);CHKERRQ(ierr); 328d2e16ddcSPeter Brune } 32919653cdaSPeter Brune } else { 33098b3e84cSPeter Brune /* select the current size of the subspace */ 3311e633543SBarry Smith if (l < ngmres->msize) l++; 33219653cdaSPeter Brune k_restart++; 33398b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 33438774f0aSPeter Brune if (ngmres->candidate) { 33538774f0aSPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; 336fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fMnorm,XM);CHKERRQ(ierr); 337d2e16ddcSPeter Brune } else { 33838774f0aSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; 339fa8c639aSPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,F,fnorm,X);CHKERRQ(ierr); 34019653cdaSPeter Brune } 341d2e16ddcSPeter Brune } 34219653cdaSPeter Brune 343ce8c27fbSBarry Smith ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); 344087dfb9eSxuemin snes->iter = k; 345f109b39eSPeter Brune snes->norm = fnorm; 346ce8c27fbSBarry Smith ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); 347a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr); 3488409ca45SMatthew G Knepley ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 349d484d688SPeter Brune ierr = VecNormBegin(Y,NORM_2,&ynorm);CHKERRQ(ierr); 350d484d688SPeter Brune ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); 351d484d688SPeter Brune ierr = VecNormEnd(Y,NORM_2,&ynorm);CHKERRQ(ierr); 352d484d688SPeter Brune ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 353d484d688SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 354087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 355a312c225SMatthew G Knepley } 356a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 357a312c225SMatthew G Knepley PetscFunctionReturn(0); 358a312c225SMatthew G Knepley } 359a312c225SMatthew G Knepley 36013a62661SPeter Brune #undef __FUNCT__ 36113a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType" 36213a62661SPeter Brune /*@ 36313a62661SPeter Brune SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES. 36413a62661SPeter Brune 36513a62661SPeter Brune Logically Collective on SNES 36613a62661SPeter Brune 36713a62661SPeter Brune Input Parameters: 36813a62661SPeter Brune + snes - the iterative context 36913a62661SPeter Brune - rtype - restart type 37013a62661SPeter Brune 37113a62661SPeter Brune Options Database: 37213a62661SPeter Brune + -snes_ngmres_restart_type<difference,periodic,none> - set the restart type 3730c777b0cSPeter Brune - -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic 37413a62661SPeter Brune 37513a62661SPeter Brune Level: intermediate 37613a62661SPeter Brune 37713a62661SPeter Brune SNESNGMRESRestartTypes: 37813a62661SPeter Brune + SNES_NGMRES_RESTART_NONE - never restart 37913a62661SPeter Brune . SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria 38013a62661SPeter Brune - SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations 38113a62661SPeter Brune 38213a62661SPeter Brune Notes: 38313a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 38413a62661SPeter Brune 38513a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch 38613a62661SPeter Brune @*/ 3870adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes,SNESNGMRESRestartType rtype) 3880adebc6cSBarry Smith { 38913a62661SPeter Brune PetscErrorCode ierr; 3905fd66863SKarl Rupp 39113a62661SPeter Brune PetscFunctionBegin; 39213a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 39313a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr); 39413a62661SPeter Brune PetscFunctionReturn(0); 39513a62661SPeter Brune } 39613a62661SPeter Brune 39713a62661SPeter Brune #undef __FUNCT__ 39813a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType" 39913a62661SPeter Brune /*@ 40013a62661SPeter Brune SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES. This determines how the candidate solution and 40113a62661SPeter Brune combined solution are used to create the next iterate. 40213a62661SPeter Brune 40313a62661SPeter Brune Logically Collective on SNES 40413a62661SPeter Brune 40513a62661SPeter Brune Input Parameters: 40613a62661SPeter Brune + snes - the iterative context 40713a62661SPeter Brune - stype - selection type 40813a62661SPeter Brune 40913a62661SPeter Brune Options Database: 41013a62661SPeter Brune . -snes_ngmres_select_type<difference,none,linesearch> 41113a62661SPeter Brune 41213a62661SPeter Brune Level: intermediate 41313a62661SPeter Brune 41413a62661SPeter Brune SNESNGMRESSelectTypes: 41513a62661SPeter Brune + SNES_NGMRES_SELECT_NONE - choose the combined solution all the time 41613a62661SPeter Brune . SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria 41713a62661SPeter Brune - SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination 41813a62661SPeter Brune 41913a62661SPeter Brune Notes: 42013a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 42113a62661SPeter Brune 42213a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch 42313a62661SPeter Brune @*/ 4240adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes,SNESNGMRESSelectType stype) 4250adebc6cSBarry Smith { 42613a62661SPeter Brune PetscErrorCode ierr; 4275fd66863SKarl Rupp 42813a62661SPeter Brune PetscFunctionBegin; 42913a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 43013a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr); 43113a62661SPeter Brune PetscFunctionReturn(0); 43213a62661SPeter Brune } 43313a62661SPeter Brune 43413a62661SPeter Brune #undef __FUNCT__ 43513a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES" 4360adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes,SNESNGMRESSelectType stype) 4370adebc6cSBarry Smith { 43813a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 4395fd66863SKarl Rupp 44013a62661SPeter Brune PetscFunctionBegin; 44113a62661SPeter Brune ngmres->select_type = stype; 44213a62661SPeter Brune PetscFunctionReturn(0); 44313a62661SPeter Brune } 44413a62661SPeter Brune 44513a62661SPeter Brune #undef __FUNCT__ 44613a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES" 4470adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes,SNESNGMRESRestartType rtype) 4480adebc6cSBarry Smith { 44913a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 4505fd66863SKarl Rupp 45113a62661SPeter Brune PetscFunctionBegin; 45213a62661SPeter Brune ngmres->restart_type = rtype; 45313a62661SPeter Brune PetscFunctionReturn(0); 45413a62661SPeter Brune } 45513a62661SPeter Brune 456dfbf837cSBarry Smith /*MC 4571867fe5bSPeter Brune SNESNGMRES - The Nonlinear Generalized Minimum Residual method. 458a312c225SMatthew G Knepley 459dfbf837cSBarry Smith Level: beginner 460dfbf837cSBarry Smith 4611867fe5bSPeter Brune Options Database: 46213a62661SPeter Brune + -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution 46338774f0aSPeter Brune . -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions 46438774f0aSPeter Brune . -snes_ngmres_candidate - Use NGMRES variant which combines candidate solutions instead of actual solutions 46513a62661SPeter Brune . -snes_ngmres_m - Number of stored previous solutions and residuals 46613a62661SPeter Brune . -snes_ngmres_restart_it - Number of iterations the restart conditions hold before restart 46713a62661SPeter Brune . -snes_ngmres_gammaA - Residual tolerance for solution select between the candidate and combination 46813a62661SPeter Brune . -snes_ngmres_gammaC - Residual tolerance for restart 46913a62661SPeter Brune . -snes_ngmres_epsilonB - Difference tolerance between subsequent solutions triggering restart 47013a62661SPeter Brune . -snes_ngmres_deltaB - Difference tolerance between residuals triggering restart 47113a62661SPeter Brune . -snes_ngmres_monitor - Prints relevant information about the ngmres iteration 4725c3e6ab7SPeter Brune . -snes_linesearch_type <basic,l2,cp> - Line search type used for the default smoother 47313a62661SPeter Brune - -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type 4741867fe5bSPeter Brune 4751867fe5bSPeter Brune Notes: 4761867fe5bSPeter Brune 4771867fe5bSPeter Brune The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized 4781867fe5bSPeter Brune optimization problem at each iteration. 4791867fe5bSPeter Brune 4801867fe5bSPeter Brune References: 4811867fe5bSPeter Brune 482dfbf837cSBarry Smith "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 483dfbf837cSBarry Smith SIAM Journal on Scientific Computing, 21(5), 2000. 484dfbf837cSBarry Smith 485dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 486dfbf837cSBarry Smith M*/ 487a312c225SMatthew G Knepley 488a312c225SMatthew G Knepley #undef __FUNCT__ 489a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 4908cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NGMRES(SNES snes) 491a312c225SMatthew G Knepley { 492a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 493a312c225SMatthew G Knepley PetscErrorCode ierr; 494a312c225SMatthew G Knepley 495a312c225SMatthew G Knepley PetscFunctionBegin; 496a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 497a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 498a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 499a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 500a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 501a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 502a312c225SMatthew G Knepley 50342f4f86dSBarry Smith snes->usespc = PETSC_TRUE; 5042c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 50546159c86SPeter Brune snes->pcside = PC_RIGHT; 50646159c86SPeter Brune snes->functype = SNES_FUNCTION_PRECONDITIONED; 5072c155ee1SBarry Smith 508a312c225SMatthew G Knepley ierr = PetscNewLog(snes,SNES_NGMRES,&ngmres);CHKERRQ(ierr); 509a312c225SMatthew G Knepley snes->data = (void*) ngmres; 510d2e16ddcSPeter Brune ngmres->msize = 30; 51119653cdaSPeter Brune 51288976e71SPeter Brune if (!snes->tolerancesset) { 5130e444f03SPeter Brune snes->max_funcs = 30000; 5140e444f03SPeter Brune snes->max_its = 10000; 51588976e71SPeter Brune } 5160e444f03SPeter Brune 51738774f0aSPeter Brune ngmres->candidate = PETSC_FALSE; 518d2e16ddcSPeter Brune 5190298fd71SBarry Smith ngmres->additive_linesearch = NULL; 520077c4231SPeter Brune ngmres->approxfunc = PETSC_FALSE; 52128ed4a04SPeter Brune ngmres->restart_it = 2; 52213a62661SPeter Brune ngmres->restart_periodic = 30; 523f109b39eSPeter Brune ngmres->gammaA = 2.0; 524f109b39eSPeter Brune ngmres->gammaC = 2.0; 525cac108bcSPeter Brune ngmres->deltaB = 0.9; 526cac108bcSPeter Brune ngmres->epsilonB = 0.1; 527e7058c64SPeter Brune 52813a62661SPeter Brune ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE; 52913a62661SPeter Brune ngmres->select_type = SNES_NGMRES_SELECT_DIFFERENCE; 53013a62661SPeter Brune 531bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetSelectType_C",SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr); 532bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartType_C",SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr); 533a312c225SMatthew G Knepley PetscFunctionReturn(0); 534a312c225SMatthew G Knepley } 53599e0435eSBarry Smith 536