113a62661SPeter Brune #include <../src/snes/impls/ngmres/snesngmres.h> /*I "petscsnes.h" I*/ 219653cdaSPeter Brune #include <petscblaslapack.h> 3a312c225SMatthew G Knepley 413a62661SPeter Brune const char *SNESNGMRESRestartTypes[] = {"NONE","PERIODIC","DIFFERENCE","SNESNGMRESRestartType","SNES_NGMRES_RESTART_",0}; 513a62661SPeter Brune const char *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); 189e764e56SPeter Brune 19a312c225SMatthew G Knepley PetscFunctionReturn(0); 20a312c225SMatthew G Knepley } 21a312c225SMatthew G Knepley 22a312c225SMatthew G Knepley #undef __FUNCT__ 23a312c225SMatthew G Knepley #define __FUNCT__ "SNESDestroy_NGMRES" 24a312c225SMatthew G Knepley PetscErrorCode SNESDestroy_NGMRES(SNES snes) 25a312c225SMatthew G Knepley { 26a312c225SMatthew G Knepley PetscErrorCode ierr; 2778440776SJed Brown SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 28a312c225SMatthew G Knepley 29a312c225SMatthew G Knepley PetscFunctionBegin; 30a312c225SMatthew G Knepley ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr); 31f109b39eSPeter Brune ierr = PetscFree5(ngmres->h, ngmres->beta, ngmres->xi, ngmres->fnorms, ngmres->q);CHKERRQ(ierr); 3219653cdaSPeter Brune ierr = PetscFree(ngmres->s);CHKERRQ(ierr); 3318aa0c0cSPeter Brune ierr = PetscFree(ngmres->xnorms);CHKERRQ(ierr); 3419653cdaSPeter Brune #if PETSC_USE_COMPLEX 3519653cdaSPeter Brune ierr = PetscFree(ngmres->rwork); 3619653cdaSPeter Brune #endif 3719653cdaSPeter Brune ierr = PetscFree(ngmres->work); 3819653cdaSPeter Brune ierr = PetscFree(snes->data); 39a312c225SMatthew G Knepley PetscFunctionReturn(0); 40a312c225SMatthew G Knepley } 41a312c225SMatthew G Knepley 42a312c225SMatthew G Knepley #undef __FUNCT__ 43a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetUp_NGMRES" 44a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes) 45a312c225SMatthew G Knepley { 46a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 47e7058c64SPeter Brune const char *optionsprefix; 4819653cdaSPeter Brune PetscInt msize,hsize; 49a312c225SMatthew G Knepley PetscErrorCode ierr; 50a312c225SMatthew G Knepley 51a312c225SMatthew G Knepley PetscFunctionBegin; 5278440776SJed Brown ierr = SNESDefaultGetWork(snes,5);CHKERRQ(ierr); 5378440776SJed Brown if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);} 5478440776SJed Brown if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);} 5578440776SJed Brown if (!ngmres->setup_called) { 56087dfb9eSxuemin msize = ngmres->msize; /* restart size */ 5719653cdaSPeter Brune hsize = msize * msize; 58087dfb9eSxuemin 5998b3e84cSPeter Brune /* explicit least squares minimization solve */ 6019653cdaSPeter Brune ierr = PetscMalloc5(hsize,PetscScalar,&ngmres->h, 6119653cdaSPeter Brune msize,PetscScalar,&ngmres->beta, 6219653cdaSPeter Brune msize,PetscScalar,&ngmres->xi, 63f109b39eSPeter Brune msize,PetscReal, &ngmres->fnorms, 6419653cdaSPeter Brune hsize,PetscScalar,&ngmres->q);CHKERRQ(ierr); 6518aa0c0cSPeter Brune if (ngmres->singlereduction) { 6618aa0c0cSPeter Brune ierr = PetscMalloc(msize*sizeof(PetscReal),&ngmres->xnorms);CHKERRQ(ierr); 6718aa0c0cSPeter Brune } 6819653cdaSPeter Brune ngmres->nrhs = 1; 6919653cdaSPeter Brune ngmres->lda = msize; 7019653cdaSPeter Brune ngmres->ldb = msize; 7119653cdaSPeter Brune ierr = PetscMalloc(msize*sizeof(PetscScalar),&ngmres->s);CHKERRQ(ierr); 7219653cdaSPeter Brune ierr = PetscMemzero(ngmres->h, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 7319653cdaSPeter Brune ierr = PetscMemzero(ngmres->q, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 7419653cdaSPeter Brune ierr = PetscMemzero(ngmres->xi, msize*sizeof(PetscScalar));CHKERRQ(ierr); 7519653cdaSPeter Brune ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr); 7619653cdaSPeter Brune ngmres->lwork = 12*msize; 7719653cdaSPeter Brune #if PETSC_USE_COMPLEX 7819653cdaSPeter Brune ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork); 7919653cdaSPeter Brune #endif 8019653cdaSPeter Brune ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work); 8178440776SJed Brown } 82e7058c64SPeter Brune 83e7058c64SPeter Brune /* linesearch setup */ 84e7058c64SPeter Brune ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 85e7058c64SPeter Brune 8613a62661SPeter Brune if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) { 87f1c6b773SPeter Brune ierr = SNESLineSearchCreate(((PetscObject)snes)->comm, &ngmres->additive_linesearch);CHKERRQ(ierr); 88f1c6b773SPeter Brune ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch, snes);CHKERRQ(ierr); 891a4f838cSPeter Brune ierr = SNESLineSearchSetType(ngmres->additive_linesearch, SNESLINESEARCHL2);CHKERRQ(ierr); 90f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch, "additive_");CHKERRQ(ierr); 91f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch, optionsprefix);CHKERRQ(ierr); 92f1c6b773SPeter Brune ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr); 93e7058c64SPeter Brune } 94e7058c64SPeter Brune 9578440776SJed Brown ngmres->setup_called = PETSC_TRUE; 96a312c225SMatthew G Knepley PetscFunctionReturn(0); 97a312c225SMatthew G Knepley } 98a312c225SMatthew G Knepley 99a312c225SMatthew G Knepley #undef __FUNCT__ 100a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES" 101a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes) 102a312c225SMatthew G Knepley { 103a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 104a312c225SMatthew G Knepley PetscErrorCode ierr; 105dfbf837cSBarry Smith PetscBool debug; 106f1c6b773SPeter Brune SNESLineSearch linesearch; 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, 11013a62661SPeter Brune (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,PETSC_NULL);CHKERRQ(ierr); 11113a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes, 11213a62661SPeter Brune (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,PETSC_NULL);CHKERRQ(ierr); 113d2e16ddcSPeter Brune ierr = PetscOptionsBool("-snes_ngmres_anderson", "Use Anderson mixing storage", "SNES", ngmres->anderson, &ngmres->anderson, PETSC_NULL);CHKERRQ(ierr); 11419653cdaSPeter Brune ierr = PetscOptionsInt("-snes_ngmres_m", "Number of directions", "SNES", ngmres->msize, &ngmres->msize, PETSC_NULL);CHKERRQ(ierr); 1150c777b0cSPeter Brune ierr = PetscOptionsInt("-snes_ngmres_restart", "Iterations before forced restart", "SNES", ngmres->restart_periodic, &ngmres->restart_periodic, PETSC_NULL);CHKERRQ(ierr); 11628ed4a04SPeter Brune ierr = PetscOptionsInt("-snes_ngmres_restart_it","Tolerance iterations before restart","SNES", ngmres->restart_it, &ngmres->restart_it, PETSC_NULL);CHKERRQ(ierr); 117dfbf837cSBarry Smith ierr = PetscOptionsBool("-snes_ngmres_monitor", "Monitor actions of NGMRES", "SNES", ngmres->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);CHKERRQ(ierr); 118dfbf837cSBarry Smith if (debug) { 119dfbf837cSBarry Smith ngmres->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 120dfbf837cSBarry Smith } 1216a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_gammaA", "Residual selection constant", "SNES", ngmres->gammaA, &ngmres->gammaA, PETSC_NULL);CHKERRQ(ierr); 1226a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_gammaC", " Residual restart constant", "SNES", ngmres->gammaC, &ngmres->gammaC, PETSC_NULL);CHKERRQ(ierr); 1236a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES", ngmres->epsilonB, &ngmres->epsilonB, PETSC_NULL);CHKERRQ(ierr); 1246a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_deltaB", "Difference residual selection constant", "SNES", ngmres->deltaB, &ngmres->deltaB, PETSC_NULL);CHKERRQ(ierr); 1254d116c7dSPeter Brune ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions", "SNES", ngmres->singlereduction, &ngmres->singlereduction, PETSC_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) { 1489e764e56SPeter Brune 149f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr); 150f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Residual selection: gammaA=%1.0e, gammaC=%1.0e\n", ngmres->gammaA, ngmres->gammaC);CHKERRQ(ierr); 151f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n", ngmres->epsilonB, ngmres->deltaB);CHKERRQ(ierr); 152a312c225SMatthew G Knepley } 153a312c225SMatthew G Knepley PetscFunctionReturn(0); 154a312c225SMatthew G Knepley } 155a312c225SMatthew G Knepley 156a312c225SMatthew G Knepley #undef __FUNCT__ 157a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES" 158211b2d39SPeter Brune 159a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes) 160a312c225SMatthew G Knepley { 161087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 16298b3e84cSPeter Brune /* present solution, residual, and preconditioned residual */ 1639f425c49SPeter Brune Vec X, F, B, D, Y; 164f109b39eSPeter Brune 165f109b39eSPeter Brune /* candidate linear combination answers */ 1664b32a720SPeter Brune Vec XA, FA, XM, FM, FPC; 16719653cdaSPeter Brune 16898b3e84cSPeter Brune /* previous iterations to construct the subspace */ 169f109b39eSPeter Brune Vec *Fdot = ngmres->Fdot; 170f109b39eSPeter Brune Vec *Xdot = ngmres->Xdot; 17119653cdaSPeter Brune 17298b3e84cSPeter Brune /* coefficients and RHS to the minimization problem */ 17319653cdaSPeter Brune PetscScalar *beta = ngmres->beta; 17419653cdaSPeter Brune PetscScalar *xi = ngmres->xi; 17518aa0c0cSPeter Brune PetscReal fnorm, fMnorm, fAnorm; 17619653cdaSPeter Brune PetscReal nu; 17719653cdaSPeter Brune PetscScalar alph_total = 0.; 17828ed4a04SPeter Brune PetscInt i, j, k, k_restart, l, ivec, restart_count = 0; 17919653cdaSPeter Brune 18098b3e84cSPeter Brune /* solution selection data */ 18119653cdaSPeter Brune PetscBool selectA, selectRestart; 18274b542b2SMatthew G Knepley PetscReal dnorm, dminnorm = 0.0, dcurnorm; 183d484d688SPeter Brune PetscReal fminnorm,xnorm,ynorm; 18419653cdaSPeter Brune 1851e633543SBarry Smith SNESConvergedReason reason; 1866e733865SPeter Brune PetscBool lssucceed,changed_y,changed_w; 187a312c225SMatthew G Knepley PetscErrorCode ierr; 188a312c225SMatthew G Knepley 189a312c225SMatthew G Knepley PetscFunctionBegin; 19098b3e84cSPeter Brune /* variable initialization */ 191a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 192f109b39eSPeter Brune X = snes->vec_sol; 193f109b39eSPeter Brune F = snes->vec_func; 194f109b39eSPeter Brune B = snes->vec_rhs; 195f109b39eSPeter Brune XA = snes->vec_sol_update; 196f109b39eSPeter Brune FA = snes->work[0]; 197f109b39eSPeter Brune D = snes->work[1]; 198f109b39eSPeter Brune 199f109b39eSPeter Brune /* work for the line search */ 200f109b39eSPeter Brune Y = snes->work[2]; 2019f425c49SPeter Brune XM = snes->work[3]; 2029f425c49SPeter Brune FM = snes->work[4]; 203a312c225SMatthew G Knepley 204a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 205a312c225SMatthew G Knepley snes->iter = 0; 206a312c225SMatthew G Knepley snes->norm = 0.; 207a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 20819653cdaSPeter Brune 20998b3e84cSPeter Brune /* initialization */ 21019653cdaSPeter Brune 21198b3e84cSPeter Brune /* r = F(x) */ 212e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 213f109b39eSPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 214a312c225SMatthew G Knepley if (snes->domainerror) { 215a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 216a312c225SMatthew G Knepley PetscFunctionReturn(0); 217a312c225SMatthew G Knepley } 218e4ed7901SPeter Brune } else { 219e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 220e4ed7901SPeter Brune } 22119653cdaSPeter Brune 222e4ed7901SPeter Brune if (!snes->norm_init_set) { 223f109b39eSPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 224f109b39eSPeter Brune if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation"); 225e4ed7901SPeter Brune } else { 226e4ed7901SPeter Brune fnorm = snes->norm_init; 227e4ed7901SPeter Brune snes->norm_init_set = PETSC_FALSE; 228e4ed7901SPeter Brune } 229e4ed7901SPeter Brune fminnorm = fnorm; 230e4ed7901SPeter Brune /* nu = (r, r) */ 231e4ed7901SPeter Brune nu = fnorm*fnorm; 23219653cdaSPeter Brune 23398b3e84cSPeter Brune /* q_{00} = nu */ 23419653cdaSPeter Brune Q(0,0) = nu; 235f109b39eSPeter Brune ngmres->fnorms[0] = fnorm; 236f109b39eSPeter Brune /* Fdot[0] = F */ 237f109b39eSPeter Brune ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr); 238f109b39eSPeter Brune ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr); 239087dfb9eSxuemin 240a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 241f109b39eSPeter Brune snes->norm = fnorm; 242a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 243f109b39eSPeter Brune SNESLogConvHistory(snes, fnorm, 0); 244f109b39eSPeter Brune ierr = SNESMonitor(snes, 0, fnorm);CHKERRQ(ierr); 245f109b39eSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 246a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 247a312c225SMatthew G Knepley 24819653cdaSPeter Brune k_restart = 1; 24919653cdaSPeter Brune l = 1; 25009c08436SPeter Brune for (k=1; k < snes->max_its+1; k++) { 25198b3e84cSPeter Brune /* select which vector of the stored subspace will be updated */ 25298b3e84cSPeter Brune ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */ 25319653cdaSPeter Brune 25498b3e84cSPeter Brune /* Computation of x^M */ 2558cc86e31SPeter Brune if (snes->pc) { 2569f425c49SPeter Brune ierr = VecCopy(X, XM);CHKERRQ(ierr); 257e4ed7901SPeter Brune ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr); 258e4ed7901SPeter Brune ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr); 2599f425c49SPeter Brune ierr = SNESSolve(snes->pc, B, XM);CHKERRQ(ierr); 2608cc86e31SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 2618cc86e31SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2628cc86e31SPeter Brune snes->reason = SNES_DIVERGED_INNER; 2638cc86e31SPeter Brune PetscFunctionReturn(0); 2648cc86e31SPeter Brune } 2654b32a720SPeter Brune ierr = SNESGetFunction(snes->pc, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 2664b32a720SPeter Brune ierr = VecCopy(FPC, FM);CHKERRQ(ierr); 2674b32a720SPeter Brune ierr = SNESGetFunctionNorm(snes->pc, &fMnorm);CHKERRQ(ierr); 2688cc86e31SPeter Brune } else { 269f109b39eSPeter Brune /* no preconditioner -- just take gradient descent with line search */ 270f109b39eSPeter Brune ierr = VecCopy(F, Y);CHKERRQ(ierr); 271e7058c64SPeter Brune ierr = VecCopy(F, FM);CHKERRQ(ierr); 272e7058c64SPeter Brune ierr = VecCopy(X, XM);CHKERRQ(ierr); 273e7058c64SPeter Brune fMnorm = fnorm; 274f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr); 275f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssucceed);CHKERRQ(ierr); 276f109b39eSPeter Brune if (!lssucceed) { 277f109b39eSPeter Brune if (++snes->numFailures >= snes->maxFailures) { 278f109b39eSPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 279f109b39eSPeter Brune PetscFunctionReturn(0); 280f109b39eSPeter Brune } 281f109b39eSPeter Brune } 2826634f59bSPeter Brune } 2831e633543SBarry Smith 28498b3e84cSPeter Brune /* r = F(x) */ 2859f425c49SPeter Brune nu = fMnorm*fMnorm; 2869f425c49SPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of F^M */ 28719653cdaSPeter Brune 28898b3e84cSPeter Brune /* construct the right hand side and xi factors */ 2898c09b6b7SPeter Brune ierr = VecMDot(FM, l, Fdot, xi);CHKERRQ(ierr); 2908c09b6b7SPeter Brune 29119653cdaSPeter Brune for (i = 0; i < l; i++) { 29219653cdaSPeter Brune beta[i] = nu - xi[i]; 29319653cdaSPeter Brune } 29419653cdaSPeter Brune 29598b3e84cSPeter Brune /* construct h */ 29619653cdaSPeter Brune for (j = 0; j < l; j++) { 29719653cdaSPeter Brune for (i = 0; i < l; i++) { 29819653cdaSPeter Brune H(i, j) = Q(i, j) - xi[i] - xi[j] + nu; 29919653cdaSPeter Brune } 30019653cdaSPeter Brune } 301f109b39eSPeter Brune 302f109b39eSPeter Brune if(l == 1) { 303f109b39eSPeter Brune /* simply set alpha[0] = beta[0] / H[0, 0] */ 304bf08dd53SPeter Brune if (H(0, 0) != 0.) { 305f109b39eSPeter Brune beta[0] = beta[0] / H(0, 0); 306f109b39eSPeter Brune } else { 307bf08dd53SPeter Brune beta[0] = 0.; 308bf08dd53SPeter Brune } 309bf08dd53SPeter Brune } else { 31019653cdaSPeter Brune #ifdef PETSC_MISSING_LAPACK_GELSS 31119653cdaSPeter Brune SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "NGMRES with LS requires the LAPACK GELSS routine."); 3124a0c5b0cSMatthew G Knepley #else 31319653cdaSPeter Brune ngmres->m = PetscBLASIntCast(l); 31419653cdaSPeter Brune ngmres->n = PetscBLASIntCast(l); 31519653cdaSPeter Brune ngmres->info = PetscBLASIntCast(0); 31619653cdaSPeter Brune ngmres->rcond = -1.; 3178e57ea43SSatish Balay ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 31819653cdaSPeter Brune #ifdef PETSC_USE_COMPLEX 31919653cdaSPeter Brune LAPACKgelss_(&ngmres->m, 32019653cdaSPeter Brune &ngmres->n, 32119653cdaSPeter Brune &ngmres->nrhs, 32219653cdaSPeter Brune ngmres->h, 32319653cdaSPeter Brune &ngmres->lda, 32419653cdaSPeter Brune ngmres->beta, 32519653cdaSPeter Brune &ngmres->ldb, 32619653cdaSPeter Brune ngmres->s, 32719653cdaSPeter Brune &ngmres->rcond, 32819653cdaSPeter Brune &ngmres->rank, 32919653cdaSPeter Brune ngmres->work, 33019653cdaSPeter Brune &ngmres->lwork, 33119653cdaSPeter Brune ngmres->rwork, 33219653cdaSPeter Brune &ngmres->info); 33319653cdaSPeter Brune #else 33419653cdaSPeter Brune LAPACKgelss_(&ngmres->m, 33519653cdaSPeter Brune &ngmres->n, 33619653cdaSPeter Brune &ngmres->nrhs, 33719653cdaSPeter Brune ngmres->h, 33819653cdaSPeter Brune &ngmres->lda, 33919653cdaSPeter Brune ngmres->beta, 34019653cdaSPeter Brune &ngmres->ldb, 34119653cdaSPeter Brune ngmres->s, 34219653cdaSPeter Brune &ngmres->rcond, 34319653cdaSPeter Brune &ngmres->rank, 34419653cdaSPeter Brune ngmres->work, 34519653cdaSPeter Brune &ngmres->lwork, 34619653cdaSPeter Brune &ngmres->info); 34719653cdaSPeter Brune #endif 3488e57ea43SSatish Balay ierr = PetscFPTrapPop();CHKERRQ(ierr); 34919653cdaSPeter Brune if (ngmres->info < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to GELSS"); 35019653cdaSPeter Brune if (ngmres->info > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SVD failed to converge"); 351a312c225SMatthew G Knepley #endif 352f109b39eSPeter Brune } 353a312c225SMatthew G Knepley 35419653cdaSPeter Brune alph_total = 0.; 35519653cdaSPeter Brune for (i = 0; i < l; i++) { 35619653cdaSPeter Brune alph_total += beta[i]; 357c0bbabecSxuemin } 358f109b39eSPeter Brune 3599f425c49SPeter Brune ierr = VecCopy(XM, XA);CHKERRQ(ierr); 360f109b39eSPeter Brune ierr = VecScale(XA, 1. - alph_total);CHKERRQ(ierr); 361087dfb9eSxuemin 3628c09b6b7SPeter Brune ierr = VecMAXPY(XA, l, beta, Xdot);CHKERRQ(ierr); 3636e733865SPeter Brune 3646e733865SPeter Brune /* check the validity of the step */ 365f89ba88eSPeter Brune ierr = VecCopy(XA,Y);CHKERRQ(ierr); 3666e733865SPeter Brune ierr = VecAXPY(Y,-1.0,X);CHKERRQ(ierr); 3676e733865SPeter Brune ierr = SNESLineSearchPostCheck(snes->linesearch,X,Y,XA,&changed_y,&changed_w);CHKERRQ(ierr); 368f109b39eSPeter Brune ierr = SNESComputeFunction(snes, XA, FA);CHKERRQ(ierr); 36919653cdaSPeter Brune 3709f425c49SPeter Brune /* differences for selection and restart */ 37113a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) { 37218aa0c0cSPeter Brune if (ngmres->singlereduction) { 37318aa0c0cSPeter Brune dminnorm = -1.0; 374f109b39eSPeter Brune ierr=VecCopy(XA, D);CHKERRQ(ierr); 37518aa0c0cSPeter Brune ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr); 37618aa0c0cSPeter Brune for(i=0;i<l;i++) { 37718aa0c0cSPeter Brune ierr=VecAXPY(Xdot[i],-1.0,XA);CHKERRQ(ierr); 37818aa0c0cSPeter Brune } 37918aa0c0cSPeter Brune ierr = VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 38018aa0c0cSPeter Brune ierr = VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr); 38118aa0c0cSPeter Brune for (i=0;i<l;i++) { 38218aa0c0cSPeter Brune ierr = VecNormBegin(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr); 38318aa0c0cSPeter Brune } 38418aa0c0cSPeter Brune ierr = VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 38518aa0c0cSPeter Brune ierr = VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr); 38618aa0c0cSPeter Brune for (i=0;i<l;i++) { 38718aa0c0cSPeter Brune ierr = VecNormEnd(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr); 38818aa0c0cSPeter Brune } 38918aa0c0cSPeter Brune for(i=0;i<l;i++) { 39018aa0c0cSPeter Brune dcurnorm = ngmres->xnorms[i]; 39118aa0c0cSPeter Brune if ((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm; 39218aa0c0cSPeter Brune ierr=VecAXPY(Xdot[i],1.0,XA);CHKERRQ(ierr); 39318aa0c0cSPeter Brune } 39418aa0c0cSPeter Brune } else { 39518aa0c0cSPeter Brune ierr=VecCopy(XA, D);CHKERRQ(ierr); 39618aa0c0cSPeter Brune ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr); 39718aa0c0cSPeter Brune ierr=VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr); 39818aa0c0cSPeter Brune ierr=VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 39918aa0c0cSPeter Brune ierr=VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr); 40018aa0c0cSPeter Brune ierr=VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 401f109b39eSPeter Brune dminnorm = -1.0; 40219653cdaSPeter Brune for(i=0;i<l;i++) { 403f109b39eSPeter Brune ierr=VecCopy(XA, D);CHKERRQ(ierr); 404f109b39eSPeter Brune ierr=VecAXPY(D, -1.0, Xdot[i]);CHKERRQ(ierr); 405f109b39eSPeter Brune ierr=VecNorm(D, NORM_2, &dcurnorm);CHKERRQ(ierr); 406f109b39eSPeter Brune if((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm; 40719653cdaSPeter Brune } 40818aa0c0cSPeter Brune } 40913a62661SPeter Brune } else { 41013a62661SPeter Brune ierr = VecNorm(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 41113a62661SPeter Brune } 4129f425c49SPeter Brune /* combination (additive) or selection (multiplicative) of the N-GMRES solution */ 41313a62661SPeter Brune if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) { 4149f425c49SPeter Brune /* X = X + \lambda(XA - X) */ 4159f425c49SPeter Brune if (ngmres->monitor) { 4169f425c49SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr); 4179f425c49SPeter Brune } 41813a62661SPeter Brune ierr = VecCopy(FM, F);CHKERRQ(ierr); 41913a62661SPeter Brune ierr = VecCopy(XM, X);CHKERRQ(ierr); 4209f425c49SPeter Brune ierr = VecCopy(XA, Y);CHKERRQ(ierr); 421eb1825c3SPeter Brune ierr = VecAYPX(Y, -1.0, X);CHKERRQ(ierr); 422d484d688SPeter Brune fnorm = fMnorm; 423f1c6b773SPeter Brune ierr = SNESLineSearchApply(ngmres->additive_linesearch,X,F,&fnorm,Y);CHKERRQ(ierr); 424f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(ngmres->additive_linesearch, &lssucceed);CHKERRQ(ierr); 4259f425c49SPeter Brune if (!lssucceed) { 4269f425c49SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 4279f425c49SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 4289f425c49SPeter Brune PetscFunctionReturn(0); 4299f425c49SPeter Brune } 4309f425c49SPeter Brune } 4319f425c49SPeter Brune if (ngmres->monitor) { 4329f425c49SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Additive solution: ||F||_2 = %e\n", fnorm);CHKERRQ(ierr); 4339f425c49SPeter Brune } 43413a62661SPeter Brune } else if (ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) { 4359f425c49SPeter Brune selectA = PETSC_TRUE; 4369f425c49SPeter Brune /* Conditions for choosing the accelerated answer */ 4379f425c49SPeter Brune /* Criterion A -- the norm of the function isn't increased above the minimum by too much */ 4389f425c49SPeter Brune if (fAnorm >= ngmres->gammaA*fminnorm) { 4399f425c49SPeter Brune selectA = PETSC_FALSE; 4409f425c49SPeter Brune } 4419f425c49SPeter Brune /* Criterion B -- the choice of x^A isn't too close to some other choice */ 442cf22de31SPeter Brune if (ngmres->epsilonB*dnorm<dminnorm || PetscSqrtReal(fnorm)<ngmres->deltaB*PetscSqrtReal(fminnorm)) { 44319653cdaSPeter Brune } else { 44419653cdaSPeter Brune selectA=PETSC_FALSE; 44519653cdaSPeter Brune } 44619653cdaSPeter Brune if (selectA) { 447dfbf837cSBarry Smith if (ngmres->monitor) { 4489e764e56SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_A, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr); 449dfbf837cSBarry Smith } 45098b3e84cSPeter Brune /* copy it over */ 451f109b39eSPeter Brune fnorm = fAnorm; 452f109b39eSPeter Brune nu = fnorm*fnorm; 453f109b39eSPeter Brune ierr = VecCopy(FA, F);CHKERRQ(ierr); 454f109b39eSPeter Brune ierr = VecCopy(XA, X);CHKERRQ(ierr); 45519653cdaSPeter Brune } else { 456dfbf837cSBarry Smith if (ngmres->monitor) { 457*5b0d26cfSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_M, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr); 458dfbf837cSBarry Smith } 4599f425c49SPeter Brune fnorm = fMnorm; 4609f425c49SPeter Brune nu = fnorm*fnorm; 461d484d688SPeter Brune ierr = VecCopy(XM, Y);CHKERRQ(ierr); 462d484d688SPeter Brune ierr = VecAXPY(Y,-1.0,X);CHKERRQ(ierr); 4639f425c49SPeter Brune ierr = VecCopy(FM, F);CHKERRQ(ierr); 4649f425c49SPeter Brune ierr = VecCopy(XM, X);CHKERRQ(ierr); 4659f425c49SPeter Brune } 46613a62661SPeter Brune } else { /* none */ 46713a62661SPeter Brune fnorm = fAnorm; 46813a62661SPeter Brune nu = fnorm*fnorm; 46913a62661SPeter Brune ierr = VecCopy(FA, F);CHKERRQ(ierr); 47013a62661SPeter Brune ierr = VecCopy(XA, X);CHKERRQ(ierr); 47119653cdaSPeter Brune } 472211b2d39SPeter Brune 47319653cdaSPeter Brune selectRestart = PETSC_FALSE; 47413a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) { 47598b3e84cSPeter Brune /* difference stagnation restart */ 476cf22de31SPeter Brune if((ngmres->epsilonB*dnorm > dminnorm) && (PetscSqrtReal(fAnorm) > ngmres->deltaB*PetscSqrtReal(fminnorm))) { 477dfbf837cSBarry Smith if (ngmres->monitor) { 478f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "difference restart: %e > %e\n", ngmres->epsilonB*dnorm, dminnorm);CHKERRQ(ierr); 479dfbf837cSBarry Smith } 48019653cdaSPeter Brune selectRestart = PETSC_TRUE; 48119653cdaSPeter Brune } 48298b3e84cSPeter Brune /* residual stagnation restart */ 483cf22de31SPeter Brune if (PetscSqrtReal(fAnorm) > ngmres->gammaC*PetscSqrtReal(fminnorm)) { 484dfbf837cSBarry Smith if (ngmres->monitor) { 485cf22de31SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "residual restart: %e > %e\n", PetscSqrtReal(fAnorm), ngmres->gammaC*PetscSqrtReal(fminnorm));CHKERRQ(ierr); 486dfbf837cSBarry Smith } 48719653cdaSPeter Brune selectRestart = PETSC_TRUE; 48819653cdaSPeter Brune } 48928ed4a04SPeter Brune /* if the restart conditions persist for more than restart_it iterations, restart. */ 49019653cdaSPeter Brune if (selectRestart) { 49128ed4a04SPeter Brune restart_count++; 49228ed4a04SPeter Brune } else { 49328ed4a04SPeter Brune restart_count = 0; 49428ed4a04SPeter Brune } 49513a62661SPeter Brune } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) { 49613a62661SPeter Brune if (k_restart > ngmres->restart_periodic) { 49713a62661SPeter Brune if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor, "periodic restart after %D iterations\n", k_restart);CHKERRQ(ierr); 49813a62661SPeter Brune restart_count = ngmres->restart_it; 49913a62661SPeter Brune } 50013a62661SPeter Brune } 50128ed4a04SPeter Brune /* restart after restart conditions have persisted for a fixed number of iterations */ 50228ed4a04SPeter Brune if (restart_count >= ngmres->restart_it) { 503dfbf837cSBarry Smith if (ngmres->monitor){ 504dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Restarted at iteration %d\n", k_restart);CHKERRQ(ierr); 505dfbf837cSBarry Smith } 50628ed4a04SPeter Brune restart_count = 0; 50719653cdaSPeter Brune k_restart = 1; 50819653cdaSPeter Brune l = 1; 50998b3e84cSPeter Brune /* q_{00} = nu */ 510d2e16ddcSPeter Brune if (ngmres->anderson) { 511d2e16ddcSPeter Brune ngmres->fnorms[0] = fMnorm; 512d2e16ddcSPeter Brune nu = fMnorm*fMnorm; 513d2e16ddcSPeter Brune Q(0,0) = nu; 514d2e16ddcSPeter Brune /* Fdot[0] = F */ 515d2e16ddcSPeter Brune ierr = VecCopy(XM, Xdot[0]);CHKERRQ(ierr); 516d2e16ddcSPeter Brune ierr = VecCopy(FM, Fdot[0]);CHKERRQ(ierr); 517d2e16ddcSPeter Brune } else { 518f109b39eSPeter Brune ngmres->fnorms[0] = fnorm; 519f109b39eSPeter Brune nu = fnorm*fnorm; 52019653cdaSPeter Brune Q(0,0) = nu; 521f109b39eSPeter Brune /* Fdot[0] = F */ 522f109b39eSPeter Brune ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr); 523f109b39eSPeter Brune ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr); 524d2e16ddcSPeter Brune } 52519653cdaSPeter Brune } else { 52698b3e84cSPeter Brune /* select the current size of the subspace */ 5271e633543SBarry Smith if (l < ngmres->msize) l++; 52819653cdaSPeter Brune k_restart++; 52998b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 530d2e16ddcSPeter Brune if (ngmres->anderson) { 531d2e16ddcSPeter Brune ierr = VecCopy(FM, Fdot[ivec]);CHKERRQ(ierr); 532d2e16ddcSPeter Brune ierr = VecCopy(XM, Xdot[ivec]);CHKERRQ(ierr); 533d2e16ddcSPeter Brune ngmres->fnorms[ivec] = fMnorm; 534d2e16ddcSPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of FM */ 53518aa0c0cSPeter Brune xi[ivec] = fMnorm*fMnorm; 536d2e16ddcSPeter Brune for (i = 0; i < l; i++) { 53718aa0c0cSPeter Brune Q(i, ivec) = xi[i]; 53818aa0c0cSPeter Brune Q(ivec, i) = xi[i]; 539d2e16ddcSPeter Brune } 540d2e16ddcSPeter Brune } else { 541f109b39eSPeter Brune ierr = VecCopy(F, Fdot[ivec]);CHKERRQ(ierr); 542f109b39eSPeter Brune ierr = VecCopy(X, Xdot[ivec]);CHKERRQ(ierr); 543f109b39eSPeter Brune ngmres->fnorms[ivec] = fnorm; 544d2e16ddcSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; /* the minimum norm is now of FA */ 54518aa0c0cSPeter Brune ierr = VecMDot(F, l, Fdot, xi);CHKERRQ(ierr); 54619653cdaSPeter Brune for (i = 0; i < l; i++) { 54718aa0c0cSPeter Brune Q(i, ivec) = xi[i]; 54818aa0c0cSPeter Brune Q(ivec, i) = xi[i]; 54919653cdaSPeter Brune } 55019653cdaSPeter Brune } 551d2e16ddcSPeter Brune } 55219653cdaSPeter Brune 5538409ca45SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 554087dfb9eSxuemin snes->iter = k; 555f109b39eSPeter Brune snes->norm = fnorm; 5568409ca45SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 5578409ca45SMatthew G Knepley SNESLogConvHistory(snes, snes->norm, snes->iter); 5588409ca45SMatthew G Knepley ierr = SNESMonitor(snes, snes->iter, snes->norm);CHKERRQ(ierr); 559d484d688SPeter Brune ierr = VecNormBegin(Y,NORM_2,&ynorm);CHKERRQ(ierr); 560d484d688SPeter Brune ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); 561d484d688SPeter Brune ierr = VecNormEnd(Y,NORM_2,&ynorm);CHKERRQ(ierr); 562d484d688SPeter Brune ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 563d484d688SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 564087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 565a312c225SMatthew G Knepley } 566a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 567a312c225SMatthew G Knepley PetscFunctionReturn(0); 568a312c225SMatthew G Knepley } 569a312c225SMatthew G Knepley 57013a62661SPeter Brune #undef __FUNCT__ 57113a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType" 57213a62661SPeter Brune /*@ 57313a62661SPeter Brune SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES. 57413a62661SPeter Brune 57513a62661SPeter Brune Logically Collective on SNES 57613a62661SPeter Brune 57713a62661SPeter Brune Input Parameters: 57813a62661SPeter Brune + snes - the iterative context 57913a62661SPeter Brune - rtype - restart type 58013a62661SPeter Brune 58113a62661SPeter Brune Options Database: 58213a62661SPeter Brune + -snes_ngmres_restart_type<difference,periodic,none> - set the restart type 5830c777b0cSPeter Brune - -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic 58413a62661SPeter Brune 58513a62661SPeter Brune Level: intermediate 58613a62661SPeter Brune 58713a62661SPeter Brune SNESNGMRESRestartTypes: 58813a62661SPeter Brune + SNES_NGMRES_RESTART_NONE - never restart 58913a62661SPeter Brune . SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria 59013a62661SPeter Brune - SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations 59113a62661SPeter Brune 59213a62661SPeter Brune Notes: 59313a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 59413a62661SPeter Brune 59513a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch 59613a62661SPeter Brune @*/ 59713a62661SPeter Brune PetscErrorCode SNESNGMRESSetRestartType(SNES snes, SNESNGMRESRestartType rtype) { 59813a62661SPeter Brune PetscErrorCode ierr; 59913a62661SPeter Brune PetscFunctionBegin; 60013a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 60113a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr); 60213a62661SPeter Brune PetscFunctionReturn(0); 60313a62661SPeter Brune } 60413a62661SPeter Brune 60513a62661SPeter Brune #undef __FUNCT__ 60613a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType" 60713a62661SPeter Brune /*@ 60813a62661SPeter Brune SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES. This determines how the candidate solution and 60913a62661SPeter Brune combined solution are used to create the next iterate. 61013a62661SPeter Brune 61113a62661SPeter Brune Logically Collective on SNES 61213a62661SPeter Brune 61313a62661SPeter Brune Input Parameters: 61413a62661SPeter Brune + snes - the iterative context 61513a62661SPeter Brune - stype - selection type 61613a62661SPeter Brune 61713a62661SPeter Brune Options Database: 61813a62661SPeter Brune . -snes_ngmres_select_type<difference,none,linesearch> 61913a62661SPeter Brune 62013a62661SPeter Brune Level: intermediate 62113a62661SPeter Brune 62213a62661SPeter Brune SNESNGMRESSelectTypes: 62313a62661SPeter Brune + SNES_NGMRES_SELECT_NONE - choose the combined solution all the time 62413a62661SPeter Brune . SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria 62513a62661SPeter Brune - SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination 62613a62661SPeter Brune 62713a62661SPeter Brune Notes: 62813a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 62913a62661SPeter Brune 63013a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch 63113a62661SPeter Brune @*/ 63213a62661SPeter Brune 63313a62661SPeter Brune PetscErrorCode SNESNGMRESSetSelectType(SNES snes, SNESNGMRESSelectType stype) { 63413a62661SPeter Brune PetscErrorCode ierr; 63513a62661SPeter Brune PetscFunctionBegin; 63613a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 63713a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr); 63813a62661SPeter Brune PetscFunctionReturn(0); 63913a62661SPeter Brune } 64013a62661SPeter Brune 64113a62661SPeter Brune 64213a62661SPeter Brune EXTERN_C_BEGIN 64313a62661SPeter Brune #undef __FUNCT__ 64413a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES" 64513a62661SPeter Brune 64613a62661SPeter Brune PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes, SNESNGMRESSelectType stype) { 64713a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES *)snes->data; 64813a62661SPeter Brune PetscFunctionBegin; 64913a62661SPeter Brune ngmres->select_type = stype; 65013a62661SPeter Brune PetscFunctionReturn(0); 65113a62661SPeter Brune } 65213a62661SPeter Brune 65313a62661SPeter Brune #undef __FUNCT__ 65413a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES" 65513a62661SPeter Brune 65613a62661SPeter Brune PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes, SNESNGMRESRestartType rtype) { 65713a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES *)snes->data; 65813a62661SPeter Brune PetscFunctionBegin; 65913a62661SPeter Brune ngmres->restart_type = rtype; 66013a62661SPeter Brune PetscFunctionReturn(0); 66113a62661SPeter Brune } 66213a62661SPeter Brune EXTERN_C_END 66313a62661SPeter Brune 66413a62661SPeter Brune 665dfbf837cSBarry Smith /*MC 6661867fe5bSPeter Brune SNESNGMRES - The Nonlinear Generalized Minimum Residual method. 667a312c225SMatthew G Knepley 668dfbf837cSBarry Smith Level: beginner 669dfbf837cSBarry Smith 6701867fe5bSPeter Brune Options Database: 67113a62661SPeter Brune + -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution 67213a62661SPeter Brune + -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions 67313a62661SPeter Brune . -snes_ngmres_anderson - Use Anderson mixing NGMRES variant which combines candidate solutions instead of actual solutions 67413a62661SPeter Brune . -snes_ngmres_m - Number of stored previous solutions and residuals 67513a62661SPeter Brune . -snes_ngmres_restart_it - Number of iterations the restart conditions hold before restart 67613a62661SPeter Brune . -snes_ngmres_gammaA - Residual tolerance for solution select between the candidate and combination 67713a62661SPeter Brune . -snes_ngmres_gammaC - Residual tolerance for restart 67813a62661SPeter Brune . -snes_ngmres_epsilonB - Difference tolerance between subsequent solutions triggering restart 67913a62661SPeter Brune . -snes_ngmres_deltaB - Difference tolerance between residuals triggering restart 68013a62661SPeter Brune . -snes_ngmres_monitor - Prints relevant information about the ngmres iteration 68113a62661SPeter Brune . -snes_linesearch_type <basic,basicnonorms,quadratic,critical> - Line search type used for the default smoother 68213a62661SPeter Brune - -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type 6831867fe5bSPeter Brune 6841867fe5bSPeter Brune Notes: 6851867fe5bSPeter Brune 6861867fe5bSPeter Brune The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized 6871867fe5bSPeter Brune optimization problem at each iteration. 6881867fe5bSPeter Brune 6891867fe5bSPeter Brune References: 6901867fe5bSPeter Brune 691dfbf837cSBarry Smith "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 692dfbf837cSBarry Smith SIAM Journal on Scientific Computing, 21(5), 2000. 693dfbf837cSBarry Smith 694dfbf837cSBarry Smith This is also the same as the algorithm called Anderson acceleration introduced in "D. G. Anderson. Iterative procedures for nonlinear integral equations. 695dfbf837cSBarry Smith J. Assoc. Comput. Mach., 12:547–560, 1965." 696dfbf837cSBarry Smith 697dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 698dfbf837cSBarry Smith M*/ 699a312c225SMatthew G Knepley 700a312c225SMatthew G Knepley EXTERN_C_BEGIN 701a312c225SMatthew G Knepley #undef __FUNCT__ 702a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 703a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes) 704a312c225SMatthew G Knepley { 705a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 706a312c225SMatthew G Knepley PetscErrorCode ierr; 707a312c225SMatthew G Knepley 708a312c225SMatthew G Knepley PetscFunctionBegin; 709a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 710a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 711a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 712a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 713a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 714a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 715a312c225SMatthew G Knepley 71642f4f86dSBarry Smith snes->usespc = PETSC_TRUE; 7172c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 7182c155ee1SBarry Smith 719a312c225SMatthew G Knepley ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr); 720a312c225SMatthew G Knepley snes->data = (void*) ngmres; 721d2e16ddcSPeter Brune ngmres->msize = 30; 72219653cdaSPeter Brune 72388976e71SPeter Brune if (!snes->tolerancesset) { 7240e444f03SPeter Brune snes->max_funcs = 30000; 7250e444f03SPeter Brune snes->max_its = 10000; 72688976e71SPeter Brune } 7270e444f03SPeter Brune 728d2e16ddcSPeter Brune ngmres->anderson = PETSC_FALSE; 729d2e16ddcSPeter Brune 730e7058c64SPeter Brune ngmres->additive_linesearch = PETSC_NULL; 731e7058c64SPeter Brune 73228ed4a04SPeter Brune ngmres->restart_it = 2; 73313a62661SPeter Brune ngmres->restart_periodic = 30; 734f109b39eSPeter Brune ngmres->gammaA = 2.0; 735f109b39eSPeter Brune ngmres->gammaC = 2.0; 736cac108bcSPeter Brune ngmres->deltaB = 0.9; 737cac108bcSPeter Brune ngmres->epsilonB = 0.1; 738e7058c64SPeter Brune 73913a62661SPeter Brune ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE; 74013a62661SPeter Brune ngmres->select_type = SNES_NGMRES_SELECT_DIFFERENCE; 74113a62661SPeter Brune 74213a62661SPeter Brune ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNGMRESSetSelectType_C","SNESNGMRESSetSelectType_NGMRES", SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr); 74313a62661SPeter Brune ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNGMRESSetRestartType_C","SNESNGMRESSetRestartType_NGMRES", SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr); 74413a62661SPeter Brune 745a312c225SMatthew G Knepley PetscFunctionReturn(0); 746a312c225SMatthew G Knepley } 747a312c225SMatthew G Knepley EXTERN_C_END 748