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; 16*f109b39eSPeter Brune ierr = VecDestroyVecs(ngmres->msize, &ngmres->Fdot);CHKERRQ(ierr); 17*f109b39eSPeter 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; 32*f109b39eSPeter 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, 60*f109b39eSPeter 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 76*f109b39eSPeter Brune ierr = VecDuplicateVecs(snes->vec_sol, ngmres->msize, &ngmres->Xdot);CHKERRQ(ierr); 77*f109b39eSPeter Brune ierr = VecDuplicateVecs(snes->vec_sol, ngmres->msize, &ngmres->Fdot);CHKERRQ(ierr); 78*f109b39eSPeter 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); 9319653cdaSPeter Brune ierr = PetscOptionsInt("-snes_ngmres_restart", "Maximum iterations before restart.", "SNES", ngmres->k_rmax, &ngmres->k_rmax, 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; 113*f109b39eSPeter 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) { 119*f109b39eSPeter Brune cstr = SNESLineSearchTypeName(snes->ls_type); 120*f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer," line search variant: %s\n",cstr);CHKERRQ(ierr); 121*f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr); 122*f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Maximum iterations before total restart: %d\n", ngmres->k_rmax);CHKERRQ(ierr); 123*f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Residual selection: gammaA=%1.0e, gammaC=%1.0e\n", ngmres->gammaA, ngmres->gammaC);CHKERRQ(ierr); 124*f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n", ngmres->epsilonB, ngmres->deltaB);CHKERRQ(ierr); 125a312c225SMatthew G Knepley } 126a312c225SMatthew G Knepley PetscFunctionReturn(0); 127a312c225SMatthew G Knepley } 128a312c225SMatthew G Knepley 129*f109b39eSPeter Brune EXTERN_C_BEGIN 130*f109b39eSPeter Brune #undef __FUNCT__ 131*f109b39eSPeter Brune #define __FUNCT__ "SNESLineSearchSetType_NGMRES" 132*f109b39eSPeter Brune PetscErrorCode SNESLineSearchSetType_NGMRES(SNES snes, SNESLineSearchType type) 133*f109b39eSPeter Brune { 134*f109b39eSPeter Brune PetscErrorCode ierr; 135*f109b39eSPeter Brune PetscFunctionBegin; 136*f109b39eSPeter Brune 137*f109b39eSPeter Brune switch (type) { 138*f109b39eSPeter Brune case SNES_LS_BASIC: 139*f109b39eSPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchNo,PETSC_NULL);CHKERRQ(ierr); 140*f109b39eSPeter Brune break; 141*f109b39eSPeter Brune case SNES_LS_BASIC_NONORMS: 142*f109b39eSPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms,PETSC_NULL);CHKERRQ(ierr); 143*f109b39eSPeter Brune break; 144*f109b39eSPeter Brune case SNES_LS_QUADRATIC: 145*f109b39eSPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchQuadraticSecant,PETSC_NULL);CHKERRQ(ierr); 146*f109b39eSPeter Brune break; 147*f109b39eSPeter Brune default: 148*f109b39eSPeter Brune SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,"Unknown line search type."); 149*f109b39eSPeter Brune break; 150*f109b39eSPeter Brune } 151*f109b39eSPeter Brune snes->ls_type = type; 152*f109b39eSPeter Brune PetscFunctionReturn(0); 153*f109b39eSPeter Brune } 154*f109b39eSPeter Brune EXTERN_C_END 155*f109b39eSPeter Brune 15619653cdaSPeter Brune 157a312c225SMatthew G Knepley #undef __FUNCT__ 158a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES" 159211b2d39SPeter Brune 160a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes) 161a312c225SMatthew G Knepley { 162087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 16398b3e84cSPeter Brune /* present solution, residual, and preconditioned residual */ 164*f109b39eSPeter Brune Vec X, F, B, D, G, W, Y; 165*f109b39eSPeter Brune 166*f109b39eSPeter Brune /* candidate linear combination answers */ 167*f109b39eSPeter Brune Vec XA, FA; 16819653cdaSPeter Brune 16998b3e84cSPeter Brune /* previous iterations to construct the subspace */ 170*f109b39eSPeter Brune Vec *Fdot = ngmres->Fdot; 171*f109b39eSPeter Brune Vec *Xdot = ngmres->Xdot; 17219653cdaSPeter Brune 17398b3e84cSPeter Brune /* coefficients and RHS to the minimization problem */ 17419653cdaSPeter Brune PetscScalar *beta = ngmres->beta; 17519653cdaSPeter Brune PetscScalar *xi = ngmres->xi; 176*f109b39eSPeter Brune PetscReal fnorm, fAnorm, gnorm, ynorm, xnorm = 0.0; 17719653cdaSPeter Brune PetscReal nu; 17819653cdaSPeter Brune PetscScalar alph_total = 0.; 17919653cdaSPeter Brune PetscScalar qentry; 18019653cdaSPeter Brune PetscInt i, j, k, k_restart, l, ivec; 18119653cdaSPeter Brune 18298b3e84cSPeter Brune /* solution selection data */ 18319653cdaSPeter Brune PetscBool selectA, selectRestart; 184*f109b39eSPeter Brune PetscReal dnorm, dminnorm, dcurnorm; 185*f109b39eSPeter Brune PetscReal fminnorm; 18619653cdaSPeter Brune 1871e633543SBarry Smith SNESConvergedReason reason; 188*f109b39eSPeter Brune PetscBool lssucceed; 189a312c225SMatthew G Knepley PetscErrorCode ierr; 190a312c225SMatthew G Knepley 191a312c225SMatthew G Knepley PetscFunctionBegin; 19298b3e84cSPeter Brune /* variable initialization */ 193a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 194*f109b39eSPeter Brune X = snes->vec_sol; 195*f109b39eSPeter Brune F = snes->vec_func; 196*f109b39eSPeter Brune B = snes->vec_rhs; 197*f109b39eSPeter Brune XA = snes->vec_sol_update; 198*f109b39eSPeter Brune FA = snes->work[0]; 199*f109b39eSPeter Brune D = snes->work[1]; 200*f109b39eSPeter Brune 201*f109b39eSPeter Brune /* work for the line search */ 202*f109b39eSPeter Brune Y = snes->work[2]; 203*f109b39eSPeter Brune G = snes->work[3]; 204*f109b39eSPeter Brune W = snes->work[4]; 205a312c225SMatthew G Knepley 206a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 207a312c225SMatthew G Knepley snes->iter = 0; 208a312c225SMatthew G Knepley snes->norm = 0.; 209a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 21019653cdaSPeter Brune 21198b3e84cSPeter Brune /* initialization */ 21219653cdaSPeter Brune 21398b3e84cSPeter Brune /* r = F(x) */ 214*f109b39eSPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 215a312c225SMatthew G Knepley if (snes->domainerror) { 216a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 217a312c225SMatthew G Knepley PetscFunctionReturn(0); 218a312c225SMatthew G Knepley } 21919653cdaSPeter Brune 22098b3e84cSPeter Brune /* nu = (r, r) */ 221*f109b39eSPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 222*f109b39eSPeter Brune fminnorm = fnorm; 223*f109b39eSPeter Brune nu = fnorm*fnorm; 224*f109b39eSPeter Brune if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation"); 22519653cdaSPeter Brune 22698b3e84cSPeter Brune /* q_{00} = nu */ 22719653cdaSPeter Brune Q(0,0) = nu; 228*f109b39eSPeter Brune ngmres->fnorms[0] = fnorm; 229*f109b39eSPeter Brune /* Fdot[0] = F */ 230*f109b39eSPeter Brune ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr); 231*f109b39eSPeter Brune ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr); 232087dfb9eSxuemin 233a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 234*f109b39eSPeter Brune snes->norm = fnorm; 235a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 236*f109b39eSPeter Brune SNESLogConvHistory(snes, fnorm, 0); 237*f109b39eSPeter Brune ierr = SNESMonitor(snes, 0, fnorm);CHKERRQ(ierr); 238*f109b39eSPeter 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; 24319653cdaSPeter Brune for (k=1; k<snes->max_its; 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 */ 2486634f59bSPeter Brune if (!snes->pc) { 249*f109b39eSPeter Brune /* no preconditioner -- just take gradient descent with line search */ 250*f109b39eSPeter Brune ierr = VecCopy(F, Y);CHKERRQ(ierr); 251*f109b39eSPeter Brune ierr = VecScale(Y, -1.0);CHKERRQ(ierr); 252*f109b39eSPeter Brune ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Y,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 253*f109b39eSPeter Brune if (!lssucceed) { 254*f109b39eSPeter Brune if (++snes->numFailures >= snes->maxFailures) { 255*f109b39eSPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 256*f109b39eSPeter Brune PetscFunctionReturn(0); 257*f109b39eSPeter Brune } 258*f109b39eSPeter Brune } 259*f109b39eSPeter Brune fnorm = gnorm; 260*f109b39eSPeter Brune ierr = VecCopy(G, F);CHKERRQ(ierr); 261*f109b39eSPeter Brune ierr = VecCopy(W, X);CHKERRQ(ierr); 2626634f59bSPeter Brune } else { 263*f109b39eSPeter Brune ierr = SNESSolve(snes->pc, B, X);CHKERRQ(ierr); 2646634f59bSPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 2651e633543SBarry Smith if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2661e633543SBarry Smith snes->reason = SNES_DIVERGED_INNER; 2671e633543SBarry Smith PetscFunctionReturn(0); 2681e633543SBarry Smith } 269*f109b39eSPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 270*f109b39eSPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 2716634f59bSPeter Brune } 2721e633543SBarry Smith 27398b3e84cSPeter Brune /* r = F(x) */ 274*f109b39eSPeter Brune nu = fnorm*fnorm; 275*f109b39eSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; /* the minimum norm is now of F^M */ 27619653cdaSPeter Brune 27798b3e84cSPeter Brune /* construct the right hand side and xi factors */ 27819653cdaSPeter Brune for (i = 0; i < l; i++) { 279*f109b39eSPeter Brune ierr = VecDot(Fdot[i], F, &xi[i]);CHKERRQ(ierr); 28019653cdaSPeter Brune beta[i] = nu - xi[i]; 28119653cdaSPeter Brune } 28219653cdaSPeter Brune 28398b3e84cSPeter Brune /* construct h */ 28419653cdaSPeter Brune for (j = 0; j < l; j++) { 28519653cdaSPeter Brune for (i = 0; i < l; i++) { 28619653cdaSPeter Brune H(i, j) = Q(i, j) - xi[i] - xi[j] + nu; 28719653cdaSPeter Brune } 28819653cdaSPeter Brune } 289*f109b39eSPeter Brune 290*f109b39eSPeter Brune if(l == 1) { 291*f109b39eSPeter Brune /* simply set alpha[0] = beta[0] / H[0, 0] */ 292*f109b39eSPeter Brune beta[0] = beta[0] / H(0, 0); 293*f109b39eSPeter Brune } else { 29419653cdaSPeter Brune #ifdef PETSC_MISSING_LAPACK_GELSS 29519653cdaSPeter Brune SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "NGMRES with LS requires the LAPACK GELSS routine."); 2964a0c5b0cSMatthew G Knepley #else 29719653cdaSPeter Brune ngmres->m = PetscBLASIntCast(l); 29819653cdaSPeter Brune ngmres->n = PetscBLASIntCast(l); 29919653cdaSPeter Brune ngmres->info = PetscBLASIntCast(0); 30019653cdaSPeter Brune ngmres->rcond = -1.; 30119653cdaSPeter Brune #ifdef PETSC_USE_COMPLEX 30219653cdaSPeter Brune LAPACKgelss_(&ngmres->m, 30319653cdaSPeter Brune &ngmres->n, 30419653cdaSPeter Brune &ngmres->nrhs, 30519653cdaSPeter Brune ngmres->h, 30619653cdaSPeter Brune &ngmres->lda, 30719653cdaSPeter Brune ngmres->beta, 30819653cdaSPeter Brune &ngmres->ldb, 30919653cdaSPeter Brune ngmres->s, 31019653cdaSPeter Brune &ngmres->rcond, 31119653cdaSPeter Brune &ngmres->rank, 31219653cdaSPeter Brune ngmres->work, 31319653cdaSPeter Brune &ngmres->lwork, 31419653cdaSPeter Brune ngmres->rwork, 31519653cdaSPeter Brune &ngmres->info); 31619653cdaSPeter Brune #else 31719653cdaSPeter Brune LAPACKgelss_(&ngmres->m, 31819653cdaSPeter Brune &ngmres->n, 31919653cdaSPeter Brune &ngmres->nrhs, 32019653cdaSPeter Brune ngmres->h, 32119653cdaSPeter Brune &ngmres->lda, 32219653cdaSPeter Brune ngmres->beta, 32319653cdaSPeter Brune &ngmres->ldb, 32419653cdaSPeter Brune ngmres->s, 32519653cdaSPeter Brune &ngmres->rcond, 32619653cdaSPeter Brune &ngmres->rank, 32719653cdaSPeter Brune ngmres->work, 32819653cdaSPeter Brune &ngmres->lwork, 32919653cdaSPeter Brune &ngmres->info); 33019653cdaSPeter Brune #endif 33119653cdaSPeter Brune if (ngmres->info < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to GELSS"); 33219653cdaSPeter Brune if (ngmres->info > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SVD failed to converge"); 333a312c225SMatthew G Knepley #endif 334*f109b39eSPeter Brune } 335a312c225SMatthew G Knepley 33619653cdaSPeter Brune alph_total = 0.; 33719653cdaSPeter Brune for (i = 0; i < l; i++) { 33819653cdaSPeter Brune alph_total += beta[i]; 339c0bbabecSxuemin } 340*f109b39eSPeter Brune 341*f109b39eSPeter Brune ierr = VecCopy(X, XA);CHKERRQ(ierr); 342*f109b39eSPeter Brune ierr = VecScale(XA, 1. - alph_total);CHKERRQ(ierr); 343087dfb9eSxuemin 34419653cdaSPeter Brune for(i=0;i<l;i++){ 345*f109b39eSPeter Brune ierr= VecAXPY(XA, beta[i], Xdot[i]);CHKERRQ(ierr); 34619653cdaSPeter Brune } 347*f109b39eSPeter Brune ierr = SNESComputeFunction(snes, XA, FA);CHKERRQ(ierr); 348*f109b39eSPeter Brune ierr = VecNorm(FA, NORM_2, &fAnorm);CHKERRQ(ierr); 34919653cdaSPeter Brune 35019653cdaSPeter Brune selectA = PETSC_TRUE; 35198b3e84cSPeter Brune /* Conditions for choosing the accelerated answer */ 35219653cdaSPeter Brune 35398b3e84cSPeter Brune /* Criterion A -- the norm of the function isn't increased above the minimum by too much */ 354*f109b39eSPeter Brune if (fAnorm >= ngmres->gammaA*fminnorm) { 35519653cdaSPeter Brune selectA = PETSC_FALSE; 356a312c225SMatthew G Knepley } 357087dfb9eSxuemin 35898b3e84cSPeter Brune /* Criterion B -- the choice of x^A isn't too close to some other choice */ 359*f109b39eSPeter Brune ierr=VecCopy(XA, D);CHKERRQ(ierr); 360*f109b39eSPeter Brune ierr=VecAXPY(D, -1.0, X);CHKERRQ(ierr); 361*f109b39eSPeter Brune ierr=VecNorm(D, NORM_2, &dnorm);CHKERRQ(ierr); 362*f109b39eSPeter Brune dminnorm = -1.0; 36319653cdaSPeter Brune for(i=0;i<l;i++) { 364*f109b39eSPeter Brune ierr=VecCopy(XA, D);CHKERRQ(ierr); 365*f109b39eSPeter Brune ierr=VecAXPY(D, -1.0, Xdot[i]);CHKERRQ(ierr); 366*f109b39eSPeter Brune ierr=VecNorm(D, NORM_2, &dcurnorm);CHKERRQ(ierr); 367*f109b39eSPeter Brune if((dcurnorm < dminnorm) || (dminnorm < 0.0)) dminnorm = dcurnorm; 36819653cdaSPeter Brune } 369*f109b39eSPeter Brune if (ngmres->epsilonB*dnorm<dminnorm || sqrt(fnorm)<ngmres->deltaB*sqrt(fminnorm)) { 37019653cdaSPeter Brune } else { 37119653cdaSPeter Brune selectA=PETSC_FALSE; 37219653cdaSPeter Brune } 373211b2d39SPeter Brune 374087dfb9eSxuemin 37519653cdaSPeter Brune if (selectA) { 376dfbf837cSBarry Smith if (ngmres->monitor) { 377*f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_A, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fnorm);CHKERRQ(ierr); 378dfbf837cSBarry Smith } 37998b3e84cSPeter Brune /* copy it over */ 380*f109b39eSPeter Brune fnorm = fAnorm; 381*f109b39eSPeter Brune nu = fnorm*fnorm; 382*f109b39eSPeter Brune ierr = VecCopy(FA, F);CHKERRQ(ierr); 383*f109b39eSPeter Brune ierr = VecCopy(XA, X);CHKERRQ(ierr); 38419653cdaSPeter Brune } else { 385dfbf837cSBarry Smith if (ngmres->monitor) { 386*f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked X_M, ||F_A||_2 = %e, ||F_M||_2 = %e\n", fAnorm, fnorm);CHKERRQ(ierr); 387dfbf837cSBarry Smith } 38819653cdaSPeter Brune } 389211b2d39SPeter Brune 39019653cdaSPeter Brune selectRestart = PETSC_FALSE; 39119653cdaSPeter Brune 39298b3e84cSPeter Brune /* maximum iteration criterion */ 39319653cdaSPeter Brune if (k_restart > ngmres->k_rmax) { 39419653cdaSPeter Brune selectRestart = PETSC_TRUE; 39519653cdaSPeter Brune } 39619653cdaSPeter Brune 39798b3e84cSPeter Brune /* difference stagnation restart */ 398*f109b39eSPeter Brune if((ngmres->epsilonB*dnorm > dminnorm) && (sqrt(fAnorm) > ngmres->deltaB*sqrt(fminnorm))) { 399dfbf837cSBarry Smith if (ngmres->monitor) { 400*f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "difference restart: %e > %e\n", ngmres->epsilonB*dnorm, dminnorm);CHKERRQ(ierr); 401dfbf837cSBarry Smith } 40219653cdaSPeter Brune selectRestart = PETSC_TRUE; 40319653cdaSPeter Brune } 40498b3e84cSPeter Brune /* residual stagnation restart */ 405*f109b39eSPeter Brune if (sqrt(fAnorm) > ngmres->gammaC*sqrt(fminnorm)) { 406dfbf837cSBarry Smith if (ngmres->monitor) { 407*f109b39eSPeter Brune ierr = PetscViewerASCIIPrintf(ngmres->monitor, "residual restart: %e > %e\n", sqrt(fAnorm), ngmres->gammaC*sqrt(fminnorm));CHKERRQ(ierr); 408dfbf837cSBarry Smith } 40919653cdaSPeter Brune selectRestart = PETSC_TRUE; 41019653cdaSPeter Brune } 41119653cdaSPeter Brune 41219653cdaSPeter Brune if (selectRestart) { 413dfbf837cSBarry Smith if (ngmres->monitor){ 414dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Restarted at iteration %d\n", k_restart);CHKERRQ(ierr); 415dfbf837cSBarry Smith } 41619653cdaSPeter Brune k_restart = 1; 41719653cdaSPeter Brune l = 1; 41898b3e84cSPeter Brune /* q_{00} = nu */ 419*f109b39eSPeter Brune ngmres->fnorms[0] = fnorm; 420*f109b39eSPeter Brune nu = fnorm*fnorm; 42119653cdaSPeter Brune Q(0,0) = nu; 422*f109b39eSPeter Brune /* Fdot[0] = F */ 423*f109b39eSPeter Brune ierr = VecCopy(X, Xdot[0]);CHKERRQ(ierr); 424*f109b39eSPeter Brune ierr = VecCopy(F, Fdot[0]);CHKERRQ(ierr); 42519653cdaSPeter Brune } else { 42698b3e84cSPeter Brune /* select the current size of the subspace */ 4271e633543SBarry Smith if (l < ngmres->msize) l++; 42819653cdaSPeter Brune k_restart++; 42998b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 430*f109b39eSPeter Brune ierr = VecCopy(F, Fdot[ivec]);CHKERRQ(ierr); 431*f109b39eSPeter Brune ierr = VecCopy(X, Xdot[ivec]);CHKERRQ(ierr); 432*f109b39eSPeter Brune ngmres->fnorms[ivec] = fnorm; 433*f109b39eSPeter Brune if (fminnorm > fnorm) fminnorm = fnorm; /* the minimum norm is now of r^A */ 43419653cdaSPeter Brune for (i = 0; i < l; i++) { 435*f109b39eSPeter Brune ierr = VecDot(F, Fdot[i], &qentry);CHKERRQ(ierr); 43619653cdaSPeter Brune Q(i, ivec) = qentry; 43719653cdaSPeter Brune Q(ivec, i) = qentry; 43819653cdaSPeter Brune } 43919653cdaSPeter Brune } 44019653cdaSPeter Brune 4418409ca45SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 442087dfb9eSxuemin snes->iter = k; 443*f109b39eSPeter Brune snes->norm = fnorm; 4448409ca45SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 4458409ca45SMatthew G Knepley SNESLogConvHistory(snes, snes->norm, snes->iter); 4468409ca45SMatthew G Knepley ierr = SNESMonitor(snes, snes->iter, snes->norm);CHKERRQ(ierr); 4478409ca45SMatthew G Knepley 448*f109b39eSPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 449087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 450a312c225SMatthew G Knepley } 451a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 452a312c225SMatthew G Knepley PetscFunctionReturn(0); 453a312c225SMatthew G Knepley } 454a312c225SMatthew G Knepley 455dfbf837cSBarry Smith /*MC 456dfbf837cSBarry Smith SNESNGMRES - The Nonlinear Generalized Minimum Residual (NGMRES) method of Oosterlee and Washio. 457a312c225SMatthew G Knepley 458dfbf837cSBarry Smith Level: beginner 459dfbf837cSBarry Smith 460dfbf837cSBarry Smith "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 461dfbf837cSBarry Smith SIAM Journal on Scientific Computing, 21(5), 2000. 462dfbf837cSBarry Smith 463dfbf837cSBarry Smith This is also the same as the algorithm called Anderson acceleration introduced in "D. G. Anderson. Iterative procedures for nonlinear integral equations. 464dfbf837cSBarry Smith J. Assoc. Comput. Mach., 12:547–560, 1965." 465dfbf837cSBarry Smith 466dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 467dfbf837cSBarry Smith M*/ 468a312c225SMatthew G Knepley 469a312c225SMatthew G Knepley EXTERN_C_BEGIN 470a312c225SMatthew G Knepley #undef __FUNCT__ 471a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 472a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes) 473a312c225SMatthew G Knepley { 474a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 475a312c225SMatthew G Knepley PetscErrorCode ierr; 476a312c225SMatthew G Knepley 477a312c225SMatthew G Knepley PetscFunctionBegin; 478a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 479a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 480a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 481a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 482a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 483a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 484a312c225SMatthew G Knepley 48542f4f86dSBarry Smith snes->usespc = PETSC_TRUE; 4862c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 4872c155ee1SBarry Smith 488a312c225SMatthew G Knepley ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr); 489a312c225SMatthew G Knepley snes->data = (void*) ngmres; 49019653cdaSPeter Brune ngmres->msize = 10; 49119653cdaSPeter Brune 492*f109b39eSPeter Brune ngmres->gammaA = 2.0; 493*f109b39eSPeter Brune ngmres->gammaC = 2.0; 494cac108bcSPeter Brune ngmres->deltaB = 0.9; 495cac108bcSPeter Brune ngmres->epsilonB = 0.1; 496cac108bcSPeter Brune ngmres->k_rmax = 200; 497*f109b39eSPeter Brune ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetType_C","SNESLineSearchSetType_NGMRES",SNESLineSearchSetType_NGMRES);CHKERRQ(ierr); 498*f109b39eSPeter Brune ierr = SNESLineSearchSetType(snes, SNES_LS_QUADRATIC);CHKERRQ(ierr); 499a312c225SMatthew G Knepley PetscFunctionReturn(0); 500a312c225SMatthew G Knepley } 501a312c225SMatthew G Knepley EXTERN_C_END 502