119653cdaSPeter Brune #include <../src/snes/impls/ngmres/snesngmres.h> 219653cdaSPeter Brune #include <petscblaslapack.h> 3a312c225SMatthew G Knepley 4a312c225SMatthew G Knepley #undef __FUNCT__ 5a312c225SMatthew G Knepley #define __FUNCT__ "SNESReset_NGMRES" 6a312c225SMatthew G Knepley PetscErrorCode SNESReset_NGMRES(SNES snes) 7a312c225SMatthew G Knepley { 8a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 9a312c225SMatthew G Knepley PetscErrorCode ierr; 10a312c225SMatthew G Knepley 11a312c225SMatthew G Knepley PetscFunctionBegin; 12f109b39eSPeter Brune ierr = VecDestroyVecs(ngmres->msize, &ngmres->Fdot);CHKERRQ(ierr); 13f109b39eSPeter Brune ierr = VecDestroyVecs(ngmres->msize, &ngmres->Xdot);CHKERRQ(ierr); 14f1c6b773SPeter Brune ierr = SNESLineSearchDestroy(&ngmres->additive_linesearch);CHKERRQ(ierr); 159e764e56SPeter Brune 16a312c225SMatthew G Knepley PetscFunctionReturn(0); 17a312c225SMatthew G Knepley } 18a312c225SMatthew G Knepley 19a312c225SMatthew G Knepley #undef __FUNCT__ 20a312c225SMatthew G Knepley #define __FUNCT__ "SNESDestroy_NGMRES" 21a312c225SMatthew G Knepley PetscErrorCode SNESDestroy_NGMRES(SNES snes) 22a312c225SMatthew G Knepley { 23a312c225SMatthew G Knepley PetscErrorCode ierr; 2478440776SJed Brown SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 25a312c225SMatthew G Knepley 26a312c225SMatthew G Knepley PetscFunctionBegin; 27a312c225SMatthew G Knepley ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr); 28f109b39eSPeter Brune ierr = PetscFree5(ngmres->h, ngmres->beta, ngmres->xi, ngmres->fnorms, ngmres->q);CHKERRQ(ierr); 2919653cdaSPeter Brune ierr = PetscFree(ngmres->s);CHKERRQ(ierr); 30*18aa0c0cSPeter Brune ierr = PetscFree(ngmres->xnorms);CHKERRQ(ierr); 3119653cdaSPeter Brune #if PETSC_USE_COMPLEX 3219653cdaSPeter Brune ierr = PetscFree(ngmres->rwork); 3319653cdaSPeter Brune #endif 3419653cdaSPeter Brune ierr = PetscFree(ngmres->work); 3519653cdaSPeter Brune ierr = PetscFree(snes->data); 36a312c225SMatthew G Knepley PetscFunctionReturn(0); 37a312c225SMatthew G Knepley } 38a312c225SMatthew G Knepley 39a312c225SMatthew G Knepley #undef __FUNCT__ 40a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetUp_NGMRES" 41a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes) 42a312c225SMatthew G Knepley { 43a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 44e7058c64SPeter Brune const char *optionsprefix; 4519653cdaSPeter Brune PetscInt msize,hsize; 46a312c225SMatthew G Knepley PetscErrorCode ierr; 47a312c225SMatthew G Knepley 48a312c225SMatthew G Knepley PetscFunctionBegin; 4978440776SJed Brown ierr = SNESDefaultGetWork(snes,5);CHKERRQ(ierr); 5078440776SJed Brown if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);} 5178440776SJed Brown if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);} 5278440776SJed Brown if (!ngmres->setup_called) { 53087dfb9eSxuemin msize = ngmres->msize; /* restart size */ 5419653cdaSPeter Brune hsize = msize * msize; 55087dfb9eSxuemin 5698b3e84cSPeter Brune /* explicit least squares minimization solve */ 5719653cdaSPeter Brune ierr = PetscMalloc5(hsize,PetscScalar,&ngmres->h, 5819653cdaSPeter Brune msize,PetscScalar,&ngmres->beta, 5919653cdaSPeter Brune msize,PetscScalar,&ngmres->xi, 60f109b39eSPeter Brune msize,PetscReal, &ngmres->fnorms, 6119653cdaSPeter Brune hsize,PetscScalar,&ngmres->q);CHKERRQ(ierr); 62*18aa0c0cSPeter Brune if (ngmres->singlereduction) { 63*18aa0c0cSPeter Brune ierr = PetscMalloc(msize*sizeof(PetscReal),&ngmres->xnorms);CHKERRQ(ierr); 64*18aa0c0cSPeter Brune } 6519653cdaSPeter Brune ngmres->nrhs = 1; 6619653cdaSPeter Brune ngmres->lda = msize; 6719653cdaSPeter Brune ngmres->ldb = msize; 6819653cdaSPeter Brune ierr = PetscMalloc(msize*sizeof(PetscScalar),&ngmres->s);CHKERRQ(ierr); 6919653cdaSPeter Brune ierr = PetscMemzero(ngmres->h, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 7019653cdaSPeter Brune ierr = PetscMemzero(ngmres->q, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 7119653cdaSPeter Brune ierr = PetscMemzero(ngmres->xi, msize*sizeof(PetscScalar));CHKERRQ(ierr); 7219653cdaSPeter Brune ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr); 7319653cdaSPeter Brune ngmres->lwork = 12*msize; 7419653cdaSPeter Brune #if PETSC_USE_COMPLEX 7519653cdaSPeter Brune ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork); 7619653cdaSPeter Brune #endif 7719653cdaSPeter Brune ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work); 7878440776SJed Brown } 79e7058c64SPeter Brune 80e7058c64SPeter Brune /* linesearch setup */ 81e7058c64SPeter Brune ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 82e7058c64SPeter Brune 83e7058c64SPeter Brune if (ngmres->additive) { 84f1c6b773SPeter Brune ierr = SNESLineSearchCreate(((PetscObject)snes)->comm, &ngmres->additive_linesearch);CHKERRQ(ierr); 85f1c6b773SPeter Brune ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch, snes);CHKERRQ(ierr); 861a4f838cSPeter Brune ierr = SNESLineSearchSetType(ngmres->additive_linesearch, SNESLINESEARCHL2);CHKERRQ(ierr); 87f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch, "additive_");CHKERRQ(ierr); 88f1c6b773SPeter Brune ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch, optionsprefix);CHKERRQ(ierr); 89f1c6b773SPeter Brune ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr); 90e7058c64SPeter Brune } 91e7058c64SPeter Brune 9278440776SJed Brown ngmres->setup_called = PETSC_TRUE; 93a312c225SMatthew G Knepley PetscFunctionReturn(0); 94a312c225SMatthew G Knepley } 95a312c225SMatthew G Knepley 96a312c225SMatthew G Knepley #undef __FUNCT__ 97a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES" 98a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes) 99a312c225SMatthew G Knepley { 100a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 101a312c225SMatthew G Knepley PetscErrorCode ierr; 102dfbf837cSBarry Smith PetscBool debug; 103f1c6b773SPeter Brune SNESLineSearch linesearch; 104a312c225SMatthew G Knepley PetscFunctionBegin; 105a312c225SMatthew G Knepley ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr); 1069f425c49SPeter Brune ierr = PetscOptionsBool("-snes_ngmres_additive", "Use additive variant vs. choice", "SNES", ngmres->additive, &ngmres->additive, PETSC_NULL);CHKERRQ(ierr); 107d2e16ddcSPeter Brune ierr = PetscOptionsBool("-snes_ngmres_anderson", "Use Anderson mixing storage", "SNES", ngmres->anderson, &ngmres->anderson, PETSC_NULL);CHKERRQ(ierr); 10819653cdaSPeter Brune ierr = PetscOptionsInt("-snes_ngmres_m", "Number of directions", "SNES", ngmres->msize, &ngmres->msize, PETSC_NULL);CHKERRQ(ierr); 10928ed4a04SPeter Brune ierr = PetscOptionsInt("-snes_ngmres_restart_it","Tolerance iterations before restart","SNES", ngmres->restart_it, &ngmres->restart_it, PETSC_NULL);CHKERRQ(ierr); 110dfbf837cSBarry Smith ierr = PetscOptionsBool("-snes_ngmres_monitor", "Monitor actions of NGMRES", "SNES", ngmres->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);CHKERRQ(ierr); 111dfbf837cSBarry Smith if (debug) { 112dfbf837cSBarry Smith ngmres->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 113dfbf837cSBarry Smith } 1146a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_gammaA", "Residual selection constant", "SNES", ngmres->gammaA, &ngmres->gammaA, PETSC_NULL);CHKERRQ(ierr); 1156a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_gammaC", " Residual restart constant", "SNES", ngmres->gammaC, &ngmres->gammaC, PETSC_NULL);CHKERRQ(ierr); 1166a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES", ngmres->epsilonB, &ngmres->epsilonB, PETSC_NULL);CHKERRQ(ierr); 1176a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_deltaB", "Difference residual selection constant", "SNES", ngmres->deltaB, &ngmres->deltaB, PETSC_NULL);CHKERRQ(ierr); 118*18aa0c0cSPeter Brune ierr = PetscOptionsBool("-snes_ngmres_singlereduction", "Aggregate reductions", "SNES", ngmres->singlereduction, &ngmres->singlereduction, PETSC_NULL);CHKERRQ(ierr); 119a312c225SMatthew G Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1206a7cf640SPeter Brune if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA; 1219e764e56SPeter Brune 1229e764e56SPeter Brune /* set the default type of the line search if the user hasn't already. */ 1239e764e56SPeter Brune if (!snes->linesearch) { 124f1c6b773SPeter Brune ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr); 1251a4f838cSPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC);CHKERRQ(ierr); 1269e764e56SPeter Brune } 127a312c225SMatthew G Knepley PetscFunctionReturn(0); 128a312c225SMatthew G Knepley } 129a312c225SMatthew G Knepley 130a312c225SMatthew G Knepley #undef __FUNCT__ 131a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES" 132a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes, PetscViewer viewer) 133a312c225SMatthew G Knepley { 134a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 135a312c225SMatthew G Knepley PetscBool iascii; 136a312c225SMatthew G Knepley PetscErrorCode ierr; 137a312c225SMatthew G Knepley 138a312c225SMatthew G Knepley PetscFunctionBegin; 139a312c225SMatthew G Knepley ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 140a312c225SMatthew G Knepley if (iascii) { 1419e764e56SPeter Brune 142f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr); 143f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Residual selection: gammaA=%1.0e, gammaC=%1.0e\n", ngmres->gammaA, ngmres->gammaC);CHKERRQ(ierr); 144f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n", ngmres->epsilonB, ngmres->deltaB);CHKERRQ(ierr); 145a312c225SMatthew G Knepley } 146a312c225SMatthew G Knepley PetscFunctionReturn(0); 147a312c225SMatthew G Knepley } 148a312c225SMatthew G Knepley 149a312c225SMatthew G Knepley #undef __FUNCT__ 150a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES" 151211b2d39SPeter Brune 152a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes) 153a312c225SMatthew G Knepley { 154087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 15598b3e84cSPeter Brune /* present solution, residual, and preconditioned residual */ 1569f425c49SPeter Brune Vec X, F, B, D, Y; 157f109b39eSPeter Brune 158f109b39eSPeter Brune /* candidate linear combination answers */ 1594b32a720SPeter Brune Vec XA, FA, XM, FM, FPC; 16019653cdaSPeter Brune 16198b3e84cSPeter Brune /* previous iterations to construct the subspace */ 162f109b39eSPeter Brune Vec *Fdot = ngmres->Fdot; 163f109b39eSPeter Brune Vec *Xdot = ngmres->Xdot; 16419653cdaSPeter Brune 16598b3e84cSPeter Brune /* coefficients and RHS to the minimization problem */ 16619653cdaSPeter Brune PetscScalar *beta = ngmres->beta; 16719653cdaSPeter Brune PetscScalar *xi = ngmres->xi; 168*18aa0c0cSPeter Brune PetscReal fnorm, fMnorm, fAnorm; 16919653cdaSPeter Brune PetscReal nu; 17019653cdaSPeter Brune PetscScalar alph_total = 0.; 17128ed4a04SPeter Brune PetscInt i, j, k, k_restart, l, ivec, restart_count = 0; 17219653cdaSPeter Brune 17398b3e84cSPeter Brune /* solution selection data */ 17419653cdaSPeter Brune PetscBool selectA, selectRestart; 175f109b39eSPeter Brune PetscReal dnorm, dminnorm, dcurnorm; 176f109b39eSPeter Brune PetscReal fminnorm; 17719653cdaSPeter Brune 1781e633543SBarry Smith SNESConvergedReason reason; 179f109b39eSPeter Brune PetscBool lssucceed; 180a312c225SMatthew G Knepley PetscErrorCode ierr; 181a312c225SMatthew G Knepley 182a312c225SMatthew G Knepley PetscFunctionBegin; 18398b3e84cSPeter Brune /* variable initialization */ 184a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 185f109b39eSPeter Brune X = snes->vec_sol; 186f109b39eSPeter Brune F = snes->vec_func; 187f109b39eSPeter Brune B = snes->vec_rhs; 188f109b39eSPeter Brune XA = snes->vec_sol_update; 189f109b39eSPeter Brune FA = snes->work[0]; 190f109b39eSPeter Brune D = snes->work[1]; 191f109b39eSPeter Brune 192f109b39eSPeter Brune /* work for the line search */ 193f109b39eSPeter Brune Y = snes->work[2]; 1949f425c49SPeter Brune XM = snes->work[3]; 1959f425c49SPeter Brune FM = snes->work[4]; 196a312c225SMatthew G Knepley 197a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 198a312c225SMatthew G Knepley snes->iter = 0; 199a312c225SMatthew G Knepley snes->norm = 0.; 200a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 20119653cdaSPeter Brune 20298b3e84cSPeter Brune /* initialization */ 20319653cdaSPeter Brune 20498b3e84cSPeter Brune /* r = F(x) */ 205e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 206f109b39eSPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 207a312c225SMatthew G Knepley if (snes->domainerror) { 208a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 209a312c225SMatthew G Knepley PetscFunctionReturn(0); 210a312c225SMatthew G Knepley } 211e4ed7901SPeter Brune } else { 212e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 213e4ed7901SPeter Brune } 21419653cdaSPeter Brune 215e4ed7901SPeter Brune if (!snes->norm_init_set) { 216f109b39eSPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 217f109b39eSPeter Brune if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation"); 218e4ed7901SPeter Brune } else { 219e4ed7901SPeter Brune fnorm = snes->norm_init; 220e4ed7901SPeter Brune snes->norm_init_set = PETSC_FALSE; 221e4ed7901SPeter Brune } 222e4ed7901SPeter Brune fminnorm = fnorm; 223e4ed7901SPeter Brune /* nu = (r, r) */ 224e4ed7901SPeter Brune nu = fnorm*fnorm; 22519653cdaSPeter Brune 22698b3e84cSPeter Brune /* q_{00} = nu */ 22719653cdaSPeter Brune Q(0,0) = nu; 228f109b39eSPeter Brune ngmres->fnorms[0] = fnorm; 229f109b39eSPeter Brune /* Fdot[0] = F */ 230f109b39eSPeter Brune ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr); 231f109b39eSPeter Brune ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr); 232087dfb9eSxuemin 233a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 234f109b39eSPeter Brune snes->norm = fnorm; 235a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 236f109b39eSPeter Brune SNESLogConvHistory(snes, fnorm, 0); 237f109b39eSPeter Brune ierr = SNESMonitor(snes, 0, fnorm);CHKERRQ(ierr); 238f109b39eSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 239a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 240a312c225SMatthew G Knepley 24119653cdaSPeter Brune k_restart = 1; 24219653cdaSPeter Brune l = 1; 24309c08436SPeter Brune for (k=1; k < snes->max_its+1; k++) { 24498b3e84cSPeter Brune /* select which vector of the stored subspace will be updated */ 24598b3e84cSPeter Brune ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */ 24619653cdaSPeter Brune 24798b3e84cSPeter Brune /* Computation of x^M */ 2488cc86e31SPeter Brune if (snes->pc) { 2499f425c49SPeter Brune ierr = VecCopy(X, XM);CHKERRQ(ierr); 250e4ed7901SPeter Brune ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr); 251e4ed7901SPeter Brune ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr); 2529f425c49SPeter Brune ierr = SNESSolve(snes->pc, B, XM);CHKERRQ(ierr); 2538cc86e31SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 2548cc86e31SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2558cc86e31SPeter Brune snes->reason = SNES_DIVERGED_INNER; 2568cc86e31SPeter Brune PetscFunctionReturn(0); 2578cc86e31SPeter Brune } 2584b32a720SPeter Brune ierr = SNESGetFunction(snes->pc, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 2594b32a720SPeter Brune ierr = VecCopy(FPC, FM);CHKERRQ(ierr); 2604b32a720SPeter Brune ierr = SNESGetFunctionNorm(snes->pc, &fMnorm);CHKERRQ(ierr); 2618cc86e31SPeter Brune } else { 262f109b39eSPeter Brune /* no preconditioner -- just take gradient descent with line search */ 263f109b39eSPeter Brune ierr = VecCopy(F, Y);CHKERRQ(ierr); 264e7058c64SPeter Brune ierr = VecCopy(F, FM);CHKERRQ(ierr); 265e7058c64SPeter Brune ierr = VecCopy(X, XM);CHKERRQ(ierr); 266e7058c64SPeter Brune fMnorm = fnorm; 267f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr); 268f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssucceed);CHKERRQ(ierr); 269f109b39eSPeter Brune if (!lssucceed) { 270f109b39eSPeter Brune if (++snes->numFailures >= snes->maxFailures) { 271f109b39eSPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 272f109b39eSPeter Brune PetscFunctionReturn(0); 273f109b39eSPeter Brune } 274f109b39eSPeter Brune } 2756634f59bSPeter Brune } 2761e633543SBarry Smith 27798b3e84cSPeter Brune /* r = F(x) */ 2789f425c49SPeter Brune nu = fMnorm*fMnorm; 2799f425c49SPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of F^M */ 28019653cdaSPeter Brune 28198b3e84cSPeter Brune /* construct the right hand side and xi factors */ 2828c09b6b7SPeter Brune ierr = VecMDot(FM, l, Fdot, xi);CHKERRQ(ierr); 2838c09b6b7SPeter Brune 28419653cdaSPeter Brune for (i = 0; i < l; i++) { 28519653cdaSPeter Brune beta[i] = nu - xi[i]; 28619653cdaSPeter Brune } 28719653cdaSPeter Brune 28898b3e84cSPeter Brune /* construct h */ 28919653cdaSPeter Brune for (j = 0; j < l; j++) { 29019653cdaSPeter Brune for (i = 0; i < l; i++) { 29119653cdaSPeter Brune H(i, j) = Q(i, j) - xi[i] - xi[j] + nu; 29219653cdaSPeter Brune } 29319653cdaSPeter Brune } 294f109b39eSPeter Brune 295f109b39eSPeter Brune if(l == 1) { 296f109b39eSPeter Brune /* simply set alpha[0] = beta[0] / H[0, 0] */ 297f109b39eSPeter Brune beta[0] = beta[0] / H(0, 0); 298f109b39eSPeter Brune } else { 29919653cdaSPeter Brune #ifdef PETSC_MISSING_LAPACK_GELSS 30019653cdaSPeter Brune SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "NGMRES with LS requires the LAPACK GELSS routine."); 3014a0c5b0cSMatthew G Knepley #else 30219653cdaSPeter Brune ngmres->m = PetscBLASIntCast(l); 30319653cdaSPeter Brune ngmres->n = PetscBLASIntCast(l); 30419653cdaSPeter Brune ngmres->info = PetscBLASIntCast(0); 30519653cdaSPeter Brune ngmres->rcond = -1.; 3068e57ea43SSatish Balay ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 30719653cdaSPeter Brune #ifdef PETSC_USE_COMPLEX 30819653cdaSPeter Brune LAPACKgelss_(&ngmres->m, 30919653cdaSPeter Brune &ngmres->n, 31019653cdaSPeter Brune &ngmres->nrhs, 31119653cdaSPeter Brune ngmres->h, 31219653cdaSPeter Brune &ngmres->lda, 31319653cdaSPeter Brune ngmres->beta, 31419653cdaSPeter Brune &ngmres->ldb, 31519653cdaSPeter Brune ngmres->s, 31619653cdaSPeter Brune &ngmres->rcond, 31719653cdaSPeter Brune &ngmres->rank, 31819653cdaSPeter Brune ngmres->work, 31919653cdaSPeter Brune &ngmres->lwork, 32019653cdaSPeter Brune ngmres->rwork, 32119653cdaSPeter Brune &ngmres->info); 32219653cdaSPeter Brune #else 32319653cdaSPeter Brune LAPACKgelss_(&ngmres->m, 32419653cdaSPeter Brune &ngmres->n, 32519653cdaSPeter Brune &ngmres->nrhs, 32619653cdaSPeter Brune ngmres->h, 32719653cdaSPeter Brune &ngmres->lda, 32819653cdaSPeter Brune ngmres->beta, 32919653cdaSPeter Brune &ngmres->ldb, 33019653cdaSPeter Brune ngmres->s, 33119653cdaSPeter Brune &ngmres->rcond, 33219653cdaSPeter Brune &ngmres->rank, 33319653cdaSPeter Brune ngmres->work, 33419653cdaSPeter Brune &ngmres->lwork, 33519653cdaSPeter Brune &ngmres->info); 33619653cdaSPeter Brune #endif 3378e57ea43SSatish Balay ierr = PetscFPTrapPop();CHKERRQ(ierr); 33819653cdaSPeter Brune if (ngmres->info < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to GELSS"); 33919653cdaSPeter Brune if (ngmres->info > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SVD failed to converge"); 340a312c225SMatthew G Knepley #endif 341f109b39eSPeter Brune } 342a312c225SMatthew G Knepley 34319653cdaSPeter Brune alph_total = 0.; 34419653cdaSPeter Brune for (i = 0; i < l; i++) { 34519653cdaSPeter Brune alph_total += beta[i]; 346c0bbabecSxuemin } 347f109b39eSPeter Brune 3489f425c49SPeter Brune ierr = VecCopy(XM, XA);CHKERRQ(ierr); 349f109b39eSPeter Brune ierr = VecScale(XA, 1. - alph_total);CHKERRQ(ierr); 350087dfb9eSxuemin 3518c09b6b7SPeter Brune ierr = VecMAXPY(XA, l, beta, Xdot);CHKERRQ(ierr); 352f109b39eSPeter Brune ierr = SNESComputeFunction(snes, XA, FA);CHKERRQ(ierr); 35319653cdaSPeter Brune 3549f425c49SPeter Brune /* differences for selection and restart */ 355*18aa0c0cSPeter Brune 356*18aa0c0cSPeter Brune if (ngmres->singlereduction) { 357*18aa0c0cSPeter Brune dminnorm = -1.0; 358f109b39eSPeter Brune ierr=VecCopy(XA, D);CHKERRQ(ierr); 359*18aa0c0cSPeter Brune ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr); 360*18aa0c0cSPeter Brune for(i=0;i<l;i++) { 361*18aa0c0cSPeter Brune ierr=VecAXPY(Xdot[i],-1.0,XA);CHKERRQ(ierr); 362*18aa0c0cSPeter Brune } 363*18aa0c0cSPeter Brune ierr = VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 364*18aa0c0cSPeter Brune ierr = VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr); 365*18aa0c0cSPeter Brune for (i=0;i<l;i++) { 366*18aa0c0cSPeter Brune ierr = VecNormBegin(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr); 367*18aa0c0cSPeter Brune } 368*18aa0c0cSPeter Brune ierr = VecNormEnd(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 369*18aa0c0cSPeter Brune ierr = VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr); 370*18aa0c0cSPeter Brune for (i=0;i<l;i++) { 371*18aa0c0cSPeter Brune ierr = VecNormEnd(Xdot[i], NORM_2, &ngmres->xnorms[i]);CHKERRQ(ierr); 372*18aa0c0cSPeter Brune } 373*18aa0c0cSPeter Brune for(i=0;i<l;i++) { 374*18aa0c0cSPeter Brune dcurnorm = ngmres->xnorms[i]; 375*18aa0c0cSPeter Brune if ((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm; 376*18aa0c0cSPeter Brune ierr=VecAXPY(Xdot[i],1.0,XA);CHKERRQ(ierr); 377*18aa0c0cSPeter Brune } 378*18aa0c0cSPeter Brune } else { 379*18aa0c0cSPeter Brune ierr=VecCopy(XA, D);CHKERRQ(ierr); 380*18aa0c0cSPeter Brune ierr=VecAXPY(D, -1.0, XM);CHKERRQ(ierr); 381*18aa0c0cSPeter Brune ierr=VecNormBegin(D, NORM_2, &dnorm);CHKERRQ(ierr); 382*18aa0c0cSPeter Brune ierr=VecNormBegin(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 383*18aa0c0cSPeter Brune ierr=VecNormEnd(D, NORM_2, &dnorm);CHKERRQ(ierr); 384*18aa0c0cSPeter 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 } 392*18aa0c0cSPeter Brune } 3939f425c49SPeter Brune 3949f425c49SPeter Brune /* combination (additive) or selection (multiplicative) of the N-GMRES solution */ 3959f425c49SPeter Brune if (ngmres->additive) { 3969f425c49SPeter Brune /* X = X + \lambda(XA - X) */ 3979f425c49SPeter Brune if (ngmres->monitor) { 3989f425c49SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr); 3999f425c49SPeter Brune } 4009f425c49SPeter Brune ierr = VecCopy(XA, Y);CHKERRQ(ierr); 401eb1825c3SPeter Brune ierr = VecAYPX(Y, -1.0, X);CHKERRQ(ierr); 402f1c6b773SPeter Brune ierr = SNESLineSearchApply(ngmres->additive_linesearch,X,F,&fnorm,Y);CHKERRQ(ierr); 403f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(ngmres->additive_linesearch, &lssucceed);CHKERRQ(ierr); 4049f425c49SPeter Brune if (!lssucceed) { 4059f425c49SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 4069f425c49SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 4079f425c49SPeter Brune PetscFunctionReturn(0); 4089f425c49SPeter Brune } 4099f425c49SPeter Brune } 4109f425c49SPeter Brune if (ngmres->monitor) { 4119f425c49SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Additive solution: ||F||_2 = %e\n", fnorm);CHKERRQ(ierr); 4129f425c49SPeter Brune } 4139f425c49SPeter Brune } else { 4149f425c49SPeter Brune selectA = PETSC_TRUE; 4159f425c49SPeter Brune /* Conditions for choosing the accelerated answer */ 4169f425c49SPeter Brune /* Criterion A -- the norm of the function isn't increased above the minimum by too much */ 4179f425c49SPeter Brune if (fAnorm >= ngmres->gammaA*fminnorm) { 4189f425c49SPeter Brune selectA = PETSC_FALSE; 4199f425c49SPeter Brune } 4209f425c49SPeter Brune /* Criterion B -- the choice of x^A isn't too close to some other choice */ 421cf22de31SPeter Brune if (ngmres->epsilonB*dnorm<dminnorm || PetscSqrtReal(fnorm)<ngmres->deltaB*PetscSqrtReal(fminnorm)) { 42219653cdaSPeter Brune } else { 42319653cdaSPeter Brune selectA=PETSC_FALSE; 42419653cdaSPeter Brune } 42519653cdaSPeter Brune if (selectA) { 426dfbf837cSBarry Smith if (ngmres->monitor) { 4279e764e56SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_A, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fMnorm);CHKERRQ(ierr); 428dfbf837cSBarry Smith } 42998b3e84cSPeter Brune /* copy it over */ 430f109b39eSPeter Brune fnorm = fAnorm; 431f109b39eSPeter Brune nu = fnorm*fnorm; 432f109b39eSPeter Brune ierr = VecCopy(FA, F);CHKERRQ(ierr); 433f109b39eSPeter Brune ierr = VecCopy(XA, X);CHKERRQ(ierr); 43419653cdaSPeter Brune } else { 435dfbf837cSBarry Smith if (ngmres->monitor) { 436f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_M, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fnorm);CHKERRQ(ierr); 437dfbf837cSBarry Smith } 4389f425c49SPeter Brune fnorm = fMnorm; 4399f425c49SPeter Brune nu = fnorm*fnorm; 4409f425c49SPeter Brune ierr = VecCopy(FM, F);CHKERRQ(ierr); 4419f425c49SPeter Brune ierr = VecCopy(XM, X);CHKERRQ(ierr); 4429f425c49SPeter Brune } 44319653cdaSPeter Brune } 444211b2d39SPeter Brune 44519653cdaSPeter Brune selectRestart = PETSC_FALSE; 44619653cdaSPeter Brune 44798b3e84cSPeter Brune /* difference stagnation restart */ 448cf22de31SPeter Brune if((ngmres->epsilonB*dnorm > dminnorm) && (PetscSqrtReal(fAnorm) > ngmres->deltaB*PetscSqrtReal(fminnorm))) { 449dfbf837cSBarry Smith if (ngmres->monitor) { 450f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "difference restart: %e > %e\n", ngmres->epsilonB*dnorm, dminnorm);CHKERRQ(ierr); 451dfbf837cSBarry Smith } 45219653cdaSPeter Brune selectRestart = PETSC_TRUE; 45319653cdaSPeter Brune } 45498b3e84cSPeter Brune /* residual stagnation restart */ 455cf22de31SPeter Brune if (PetscSqrtReal(fAnorm) > ngmres->gammaC*PetscSqrtReal(fminnorm)) { 456dfbf837cSBarry Smith if (ngmres->monitor) { 457cf22de31SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "residual restart: %e > %e\n", PetscSqrtReal(fAnorm), ngmres->gammaC*PetscSqrtReal(fminnorm));CHKERRQ(ierr); 458dfbf837cSBarry Smith } 45919653cdaSPeter Brune selectRestart = PETSC_TRUE; 46019653cdaSPeter Brune } 46119653cdaSPeter Brune 46228ed4a04SPeter Brune /* if the restart conditions persist for more than restart_it iterations, restart. */ 46319653cdaSPeter Brune if (selectRestart) { 46428ed4a04SPeter Brune restart_count++; 46528ed4a04SPeter Brune } else { 46628ed4a04SPeter Brune restart_count = 0; 46728ed4a04SPeter Brune } 46828ed4a04SPeter Brune 46928ed4a04SPeter Brune /* restart after restart conditions have persisted for a fixed number of iterations */ 47028ed4a04SPeter Brune if (restart_count >= ngmres->restart_it) { 471dfbf837cSBarry Smith if (ngmres->monitor){ 472dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Restarted at iteration %d\n", k_restart);CHKERRQ(ierr); 473dfbf837cSBarry Smith } 47428ed4a04SPeter Brune restart_count = 0; 47519653cdaSPeter Brune k_restart = 1; 47619653cdaSPeter Brune l = 1; 47798b3e84cSPeter Brune /* q_{00} = nu */ 478d2e16ddcSPeter Brune if (ngmres->anderson) { 479d2e16ddcSPeter Brune ngmres->fnorms[0] = fMnorm; 480d2e16ddcSPeter Brune nu = fMnorm*fMnorm; 481d2e16ddcSPeter Brune Q(0,0) = nu; 482d2e16ddcSPeter Brune /* Fdot[0] = F */ 483d2e16ddcSPeter Brune ierr = VecCopy(XM, Xdot[0]);CHKERRQ(ierr); 484d2e16ddcSPeter Brune ierr = VecCopy(FM, Fdot[0]);CHKERRQ(ierr); 485d2e16ddcSPeter Brune } else { 486f109b39eSPeter Brune ngmres->fnorms[0] = fnorm; 487f109b39eSPeter Brune nu = fnorm*fnorm; 48819653cdaSPeter Brune Q(0,0) = nu; 489f109b39eSPeter Brune /* Fdot[0] = F */ 490f109b39eSPeter Brune ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr); 491f109b39eSPeter Brune ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr); 492d2e16ddcSPeter Brune } 49319653cdaSPeter Brune } else { 49498b3e84cSPeter Brune /* select the current size of the subspace */ 4951e633543SBarry Smith if (l < ngmres->msize) l++; 49619653cdaSPeter Brune k_restart++; 49798b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 498d2e16ddcSPeter Brune if (ngmres->anderson) { 499d2e16ddcSPeter Brune ierr = VecCopy(FM, Fdot[ivec]);CHKERRQ(ierr); 500d2e16ddcSPeter Brune ierr = VecCopy(XM, Xdot[ivec]);CHKERRQ(ierr); 501d2e16ddcSPeter Brune ngmres->fnorms[ivec] = fMnorm; 502d2e16ddcSPeter Brune if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of FM */ 503*18aa0c0cSPeter Brune xi[ivec] = fMnorm*fMnorm; 504d2e16ddcSPeter Brune for (i = 0; i < l; i++) { 505*18aa0c0cSPeter Brune Q(i, ivec) = xi[i]; 506*18aa0c0cSPeter Brune Q(ivec, i) = xi[i]; 507d2e16ddcSPeter Brune } 508d2e16ddcSPeter Brune } else { 509f109b39eSPeter Brune ierr = VecCopy(F, Fdot[ivec]);CHKERRQ(ierr); 510f109b39eSPeter Brune ierr = VecCopy(X, Xdot[ivec]);CHKERRQ(ierr); 511f109b39eSPeter Brune ngmres->fnorms[ivec] = fnorm; 512d2e16ddcSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; /* the minimum norm is now of FA */ 513*18aa0c0cSPeter Brune ierr = VecMDot(F, l, Fdot, xi);CHKERRQ(ierr); 51419653cdaSPeter Brune for (i = 0; i < l; i++) { 515*18aa0c0cSPeter Brune Q(i, ivec) = xi[i]; 516*18aa0c0cSPeter Brune Q(ivec, i) = xi[i]; 51719653cdaSPeter Brune } 51819653cdaSPeter Brune } 519d2e16ddcSPeter Brune } 52019653cdaSPeter Brune 5218409ca45SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 522087dfb9eSxuemin snes->iter = k; 523f109b39eSPeter Brune snes->norm = fnorm; 5248409ca45SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 5258409ca45SMatthew G Knepley SNESLogConvHistory(snes, snes->norm, snes->iter); 5268409ca45SMatthew G Knepley ierr = SNESMonitor(snes, snes->iter, snes->norm);CHKERRQ(ierr); 5278409ca45SMatthew G Knepley 528*18aa0c0cSPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 529087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 530a312c225SMatthew G Knepley } 531a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 532a312c225SMatthew G Knepley PetscFunctionReturn(0); 533a312c225SMatthew G Knepley } 534a312c225SMatthew G Knepley 535dfbf837cSBarry Smith /*MC 5361867fe5bSPeter Brune SNESNGMRES - The Nonlinear Generalized Minimum Residual method. 537a312c225SMatthew G Knepley 538dfbf837cSBarry Smith Level: beginner 539dfbf837cSBarry Smith 5401867fe5bSPeter Brune Options Database: 5411867fe5bSPeter Brune + -snes_ngmres_additive - Use a variant that line-searches between the candidate solution and the combined solution. 5421867fe5bSPeter Brune . -snes_ngmres_anderson - Use Anderson mixing NGMRES variant which combines candidate solutions instead of actual solutions. 5431867fe5bSPeter Brune . -snes_ngmres_m - Number of stored previous solutions and residuals. 5441867fe5bSPeter Brune . -snes_ngmres_restart_it - Number of iterations the restart conditions hold before restart. 5451867fe5bSPeter Brune . -snes_ngmres_gammaA - Residual tolerance for solution selection between the candidate and combination. 5461867fe5bSPeter Brune . -snes_ngmres_gammaC - Residual tolerance for restart. 5471867fe5bSPeter Brune . -snes_ngmres_epsilonB - Difference tolerance between subsequent solutions triggering restart. 5481867fe5bSPeter Brune . -snes_ngmres_deltaB - Difference tolerance between residuals triggering restart. 5491867fe5bSPeter Brune . -snes_ngmres_monitor - Prints relevant information about the ngmres iteration. 550f3aaf736SPeter Brune - -snes_ls <basic,basicnonorms,quadratic,critical> - Line search type. 5511867fe5bSPeter Brune 5521867fe5bSPeter Brune Notes: 5531867fe5bSPeter Brune 5541867fe5bSPeter Brune The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized 5551867fe5bSPeter Brune optimization problem at each iteration. 5561867fe5bSPeter Brune 5571867fe5bSPeter Brune References: 5581867fe5bSPeter Brune 559dfbf837cSBarry Smith "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 560dfbf837cSBarry Smith SIAM Journal on Scientific Computing, 21(5), 2000. 561dfbf837cSBarry Smith 562dfbf837cSBarry Smith This is also the same as the algorithm called Anderson acceleration introduced in "D. G. Anderson. Iterative procedures for nonlinear integral equations. 563dfbf837cSBarry Smith J. Assoc. Comput. Mach., 12:547–560, 1965." 564dfbf837cSBarry Smith 565dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 566dfbf837cSBarry Smith M*/ 567a312c225SMatthew G Knepley 568a312c225SMatthew G Knepley EXTERN_C_BEGIN 569a312c225SMatthew G Knepley #undef __FUNCT__ 570a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 571a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes) 572a312c225SMatthew G Knepley { 573a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 574a312c225SMatthew G Knepley PetscErrorCode ierr; 575a312c225SMatthew G Knepley 576a312c225SMatthew G Knepley PetscFunctionBegin; 577a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 578a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 579a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 580a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 581a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 582a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 583a312c225SMatthew G Knepley 58442f4f86dSBarry Smith snes->usespc = PETSC_TRUE; 5852c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 5862c155ee1SBarry Smith 587a312c225SMatthew G Knepley ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr); 588a312c225SMatthew G Knepley snes->data = (void*) ngmres; 589d2e16ddcSPeter Brune ngmres->msize = 30; 59019653cdaSPeter Brune 59188976e71SPeter Brune if (!snes->tolerancesset) { 5920e444f03SPeter Brune snes->max_funcs = 30000; 5930e444f03SPeter Brune snes->max_its = 10000; 59488976e71SPeter Brune } 5950e444f03SPeter Brune 596d2e16ddcSPeter Brune ngmres->additive = PETSC_FALSE; 597d2e16ddcSPeter Brune ngmres->anderson = PETSC_FALSE; 598d2e16ddcSPeter Brune 599e7058c64SPeter Brune ngmres->additive_linesearch = PETSC_NULL; 600e7058c64SPeter Brune 60128ed4a04SPeter Brune ngmres->restart_it = 2; 602f109b39eSPeter Brune ngmres->gammaA = 2.0; 603f109b39eSPeter Brune ngmres->gammaC = 2.0; 604cac108bcSPeter Brune ngmres->deltaB = 0.9; 605cac108bcSPeter Brune ngmres->epsilonB = 0.1; 606e7058c64SPeter Brune 607a312c225SMatthew G Knepley PetscFunctionReturn(0); 608a312c225SMatthew G Knepley } 609a312c225SMatthew G Knepley EXTERN_C_END 610