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); 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 3522d28d08SBarry Smith ierr = PetscFree(ngmres->rwork);CHKERRQ(ierr); 3619653cdaSPeter Brune #endif 3722d28d08SBarry Smith ierr = PetscFree(ngmres->work);CHKERRQ(ierr); 3822d28d08SBarry Smith ierr = PetscFree(snes->data);CHKERRQ(ierr); 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 7822d28d08SBarry Smith ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork);CHKERRQ(ierr); 7919653cdaSPeter Brune #endif 8022d28d08SBarry Smith ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work);CHKERRQ(ierr); 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; 1070adebc6cSBarry Smith 108a312c225SMatthew G Knepley PetscFunctionBegin; 109a312c225SMatthew G Knepley ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr); 11013a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes, 11113a62661SPeter Brune (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,PETSC_NULL);CHKERRQ(ierr); 11213a62661SPeter Brune ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes, 11313a62661SPeter Brune (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,PETSC_NULL);CHKERRQ(ierr); 114d2e16ddcSPeter Brune ierr = PetscOptionsBool("-snes_ngmres_anderson", "Use Anderson mixing storage", "SNES", ngmres->anderson, &ngmres->anderson, PETSC_NULL);CHKERRQ(ierr); 11519653cdaSPeter Brune ierr = PetscOptionsInt("-snes_ngmres_m", "Number of directions", "SNES", ngmres->msize, &ngmres->msize, PETSC_NULL);CHKERRQ(ierr); 1160c777b0cSPeter Brune ierr = PetscOptionsInt("-snes_ngmres_restart", "Iterations before forced restart", "SNES", ngmres->restart_periodic, &ngmres->restart_periodic, PETSC_NULL);CHKERRQ(ierr); 11728ed4a04SPeter Brune ierr = PetscOptionsInt("-snes_ngmres_restart_it","Tolerance iterations before restart","SNES", ngmres->restart_it, &ngmres->restart_it, PETSC_NULL);CHKERRQ(ierr); 118dfbf837cSBarry Smith ierr = PetscOptionsBool("-snes_ngmres_monitor", "Monitor actions of NGMRES", "SNES", ngmres->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);CHKERRQ(ierr); 119dfbf837cSBarry Smith if (debug) { 120dfbf837cSBarry Smith ngmres->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 121dfbf837cSBarry Smith } 1226a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_gammaA", "Residual selection constant", "SNES", ngmres->gammaA, &ngmres->gammaA, PETSC_NULL);CHKERRQ(ierr); 1236a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_gammaC", " Residual restart constant", "SNES", ngmres->gammaC, &ngmres->gammaC, PETSC_NULL);CHKERRQ(ierr); 1246a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES", ngmres->epsilonB, &ngmres->epsilonB, PETSC_NULL);CHKERRQ(ierr); 1256a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_deltaB", "Difference residual selection constant", "SNES", ngmres->deltaB, &ngmres->deltaB, PETSC_NULL);CHKERRQ(ierr); 1264d116c7dSPeter Brune ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions", "SNES", ngmres->singlereduction, &ngmres->singlereduction, PETSC_NULL);CHKERRQ(ierr); 127a312c225SMatthew G Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1286a7cf640SPeter Brune if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA; 1299e764e56SPeter Brune 1309e764e56SPeter Brune /* set the default type of the line search if the user hasn't already. */ 1319e764e56SPeter Brune if (!snes->linesearch) { 132f1c6b773SPeter Brune ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr); 1331a4f838cSPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC);CHKERRQ(ierr); 1349e764e56SPeter Brune } 135a312c225SMatthew G Knepley PetscFunctionReturn(0); 136a312c225SMatthew G Knepley } 137a312c225SMatthew G Knepley 138a312c225SMatthew G Knepley #undef __FUNCT__ 139a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES" 140a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes, PetscViewer viewer) 141a312c225SMatthew G Knepley { 142a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 143a312c225SMatthew G Knepley PetscBool iascii; 144a312c225SMatthew G Knepley PetscErrorCode ierr; 145a312c225SMatthew G Knepley 146a312c225SMatthew G Knepley PetscFunctionBegin; 147251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 148a312c225SMatthew G Knepley if (iascii) { 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" 158a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes) 159a312c225SMatthew G Knepley { 160087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 16198b3e84cSPeter Brune /* present solution, residual, and preconditioned residual */ 1629f425c49SPeter Brune Vec X, F, B, D, Y; 163f109b39eSPeter Brune 164f109b39eSPeter Brune /* candidate linear combination answers */ 1654b32a720SPeter Brune Vec XA, FA, XM, FM, FPC; 16619653cdaSPeter Brune 16798b3e84cSPeter Brune /* previous iterations to construct the subspace */ 168f109b39eSPeter Brune Vec *Fdot = ngmres->Fdot; 169f109b39eSPeter Brune Vec *Xdot = ngmres->Xdot; 17019653cdaSPeter Brune 17198b3e84cSPeter Brune /* coefficients and RHS to the minimization problem */ 17219653cdaSPeter Brune PetscScalar *beta = ngmres->beta; 17319653cdaSPeter Brune PetscScalar *xi = ngmres->xi; 17418aa0c0cSPeter Brune PetscReal fnorm, fMnorm, fAnorm; 17519653cdaSPeter Brune PetscReal nu; 17619653cdaSPeter Brune PetscScalar alph_total = 0.; 17728ed4a04SPeter Brune PetscInt i, j, k, k_restart, l, ivec, restart_count = 0; 17819653cdaSPeter Brune 17998b3e84cSPeter Brune /* solution selection data */ 18019653cdaSPeter Brune PetscBool selectA, selectRestart; 18174b542b2SMatthew G Knepley PetscReal dnorm, dminnorm = 0.0, dcurnorm; 182d484d688SPeter Brune PetscReal fminnorm,xnorm,ynorm; 18319653cdaSPeter Brune 1841e633543SBarry Smith SNESConvergedReason reason; 1856e733865SPeter Brune PetscBool lssucceed,changed_y,changed_w; 186a312c225SMatthew G Knepley PetscErrorCode ierr; 187a312c225SMatthew G Knepley 188a312c225SMatthew G Knepley PetscFunctionBegin; 18998b3e84cSPeter Brune /* variable initialization */ 190a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 191f109b39eSPeter Brune X = snes->vec_sol; 192f109b39eSPeter Brune F = snes->vec_func; 193f109b39eSPeter Brune B = snes->vec_rhs; 194f109b39eSPeter Brune XA = snes->vec_sol_update; 195f109b39eSPeter Brune FA = snes->work[0]; 196f109b39eSPeter Brune D = snes->work[1]; 197f109b39eSPeter Brune 198f109b39eSPeter Brune /* work for the line search */ 199f109b39eSPeter Brune Y = snes->work[2]; 2009f425c49SPeter Brune XM = snes->work[3]; 2019f425c49SPeter Brune FM = snes->work[4]; 202a312c225SMatthew G Knepley 203a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 204a312c225SMatthew G Knepley snes->iter = 0; 205a312c225SMatthew G Knepley snes->norm = 0.; 206a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 20719653cdaSPeter Brune 20898b3e84cSPeter Brune /* initialization */ 20919653cdaSPeter Brune 21098b3e84cSPeter Brune /* r = F(x) */ 211e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 212f109b39eSPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 213a312c225SMatthew G Knepley if (snes->domainerror) { 214a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 215a312c225SMatthew G Knepley PetscFunctionReturn(0); 216a312c225SMatthew G Knepley } 217e4ed7901SPeter Brune } else { 218e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 219e4ed7901SPeter Brune } 22019653cdaSPeter Brune 221e4ed7901SPeter Brune if (!snes->norm_init_set) { 222f109b39eSPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 223b707f0f7SPeter Brune if (PetscIsInfOrNanReal(fnorm)) SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation"); 224e4ed7901SPeter Brune } else { 225e4ed7901SPeter Brune fnorm = snes->norm_init; 226e4ed7901SPeter Brune snes->norm_init_set = PETSC_FALSE; 227e4ed7901SPeter Brune } 228e4ed7901SPeter Brune fminnorm = fnorm; 229e4ed7901SPeter Brune /* nu = (r, r) */ 230e4ed7901SPeter Brune nu = fnorm*fnorm; 23119653cdaSPeter Brune 23298b3e84cSPeter Brune /* q_{00} = nu */ 23319653cdaSPeter Brune Q(0,0) = nu; 234f109b39eSPeter Brune ngmres->fnorms[0] = fnorm; 235f109b39eSPeter Brune /* Fdot[0] = F */ 236f109b39eSPeter Brune ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr); 237f109b39eSPeter Brune ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr); 238087dfb9eSxuemin 239a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 240f109b39eSPeter Brune snes->norm = fnorm; 241a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 242f109b39eSPeter Brune SNESLogConvHistory(snes, fnorm, 0); 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 } 2684b32a720SPeter Brune ierr = SNESGetFunction(snes->pc, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 2694b32a720SPeter Brune ierr = VecCopy(FPC, FM);CHKERRQ(ierr); 2704b32a720SPeter Brune ierr = SNESGetFunctionNorm(snes->pc, &fMnorm);CHKERRQ(ierr); 2718cc86e31SPeter Brune } else { 272f109b39eSPeter Brune /* no preconditioner -- just take gradient descent with line search */ 273f109b39eSPeter Brune ierr = VecCopy(F, Y);CHKERRQ(ierr); 274e7058c64SPeter Brune ierr = VecCopy(F, FM);CHKERRQ(ierr); 275e7058c64SPeter Brune ierr = VecCopy(X, XM);CHKERRQ(ierr); 276e7058c64SPeter Brune fMnorm = fnorm; 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 } 2861e633543SBarry Smith 28798b3e84cSPeter Brune /* r = F(x) */ 2889f425c49SPeter Brune nu = fMnorm*fMnorm; 2899f425c49SPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of F^M */ 29019653cdaSPeter Brune 29198b3e84cSPeter Brune /* construct the right hand side and xi factors */ 2928c09b6b7SPeter Brune ierr = VecMDot(FM, l, Fdot, xi);CHKERRQ(ierr); 2938c09b6b7SPeter Brune 29419653cdaSPeter Brune for (i = 0; i < l; i++) { 29519653cdaSPeter Brune beta[i] = nu - xi[i]; 29619653cdaSPeter Brune } 29719653cdaSPeter Brune 29898b3e84cSPeter Brune /* construct h */ 29919653cdaSPeter Brune for (j = 0; j < l; j++) { 30019653cdaSPeter Brune for (i = 0; i < l; i++) { 30119653cdaSPeter Brune H(i, j) = Q(i, j) - xi[i] - xi[j] + nu; 30219653cdaSPeter Brune } 30319653cdaSPeter Brune } 304f109b39eSPeter Brune 305f109b39eSPeter Brune if (l == 1) { 306f109b39eSPeter Brune /* simply set alpha[0] = beta[0] / H[0, 0] */ 307bf08dd53SPeter Brune if (H(0, 0) != 0.) { 308f109b39eSPeter Brune beta[0] = beta[0] / H(0, 0); 309f109b39eSPeter Brune } else { 310bf08dd53SPeter Brune beta[0] = 0.; 311bf08dd53SPeter Brune } 312bf08dd53SPeter Brune } else { 313519f805aSKarl Rupp #if defined(PETSC_MISSING_LAPACK_GELSS) 314b707f0f7SPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_SUP, "NGMRES with LS requires the LAPACK GELSS routine."); 3154a0c5b0cSMatthew G Knepley #else 316*c5df96a5SBarry Smith ierr = PetscBLASIntCast(l,&ngmres->m);CHKERRQ(ierr); 317*c5df96a5SBarry Smith ierr = PetscBLASIntCast(l,&ngmres->n);CHKERRQ(ierr); 318*c5df96a5SBarry Smith ngmres->info = 0; 31919653cdaSPeter Brune ngmres->rcond = -1.; 3208e57ea43SSatish Balay ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 321519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 322*c5df96a5SBarry Smith LAPACKgelss_(&ngmres->m,&ngmres->n,&ngmres->nrhs,ngmres->h,&ngmres->lda,ngmres->beta,&ngmres->ldb,ngmres->s,&ngmres->rcond, 323*c5df96a5SBarry Smith &ngmres->rank,ngmres->work,&ngmres->lwork,ngmres->rwork,&ngmres->info); 32419653cdaSPeter Brune #else 325*c5df96a5SBarry Smith LAPACKgelss_(&ngmres->m,&ngmres->n,&ngmres->nrhs,ngmres->h,&ngmres->lda,ngmres->beta,&ngmres->ldb,ngmres->s,&ngmres->rcond, 326*c5df96a5SBarry Smith &ngmres->rank,ngmres->work,&ngmres->lwork,&ngmres->info); 32719653cdaSPeter Brune #endif 3288e57ea43SSatish Balay ierr = PetscFPTrapPop();CHKERRQ(ierr); 329b707f0f7SPeter Brune if (ngmres->info < 0) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_LIB,"Bad argument to GELSS"); 330b707f0f7SPeter Brune if (ngmres->info > 0) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_LIB,"SVD failed to converge"); 331a312c225SMatthew G Knepley #endif 332f109b39eSPeter Brune } 333a312c225SMatthew G Knepley 334b707f0f7SPeter Brune for (i=0;i<l;i++) { 335f23aa3ddSBarry Smith if (PetscIsInfOrNanScalar(beta[i])) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_LIB,"SVD generated inconsistent output: NaN or Inf"); 336b707f0f7SPeter Brune } 337b707f0f7SPeter Brune 33819653cdaSPeter Brune alph_total = 0.; 33919653cdaSPeter Brune for (i = 0; i < l; i++) { 34019653cdaSPeter Brune alph_total += beta[i]; 341c0bbabecSxuemin } 342f109b39eSPeter Brune 3439f425c49SPeter Brune ierr = VecCopy(XM, XA);CHKERRQ(ierr); 344f109b39eSPeter Brune ierr = VecScale(XA, 1. - alph_total);CHKERRQ(ierr); 345087dfb9eSxuemin 3468c09b6b7SPeter Brune ierr = VecMAXPY(XA, l, beta, Xdot);CHKERRQ(ierr); 3476e733865SPeter Brune 3486e733865SPeter Brune /* check the validity of the step */ 349f89ba88eSPeter Brune ierr = VecCopy(XA,Y);CHKERRQ(ierr); 3506e733865SPeter Brune ierr = VecAXPY(Y,-1.0,X);CHKERRQ(ierr); 3516e733865SPeter Brune ierr = SNESLineSearchPostCheck(snes->linesearch,X,Y,XA,&changed_y,&changed_w);CHKERRQ(ierr); 352f109b39eSPeter Brune ierr = SNESComputeFunction(snes, XA, FA);CHKERRQ(ierr); 35319653cdaSPeter Brune 3549f425c49SPeter Brune /* differences for selection and restart */ 35513a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) { 35618aa0c0cSPeter Brune if (ngmres->singlereduction) { 35718aa0c0cSPeter Brune dminnorm = -1.0; 358f109b39eSPeter Brune ierr=VecCopy(XA, D);CHKERRQ(ierr); 35918aa0c0cSPeter Brune ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr); 36018aa0c0cSPeter Brune for (i=0;i<l;i++) { 36118aa0c0cSPeter Brune ierr=VecAXPY(Xdot[i],-1.0,XA);CHKERRQ(ierr); 36218aa0c0cSPeter Brune } 36318aa0c0cSPeter Brune ierr = VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 36418aa0c0cSPeter Brune ierr = VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr); 36518aa0c0cSPeter Brune for (i=0;i<l;i++) { 36618aa0c0cSPeter Brune ierr = VecNormBegin(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr); 36718aa0c0cSPeter Brune } 36818aa0c0cSPeter Brune ierr = VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 36918aa0c0cSPeter Brune ierr = VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr); 37018aa0c0cSPeter Brune for (i=0;i<l;i++) { 37118aa0c0cSPeter Brune ierr = VecNormEnd(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr); 37218aa0c0cSPeter Brune } 37318aa0c0cSPeter Brune for (i=0;i<l;i++) { 37418aa0c0cSPeter Brune dcurnorm = ngmres->xnorms[i]; 37518aa0c0cSPeter Brune if ((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm; 37618aa0c0cSPeter Brune ierr=VecAXPY(Xdot[i],1.0,XA);CHKERRQ(ierr); 37718aa0c0cSPeter Brune } 37818aa0c0cSPeter Brune } else { 37918aa0c0cSPeter Brune ierr=VecCopy(XA, D);CHKERRQ(ierr); 38018aa0c0cSPeter Brune ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr); 38118aa0c0cSPeter Brune ierr=VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr); 38218aa0c0cSPeter Brune ierr=VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 38318aa0c0cSPeter Brune ierr=VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr); 38418aa0c0cSPeter Brune ierr=VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 385f109b39eSPeter Brune dminnorm = -1.0; 38619653cdaSPeter Brune for (i=0;i<l;i++) { 387f109b39eSPeter Brune ierr=VecCopy(XA, D);CHKERRQ(ierr); 388f109b39eSPeter Brune ierr=VecAXPY(D, -1.0, Xdot[i]);CHKERRQ(ierr); 389f109b39eSPeter Brune ierr=VecNorm(D, NORM_2, &dcurnorm);CHKERRQ(ierr); 390f109b39eSPeter Brune if ((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm; 39119653cdaSPeter Brune } 39218aa0c0cSPeter Brune } 39313a62661SPeter Brune } else { 39413a62661SPeter Brune ierr = VecNorm(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 39513a62661SPeter Brune } 396b707f0f7SPeter Brune if (PetscIsInfOrNanReal(fAnorm)) SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation"); 3979f425c49SPeter Brune /* combination (additive) or selection (multiplicative) of the N-GMRES solution */ 39813a62661SPeter Brune if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) { 3999f425c49SPeter Brune /* X = X + \lambda(XA - X) */ 4009f425c49SPeter Brune if (ngmres->monitor) { 4019f425c49SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr); 4029f425c49SPeter Brune } 40313a62661SPeter Brune ierr = VecCopy(FM, F);CHKERRQ(ierr); 40413a62661SPeter Brune ierr = VecCopy(XM, X);CHKERRQ(ierr); 4059f425c49SPeter Brune ierr = VecCopy(XA, Y);CHKERRQ(ierr); 406eb1825c3SPeter Brune ierr = VecAYPX(Y, -1.0, X);CHKERRQ(ierr); 407d484d688SPeter Brune fnorm = fMnorm; 408f1c6b773SPeter Brune ierr = SNESLineSearchApply(ngmres->additive_linesearch,X,F,&fnorm,Y);CHKERRQ(ierr); 409f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(ngmres->additive_linesearch, &lssucceed);CHKERRQ(ierr); 4109f425c49SPeter Brune if (!lssucceed) { 4119f425c49SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 4129f425c49SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 4139f425c49SPeter Brune PetscFunctionReturn(0); 4149f425c49SPeter Brune } 4159f425c49SPeter Brune } 4169f425c49SPeter Brune if (ngmres->monitor) { 4179f425c49SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Additive solution: ||F||_2 = %e\n", fnorm);CHKERRQ(ierr); 4189f425c49SPeter Brune } 41913a62661SPeter Brune } else if (ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) { 4209f425c49SPeter Brune selectA = PETSC_TRUE; 4219f425c49SPeter Brune /* Conditions for choosing the accelerated answer */ 4229f425c49SPeter Brune /* Criterion A -- the norm of the function isn't increased above the minimum by too much */ 4239f425c49SPeter Brune if (fAnorm >= ngmres->gammaA*fminnorm) { 4249f425c49SPeter Brune selectA = PETSC_FALSE; 4259f425c49SPeter Brune } 4269f425c49SPeter Brune /* Criterion B -- the choice of x^A isn't too close to some other choice */ 427cf22de31SPeter Brune if (ngmres->epsilonB*dnorm<dminnorm || PetscSqrtReal(fnorm)<ngmres->deltaB*PetscSqrtReal(fminnorm)) { 42819653cdaSPeter Brune } else { 42919653cdaSPeter Brune selectA=PETSC_FALSE; 43019653cdaSPeter Brune } 43119653cdaSPeter Brune if (selectA) { 432dfbf837cSBarry Smith if (ngmres->monitor) { 4339e764e56SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_A, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr); 434dfbf837cSBarry Smith } 43598b3e84cSPeter Brune /* copy it over */ 436f109b39eSPeter Brune fnorm = fAnorm; 437f109b39eSPeter Brune nu = fnorm*fnorm; 438f109b39eSPeter Brune ierr = VecCopy(FA, F);CHKERRQ(ierr); 439f109b39eSPeter Brune ierr = VecCopy(XA, X);CHKERRQ(ierr); 44019653cdaSPeter Brune } else { 441dfbf837cSBarry Smith if (ngmres->monitor) { 4425b0d26cfSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_M, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr); 443dfbf837cSBarry Smith } 4449f425c49SPeter Brune fnorm = fMnorm; 4459f425c49SPeter Brune nu = fnorm*fnorm; 446d484d688SPeter Brune ierr = VecCopy(XM, Y);CHKERRQ(ierr); 447d484d688SPeter Brune ierr = VecAXPY(Y,-1.0,X);CHKERRQ(ierr); 4489f425c49SPeter Brune ierr = VecCopy(FM, F);CHKERRQ(ierr); 4499f425c49SPeter Brune ierr = VecCopy(XM, X);CHKERRQ(ierr); 4509f425c49SPeter Brune } 45113a62661SPeter Brune } else { /* none */ 45213a62661SPeter Brune fnorm = fAnorm; 45313a62661SPeter Brune nu = fnorm*fnorm; 45413a62661SPeter Brune ierr = VecCopy(FA, F);CHKERRQ(ierr); 45513a62661SPeter Brune ierr = VecCopy(XA, X);CHKERRQ(ierr); 45619653cdaSPeter Brune } 457211b2d39SPeter Brune 45819653cdaSPeter Brune selectRestart = PETSC_FALSE; 45913a62661SPeter Brune if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) { 46098b3e84cSPeter Brune /* difference stagnation restart */ 461cf22de31SPeter Brune if ((ngmres->epsilonB*dnorm > dminnorm) && (PetscSqrtReal(fAnorm) > ngmres->deltaB*PetscSqrtReal(fminnorm))) { 462dfbf837cSBarry Smith if (ngmres->monitor) { 463f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "difference restart: %e > %e\n", ngmres->epsilonB*dnorm, dminnorm);CHKERRQ(ierr); 464dfbf837cSBarry Smith } 46519653cdaSPeter Brune selectRestart = PETSC_TRUE; 46619653cdaSPeter Brune } 46798b3e84cSPeter Brune /* residual stagnation restart */ 468cf22de31SPeter Brune if (PetscSqrtReal(fAnorm) > ngmres->gammaC*PetscSqrtReal(fminnorm)) { 469dfbf837cSBarry Smith if (ngmres->monitor) { 470cf22de31SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "residual restart: %e > %e\n", PetscSqrtReal(fAnorm), ngmres->gammaC*PetscSqrtReal(fminnorm));CHKERRQ(ierr); 471dfbf837cSBarry Smith } 47219653cdaSPeter Brune selectRestart = PETSC_TRUE; 47319653cdaSPeter Brune } 47428ed4a04SPeter Brune /* if the restart conditions persist for more than restart_it iterations, restart. */ 47519653cdaSPeter Brune if (selectRestart) { 47628ed4a04SPeter Brune restart_count++; 47728ed4a04SPeter Brune } else { 47828ed4a04SPeter Brune restart_count = 0; 47928ed4a04SPeter Brune } 48013a62661SPeter Brune } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) { 48113a62661SPeter Brune if (k_restart > ngmres->restart_periodic) { 48213a62661SPeter Brune if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor, "periodic restart after %D iterations\n", k_restart);CHKERRQ(ierr); 48313a62661SPeter Brune restart_count = ngmres->restart_it; 48413a62661SPeter Brune } 48513a62661SPeter Brune } 48628ed4a04SPeter Brune /* restart after restart conditions have persisted for a fixed number of iterations */ 48728ed4a04SPeter Brune if (restart_count >= ngmres->restart_it) { 488dfbf837cSBarry Smith if (ngmres->monitor) { 489dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Restarted at iteration %d\n", k_restart);CHKERRQ(ierr); 490dfbf837cSBarry Smith } 49128ed4a04SPeter Brune restart_count = 0; 49219653cdaSPeter Brune k_restart = 1; 49319653cdaSPeter Brune l = 1; 49498b3e84cSPeter Brune /* q_{00} = nu */ 495d2e16ddcSPeter Brune if (ngmres->anderson) { 496d2e16ddcSPeter Brune ngmres->fnorms[0] = fMnorm; 497d2e16ddcSPeter Brune nu = fMnorm*fMnorm; 498d2e16ddcSPeter Brune Q(0,0) = nu; 499d2e16ddcSPeter Brune /* Fdot[0] = F */ 500d2e16ddcSPeter Brune ierr = VecCopy(XM, Xdot[0]);CHKERRQ(ierr); 501d2e16ddcSPeter Brune ierr = VecCopy(FM, Fdot[0]);CHKERRQ(ierr); 502d2e16ddcSPeter Brune } else { 503f109b39eSPeter Brune ngmres->fnorms[0] = fnorm; 504f109b39eSPeter Brune nu = fnorm*fnorm; 50519653cdaSPeter Brune Q(0,0) = nu; 506f109b39eSPeter Brune /* Fdot[0] = F */ 507f109b39eSPeter Brune ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr); 508f109b39eSPeter Brune ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr); 509d2e16ddcSPeter Brune } 51019653cdaSPeter Brune } else { 51198b3e84cSPeter Brune /* select the current size of the subspace */ 5121e633543SBarry Smith if (l < ngmres->msize) l++; 51319653cdaSPeter Brune k_restart++; 51498b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 515d2e16ddcSPeter Brune if (ngmres->anderson) { 516d2e16ddcSPeter Brune ierr = VecCopy(FM, Fdot[ivec]);CHKERRQ(ierr); 517d2e16ddcSPeter Brune ierr = VecCopy(XM, Xdot[ivec]);CHKERRQ(ierr); 518d2e16ddcSPeter Brune ngmres->fnorms[ivec] = fMnorm; 519d2e16ddcSPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of FM */ 52018aa0c0cSPeter Brune xi[ivec] = fMnorm*fMnorm; 521d2e16ddcSPeter Brune for (i = 0; i < l; i++) { 52218aa0c0cSPeter Brune Q(i, ivec) = xi[i]; 52318aa0c0cSPeter Brune Q(ivec, i) = xi[i]; 524d2e16ddcSPeter Brune } 525d2e16ddcSPeter Brune } else { 526f109b39eSPeter Brune ierr = VecCopy(F, Fdot[ivec]);CHKERRQ(ierr); 527f109b39eSPeter Brune ierr = VecCopy(X, Xdot[ivec]);CHKERRQ(ierr); 528f109b39eSPeter Brune ngmres->fnorms[ivec] = fnorm; 529d2e16ddcSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; /* the minimum norm is now of FA */ 53018aa0c0cSPeter Brune ierr = VecMDot(F, l, Fdot, xi);CHKERRQ(ierr); 53119653cdaSPeter Brune for (i = 0; i < l; i++) { 53218aa0c0cSPeter Brune Q(i, ivec) = xi[i]; 53318aa0c0cSPeter Brune Q(ivec, i) = xi[i]; 53419653cdaSPeter Brune } 53519653cdaSPeter Brune } 536d2e16ddcSPeter Brune } 53719653cdaSPeter Brune 5388409ca45SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 539087dfb9eSxuemin snes->iter = k; 540f109b39eSPeter Brune snes->norm = fnorm; 5418409ca45SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 5428409ca45SMatthew G Knepley SNESLogConvHistory(snes, snes->norm, snes->iter); 5438409ca45SMatthew G Knepley ierr = SNESMonitor(snes, snes->iter, snes->norm);CHKERRQ(ierr); 544d484d688SPeter Brune ierr = VecNormBegin(Y,NORM_2,&ynorm);CHKERRQ(ierr); 545d484d688SPeter Brune ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr); 546d484d688SPeter Brune ierr = VecNormEnd(Y,NORM_2,&ynorm);CHKERRQ(ierr); 547d484d688SPeter Brune ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr); 548d484d688SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 549087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 550a312c225SMatthew G Knepley } 551a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 552a312c225SMatthew G Knepley PetscFunctionReturn(0); 553a312c225SMatthew G Knepley } 554a312c225SMatthew G Knepley 55513a62661SPeter Brune #undef __FUNCT__ 55613a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType" 55713a62661SPeter Brune /*@ 55813a62661SPeter Brune SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES. 55913a62661SPeter Brune 56013a62661SPeter Brune Logically Collective on SNES 56113a62661SPeter Brune 56213a62661SPeter Brune Input Parameters: 56313a62661SPeter Brune + snes - the iterative context 56413a62661SPeter Brune - rtype - restart type 56513a62661SPeter Brune 56613a62661SPeter Brune Options Database: 56713a62661SPeter Brune + -snes_ngmres_restart_type<difference,periodic,none> - set the restart type 5680c777b0cSPeter Brune - -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic 56913a62661SPeter Brune 57013a62661SPeter Brune Level: intermediate 57113a62661SPeter Brune 57213a62661SPeter Brune SNESNGMRESRestartTypes: 57313a62661SPeter Brune + SNES_NGMRES_RESTART_NONE - never restart 57413a62661SPeter Brune . SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria 57513a62661SPeter Brune - SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations 57613a62661SPeter Brune 57713a62661SPeter Brune Notes: 57813a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 57913a62661SPeter Brune 58013a62661SPeter Brune .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch 58113a62661SPeter Brune @*/ 5820adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType(SNES snes, SNESNGMRESRestartType rtype) 5830adebc6cSBarry Smith { 58413a62661SPeter Brune PetscErrorCode ierr; 58513a62661SPeter Brune PetscFunctionBegin; 58613a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 58713a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr); 58813a62661SPeter Brune PetscFunctionReturn(0); 58913a62661SPeter Brune } 59013a62661SPeter Brune 59113a62661SPeter Brune #undef __FUNCT__ 59213a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType" 59313a62661SPeter Brune /*@ 59413a62661SPeter Brune SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES. This determines how the candidate solution and 59513a62661SPeter Brune combined solution are used to create the next iterate. 59613a62661SPeter Brune 59713a62661SPeter Brune Logically Collective on SNES 59813a62661SPeter Brune 59913a62661SPeter Brune Input Parameters: 60013a62661SPeter Brune + snes - the iterative context 60113a62661SPeter Brune - stype - selection type 60213a62661SPeter Brune 60313a62661SPeter Brune Options Database: 60413a62661SPeter Brune . -snes_ngmres_select_type<difference,none,linesearch> 60513a62661SPeter Brune 60613a62661SPeter Brune Level: intermediate 60713a62661SPeter Brune 60813a62661SPeter Brune SNESNGMRESSelectTypes: 60913a62661SPeter Brune + SNES_NGMRES_SELECT_NONE - choose the combined solution all the time 61013a62661SPeter Brune . SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria 61113a62661SPeter Brune - SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination 61213a62661SPeter Brune 61313a62661SPeter Brune Notes: 61413a62661SPeter Brune The default line search used is the L2 line search and it requires two additional function evaluations. 61513a62661SPeter Brune 61613a62661SPeter Brune .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch 61713a62661SPeter Brune @*/ 6180adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType(SNES snes, SNESNGMRESSelectType stype) 6190adebc6cSBarry Smith { 62013a62661SPeter Brune PetscErrorCode ierr; 62113a62661SPeter Brune PetscFunctionBegin; 62213a62661SPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 62313a62661SPeter Brune ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr); 62413a62661SPeter Brune PetscFunctionReturn(0); 62513a62661SPeter Brune } 62613a62661SPeter Brune 62713a62661SPeter Brune EXTERN_C_BEGIN 62813a62661SPeter Brune #undef __FUNCT__ 62913a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES" 6300adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes, SNESNGMRESSelectType stype) 6310adebc6cSBarry Smith { 63213a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES *)snes->data; 63313a62661SPeter Brune PetscFunctionBegin; 63413a62661SPeter Brune ngmres->select_type = stype; 63513a62661SPeter Brune PetscFunctionReturn(0); 63613a62661SPeter Brune } 63713a62661SPeter Brune 63813a62661SPeter Brune #undef __FUNCT__ 63913a62661SPeter Brune #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES" 6400adebc6cSBarry Smith PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes, SNESNGMRESRestartType rtype) 6410adebc6cSBarry Smith { 64213a62661SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES *)snes->data; 64313a62661SPeter Brune PetscFunctionBegin; 64413a62661SPeter Brune ngmres->restart_type = rtype; 64513a62661SPeter Brune PetscFunctionReturn(0); 64613a62661SPeter Brune } 64713a62661SPeter Brune EXTERN_C_END 64813a62661SPeter Brune 649dfbf837cSBarry Smith /*MC 6501867fe5bSPeter Brune SNESNGMRES - The Nonlinear Generalized Minimum Residual method. 651a312c225SMatthew G Knepley 652dfbf837cSBarry Smith Level: beginner 653dfbf837cSBarry Smith 6541867fe5bSPeter Brune Options Database: 65513a62661SPeter Brune + -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution 65613a62661SPeter Brune + -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions 65713a62661SPeter Brune . -snes_ngmres_anderson - Use Anderson mixing NGMRES variant which combines candidate solutions instead of actual solutions 65813a62661SPeter Brune . -snes_ngmres_m - Number of stored previous solutions and residuals 65913a62661SPeter Brune . -snes_ngmres_restart_it - Number of iterations the restart conditions hold before restart 66013a62661SPeter Brune . -snes_ngmres_gammaA - Residual tolerance for solution select between the candidate and combination 66113a62661SPeter Brune . -snes_ngmres_gammaC - Residual tolerance for restart 66213a62661SPeter Brune . -snes_ngmres_epsilonB - Difference tolerance between subsequent solutions triggering restart 66313a62661SPeter Brune . -snes_ngmres_deltaB - Difference tolerance between residuals triggering restart 66413a62661SPeter Brune . -snes_ngmres_monitor - Prints relevant information about the ngmres iteration 66513a62661SPeter Brune . -snes_linesearch_type <basic,basicnonorms,quadratic,critical> - Line search type used for the default smoother 66613a62661SPeter Brune - -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type 6671867fe5bSPeter Brune 6681867fe5bSPeter Brune Notes: 6691867fe5bSPeter Brune 6701867fe5bSPeter Brune The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized 6711867fe5bSPeter Brune optimization problem at each iteration. 6721867fe5bSPeter Brune 6731867fe5bSPeter Brune References: 6741867fe5bSPeter Brune 675dfbf837cSBarry Smith "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 676dfbf837cSBarry Smith SIAM Journal on Scientific Computing, 21(5), 2000. 677dfbf837cSBarry Smith 678dfbf837cSBarry Smith This is also the same as the algorithm called Anderson acceleration introduced in "D. G. Anderson. Iterative procedures for nonlinear integral equations. 679dfbf837cSBarry Smith J. Assoc. Comput. Mach., 12:547–560, 1965." 680dfbf837cSBarry Smith 681dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 682dfbf837cSBarry Smith M*/ 683a312c225SMatthew G Knepley 684a312c225SMatthew G Knepley EXTERN_C_BEGIN 685a312c225SMatthew G Knepley #undef __FUNCT__ 686a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 687a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes) 688a312c225SMatthew G Knepley { 689a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 690a312c225SMatthew G Knepley PetscErrorCode ierr; 691a312c225SMatthew G Knepley 692a312c225SMatthew G Knepley PetscFunctionBegin; 693a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 694a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 695a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 696a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 697a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 698a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 699a312c225SMatthew G Knepley 70042f4f86dSBarry Smith snes->usespc = PETSC_TRUE; 7012c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 7022c155ee1SBarry Smith 703a312c225SMatthew G Knepley ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr); 704a312c225SMatthew G Knepley snes->data = (void*) ngmres; 705d2e16ddcSPeter Brune ngmres->msize = 30; 70619653cdaSPeter Brune 70788976e71SPeter Brune if (!snes->tolerancesset) { 7080e444f03SPeter Brune snes->max_funcs = 30000; 7090e444f03SPeter Brune snes->max_its = 10000; 71088976e71SPeter Brune } 7110e444f03SPeter Brune 712d2e16ddcSPeter Brune ngmres->anderson = PETSC_FALSE; 713d2e16ddcSPeter Brune 714e7058c64SPeter Brune ngmres->additive_linesearch = PETSC_NULL; 715e7058c64SPeter Brune 71628ed4a04SPeter Brune ngmres->restart_it = 2; 71713a62661SPeter Brune ngmres->restart_periodic = 30; 718f109b39eSPeter Brune ngmres->gammaA = 2.0; 719f109b39eSPeter Brune ngmres->gammaC = 2.0; 720cac108bcSPeter Brune ngmres->deltaB = 0.9; 721cac108bcSPeter Brune ngmres->epsilonB = 0.1; 722e7058c64SPeter Brune 72313a62661SPeter Brune ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE; 72413a62661SPeter Brune ngmres->select_type = SNES_NGMRES_SELECT_DIFFERENCE; 72513a62661SPeter Brune 72613a62661SPeter Brune ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNGMRESSetSelectType_C","SNESNGMRESSetSelectType_NGMRES", SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr); 72713a62661SPeter Brune ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNGMRESSetRestartType_C","SNESNGMRESSetRestartType_NGMRES", SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr); 72813a62661SPeter Brune 729a312c225SMatthew G Knepley PetscFunctionReturn(0); 730a312c225SMatthew G Knepley } 731a312c225SMatthew G Knepley EXTERN_C_END 732