1*f31c9d25SPeter Brune #include <../src/snes/impls/ngmres/snesngmres.h> /*I "petscsnes.h" I*/ 2*f31c9d25SPeter Brune 3*f31c9d25SPeter Brune PETSC_EXTERN PetscErrorCode SNESDestroy_NGMRES(SNES); 4*f31c9d25SPeter Brune PETSC_EXTERN PetscErrorCode SNESReset_NGMRES(SNES); 5*f31c9d25SPeter Brune PETSC_EXTERN PetscErrorCode SNESSetUp_NGMRES(SNES); 6*f31c9d25SPeter Brune PETSC_EXTERN PetscErrorCode SNESView_NGMRES(SNES,PetscViewer); 7*f31c9d25SPeter Brune 8*f31c9d25SPeter Brune 9*f31c9d25SPeter Brune #undef __FUNCT__ 10*f31c9d25SPeter Brune #define __FUNCT__ "SNESSetFromOptions_Anderson" 11*f31c9d25SPeter Brune PetscErrorCode SNESSetFromOptions_Anderson(SNES snes) 12*f31c9d25SPeter Brune { 13*f31c9d25SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 14*f31c9d25SPeter Brune PetscErrorCode ierr; 15*f31c9d25SPeter Brune PetscBool debug; 16*f31c9d25SPeter Brune SNESLineSearch linesearch; 17*f31c9d25SPeter Brune 18*f31c9d25SPeter Brune PetscFunctionBegin; 19*f31c9d25SPeter Brune ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr); 20*f31c9d25SPeter Brune ierr = PetscOptionsInt("-snes_anderson_m","Number of directions","SNES",ngmres->msize,&ngmres->msize,PETSC_NULL);CHKERRQ(ierr); 21*f31c9d25SPeter Brune ierr = PetscOptionsReal("-snes_anderson_beta","Number of directions","SNES",ngmres->andersonBeta,&ngmres->andersonBeta,PETSC_NULL);CHKERRQ(ierr); 22*f31c9d25SPeter Brune ierr = PetscOptionsBool("-snes_anderson_monitor","Monitor actions of NGMRES","SNES",ngmres->monitor ? PETSC_TRUE: PETSC_FALSE,&debug,PETSC_NULL);CHKERRQ(ierr); 23*f31c9d25SPeter Brune if (debug) { 24*f31c9d25SPeter Brune ngmres->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 25*f31c9d25SPeter Brune } 26*f31c9d25SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 27*f31c9d25SPeter Brune /* set the default type of the line search if the user hasn't already. */ 28*f31c9d25SPeter Brune if (!snes->linesearch) { 29*f31c9d25SPeter Brune ierr = SNESGetSNESLineSearch(snes,&linesearch);CHKERRQ(ierr); 30*f31c9d25SPeter Brune ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr); 31*f31c9d25SPeter Brune } 32*f31c9d25SPeter Brune PetscFunctionReturn(0); 33*f31c9d25SPeter Brune } 34*f31c9d25SPeter Brune 35*f31c9d25SPeter Brune #undef __FUNCT__ 36*f31c9d25SPeter Brune #define __FUNCT__ "SNESSolve_Anderson" 37*f31c9d25SPeter Brune PetscErrorCode SNESSolve_Anderson(SNES snes) 38*f31c9d25SPeter Brune { 39*f31c9d25SPeter Brune SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 40*f31c9d25SPeter Brune /* present solution, residual, and preconditioned residual */ 41*f31c9d25SPeter Brune Vec X,F,B; 42*f31c9d25SPeter Brune 43*f31c9d25SPeter Brune /* candidate linear combination answers */ 44*f31c9d25SPeter Brune Vec XA,FA,XM,FM,FPC; 45*f31c9d25SPeter Brune 46*f31c9d25SPeter Brune /* coefficients and RHS to the minimization problem */ 47*f31c9d25SPeter Brune PetscReal fnorm,fMnorm; 48*f31c9d25SPeter Brune PetscInt k,k_restart,l,ivec; 49*f31c9d25SPeter Brune 50*f31c9d25SPeter Brune SNESConvergedReason reason; 51*f31c9d25SPeter Brune PetscErrorCode ierr; 52*f31c9d25SPeter Brune 53*f31c9d25SPeter Brune PetscFunctionBegin; 54*f31c9d25SPeter Brune /* variable initialization */ 55*f31c9d25SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 56*f31c9d25SPeter Brune X = snes->vec_sol; 57*f31c9d25SPeter Brune F = snes->vec_func; 58*f31c9d25SPeter Brune B = snes->vec_rhs; 59*f31c9d25SPeter Brune XA = snes->vec_sol_update; 60*f31c9d25SPeter Brune FA = snes->work[0]; 61*f31c9d25SPeter Brune 62*f31c9d25SPeter Brune /* work for the line search */ 63*f31c9d25SPeter Brune XM = snes->work[3]; 64*f31c9d25SPeter Brune FM = snes->work[4]; 65*f31c9d25SPeter Brune 66*f31c9d25SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 67*f31c9d25SPeter Brune snes->iter = 0; 68*f31c9d25SPeter Brune snes->norm = 0.; 69*f31c9d25SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 70*f31c9d25SPeter Brune 71*f31c9d25SPeter Brune /* initialization */ 72*f31c9d25SPeter Brune 73*f31c9d25SPeter Brune /* r = F(x) */ 74*f31c9d25SPeter Brune if (!snes->vec_func_init_set) { 75*f31c9d25SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 76*f31c9d25SPeter Brune if (snes->domainerror) { 77*f31c9d25SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 78*f31c9d25SPeter Brune PetscFunctionReturn(0); 79*f31c9d25SPeter Brune } 80*f31c9d25SPeter Brune } else { 81*f31c9d25SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 82*f31c9d25SPeter Brune } 83*f31c9d25SPeter Brune 84*f31c9d25SPeter Brune if (!snes->norm_init_set) { 85*f31c9d25SPeter Brune ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 86*f31c9d25SPeter Brune if (PetscIsInfOrNanReal(fnorm)) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_FP,"Infinite or not-a-number generated in function evaluation"); 87*f31c9d25SPeter Brune } else { 88*f31c9d25SPeter Brune fnorm = snes->norm_init; 89*f31c9d25SPeter Brune snes->norm_init_set = PETSC_FALSE; 90*f31c9d25SPeter Brune } 91*f31c9d25SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 92*f31c9d25SPeter Brune snes->norm = fnorm; 93*f31c9d25SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 94*f31c9d25SPeter Brune SNESLogConvHistory(snes,fnorm,0); 95*f31c9d25SPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 96*f31c9d25SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 97*f31c9d25SPeter Brune if (snes->reason) PetscFunctionReturn(0); 98*f31c9d25SPeter Brune 99*f31c9d25SPeter Brune k_restart = 0; 100*f31c9d25SPeter Brune l = 0; 101*f31c9d25SPeter Brune for (k=1; k < snes->max_its+1; k++) { 102*f31c9d25SPeter Brune /* select which vector of the stored subspace will be updated */ 103*f31c9d25SPeter Brune ivec = k_restart % ngmres->msize; 104*f31c9d25SPeter Brune if (snes->pc && snes->pcside == PC_RIGHT) { 105*f31c9d25SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 106*f31c9d25SPeter Brune ierr = SNESSetInitialFunction(snes->pc,F);CHKERRQ(ierr); 107*f31c9d25SPeter Brune ierr = SNESSetInitialFunctionNorm(snes->pc,fnorm);CHKERRQ(ierr); 108*f31c9d25SPeter Brune 109*f31c9d25SPeter Brune ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); 110*f31c9d25SPeter Brune ierr = SNESSolve(snes->pc,B,XM);CHKERRQ(ierr); 111*f31c9d25SPeter Brune ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); 112*f31c9d25SPeter Brune 113*f31c9d25SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 114*f31c9d25SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 115*f31c9d25SPeter Brune snes->reason = SNES_DIVERGED_INNER; 116*f31c9d25SPeter Brune PetscFunctionReturn(0); 117*f31c9d25SPeter Brune } 118*f31c9d25SPeter Brune ierr = SNESGetFunction(snes->pc,&FPC,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 119*f31c9d25SPeter Brune ierr = VecCopy(FPC,FM);CHKERRQ(ierr); 120*f31c9d25SPeter Brune ierr = SNESGetFunctionNorm(snes->pc,&fMnorm);CHKERRQ(ierr); 121*f31c9d25SPeter Brune if (ngmres->andersonBeta != 1.0) { 122*f31c9d25SPeter Brune VecAXPBY(XM,(1.0 - ngmres->andersonBeta),ngmres->andersonBeta,X);CHKERRQ(ierr); 123*f31c9d25SPeter Brune } 124*f31c9d25SPeter Brune } else { 125*f31c9d25SPeter Brune ierr = VecCopy(F,FM);CHKERRQ(ierr); 126*f31c9d25SPeter Brune ierr = VecCopy(X,XM);CHKERRQ(ierr); 127*f31c9d25SPeter Brune ierr = VecAXPY(XM,-ngmres->andersonBeta,FM);CHKERRQ(ierr); 128*f31c9d25SPeter Brune fMnorm = fnorm; 129*f31c9d25SPeter Brune } 130*f31c9d25SPeter Brune 131*f31c9d25SPeter Brune ierr = SNESNGMRESFormCombinedSolution_Private(snes,l,XM,FM,fMnorm,X,XA,FA); 132*f31c9d25SPeter Brune 133*f31c9d25SPeter Brune if (l < ngmres->msize)l++; 134*f31c9d25SPeter Brune k_restart++; 135*f31c9d25SPeter Brune ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fnorm,XM); 136*f31c9d25SPeter Brune 137*f31c9d25SPeter Brune ierr = VecNorm(FA,NORM_2,&fnorm);CHKERRQ(ierr); 138*f31c9d25SPeter Brune ierr = VecCopy(XA,X);CHKERRQ(ierr); 139*f31c9d25SPeter Brune ierr = VecCopy(FA,F);CHKERRQ(ierr); 140*f31c9d25SPeter Brune 141*f31c9d25SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 142*f31c9d25SPeter Brune snes->iter = k; 143*f31c9d25SPeter Brune snes->norm = fnorm; 144*f31c9d25SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 145*f31c9d25SPeter Brune SNESLogConvHistory(snes,snes->norm,snes->iter); 146*f31c9d25SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 147*f31c9d25SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 148*f31c9d25SPeter Brune if (snes->reason) PetscFunctionReturn(0); 149*f31c9d25SPeter Brune } 150*f31c9d25SPeter Brune snes->reason = SNES_DIVERGED_MAX_IT; 151*f31c9d25SPeter Brune PetscFunctionReturn(0); 152*f31c9d25SPeter Brune } 153*f31c9d25SPeter Brune 154*f31c9d25SPeter Brune /*MC 155*f31c9d25SPeter Brune SNESAnderson - Anderson Mixing method. 156*f31c9d25SPeter Brune 157*f31c9d25SPeter Brune Level: beginner 158*f31c9d25SPeter Brune 159*f31c9d25SPeter Brune Options Database: 160*f31c9d25SPeter Brune + -snes_anderson_m - Number of stored previous solutions and residuals 161*f31c9d25SPeter Brune . -snes_anderson_beta - Relaxation parameter; X_{update} = X + \beta F 162*f31c9d25SPeter Brune - -snes_anderson_monitor - Prints relevant information about the ngmres iteration 163*f31c9d25SPeter Brune 164*f31c9d25SPeter Brune Notes: 165*f31c9d25SPeter Brune 166*f31c9d25SPeter Brune The Anderson Mixing method combines m previous solutions into a minimum-residual solution by solving a small linearized 167*f31c9d25SPeter Brune optimization problem at each iteration. 168*f31c9d25SPeter Brune 169*f31c9d25SPeter Brune References: 170*f31c9d25SPeter Brune 171*f31c9d25SPeter Brune "D. G. Anderson. Iterative procedures for nonlinear integral equations. 172*f31c9d25SPeter Brune J. Assoc. Comput. Mach., 12:547–560, 1965." 173*f31c9d25SPeter Brune 174*f31c9d25SPeter Brune .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 175*f31c9d25SPeter Brune M*/ 176*f31c9d25SPeter Brune 177*f31c9d25SPeter Brune EXTERN_C_BEGIN 178*f31c9d25SPeter Brune #undef __FUNCT__ 179*f31c9d25SPeter Brune #define __FUNCT__ "SNESCreate_Anderson" 180*f31c9d25SPeter Brune PetscErrorCode SNESCreate_Anderson(SNES snes) 181*f31c9d25SPeter Brune { 182*f31c9d25SPeter Brune SNES_NGMRES *ngmres; 183*f31c9d25SPeter Brune PetscErrorCode ierr; 184*f31c9d25SPeter Brune 185*f31c9d25SPeter Brune PetscFunctionBegin; 186*f31c9d25SPeter Brune snes->ops->destroy = SNESDestroy_NGMRES; 187*f31c9d25SPeter Brune snes->ops->setup = SNESSetUp_NGMRES; 188*f31c9d25SPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_Anderson; 189*f31c9d25SPeter Brune snes->ops->view = SNESView_NGMRES; 190*f31c9d25SPeter Brune snes->ops->solve = SNESSolve_Anderson; 191*f31c9d25SPeter Brune snes->ops->reset = SNESReset_NGMRES; 192*f31c9d25SPeter Brune 193*f31c9d25SPeter Brune snes->usespc = PETSC_TRUE; 194*f31c9d25SPeter Brune snes->usesksp = PETSC_FALSE; 195*f31c9d25SPeter Brune 196*f31c9d25SPeter Brune ierr = PetscNewLog(snes,SNES_NGMRES,&ngmres);CHKERRQ(ierr); 197*f31c9d25SPeter Brune snes->data = (void*) ngmres; 198*f31c9d25SPeter Brune ngmres->msize = 30; 199*f31c9d25SPeter Brune 200*f31c9d25SPeter Brune if (!snes->tolerancesset) { 201*f31c9d25SPeter Brune snes->max_funcs = 30000; 202*f31c9d25SPeter Brune snes->max_its = 10000; 203*f31c9d25SPeter Brune } 204*f31c9d25SPeter Brune 205*f31c9d25SPeter Brune ngmres->additive_linesearch = PETSC_NULL; 206*f31c9d25SPeter Brune 207*f31c9d25SPeter Brune ngmres->restart_it = 2; 208*f31c9d25SPeter Brune ngmres->restart_periodic = 30; 209*f31c9d25SPeter Brune ngmres->gammaA = 2.0; 210*f31c9d25SPeter Brune ngmres->gammaC = 2.0; 211*f31c9d25SPeter Brune ngmres->deltaB = 0.9; 212*f31c9d25SPeter Brune ngmres->epsilonB = 0.1; 213*f31c9d25SPeter Brune 214*f31c9d25SPeter Brune ngmres->andersonBeta = 1.0; 215*f31c9d25SPeter Brune 216*f31c9d25SPeter Brune PetscFunctionReturn(0); 217*f31c9d25SPeter Brune } 218*f31c9d25SPeter Brune EXTERN_C_END 219