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; 90*dfbf837cSBarry 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); 96*dfbf837cSBarry Smith ierr = PetscOptionsBool("-snes_ngmres_monitor", "Monitor actions of NGMRES", "SNES", ngmres->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);CHKERRQ(ierr); 97*dfbf837cSBarry Smith if (debug) { 98*dfbf837cSBarry Smith ngmres->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 99*dfbf837cSBarry 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 { 1324a0c5b0cSMatthew G Knepley SNES pc; 133087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 13419653cdaSPeter Brune 13519653cdaSPeter Brune 13619653cdaSPeter Brune 13798b3e84cSPeter Brune /* present solution, residual, and preconditioned residual */ 138c878e8e6SPeter Brune Vec x, r, b, d; 13919653cdaSPeter Brune Vec x_A, r_A; 14019653cdaSPeter Brune 14198b3e84cSPeter Brune /* previous iterations to construct the subspace */ 14219653cdaSPeter Brune Vec *rdot = ngmres->rdot; 14319653cdaSPeter Brune Vec *xdot = ngmres->xdot; 14419653cdaSPeter Brune 14598b3e84cSPeter Brune /* coefficients and RHS to the minimization problem */ 14619653cdaSPeter Brune PetscScalar *beta = ngmres->beta; 14719653cdaSPeter Brune PetscScalar *xi = ngmres->xi; 14819653cdaSPeter Brune PetscReal r_norm, r_A_norm; 14919653cdaSPeter Brune PetscReal nu; 15019653cdaSPeter Brune PetscScalar alph_total = 0.; 15119653cdaSPeter Brune PetscScalar qentry; 15219653cdaSPeter Brune PetscInt i, j, k, k_restart, l, ivec; 15319653cdaSPeter Brune 15498b3e84cSPeter Brune /* solution selection data */ 15519653cdaSPeter Brune PetscBool selectA, selectRestart; 15619653cdaSPeter Brune PetscReal d_norm, d_min_norm, d_cur_norm; 15719653cdaSPeter Brune PetscReal r_min_norm; 15819653cdaSPeter Brune 159a312c225SMatthew G Knepley PetscErrorCode ierr; 160a312c225SMatthew G Knepley 161a312c225SMatthew G Knepley PetscFunctionBegin; 16298b3e84cSPeter Brune /* variable initialization */ 163a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 16419653cdaSPeter Brune x = snes->vec_sol; 16519653cdaSPeter Brune r = snes->vec_func; 16619653cdaSPeter Brune b = snes->vec_rhs; 16719653cdaSPeter Brune x_A = snes->vec_sol_update; 168c878e8e6SPeter Brune r_A = snes->work[0]; 169c878e8e6SPeter Brune d = snes->work[1]; 170732c72c5SBarry Smith r = snes->work[2]; 171a312c225SMatthew G Knepley 1724a0c5b0cSMatthew G Knepley ierr = SNESGetPC(snes, &pc);CHKERRQ(ierr); 173a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 174a312c225SMatthew G Knepley snes->iter = 0; 175a312c225SMatthew G Knepley snes->norm = 0.; 176a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 17719653cdaSPeter Brune 17898b3e84cSPeter Brune /* initialization */ 17919653cdaSPeter Brune 18098b3e84cSPeter Brune /* r = F(x) */ 18198b3e84cSPeter Brune ierr = SNESComputeFunction(snes, x, r);CHKERRQ(ierr); 182a312c225SMatthew G Knepley if (snes->domainerror) { 183a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 184a312c225SMatthew G Knepley PetscFunctionReturn(0); 185a312c225SMatthew G Knepley } 18619653cdaSPeter Brune 18798b3e84cSPeter Brune /* nu = (r, r) */ 18819653cdaSPeter Brune ierr = VecNorm(r, NORM_2, &r_norm);CHKERRQ(ierr); 18919653cdaSPeter Brune r_min_norm = r_norm; 19019653cdaSPeter Brune nu = r_norm*r_norm; 191*dfbf837cSBarry Smith if (PetscIsInfOrNanReal(r_norm)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Infinite or not-a-number generated in function evaluation"); 19219653cdaSPeter Brune 19398b3e84cSPeter Brune /* q_{00} = nu */ 19419653cdaSPeter Brune Q(0,0) = nu; 19519653cdaSPeter Brune ngmres->r_norms[0] = r_norm; 19698b3e84cSPeter Brune /* rdot[0] = r */ 19719653cdaSPeter Brune ierr = VecCopy(x, xdot[0]);CHKERRQ(ierr); 19819653cdaSPeter Brune ierr = VecCopy(r, rdot[0]);CHKERRQ(ierr); 199087dfb9eSxuemin 200a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 20119653cdaSPeter Brune snes->norm = r_norm; 202a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 20319653cdaSPeter Brune SNESLogConvHistory(snes, r_norm, 0); 20419653cdaSPeter Brune ierr = SNESMonitor(snes, 0, r_norm);CHKERRQ(ierr); 20519653cdaSPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,r_norm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 206a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 207a312c225SMatthew G Knepley 20819653cdaSPeter Brune k_restart = 1; 20919653cdaSPeter Brune l = 1; 21019653cdaSPeter Brune for (k=1; k<snes->max_its; k++) { 211087dfb9eSxuemin 21298b3e84cSPeter Brune /* select which vector of the stored subspace will be updated */ 21398b3e84cSPeter Brune ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */ 21419653cdaSPeter Brune 21598b3e84cSPeter Brune /* Computation of x^M */ 21619653cdaSPeter Brune ierr = SNESSolve(pc, b, x);CHKERRQ(ierr); 21798b3e84cSPeter Brune /* r = F(x) */ 21819653cdaSPeter Brune ierr = SNESComputeFunction(snes, x, r);CHKERRQ(ierr); 21919653cdaSPeter Brune ierr = VecNorm(r, NORM_2, &r_norm);CHKERRQ(ierr); 22098b3e84cSPeter Brune /* nu = (r, r) */ 22119653cdaSPeter Brune ngmres->r_norms[ivec] = r_norm; 22219653cdaSPeter Brune nu = r_norm*r_norm; 22398b3e84cSPeter Brune if (r_min_norm > r_norm) r_min_norm = r_norm; /* the minimum norm is now of r^M */ 22419653cdaSPeter Brune 22598b3e84cSPeter Brune /* construct the right hand side and xi factors */ 22619653cdaSPeter Brune for (i = 0; i < l; i++) { 22719653cdaSPeter Brune VecDot(rdot[i], r, &xi[i]); 22819653cdaSPeter Brune beta[i] = nu - xi[i]; 22919653cdaSPeter Brune } 23019653cdaSPeter Brune 23198b3e84cSPeter Brune /* construct h */ 23219653cdaSPeter Brune for (j = 0; j < l; j++) { 23319653cdaSPeter Brune for (i = 0; i < l; i++) { 23419653cdaSPeter Brune H(i, j) = Q(i, j) - xi[i] - xi[j] + nu; 23519653cdaSPeter Brune } 23619653cdaSPeter Brune } 23719653cdaSPeter Brune #ifdef PETSC_MISSING_LAPACK_GELSS 23819653cdaSPeter Brune SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "NGMRES with LS requires the LAPACK GELSS routine."); 2394a0c5b0cSMatthew G Knepley #else 24019653cdaSPeter Brune ngmres->m = PetscBLASIntCast(l); 24119653cdaSPeter Brune ngmres->n = PetscBLASIntCast(l); 24219653cdaSPeter Brune ngmres->info = PetscBLASIntCast(0); 24319653cdaSPeter Brune ngmres->rcond = -1.; 24419653cdaSPeter Brune ngmres->nrhs = 1; 24519653cdaSPeter Brune #ifdef PETSC_USE_COMPLEX 24619653cdaSPeter Brune LAPACKgelss_(&ngmres->m, 24719653cdaSPeter Brune &ngmres->n, 24819653cdaSPeter Brune &ngmres->nrhs, 24919653cdaSPeter Brune ngmres->h, 25019653cdaSPeter Brune &ngmres->lda, 25119653cdaSPeter Brune ngmres->beta, 25219653cdaSPeter Brune &ngmres->ldb, 25319653cdaSPeter Brune ngmres->s, 25419653cdaSPeter Brune &ngmres->rcond, 25519653cdaSPeter Brune &ngmres->rank, 25619653cdaSPeter Brune ngmres->work, 25719653cdaSPeter Brune &ngmres->lwork, 25819653cdaSPeter Brune ngmres->rwork, 25919653cdaSPeter Brune &ngmres->info); 26019653cdaSPeter Brune #else 26119653cdaSPeter Brune LAPACKgelss_(&ngmres->m, 26219653cdaSPeter Brune &ngmres->n, 26319653cdaSPeter Brune &ngmres->nrhs, 26419653cdaSPeter Brune ngmres->h, 26519653cdaSPeter Brune &ngmres->lda, 26619653cdaSPeter Brune ngmres->beta, 26719653cdaSPeter Brune &ngmres->ldb, 26819653cdaSPeter Brune ngmres->s, 26919653cdaSPeter Brune &ngmres->rcond, 27019653cdaSPeter Brune &ngmres->rank, 27119653cdaSPeter Brune ngmres->work, 27219653cdaSPeter Brune &ngmres->lwork, 27319653cdaSPeter Brune &ngmres->info); 27419653cdaSPeter Brune #endif 27519653cdaSPeter Brune if (ngmres->info < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to GELSS"); 27619653cdaSPeter Brune if (ngmres->info > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SVD failed to converge"); 277a312c225SMatthew G Knepley #endif 278a312c225SMatthew G Knepley 27919653cdaSPeter Brune alph_total = 0.; 28019653cdaSPeter Brune for (i = 0; i < l; i++) { 28119653cdaSPeter Brune alph_total += beta[i]; 282c0bbabecSxuemin } 28319653cdaSPeter Brune ierr = VecCopy(x, x_A);CHKERRQ(ierr); 28419653cdaSPeter Brune ierr = VecScale(x_A, 1. - alph_total);CHKERRQ(ierr); 285087dfb9eSxuemin 28619653cdaSPeter Brune for(i=0;i<l;i++){ 28719653cdaSPeter Brune ierr= VecAXPY(x_A, beta[i], xdot[i]);CHKERRQ(ierr); 28819653cdaSPeter Brune } 28919653cdaSPeter Brune ierr = SNESComputeFunction(snes, x_A, r_A);CHKERRQ(ierr); 29019653cdaSPeter Brune ierr = VecNorm(r_A, NORM_2, &r_A_norm);CHKERRQ(ierr); 29119653cdaSPeter Brune 29219653cdaSPeter Brune selectA = PETSC_TRUE; 29398b3e84cSPeter Brune /* Conditions for choosing the accelerated answer */ 29419653cdaSPeter Brune 29598b3e84cSPeter Brune /* Criterion A -- the norm of the function isn't increased above the minimum by too much */ 29619653cdaSPeter Brune if (r_A_norm >= ngmres->gammaA*r_min_norm) { 29719653cdaSPeter Brune selectA = PETSC_FALSE; 298a312c225SMatthew G Knepley } 299087dfb9eSxuemin 30098b3e84cSPeter Brune /* Criterion B -- the choice of x^A isn't too close to some other choice */ 30119653cdaSPeter Brune ierr=VecCopy(x_A,d);CHKERRQ(ierr); 30219653cdaSPeter Brune ierr=VecAXPY(d,-1,x);CHKERRQ(ierr); 30319653cdaSPeter Brune ierr=VecNorm(d,NORM_2,&d_norm);CHKERRQ(ierr); 3049261d27aSPeter Brune d_min_norm = -1.0; 30519653cdaSPeter Brune for(i=0;i<l;i++) { 30619653cdaSPeter Brune ierr=VecCopy(x_A,d);CHKERRQ(ierr); 30719653cdaSPeter Brune ierr=VecAXPY(d,-1,xdot[i]);CHKERRQ(ierr); 30819653cdaSPeter Brune ierr=VecNorm(d,NORM_2,&d_cur_norm);CHKERRQ(ierr); 3099261d27aSPeter Brune if((d_cur_norm < d_min_norm) || (d_min_norm < 0.0)) d_min_norm = d_cur_norm; 31019653cdaSPeter Brune } 31119653cdaSPeter Brune if (ngmres->epsilonB*d_norm<d_min_norm || sqrt(r_norm)<ngmres->deltaB*sqrt(r_min_norm)) { 31219653cdaSPeter Brune } else { 31319653cdaSPeter Brune selectA=PETSC_FALSE; 31419653cdaSPeter Brune } 315211b2d39SPeter Brune 316087dfb9eSxuemin 31719653cdaSPeter Brune if (selectA) { 318*dfbf837cSBarry Smith if (ngmres->monitor) { 319*dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked r_A, ||r_A||_2 = %e, ||r_M||_2 = %e\n", r_A_norm, r_norm);CHKERRQ(ierr); 320*dfbf837cSBarry Smith } 32198b3e84cSPeter Brune /* copy it over */ 32219653cdaSPeter Brune r_norm = r_A_norm; 32319653cdaSPeter Brune nu = r_norm*r_norm; 32419653cdaSPeter Brune ierr = VecCopy(r_A, r);CHKERRQ(ierr); 32519653cdaSPeter Brune ierr = VecCopy(x_A, x);CHKERRQ(ierr); 32619653cdaSPeter Brune } else { 327*dfbf837cSBarry Smith if (ngmres->monitor) { 328*dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "picked r_M, ||r_A||_2 = %e, ||r_M||_2 = %e\n", r_A_norm, r_norm);CHKERRQ(ierr); 329*dfbf837cSBarry Smith } 33019653cdaSPeter Brune } 331211b2d39SPeter Brune 33219653cdaSPeter Brune selectRestart = PETSC_FALSE; 33319653cdaSPeter Brune 33498b3e84cSPeter Brune /* maximum iteration criterion */ 33519653cdaSPeter Brune if (k_restart > ngmres->k_rmax) { 33619653cdaSPeter Brune selectRestart = PETSC_TRUE; 33719653cdaSPeter Brune } 33819653cdaSPeter Brune 33998b3e84cSPeter Brune /* difference stagnation restart */ 340*dfbf837cSBarry Smith if ((ngmres->epsilonB*d_norm > d_min_norm) && (sqrt(r_A_norm) > ngmres->deltaB*sqrt(r_min_norm))) { 341*dfbf837cSBarry Smith if (ngmres->monitor) { 342*dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "difference restart: %e > %e\n", ngmres->epsilonB*d_norm, d_min_norm);CHKERRQ(ierr); 343*dfbf837cSBarry Smith } 34419653cdaSPeter Brune selectRestart = PETSC_TRUE; 34519653cdaSPeter Brune } 34619653cdaSPeter Brune 34798b3e84cSPeter Brune /* residual stagnation restart */ 34819653cdaSPeter Brune if (sqrt(r_A_norm) > ngmres->gammaC*sqrt(r_min_norm)) { 349*dfbf837cSBarry Smith if (ngmres->monitor) { 350*dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "residual restart: %e > %e\n", sqrt(r_A_norm), ngmres->gammaC*sqrt(r_min_norm));CHKERRQ(ierr); 351*dfbf837cSBarry Smith } 35219653cdaSPeter Brune selectRestart = PETSC_TRUE; 35319653cdaSPeter Brune } 35419653cdaSPeter Brune 35519653cdaSPeter Brune if (selectRestart) { 356*dfbf837cSBarry Smith if (ngmres->monitor){ 357*dfbf837cSBarry Smith ierr = PetscViewerASCIIPrintf(ngmres->monitor, "Restarted at iteration %d\n", k_restart);CHKERRQ(ierr); 358*dfbf837cSBarry Smith } 35919653cdaSPeter Brune k_restart = 1; 36019653cdaSPeter Brune l = 1; 36198b3e84cSPeter Brune /* q_{00} = nu */ 36219653cdaSPeter Brune ngmres->r_norms[0] = r_norm; 36319653cdaSPeter Brune nu = r_norm*r_norm; 36419653cdaSPeter Brune Q(0,0) = nu; 36598b3e84cSPeter Brune /* rdot[0] = r */ 36619653cdaSPeter Brune ierr = VecCopy(x, xdot[0]);CHKERRQ(ierr); 36719653cdaSPeter Brune ierr = VecCopy(r, rdot[0]);CHKERRQ(ierr); 36819653cdaSPeter Brune } else { 36998b3e84cSPeter Brune /* select the current size of the subspace */ 37019653cdaSPeter Brune if (l < ngmres->msize) { 37119653cdaSPeter Brune l++; 37219653cdaSPeter Brune } 37319653cdaSPeter Brune k_restart++; 37498b3e84cSPeter Brune /* place the current entry in the list of previous entries */ 37519653cdaSPeter Brune ierr = VecCopy(r, rdot[ivec]);CHKERRQ(ierr); 37619653cdaSPeter Brune ierr = VecCopy(x, xdot[ivec]);CHKERRQ(ierr); 37719653cdaSPeter Brune ngmres->r_norms[ivec] = r_norm; 37898b3e84cSPeter Brune if (r_min_norm > r_norm) r_min_norm = r_norm; /* the minimum norm is now of r^A */ 37919653cdaSPeter Brune for (i = 0; i < l; i++) { 38019653cdaSPeter Brune VecDot(r, rdot[i], &qentry); 38119653cdaSPeter Brune Q(i, ivec) = qentry; 38219653cdaSPeter Brune Q(ivec, i) = qentry; 38319653cdaSPeter Brune } 38419653cdaSPeter Brune } 38519653cdaSPeter Brune 38619653cdaSPeter Brune SNESLogConvHistory(snes, r_norm, k); 38719653cdaSPeter Brune ierr = SNESMonitor(snes, k, r_norm);CHKERRQ(ierr); 38819653cdaSPeter Brune 389087dfb9eSxuemin snes->iter =k; 39019653cdaSPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,r_norm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 391087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 392a312c225SMatthew G Knepley } 393a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 394a312c225SMatthew G Knepley PetscFunctionReturn(0); 395a312c225SMatthew G Knepley } 396a312c225SMatthew G Knepley 397*dfbf837cSBarry Smith /*MC 398*dfbf837cSBarry Smith SNESNGMRES - The Nonlinear Generalized Minimum Residual (NGMRES) method of Oosterlee and Washio. 399a312c225SMatthew G Knepley 400*dfbf837cSBarry Smith Level: beginner 401*dfbf837cSBarry Smith 402*dfbf837cSBarry Smith "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 403*dfbf837cSBarry Smith SIAM Journal on Scientific Computing, 21(5), 2000. 404*dfbf837cSBarry Smith 405*dfbf837cSBarry Smith This is also the same as the algorithm called Anderson acceleration introduced in "D. G. Anderson. Iterative procedures for nonlinear integral equations. 406*dfbf837cSBarry Smith J. Assoc. Comput. Mach., 12:547–560, 1965." 407*dfbf837cSBarry Smith 408*dfbf837cSBarry Smith .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 409*dfbf837cSBarry Smith M*/ 410a312c225SMatthew G Knepley 411a312c225SMatthew G Knepley EXTERN_C_BEGIN 412a312c225SMatthew G Knepley #undef __FUNCT__ 413a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 414a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes) 415a312c225SMatthew G Knepley { 416a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 417a312c225SMatthew G Knepley PetscErrorCode ierr; 418a312c225SMatthew G Knepley 419a312c225SMatthew G Knepley PetscFunctionBegin; 420a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 421a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 422a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 423a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 424a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 425a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 426a312c225SMatthew G Knepley 427a312c225SMatthew G Knepley ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr); 428a312c225SMatthew G Knepley snes->data = (void*) ngmres; 42919653cdaSPeter Brune ngmres->msize = 10; 43019653cdaSPeter Brune 43119653cdaSPeter Brune ngmres->gammaA = 2.; 43219653cdaSPeter Brune ngmres->gammaC = 2.; 433cac108bcSPeter Brune ngmres->deltaB = 0.9; 434cac108bcSPeter Brune ngmres->epsilonB = 0.1; 435cac108bcSPeter Brune ngmres->k_rmax = 200; 4364a0c5b0cSMatthew G Knepley 4374a0c5b0cSMatthew G Knepley ierr = SNESGetPC(snes, &snes->pc);CHKERRQ(ierr); 438a312c225SMatthew G Knepley PetscFunctionReturn(0); 439a312c225SMatthew G Knepley } 440a312c225SMatthew G Knepley EXTERN_C_END 441