1a312c225SMatthew G Knepley /* Defines the basic SNES object */ 219653cdaSPeter Brune #include <../src/snes/impls/ngmres/snesngmres.h> 319653cdaSPeter Brune #include <petscblaslapack.h> 4a312c225SMatthew G Knepley 5087dfb9eSxuemin 6087dfb9eSxuemin 7087dfb9eSxuemin 8a312c225SMatthew G Knepley #undef __FUNCT__ 9a312c225SMatthew G Knepley #define __FUNCT__ "SNESReset_NGMRES" 10a312c225SMatthew G Knepley PetscErrorCode SNESReset_NGMRES(SNES snes) 11a312c225SMatthew G Knepley { 12a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 13a312c225SMatthew G Knepley PetscErrorCode ierr; 14a312c225SMatthew G Knepley 15a312c225SMatthew G Knepley PetscFunctionBegin; 16f109b39eSPeter Brune ierr = VecDestroyVecs(ngmres->msize, &ngmres->Fdot);CHKERRQ(ierr); 17f109b39eSPeter Brune ierr = VecDestroyVecs(ngmres->msize, &ngmres->Xdot);CHKERRQ(ierr); 18732c72c5SBarry Smith if (snes->work) {ierr = VecDestroyVecs(snes->nwork, &snes->work);CHKERRQ(ierr);} 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; 27a312c225SMatthew G Knepley 28a312c225SMatthew G Knepley PetscFunctionBegin; 29a312c225SMatthew G Knepley ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr); 3019653cdaSPeter Brune if (snes->data) { 3119653cdaSPeter Brune SNES_NGMRES * ngmres = (SNES_NGMRES *)snes->data; 32f109b39eSPeter Brune ierr = PetscFree5(ngmres->h, ngmres->beta, ngmres->xi, ngmres->fnorms, ngmres->q);CHKERRQ(ierr); 3319653cdaSPeter Brune ierr = PetscFree(ngmres->s);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 } 3919653cdaSPeter Brune ierr = PetscFree(snes->data); 40a312c225SMatthew G Knepley PetscFunctionReturn(0); 41a312c225SMatthew G Knepley } 42a312c225SMatthew G Knepley 43a312c225SMatthew G Knepley #undef __FUNCT__ 44a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetUp_NGMRES" 45a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes) 46a312c225SMatthew G Knepley { 47a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 4819653cdaSPeter Brune PetscInt msize,hsize; 49a312c225SMatthew G Knepley PetscErrorCode ierr; 50a312c225SMatthew G Knepley 51a312c225SMatthew G Knepley PetscFunctionBegin; 52087dfb9eSxuemin msize = ngmres->msize; /* restart size */ 5319653cdaSPeter Brune hsize = msize * msize; 54087dfb9eSxuemin 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); 6219653cdaSPeter Brune ngmres->nrhs = 1; 6319653cdaSPeter Brune ngmres->lda = msize; 6419653cdaSPeter Brune ngmres->ldb = msize; 6519653cdaSPeter Brune ierr = PetscMalloc(msize*sizeof(PetscScalar),&ngmres->s);CHKERRQ(ierr); 6619653cdaSPeter Brune ierr = PetscMemzero(ngmres->h, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 6719653cdaSPeter Brune ierr = PetscMemzero(ngmres->q, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 6819653cdaSPeter Brune ierr = PetscMemzero(ngmres->xi, msize*sizeof(PetscScalar));CHKERRQ(ierr); 6919653cdaSPeter Brune ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr); 7019653cdaSPeter Brune ngmres->lwork = 12*msize; 7119653cdaSPeter Brune #if PETSC_USE_COMPLEX 7219653cdaSPeter Brune ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork); 7319653cdaSPeter Brune #endif 7419653cdaSPeter Brune ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work); 75211b2d39SPeter Brune 76f109b39eSPeter Brune ierr = VecDuplicateVecs(snes->vec_sol, ngmres->msize, &ngmres->Xdot);CHKERRQ(ierr); 77f109b39eSPeter Brune ierr = VecDuplicateVecs(snes->vec_sol, ngmres->msize, &ngmres->Fdot);CHKERRQ(ierr); 78f109b39eSPeter Brune ierr = SNESDefaultGetWork(snes, 5);CHKERRQ(ierr); 79a312c225SMatthew G Knepley PetscFunctionReturn(0); 80a312c225SMatthew G Knepley } 81a312c225SMatthew G Knepley 82a312c225SMatthew G Knepley #undef __FUNCT__ 83a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES" 84a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes) 85a312c225SMatthew G Knepley { 86a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 87a312c225SMatthew G Knepley PetscErrorCode ierr; 88dfbf837cSBarry Smith PetscBool debug; 89a312c225SMatthew G Knepley 90a312c225SMatthew G Knepley PetscFunctionBegin; 91a312c225SMatthew G Knepley ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr); 9219653cdaSPeter Brune ierr = PetscOptionsInt("-snes_ngmres_m", "Number of directions", "SNES", ngmres->msize, &ngmres->msize, PETSC_NULL);CHKERRQ(ierr); 9328ed4a04SPeter Brune ierr = PetscOptionsInt("-snes_ngmres_restart_it","Tolerance iterations before restart","SNES", ngmres->restart_it, &ngmres->restart_it, PETSC_NULL);CHKERRQ(ierr); 94dfbf837cSBarry Smith ierr = PetscOptionsBool("-snes_ngmres_monitor", "Monitor actions of NGMRES", "SNES", ngmres->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);CHKERRQ(ierr); 95dfbf837cSBarry Smith if (debug) { 96dfbf837cSBarry Smith ngmres->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 97dfbf837cSBarry Smith } 986a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_gammaA", "Residual selection constant", "SNES", ngmres->gammaA, &ngmres->gammaA, PETSC_NULL);CHKERRQ(ierr); 996a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_gammaC", " Residual restart constant", "SNES", ngmres->gammaC, &ngmres->gammaC, PETSC_NULL);CHKERRQ(ierr); 1006a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES", ngmres->epsilonB, &ngmres->epsilonB, PETSC_NULL);CHKERRQ(ierr); 1016a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_deltaB", "Difference residual selection constant", "SNES", ngmres->deltaB, &ngmres->deltaB, PETSC_NULL);CHKERRQ(ierr); 102a312c225SMatthew G Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1036a7cf640SPeter Brune if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA; 104a312c225SMatthew G Knepley PetscFunctionReturn(0); 105a312c225SMatthew G Knepley } 106a312c225SMatthew G Knepley 107a312c225SMatthew G Knepley #undef __FUNCT__ 108a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES" 109a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes, PetscViewer viewer) 110a312c225SMatthew G Knepley { 111a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 112a312c225SMatthew G Knepley PetscBool iascii; 113f109b39eSPeter Brune const char *cstr; 114a312c225SMatthew G Knepley PetscErrorCode ierr; 115a312c225SMatthew G Knepley 116a312c225SMatthew G Knepley PetscFunctionBegin; 117a312c225SMatthew G Knepley ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 118a312c225SMatthew G Knepley if (iascii) { 119f109b39eSPeter Brune cstr = SNESLineSearchTypeName(snes->ls_type); 120f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " line search variant: %s\n",cstr);CHKERRQ(ierr); 121f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr); 122f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Residual selection: gammaA=%1.0e, gammaC=%1.0e\n", ngmres->gammaA, ngmres->gammaC);CHKERRQ(ierr); 123f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n", ngmres->epsilonB, ngmres->deltaB);CHKERRQ(ierr); 124a312c225SMatthew G Knepley } 125a312c225SMatthew G Knepley PetscFunctionReturn(0); 126a312c225SMatthew G Knepley } 127a312c225SMatthew G Knepley 128f109b39eSPeter Brune EXTERN_C_BEGIN 129f109b39eSPeter Brune #undef __FUNCT__ 130f109b39eSPeter Brune #define __FUNCT__ "SNESLineSearchSetType_NGMRES" 131f109b39eSPeter Brune PetscErrorCode SNESLineSearchSetType_NGMRES(SNES snes, SNESLineSearchType type) 132f109b39eSPeter Brune { 133f109b39eSPeter Brune PetscErrorCode ierr; 134f109b39eSPeter Brune PetscFunctionBegin; 135f109b39eSPeter Brune 136f109b39eSPeter Brune switch (type) { 137f109b39eSPeter Brune case SNES_LS_BASIC: 138f109b39eSPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchNo,PETSC_NULL);CHKERRQ(ierr); 139f109b39eSPeter Brune break; 140f109b39eSPeter Brune case SNES_LS_BASIC_NONORMS: 141f109b39eSPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms,PETSC_NULL);CHKERRQ(ierr); 142f109b39eSPeter Brune break; 143f109b39eSPeter Brune case SNES_LS_QUADRATIC: 144f109b39eSPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchQuadraticSecant,PETSC_NULL);CHKERRQ(ierr); 145f109b39eSPeter Brune break; 146f109b39eSPeter Brune default: 147f109b39eSPeter Brune SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,"Unknown line search type."); 148f109b39eSPeter Brune break; 149f109b39eSPeter Brune } 150f109b39eSPeter Brune snes->ls_type = type; 151f109b39eSPeter Brune PetscFunctionReturn(0); 152f109b39eSPeter Brune } 153f109b39eSPeter Brune EXTERN_C_END 154f109b39eSPeter Brune 15519653cdaSPeter Brune 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 */ 163f109b39eSPeter Brune Vec X, F, B, D, G, W, Y; 164f109b39eSPeter Brune 165f109b39eSPeter Brune /* candidate linear combination answers */ 166f109b39eSPeter Brune Vec XA, FA; 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; 175f109b39eSPeter Brune PetscReal fnorm, fAnorm, gnorm, ynorm, xnorm = 0.0; 17619653cdaSPeter Brune PetscReal nu; 17719653cdaSPeter Brune PetscScalar alph_total = 0.; 17819653cdaSPeter Brune PetscScalar qentry; 17928ed4a04SPeter Brune PetscInt i, j, k, k_restart, l, ivec, restart_count = 0; 18019653cdaSPeter Brune 18198b3e84cSPeter Brune /* solution selection data */ 18219653cdaSPeter Brune PetscBool selectA, selectRestart; 183f109b39eSPeter Brune PetscReal dnorm, dminnorm, dcurnorm; 184f109b39eSPeter Brune PetscReal fminnorm; 18519653cdaSPeter Brune 1861e633543SBarry Smith SNESConvergedReason reason; 187f109b39eSPeter Brune PetscBool lssucceed; 188a312c225SMatthew G Knepley PetscErrorCode ierr; 189a312c225SMatthew G Knepley 190a312c225SMatthew G Knepley PetscFunctionBegin; 19198b3e84cSPeter Brune /* variable initialization */ 192a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 193f109b39eSPeter Brune X = snes->vec_sol; 194f109b39eSPeter Brune F = snes->vec_func; 195f109b39eSPeter Brune B = snes->vec_rhs; 196f109b39eSPeter Brune XA = snes->vec_sol_update; 197f109b39eSPeter Brune FA = snes->work[0]; 198f109b39eSPeter Brune D = snes->work[1]; 199f109b39eSPeter Brune 200f109b39eSPeter Brune /* work for the line search */ 201f109b39eSPeter Brune Y = snes->work[2]; 202f109b39eSPeter Brune G = snes->work[3]; 203f109b39eSPeter Brune W = snes->work[4]; 204a312c225SMatthew G Knepley 205a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 206a312c225SMatthew G Knepley snes->iter = 0; 207a312c225SMatthew G Knepley snes->norm = 0.; 208a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 20919653cdaSPeter Brune 21098b3e84cSPeter Brune /* initialization */ 21119653cdaSPeter Brune 21298b3e84cSPeter Brune /* r = F(x) */ 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 } 21819653cdaSPeter Brune 21998b3e84cSPeter Brune /* nu = (r, r) */ 220f109b39eSPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 221f109b39eSPeter Brune fminnorm = fnorm; 222f109b39eSPeter Brune nu = fnorm*fnorm; 223f109b39eSPeter Brune if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation"); 22419653cdaSPeter Brune 22598b3e84cSPeter Brune /* q_{00} = nu */ 22619653cdaSPeter Brune Q(0,0) = nu; 227f109b39eSPeter Brune ngmres->fnorms[0] = fnorm; 228f109b39eSPeter Brune /* Fdot[0] = F */ 229f109b39eSPeter Brune ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr); 230f109b39eSPeter Brune ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr); 231087dfb9eSxuemin 232a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 233f109b39eSPeter Brune snes->norm = fnorm; 234a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 235f109b39eSPeter Brune SNESLogConvHistory(snes, fnorm, 0); 236f109b39eSPeter Brune ierr = SNESMonitor(snes, 0, fnorm);CHKERRQ(ierr); 237f109b39eSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 238a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 239a312c225SMatthew G Knepley 24019653cdaSPeter Brune k_restart = 1; 24119653cdaSPeter Brune l = 1; 24219653cdaSPeter Brune for (k=1; k<snes->max_its; k++) { 24398b3e84cSPeter Brune /* select which vector of the stored subspace will be updated */ 24498b3e84cSPeter Brune ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */ 24519653cdaSPeter Brune 24698b3e84cSPeter Brune /* Computation of x^M */ 2476634f59bSPeter Brune if (!snes->pc) { 248f109b39eSPeter Brune /* no preconditioner -- just take gradient descent with line search */ 249f109b39eSPeter Brune ierr = VecCopy(F, Y);CHKERRQ(ierr); 250f109b39eSPeter Brune ierr = VecScale(Y, -1.0);CHKERRQ(ierr); 251f109b39eSPeter Brune ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Y,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 252f109b39eSPeter Brune if (!lssucceed) { 253f109b39eSPeter Brune if (++snes->numFailures >= snes->maxFailures) { 254f109b39eSPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 255f109b39eSPeter Brune PetscFunctionReturn(0); 256f109b39eSPeter Brune } 257f109b39eSPeter Brune } 258f109b39eSPeter Brune fnorm = gnorm; 259f109b39eSPeter Brune ierr = VecCopy(G, F);CHKERRQ(ierr); 260f109b39eSPeter Brune ierr = VecCopy(W, X);CHKERRQ(ierr); 2616634f59bSPeter Brune } else { 262f109b39eSPeter Brune ierr = SNESSolve(snes->pc, B, X);CHKERRQ(ierr); 2636634f59bSPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 2641e633543SBarry Smith if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2651e633543SBarry Smith snes->reason = SNES_DIVERGED_INNER; 2661e633543SBarry Smith PetscFunctionReturn(0); 2671e633543SBarry Smith } 268f109b39eSPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 269f109b39eSPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 2706634f59bSPeter Brune } 2711e633543SBarry Smith 27298b3e84cSPeter Brune /* r = F(x) */ 273f109b39eSPeter Brune nu = fnorm*fnorm; 274f109b39eSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; /* the minimum norm is now of F^M */ 27519653cdaSPeter Brune 27698b3e84cSPeter Brune /* construct the right hand side and xi factors */ 27719653cdaSPeter Brune for (i = 0; i < l; i++) { 278f109b39eSPeter Brune ierr = VecDot(Fdot[i], F, &xi[i]);CHKERRQ(ierr); 27919653cdaSPeter Brune beta[i] = nu - xi[i]; 28019653cdaSPeter Brune } 28119653cdaSPeter Brune 28298b3e84cSPeter Brune /* construct h */ 28319653cdaSPeter Brune for (j = 0; j < l; j++) { 28419653cdaSPeter Brune for (i = 0; i < l; i++) { 28519653cdaSPeter Brune H(i, j) = Q(i, j) - xi[i] - xi[j] + nu; 28619653cdaSPeter Brune } 28719653cdaSPeter Brune } 288f109b39eSPeter Brune 289f109b39eSPeter Brune if(l == 1) { 290f109b39eSPeter Brune /* simply set alpha[0] = beta[0] / H[0, 0] */ 291f109b39eSPeter Brune beta[0] = beta[0] / H(0, 0); 292f109b39eSPeter Brune } else { 29319653cdaSPeter Brune #ifdef PETSC_MISSING_LAPACK_GELSS 29419653cdaSPeter Brune SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "NGMRES with LS requires the LAPACK GELSS routine."); 2954a0c5b0cSMatthew G Knepley #else 29619653cdaSPeter Brune ngmres->m = PetscBLASIntCast(l); 29719653cdaSPeter Brune ngmres->n = PetscBLASIntCast(l); 29819653cdaSPeter Brune ngmres->info = PetscBLASIntCast(0); 29919653cdaSPeter Brune ngmres->rcond = -1.; 30019653cdaSPeter Brune #ifdef PETSC_USE_COMPLEX 30119653cdaSPeter Brune LAPACKgelss_(&ngmres->m, 30219653cdaSPeter Brune &ngmres->n, 30319653cdaSPeter Brune &ngmres->nrhs, 30419653cdaSPeter Brune ngmres->h, 30519653cdaSPeter Brune &ngmres->lda, 30619653cdaSPeter Brune ngmres->beta, 30719653cdaSPeter Brune &ngmres->ldb, 30819653cdaSPeter Brune ngmres->s, 30919653cdaSPeter Brune &ngmres->rcond, 31019653cdaSPeter Brune &ngmres->rank, 31119653cdaSPeter Brune ngmres->work, 31219653cdaSPeter Brune &ngmres->lwork, 31319653cdaSPeter Brune ngmres->rwork, 31419653cdaSPeter Brune &ngmres->info); 31519653cdaSPeter Brune #else 31619653cdaSPeter Brune LAPACKgelss_(&ngmres->m, 31719653cdaSPeter Brune &ngmres->n, 31819653cdaSPeter Brune &ngmres->nrhs, 31919653cdaSPeter Brune ngmres->h, 32019653cdaSPeter Brune &ngmres->lda, 32119653cdaSPeter Brune ngmres->beta, 32219653cdaSPeter Brune &ngmres->ldb, 32319653cdaSPeter Brune ngmres->s, 32419653cdaSPeter Brune &ngmres->rcond, 32519653cdaSPeter Brune &ngmres->rank, 32619653cdaSPeter Brune ngmres->work, 32719653cdaSPeter Brune &ngmres->lwork, 32819653cdaSPeter Brune &ngmres->info); 32919653cdaSPeter Brune #endif 33019653cdaSPeter Brune if (ngmres->info < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to GELSS"); 33119653cdaSPeter Brune if (ngmres->info > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SVD failed to converge"); 332a312c225SMatthew G Knepley #endif 333f109b39eSPeter Brune } 334a312c225SMatthew G Knepley 33519653cdaSPeter Brune alph_total = 0.; 33619653cdaSPeter Brune for (i = 0; i < l; i++) { 33719653cdaSPeter Brune alph_total += beta[i]; 338c0bbabecSxuemin } 339f109b39eSPeter Brune 340f109b39eSPeter Brune ierr = VecCopy(X, XA);CHKERRQ(ierr); 341f109b39eSPeter Brune ierr = VecScale(XA, 1. - alph_total);CHKERRQ(ierr); 342087dfb9eSxuemin 34319653cdaSPeter Brune for(i=0;i<l;i++){ 344f109b39eSPeter Brune ierr= VecAXPY(XA, beta[i], Xdot[i]);CHKERRQ(ierr); 34519653cdaSPeter Brune } 346f109b39eSPeter Brune ierr = SNESComputeFunction(snes, XA, FA);CHKERRQ(ierr); 347f109b39eSPeter Brune ierr = VecNorm(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 34819653cdaSPeter Brune 34919653cdaSPeter Brune selectA = PETSC_TRUE; 35098b3e84cSPeter Brune /* Conditions for choosing the accelerated answer */ 35119653cdaSPeter Brune 35298b3e84cSPeter Brune /* Criterion A -- the norm of the function isn't increased above the minimum by too much */ 353f109b39eSPeter Brune if (fAnorm >= ngmres->gammaA*fminnorm) { 35419653cdaSPeter Brune selectA = PETSC_FALSE; 355a312c225SMatthew G Knepley } 356087dfb9eSxuemin 35798b3e84cSPeter Brune /* Criterion B -- the choice of x^A isn't too close to some other choice */ 358f109b39eSPeter Brune ierr=VecCopy(XA, D);CHKERRQ(ierr); 359f109b39eSPeter Brune ierr=VecAXPY(D, -1.0, X);CHKERRQ(ierr); 360f109b39eSPeter Brune ierr=VecNorm(D, NORM_2, &dnorm);CHKERRQ(ierr); 361f109b39eSPeter Brune dminnorm = -1.0; 36219653cdaSPeter Brune for(i=0;i<l;i++) { 363f109b39eSPeter Brune ierr=VecCopy(XA, D);CHKERRQ(ierr); 364f109b39eSPeter Brune ierr=VecAXPY(D, -1.0, Xdot[i]);CHKERRQ(ierr); 365f109b39eSPeter Brune ierr=VecNorm(D, NORM_2, &dcurnorm);CHKERRQ(ierr); 366f109b39eSPeter Brune if((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm; 36719653cdaSPeter Brune } 368*cf22de31SPeter Brune if (ngmres->epsilonB*dnorm<dminnorm || PetscSqrtReal(fnorm)<ngmres->deltaB*PetscSqrtReal(fminnorm)) { 36919653cdaSPeter Brune } else { 37019653cdaSPeter Brune selectA=PETSC_FALSE; 37119653cdaSPeter Brune } 372211b2d39SPeter Brune 373087dfb9eSxuemin 37419653cdaSPeter Brune if (selectA) { 375dfbf837cSBarry Smith if (ngmres->monitor) { 376f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_A, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fnorm);CHKERRQ(ierr); 377dfbf837cSBarry Smith } 37898b3e84cSPeter Brune /* copy it over */ 379f109b39eSPeter Brune fnorm = fAnorm; 380f109b39eSPeter Brune nu = fnorm*fnorm; 381f109b39eSPeter Brune ierr = VecCopy(FA, F);CHKERRQ(ierr); 382f109b39eSPeter Brune ierr = VecCopy(XA, X);CHKERRQ(ierr); 38319653cdaSPeter Brune } else { 384dfbf837cSBarry Smith if (ngmres->monitor) { 385f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_M, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fnorm);CHKERRQ(ierr); 386dfbf837cSBarry Smith } 38719653cdaSPeter Brune } 388211b2d39SPeter Brune 38919653cdaSPeter Brune selectRestart = PETSC_FALSE; 39019653cdaSPeter Brune 39198b3e84cSPeter Brune /* difference stagnation restart */ 392*cf22de31SPeter Brune if((ngmres->epsilonB*dnorm > dminnorm) && (PetscSqrtReal(fAnorm) > ngmres->deltaB*PetscSqrtReal(fminnorm))) { 393dfbf837cSBarry Smith if (ngmres->monitor) { 394f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "difference restart: %e > %e\n", ngmres->epsilonB*dnorm, dminnorm);CHKERRQ(ierr); 395dfbf837cSBarry Smith } 39619653cdaSPeter Brune selectRestart = PETSC_TRUE; 39719653cdaSPeter Brune } 39898b3e84cSPeter Brune /* residual stagnation restart */ 399*cf22de31SPeter Brune if (PetscSqrtReal(fAnorm) > ngmres->gammaC*PetscSqrtReal(fminnorm)) { 400dfbf837cSBarry Smith if (ngmres->monitor) { 401*cf22de31SPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "residual restart: %e > %e\n", PetscSqrtReal(fAnorm), ngmres->gammaC*PetscSqrtReal(fminnorm));CHKERRQ(ierr); 402dfbf837cSBarry Smith } 40319653cdaSPeter Brune selectRestart = PETSC_TRUE; 40419653cdaSPeter Brune } 40519653cdaSPeter Brune 40628ed4a04SPeter Brune /* if the restart conditions persist for more than restart_it iterations, restart. */ 40719653cdaSPeter Brune if (selectRestart) { 40828ed4a04SPeter Brune restart_count++; 40928ed4a04SPeter Brune } else { 41028ed4a04SPeter Brune restart_count = 0; 41128ed4a04SPeter Brune } 41228ed4a04SPeter Brune 41328ed4a04SPeter Brune /* restart after restart conditions have persisted for a fixed number of iterations */ 41428ed4a04SPeter Brune if (restart_count >= ngmres->restart_it) { 415dfbf837cSBarry Smith if (ngmres->monitor){ 416dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Restarted at iteration %d\n", k_restart);CHKERRQ(ierr); 417dfbf837cSBarry Smith } 41828ed4a04SPeter Brune restart_count = 0; 41919653cdaSPeter Brune k_restart = 1; 42019653cdaSPeter Brune l = 1; 42198b3e84cSPeter Brune /* q_{00} = nu */ 422f109b39eSPeter Brune ngmres->fnorms[0] = fnorm; 423f109b39eSPeter Brune nu = fnorm*fnorm; 42419653cdaSPeter Brune Q(0,0) = nu; 425f109b39eSPeter Brune /* Fdot[0] = F */ 426f109b39eSPeter Brune ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr); 427f109b39eSPeter Brune ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr); 42819653cdaSPeter Brune } else { 42998b3e84cSPeter Brune /* select the current size of the subspace */ 4301e633543SBarry Smith if (l < ngmres->msize) l++; 43119653cdaSPeter Brune k_restart++; 43298b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 433f109b39eSPeter Brune ierr = VecCopy(F, Fdot[ivec]);CHKERRQ(ierr); 434f109b39eSPeter Brune ierr = VecCopy(X, Xdot[ivec]);CHKERRQ(ierr); 435f109b39eSPeter Brune ngmres->fnorms[ivec] = fnorm; 436f109b39eSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; /* the minimum norm is now of r^A */ 43719653cdaSPeter Brune for (i = 0; i < l; i++) { 438f109b39eSPeter Brune ierr = VecDot(F, Fdot[i], &qentry);CHKERRQ(ierr); 43919653cdaSPeter Brune Q(i, ivec) = qentry; 44019653cdaSPeter Brune Q(ivec, i) = qentry; 44119653cdaSPeter Brune } 44219653cdaSPeter Brune } 44319653cdaSPeter Brune 4448409ca45SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 445087dfb9eSxuemin snes->iter = k; 446f109b39eSPeter Brune snes->norm = fnorm; 4478409ca45SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 4488409ca45SMatthew G Knepley SNESLogConvHistory(snes, snes->norm, snes->iter); 4498409ca45SMatthew G Knepley ierr = SNESMonitor(snes, snes->iter, snes->norm);CHKERRQ(ierr); 4508409ca45SMatthew G Knepley 451f109b39eSPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 452087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 453a312c225SMatthew G Knepley } 454a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 455a312c225SMatthew G Knepley PetscFunctionReturn(0); 456a312c225SMatthew G Knepley } 457a312c225SMatthew G Knepley 458dfbf837cSBarry Smith /*MC 459dfbf837cSBarry Smith SNESNGMRES - The Nonlinear Generalized Minimum Residual (NGMRES) method of Oosterlee and Washio. 460a312c225SMatthew G Knepley 461dfbf837cSBarry Smith Level: beginner 462dfbf837cSBarry Smith 463dfbf837cSBarry Smith "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 464dfbf837cSBarry Smith SIAM Journal on Scientific Computing, 21(5), 2000. 465dfbf837cSBarry Smith 466dfbf837cSBarry Smith This is also the same as the algorithm called Anderson acceleration introduced in "D. G. Anderson. Iterative procedures for nonlinear integral equations. 467dfbf837cSBarry Smith J. Assoc. Comput. Mach., 12:547–560, 1965." 468dfbf837cSBarry Smith 469dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 470dfbf837cSBarry Smith M*/ 471a312c225SMatthew G Knepley 472a312c225SMatthew G Knepley EXTERN_C_BEGIN 473a312c225SMatthew G Knepley #undef __FUNCT__ 474a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 475a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes) 476a312c225SMatthew G Knepley { 477a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 478a312c225SMatthew G Knepley PetscErrorCode ierr; 479a312c225SMatthew G Knepley 480a312c225SMatthew G Knepley PetscFunctionBegin; 481a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 482a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 483a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 484a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 485a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 486a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 487a312c225SMatthew G Knepley 48842f4f86dSBarry Smith snes->usespc = PETSC_TRUE; 4892c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 4902c155ee1SBarry Smith 491a312c225SMatthew G Knepley ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr); 492a312c225SMatthew G Knepley snes->data = (void*) ngmres; 49319653cdaSPeter Brune ngmres->msize = 10; 49419653cdaSPeter Brune 49528ed4a04SPeter Brune ngmres->restart_it = 2; 496f109b39eSPeter Brune ngmres->gammaA = 2.0; 497f109b39eSPeter Brune ngmres->gammaC = 2.0; 498cac108bcSPeter Brune ngmres->deltaB = 0.9; 499cac108bcSPeter Brune ngmres->epsilonB = 0.1; 500f109b39eSPeter Brune ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetType_C","SNESLineSearchSetType_NGMRES",SNESLineSearchSetType_NGMRES);CHKERRQ(ierr); 501f109b39eSPeter Brune ierr = SNESLineSearchSetType(snes, SNES_LS_QUADRATIC);CHKERRQ(ierr); 502a312c225SMatthew G Knepley PetscFunctionReturn(0); 503a312c225SMatthew G Knepley } 504a312c225SMatthew G Knepley EXTERN_C_END 505