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; 1619653cdaSPeter Brune ierr = VecDestroyVecs(ngmres->msize, &ngmres->rdot);CHKERRQ(ierr); 1719653cdaSPeter 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; 32cac108bcSPeter Brune ierr = PetscFree5(ngmres->h, ngmres->beta, ngmres->xi, ngmres->r_norms, 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, 6019653cdaSPeter Brune msize,PetscReal,&ngmres->r_norms, 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); 66087dfb9eSxuemin 6719653cdaSPeter Brune ierr = PetscMemzero(ngmres->h,hsize*sizeof(PetscScalar));CHKERRQ(ierr); 6819653cdaSPeter Brune ierr = PetscMemzero(ngmres->q,hsize*sizeof(PetscScalar));CHKERRQ(ierr); 6919653cdaSPeter Brune ierr = PetscMemzero(ngmres->xi,msize*sizeof(PetscScalar));CHKERRQ(ierr); 7019653cdaSPeter Brune ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr); 71211b2d39SPeter Brune 7219653cdaSPeter Brune ngmres->lwork = 12*msize; 7319653cdaSPeter Brune #if PETSC_USE_COMPLEX 7419653cdaSPeter Brune ierr = PetscMalloc(sizeof(PetscReal)*ngmres->lwork,&ngmres->rwork); 7519653cdaSPeter Brune #endif 7619653cdaSPeter Brune ierr = PetscMalloc(sizeof(PetscScalar)*ngmres->lwork,&ngmres->work); 77211b2d39SPeter Brune 7819653cdaSPeter Brune ierr = VecDuplicateVecs(snes->vec_sol, ngmres->msize, &ngmres->xdot);CHKERRQ(ierr); 7919653cdaSPeter Brune ierr = VecDuplicateVecs(snes->vec_sol, ngmres->msize, &ngmres->rdot);CHKERRQ(ierr); 80732c72c5SBarry Smith ierr = SNESDefaultGetWork(snes, 3);CHKERRQ(ierr); 81a312c225SMatthew G Knepley PetscFunctionReturn(0); 82a312c225SMatthew G Knepley } 83a312c225SMatthew G Knepley 84a312c225SMatthew G Knepley #undef __FUNCT__ 85a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES" 86a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes) 87a312c225SMatthew G Knepley { 88a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 89a312c225SMatthew G Knepley PetscErrorCode ierr; 90dfbf837cSBarry Smith PetscBool debug; 91a312c225SMatthew G Knepley 92a312c225SMatthew G Knepley PetscFunctionBegin; 93a312c225SMatthew G Knepley ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr); 9419653cdaSPeter Brune ierr = PetscOptionsInt("-snes_ngmres_m", "Number of directions", "SNES", ngmres->msize, &ngmres->msize, PETSC_NULL);CHKERRQ(ierr); 9519653cdaSPeter Brune ierr = PetscOptionsInt("-snes_ngmres_restart", "Maximum iterations before restart.", "SNES", ngmres->k_rmax, &ngmres->k_rmax, PETSC_NULL);CHKERRQ(ierr); 96dfbf837cSBarry Smith ierr = PetscOptionsBool("-snes_ngmres_monitor", "Monitor actions of NGMRES", "SNES", ngmres->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);CHKERRQ(ierr); 97dfbf837cSBarry Smith if (debug) { 98dfbf837cSBarry Smith ngmres->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 99dfbf837cSBarry Smith } 1006a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_gammaA", "Residual selection constant", "SNES", ngmres->gammaA, &ngmres->gammaA, PETSC_NULL);CHKERRQ(ierr); 1016a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_gammaC", "Residual restart constant", "SNES", ngmres->gammaC, &ngmres->gammaC, PETSC_NULL);CHKERRQ(ierr); 1026a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES", ngmres->epsilonB, &ngmres->epsilonB, PETSC_NULL);CHKERRQ(ierr); 1036a7cf640SPeter Brune ierr = PetscOptionsReal("-snes_ngmres_deltaB", "Difference residual selection constant", "SNES", ngmres->deltaB, &ngmres->deltaB, PETSC_NULL);CHKERRQ(ierr); 104a312c225SMatthew G Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1056a7cf640SPeter Brune if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA; 106a312c225SMatthew G Knepley PetscFunctionReturn(0); 107a312c225SMatthew G Knepley } 108a312c225SMatthew G Knepley 109a312c225SMatthew G Knepley #undef __FUNCT__ 110a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES" 111a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes, PetscViewer viewer) 112a312c225SMatthew G Knepley { 113a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 114a312c225SMatthew G Knepley PetscBool iascii; 115a312c225SMatthew G Knepley PetscErrorCode ierr; 116a312c225SMatthew G Knepley 117a312c225SMatthew G Knepley PetscFunctionBegin; 118a312c225SMatthew G Knepley ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 119a312c225SMatthew G Knepley if (iascii) { 120a312c225SMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer, " Size of space %d\n", ngmres->msize);CHKERRQ(ierr); 121cac108bcSPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " Maximum iterations before restart %d\n", ngmres->k_rmax);CHKERRQ(ierr); 122a312c225SMatthew G Knepley } 123a312c225SMatthew G Knepley PetscFunctionReturn(0); 124a312c225SMatthew G Knepley } 125a312c225SMatthew G Knepley 12619653cdaSPeter Brune 127a312c225SMatthew G Knepley #undef __FUNCT__ 128a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES" 129211b2d39SPeter Brune 130a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes) 131a312c225SMatthew G Knepley { 132087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 13319653cdaSPeter Brune 13498b3e84cSPeter Brune /* present solution, residual, and preconditioned residual */ 135c878e8e6SPeter Brune Vec x, r, b, d; 13619653cdaSPeter Brune Vec x_A, r_A; 13719653cdaSPeter Brune 13898b3e84cSPeter Brune /* previous iterations to construct the subspace */ 13919653cdaSPeter Brune Vec *rdot = ngmres->rdot; 14019653cdaSPeter Brune Vec *xdot = ngmres->xdot; 14119653cdaSPeter Brune 14298b3e84cSPeter Brune /* coefficients and RHS to the minimization problem */ 14319653cdaSPeter Brune PetscScalar *beta = ngmres->beta; 14419653cdaSPeter Brune PetscScalar *xi = ngmres->xi; 14519653cdaSPeter Brune PetscReal r_norm, r_A_norm; 14619653cdaSPeter Brune PetscReal nu; 14719653cdaSPeter Brune PetscScalar alph_total = 0.; 14819653cdaSPeter Brune PetscScalar qentry; 14919653cdaSPeter Brune PetscInt i, j, k, k_restart, l, ivec; 15019653cdaSPeter Brune 15198b3e84cSPeter Brune /* solution selection data */ 15219653cdaSPeter Brune PetscBool selectA, selectRestart; 15319653cdaSPeter Brune PetscReal d_norm, d_min_norm, d_cur_norm; 15419653cdaSPeter Brune PetscReal r_min_norm; 15519653cdaSPeter Brune 1561e633543SBarry Smith SNESConvergedReason reason; 157a312c225SMatthew G Knepley PetscErrorCode ierr; 158a312c225SMatthew G Knepley 159a312c225SMatthew G Knepley PetscFunctionBegin; 16098b3e84cSPeter Brune /* variable initialization */ 161a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 16219653cdaSPeter Brune x = snes->vec_sol; 16319653cdaSPeter Brune r = snes->vec_func; 16419653cdaSPeter Brune b = snes->vec_rhs; 16519653cdaSPeter Brune x_A = snes->vec_sol_update; 166c878e8e6SPeter Brune r_A = snes->work[0]; 167c878e8e6SPeter Brune d = snes->work[1]; 168732c72c5SBarry Smith r = snes->work[2]; 169a312c225SMatthew G Knepley 170a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 171a312c225SMatthew G Knepley snes->iter = 0; 172a312c225SMatthew G Knepley snes->norm = 0.; 173a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 17419653cdaSPeter Brune 17598b3e84cSPeter Brune /* initialization */ 17619653cdaSPeter Brune 17798b3e84cSPeter Brune /* r = F(x) */ 17898b3e84cSPeter Brune ierr = SNESComputeFunction(snes, x, r);CHKERRQ(ierr); 179a312c225SMatthew G Knepley if (snes->domainerror) { 180a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 181a312c225SMatthew G Knepley PetscFunctionReturn(0); 182a312c225SMatthew G Knepley } 18319653cdaSPeter Brune 18498b3e84cSPeter Brune /* nu = (r, r) */ 18519653cdaSPeter Brune ierr = VecNorm(r, NORM_2, &r_norm);CHKERRQ(ierr); 18619653cdaSPeter Brune r_min_norm = r_norm; 18719653cdaSPeter Brune nu = r_norm*r_norm; 188dfbf837cSBarry Smith if (PetscIsInfOrNanReal(r_norm)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation"); 18919653cdaSPeter Brune 19098b3e84cSPeter Brune /* q_{00} = nu */ 19119653cdaSPeter Brune Q(0,0) = nu; 19219653cdaSPeter Brune ngmres->r_norms[0] = r_norm; 19398b3e84cSPeter Brune /* rdot[0] = r */ 19419653cdaSPeter Brune ierr = VecCopy(x, xdot[0]);CHKERRQ(ierr); 19519653cdaSPeter Brune ierr = VecCopy(r, rdot[0]);CHKERRQ(ierr); 196087dfb9eSxuemin 197a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 19819653cdaSPeter Brune snes->norm = r_norm; 199a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 20019653cdaSPeter Brune SNESLogConvHistory(snes, r_norm, 0); 20119653cdaSPeter Brune ierr = SNESMonitor(snes, 0, r_norm);CHKERRQ(ierr); 20219653cdaSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,r_norm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 203a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 204a312c225SMatthew G Knepley 20519653cdaSPeter Brune k_restart = 1; 20619653cdaSPeter Brune l = 1; 20719653cdaSPeter Brune for (k=1; k<snes->max_its; k++) { 208087dfb9eSxuemin 20998b3e84cSPeter Brune /* select which vector of the stored subspace will be updated */ 21098b3e84cSPeter Brune ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */ 21119653cdaSPeter Brune 21298b3e84cSPeter Brune /* Computation of x^M */ 2136634f59bSPeter Brune if (!snes->pc) { 2146634f59bSPeter Brune /* no preconditioner -- just take gradient descent */ 2156634f59bSPeter Brune ierr = VecAXPY(x, -1.0, r);CHKERRQ(ierr); 2166634f59bSPeter Brune } else { 2176634f59bSPeter Brune ierr = SNESSolve(snes->pc, b, x);CHKERRQ(ierr); 2186634f59bSPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 2191e633543SBarry Smith if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 2201e633543SBarry Smith snes->reason = SNES_DIVERGED_INNER; 2211e633543SBarry Smith PetscFunctionReturn(0); 2221e633543SBarry Smith } 2236634f59bSPeter Brune } 2241e633543SBarry Smith 22598b3e84cSPeter Brune /* r = F(x) */ 22619653cdaSPeter Brune ierr = SNESComputeFunction(snes, x, r);CHKERRQ(ierr); 22719653cdaSPeter Brune ierr = VecNorm(r, NORM_2, &r_norm);CHKERRQ(ierr); 22898b3e84cSPeter Brune /* nu = (r, r) */ 22919653cdaSPeter Brune ngmres->r_norms[ivec] = r_norm; 23019653cdaSPeter Brune nu = r_norm*r_norm; 23198b3e84cSPeter Brune if (r_min_norm > r_norm) r_min_norm = r_norm; /* the minimum norm is now of r^M */ 23219653cdaSPeter Brune 23398b3e84cSPeter Brune /* construct the right hand side and xi factors */ 23419653cdaSPeter Brune for (i = 0; i < l; i++) { 2351e633543SBarry Smith ierr = VecDot(rdot[i], r, &xi[i]);CHKERRQ(ierr); 23619653cdaSPeter Brune beta[i] = nu - xi[i]; 23719653cdaSPeter Brune } 23819653cdaSPeter Brune 23998b3e84cSPeter Brune /* construct h */ 24019653cdaSPeter Brune for (j = 0; j < l; j++) { 24119653cdaSPeter Brune for (i = 0; i < l; i++) { 24219653cdaSPeter Brune H(i, j) = Q(i, j) - xi[i] - xi[j] + nu; 24319653cdaSPeter Brune } 24419653cdaSPeter Brune } 24519653cdaSPeter Brune #ifdef PETSC_MISSING_LAPACK_GELSS 24619653cdaSPeter Brune SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "NGMRES with LS requires the LAPACK GELSS routine."); 2474a0c5b0cSMatthew G Knepley #else 24819653cdaSPeter Brune ngmres->m = PetscBLASIntCast(l); 24919653cdaSPeter Brune ngmres->n = PetscBLASIntCast(l); 25019653cdaSPeter Brune ngmres->info = PetscBLASIntCast(0); 25119653cdaSPeter Brune ngmres->rcond = -1.; 25219653cdaSPeter Brune #ifdef PETSC_USE_COMPLEX 25319653cdaSPeter Brune LAPACKgelss_(&ngmres->m, 25419653cdaSPeter Brune &ngmres->n, 25519653cdaSPeter Brune &ngmres->nrhs, 25619653cdaSPeter Brune ngmres->h, 25719653cdaSPeter Brune &ngmres->lda, 25819653cdaSPeter Brune ngmres->beta, 25919653cdaSPeter Brune &ngmres->ldb, 26019653cdaSPeter Brune ngmres->s, 26119653cdaSPeter Brune &ngmres->rcond, 26219653cdaSPeter Brune &ngmres->rank, 26319653cdaSPeter Brune ngmres->work, 26419653cdaSPeter Brune &ngmres->lwork, 26519653cdaSPeter Brune ngmres->rwork, 26619653cdaSPeter Brune &ngmres->info); 26719653cdaSPeter Brune #else 26819653cdaSPeter Brune LAPACKgelss_(&ngmres->m, 26919653cdaSPeter Brune &ngmres->n, 27019653cdaSPeter Brune &ngmres->nrhs, 27119653cdaSPeter Brune ngmres->h, 27219653cdaSPeter Brune &ngmres->lda, 27319653cdaSPeter Brune ngmres->beta, 27419653cdaSPeter Brune &ngmres->ldb, 27519653cdaSPeter Brune ngmres->s, 27619653cdaSPeter Brune &ngmres->rcond, 27719653cdaSPeter Brune &ngmres->rank, 27819653cdaSPeter Brune ngmres->work, 27919653cdaSPeter Brune &ngmres->lwork, 28019653cdaSPeter Brune &ngmres->info); 28119653cdaSPeter Brune #endif 28219653cdaSPeter Brune if (ngmres->info < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to GELSS"); 28319653cdaSPeter Brune if (ngmres->info > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SVD failed to converge"); 284a312c225SMatthew G Knepley #endif 285a312c225SMatthew G Knepley 28619653cdaSPeter Brune alph_total = 0.; 28719653cdaSPeter Brune for (i = 0; i < l; i++) { 28819653cdaSPeter Brune alph_total += beta[i]; 289c0bbabecSxuemin } 29019653cdaSPeter Brune ierr = VecCopy(x, x_A);CHKERRQ(ierr); 29119653cdaSPeter Brune ierr = VecScale(x_A, 1. - alph_total);CHKERRQ(ierr); 292087dfb9eSxuemin 29319653cdaSPeter Brune for(i=0;i<l;i++){ 29419653cdaSPeter Brune ierr= VecAXPY(x_A, beta[i], xdot[i]);CHKERRQ(ierr); 29519653cdaSPeter Brune } 29619653cdaSPeter Brune ierr = SNESComputeFunction(snes, x_A, r_A);CHKERRQ(ierr); 29719653cdaSPeter Brune ierr = VecNorm(r_A, NORM_2, &r_A_norm);CHKERRQ(ierr); 29819653cdaSPeter Brune 29919653cdaSPeter Brune selectA = PETSC_TRUE; 30098b3e84cSPeter Brune /* Conditions for choosing the accelerated answer */ 30119653cdaSPeter Brune 30298b3e84cSPeter Brune /* Criterion A -- the norm of the function isn't increased above the minimum by too much */ 30319653cdaSPeter Brune if (r_A_norm >= ngmres->gammaA*r_min_norm) { 30419653cdaSPeter Brune selectA = PETSC_FALSE; 305a312c225SMatthew G Knepley } 306087dfb9eSxuemin 30798b3e84cSPeter Brune /* Criterion B -- the choice of x^A isn't too close to some other choice */ 30819653cdaSPeter Brune ierr=VecCopy(x_A,d);CHKERRQ(ierr); 30919653cdaSPeter Brune ierr=VecAXPY(d,-1,x);CHKERRQ(ierr); 31019653cdaSPeter Brune ierr=VecNorm(d,NORM_2,&d_norm);CHKERRQ(ierr); 3119261d27aSPeter Brune d_min_norm = -1.0; 31219653cdaSPeter Brune for(i=0;i<l;i++) { 31319653cdaSPeter Brune ierr=VecCopy(x_A,d);CHKERRQ(ierr); 31419653cdaSPeter Brune ierr=VecAXPY(d,-1,xdot[i]);CHKERRQ(ierr); 31519653cdaSPeter Brune ierr=VecNorm(d,NORM_2,&d_cur_norm);CHKERRQ(ierr); 3169261d27aSPeter Brune if((d_cur_norm < d_min_norm) || (d_min_norm < 0.0)) d_min_norm = d_cur_norm; 31719653cdaSPeter Brune } 31819653cdaSPeter Brune if (ngmres->epsilonB*d_norm<d_min_norm || sqrt(r_norm)<ngmres->deltaB*sqrt(r_min_norm)) { 31919653cdaSPeter Brune } else { 32019653cdaSPeter Brune selectA=PETSC_FALSE; 32119653cdaSPeter Brune } 322211b2d39SPeter Brune 323087dfb9eSxuemin 32419653cdaSPeter Brune if (selectA) { 325dfbf837cSBarry Smith if (ngmres->monitor) { 326dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked r_A, ||r_A||_2 = %e, ||r_M||_2 = %e\n", r_A_norm, r_norm);CHKERRQ(ierr); 327dfbf837cSBarry Smith } 32898b3e84cSPeter Brune /* copy it over */ 32919653cdaSPeter Brune r_norm = r_A_norm; 33019653cdaSPeter Brune nu = r_norm*r_norm; 33119653cdaSPeter Brune ierr = VecCopy(r_A, r);CHKERRQ(ierr); 33219653cdaSPeter Brune ierr = VecCopy(x_A, x);CHKERRQ(ierr); 33319653cdaSPeter Brune } else { 334dfbf837cSBarry Smith if (ngmres->monitor) { 335dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked r_M, ||r_A||_2 = %e, ||r_M||_2 = %e\n", r_A_norm, r_norm);CHKERRQ(ierr); 336dfbf837cSBarry Smith } 33719653cdaSPeter Brune } 338211b2d39SPeter Brune 33919653cdaSPeter Brune selectRestart = PETSC_FALSE; 34019653cdaSPeter Brune 34198b3e84cSPeter Brune /* maximum iteration criterion */ 34219653cdaSPeter Brune if (k_restart > ngmres->k_rmax) { 34319653cdaSPeter Brune selectRestart = PETSC_TRUE; 34419653cdaSPeter Brune } 34519653cdaSPeter Brune 34698b3e84cSPeter Brune /* difference stagnation restart */ 347dfbf837cSBarry Smith if ((ngmres->epsilonB*d_norm > d_min_norm) && (sqrt(r_A_norm) > ngmres->deltaB*sqrt(r_min_norm))) { 348dfbf837cSBarry Smith if (ngmres->monitor) { 349dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "difference restart: %e > %e\n", ngmres->epsilonB*d_norm, d_min_norm);CHKERRQ(ierr); 350dfbf837cSBarry Smith } 35119653cdaSPeter Brune selectRestart = PETSC_TRUE; 35219653cdaSPeter Brune } 35319653cdaSPeter Brune 35498b3e84cSPeter Brune /* residual stagnation restart */ 35519653cdaSPeter Brune if (sqrt(r_A_norm) > ngmres->gammaC*sqrt(r_min_norm)) { 356dfbf837cSBarry Smith if (ngmres->monitor) { 357dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "residual restart: %e > %e\n", sqrt(r_A_norm), ngmres->gammaC*sqrt(r_min_norm));CHKERRQ(ierr); 358dfbf837cSBarry Smith } 35919653cdaSPeter Brune selectRestart = PETSC_TRUE; 36019653cdaSPeter Brune } 36119653cdaSPeter Brune 36219653cdaSPeter Brune if (selectRestart) { 363dfbf837cSBarry Smith if (ngmres->monitor){ 364dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Restarted at iteration %d\n", k_restart);CHKERRQ(ierr); 365dfbf837cSBarry Smith } 36619653cdaSPeter Brune k_restart = 1; 36719653cdaSPeter Brune l = 1; 36898b3e84cSPeter Brune /* q_{00} = nu */ 36919653cdaSPeter Brune ngmres->r_norms[0] = r_norm; 37019653cdaSPeter Brune nu = r_norm*r_norm; 37119653cdaSPeter Brune Q(0,0) = nu; 37298b3e84cSPeter Brune /* rdot[0] = r */ 37319653cdaSPeter Brune ierr = VecCopy(x, xdot[0]);CHKERRQ(ierr); 37419653cdaSPeter Brune ierr = VecCopy(r, rdot[0]);CHKERRQ(ierr); 37519653cdaSPeter Brune } else { 37698b3e84cSPeter Brune /* select the current size of the subspace */ 3771e633543SBarry Smith if (l < ngmres->msize) l++; 37819653cdaSPeter Brune k_restart++; 37998b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 38019653cdaSPeter Brune ierr = VecCopy(r, rdot[ivec]);CHKERRQ(ierr); 38119653cdaSPeter Brune ierr = VecCopy(x, xdot[ivec]);CHKERRQ(ierr); 38219653cdaSPeter Brune ngmres->r_norms[ivec] = r_norm; 38398b3e84cSPeter Brune if (r_min_norm > r_norm) r_min_norm = r_norm; /* the minimum norm is now of r^A */ 38419653cdaSPeter Brune for (i = 0; i < l; i++) { 3851e633543SBarry Smith ierr = VecDot(r, rdot[i], &qentry);CHKERRQ(ierr); 38619653cdaSPeter Brune Q(i, ivec) = qentry; 38719653cdaSPeter Brune Q(ivec, i) = qentry; 38819653cdaSPeter Brune } 38919653cdaSPeter Brune } 39019653cdaSPeter Brune 391*8409ca45SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 392087dfb9eSxuemin snes->iter = k; 393*8409ca45SMatthew G Knepley snes->norm = r_norm; 394*8409ca45SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 395*8409ca45SMatthew G Knepley SNESLogConvHistory(snes, snes->norm, snes->iter); 396*8409ca45SMatthew G Knepley ierr = SNESMonitor(snes, snes->iter, snes->norm);CHKERRQ(ierr); 397*8409ca45SMatthew G Knepley 39819653cdaSPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,r_norm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 399087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 400a312c225SMatthew G Knepley } 401a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 402a312c225SMatthew G Knepley PetscFunctionReturn(0); 403a312c225SMatthew G Knepley } 404a312c225SMatthew G Knepley 405dfbf837cSBarry Smith /*MC 406dfbf837cSBarry Smith SNESNGMRES - The Nonlinear Generalized Minimum Residual (NGMRES) method of Oosterlee and Washio. 407a312c225SMatthew G Knepley 408dfbf837cSBarry Smith Level: beginner 409dfbf837cSBarry Smith 410dfbf837cSBarry Smith "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 411dfbf837cSBarry Smith SIAM Journal on Scientific Computing, 21(5), 2000. 412dfbf837cSBarry Smith 413dfbf837cSBarry Smith This is also the same as the algorithm called Anderson acceleration introduced in "D. G. Anderson. Iterative procedures for nonlinear integral equations. 414dfbf837cSBarry Smith J. Assoc. Comput. Mach., 12:547–560, 1965." 415dfbf837cSBarry Smith 416dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 417dfbf837cSBarry Smith M*/ 418a312c225SMatthew G Knepley 419a312c225SMatthew G Knepley EXTERN_C_BEGIN 420a312c225SMatthew G Knepley #undef __FUNCT__ 421a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 422a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes) 423a312c225SMatthew G Knepley { 424a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 425a312c225SMatthew G Knepley PetscErrorCode ierr; 426a312c225SMatthew G Knepley 427a312c225SMatthew G Knepley PetscFunctionBegin; 428a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 429a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 430a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 431a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 432a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 433a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 434a312c225SMatthew G Knepley 43542f4f86dSBarry Smith snes->usespc = PETSC_TRUE; 4362c155ee1SBarry Smith snes->usesksp = PETSC_FALSE; 4372c155ee1SBarry Smith 438a312c225SMatthew G Knepley ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr); 439a312c225SMatthew G Knepley snes->data = (void*) ngmres; 44019653cdaSPeter Brune ngmres->msize = 10; 44119653cdaSPeter Brune 44219653cdaSPeter Brune ngmres->gammaA = 2.; 44319653cdaSPeter Brune ngmres->gammaC = 2.; 444cac108bcSPeter Brune ngmres->deltaB = 0.9; 445cac108bcSPeter Brune ngmres->epsilonB = 0.1; 446cac108bcSPeter Brune ngmres->k_rmax = 200; 4474a0c5b0cSMatthew G Knepley 448a312c225SMatthew G Knepley PetscFunctionReturn(0); 449a312c225SMatthew G Knepley } 450a312c225SMatthew G Knepley EXTERN_C_END 451