1*a312c225SMatthew G Knepley /* Defines the basic SNES object */ 2*a312c225SMatthew G Knepley #include <private/snesimpl.h> 3*a312c225SMatthew G Knepley 4*a312c225SMatthew G Knepley /* Private structure for the Anderson mixing method aka nonlinear Krylov */ 5*a312c225SMatthew G Knepley typedef struct { 6*a312c225SMatthew G Knepley Vec *v, *w; 7*a312c225SMatthew G Knepley PetscReal *f2; /* 2-norms of function (residual) at each stage */ 8*a312c225SMatthew G Knepley PetscInt msize; /* maximum size of space */ 9*a312c225SMatthew G Knepley PetscInt csize; /* current size of space */ 10*a312c225SMatthew G Knepley } SNES_NGMRES; 11*a312c225SMatthew G Knepley 12*a312c225SMatthew G Knepley #undef __FUNCT__ 13*a312c225SMatthew G Knepley #define __FUNCT__ "SNESReset_NGMRES" 14*a312c225SMatthew G Knepley PetscErrorCode SNESReset_NGMRES(SNES snes) 15*a312c225SMatthew G Knepley { 16*a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 17*a312c225SMatthew G Knepley PetscErrorCode ierr; 18*a312c225SMatthew G Knepley 19*a312c225SMatthew G Knepley PetscFunctionBegin; 20*a312c225SMatthew G Knepley ierr = VecDestroyVecs(ngmres->msize, &ngmres->v);CHKERRQ(ierr); 21*a312c225SMatthew G Knepley ierr = VecDestroyVecs(ngmres->msize, &ngmres->w);CHKERRQ(ierr); 22*a312c225SMatthew G Knepley PetscFunctionReturn(0); 23*a312c225SMatthew G Knepley } 24*a312c225SMatthew G Knepley 25*a312c225SMatthew G Knepley #undef __FUNCT__ 26*a312c225SMatthew G Knepley #define __FUNCT__ "SNESDestroy_NGMRES" 27*a312c225SMatthew G Knepley PetscErrorCode SNESDestroy_NGMRES(SNES snes) 28*a312c225SMatthew G Knepley { 29*a312c225SMatthew G Knepley PetscErrorCode ierr; 30*a312c225SMatthew G Knepley 31*a312c225SMatthew G Knepley PetscFunctionBegin; 32*a312c225SMatthew G Knepley ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr); 33*a312c225SMatthew G Knepley if (snes->work) {ierr = VecDestroyVecs(snes->nwork, &snes->work);CHKERRQ(ierr);} 34*a312c225SMatthew G Knepley PetscFunctionReturn(0); 35*a312c225SMatthew G Knepley } 36*a312c225SMatthew G Knepley 37*a312c225SMatthew G Knepley #undef __FUNCT__ 38*a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetUp_NGMRES" 39*a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes) 40*a312c225SMatthew G Knepley { 41*a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 42*a312c225SMatthew G Knepley PetscErrorCode ierr; 43*a312c225SMatthew G Knepley 44*a312c225SMatthew G Knepley PetscFunctionBegin; 45*a312c225SMatthew G Knepley #if 0 46*a312c225SMatthew G Knepley if (snes->pc_side != PC_LEFT) {SETERRQ(((PetscObject) snes)->comm, PETSC_ERR_SUP, "Only left preconditioning allowed for SNESNGMRES");} 47*a312c225SMatthew G Knepley #endif 48*a312c225SMatthew G Knepley ierr = VecDuplicateVecs(snes->vec_sol, ngmres->msize, &ngmres->v);CHKERRQ(ierr); 49*a312c225SMatthew G Knepley ierr = VecDuplicateVecs(snes->vec_sol, ngmres->msize, &ngmres->w);CHKERRQ(ierr); 50*a312c225SMatthew G Knepley ierr = SNESDefaultGetWork(snes, 2);CHKERRQ(ierr); 51*a312c225SMatthew G Knepley PetscFunctionReturn(0); 52*a312c225SMatthew G Knepley } 53*a312c225SMatthew G Knepley 54*a312c225SMatthew G Knepley #undef __FUNCT__ 55*a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES" 56*a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes) 57*a312c225SMatthew G Knepley { 58*a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 59*a312c225SMatthew G Knepley PetscErrorCode ierr; 60*a312c225SMatthew G Knepley 61*a312c225SMatthew G Knepley PetscFunctionBegin; 62*a312c225SMatthew G Knepley ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr); 63*a312c225SMatthew G Knepley ierr = PetscOptionsInt("-snes_gmres_restart", "Number of directions", "SNES", ngmres->msize, &ngmres->msize, PETSC_NULL);CHKERRQ(ierr); 64*a312c225SMatthew G Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 65*a312c225SMatthew G Knepley PetscFunctionReturn(0); 66*a312c225SMatthew G Knepley } 67*a312c225SMatthew G Knepley 68*a312c225SMatthew G Knepley #undef __FUNCT__ 69*a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES" 70*a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes, PetscViewer viewer) 71*a312c225SMatthew G Knepley { 72*a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 73*a312c225SMatthew G Knepley PetscBool iascii; 74*a312c225SMatthew G Knepley PetscErrorCode ierr; 75*a312c225SMatthew G Knepley 76*a312c225SMatthew G Knepley PetscFunctionBegin; 77*a312c225SMatthew G Knepley ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 78*a312c225SMatthew G Knepley if (iascii) { 79*a312c225SMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer, " Size of space %d\n", ngmres->msize);CHKERRQ(ierr); 80*a312c225SMatthew G Knepley } else { 81*a312c225SMatthew G Knepley SETERRQ1(((PetscObject) snes)->comm, PETSC_ERR_SUP, "Viewer type %s not supported for SNESNGMRES", ((PetscObject) viewer)->type_name); 82*a312c225SMatthew G Knepley } 83*a312c225SMatthew G Knepley PetscFunctionReturn(0); 84*a312c225SMatthew G Knepley } 85*a312c225SMatthew G Knepley 86*a312c225SMatthew G Knepley #undef __FUNCT__ 87*a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES" 88*a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes) 89*a312c225SMatthew G Knepley { 90*a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 91*a312c225SMatthew G Knepley Vec X, Y, F, Pold, P, *V = ngmres->v, *W = ngmres->w; 92*a312c225SMatthew G Knepley //Vec y, w; 93*a312c225SMatthew G Knepley PetscScalar wdot; 94*a312c225SMatthew G Knepley PetscReal fnorm; 95*a312c225SMatthew G Knepley //PetscScalar rdot, abr, A0; 96*a312c225SMatthew G Knepley PetscInt i, j, k; 97*a312c225SMatthew G Knepley PetscErrorCode ierr; 98*a312c225SMatthew G Knepley 99*a312c225SMatthew G Knepley PetscFunctionBegin; 100*a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 101*a312c225SMatthew G Knepley X = snes->vec_sol; 102*a312c225SMatthew G Knepley Y = snes->vec_sol_update; 103*a312c225SMatthew G Knepley F = snes->vec_func; 104*a312c225SMatthew G Knepley Pold = snes->work[0]; 105*a312c225SMatthew G Knepley P = snes->work[1]; 106*a312c225SMatthew G Knepley 107*a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 108*a312c225SMatthew G Knepley snes->iter = 0; 109*a312c225SMatthew G Knepley snes->norm = 0.; 110*a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 111*a312c225SMatthew G Knepley ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); /* r = F(x) */ 112*a312c225SMatthew G Knepley #if 0 113*a312c225SMatthew G Knepley ierr = SNESSolve(snes->pc, F, Pold);CHKERRQ(ierr); /* p = P(r) */ 114*a312c225SMatthew G Knepley #else 115*a312c225SMatthew G Knepley ierr = VecCopy(F, Pold);CHKERRQ(ierr); /* p = r */ 116*a312c225SMatthew G Knepley #endif 117*a312c225SMatthew G Knepley if (snes->domainerror) { 118*a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 119*a312c225SMatthew G Knepley PetscFunctionReturn(0); 120*a312c225SMatthew G Knepley } 121*a312c225SMatthew G Knepley ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm = ||r|| */ 122*a312c225SMatthew G Knepley if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 123*a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 124*a312c225SMatthew G Knepley snes->norm = fnorm; 125*a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 126*a312c225SMatthew G Knepley SNESLogConvHistory(snes, fnorm, 0); 127*a312c225SMatthew G Knepley ierr = SNESMonitor(snes, 0, fnorm);CHKERRQ(ierr); 128*a312c225SMatthew G Knepley 129*a312c225SMatthew G Knepley /* set parameter for default relative tolerance convergence test */ 130*a312c225SMatthew G Knepley snes->ttol = fnorm*snes->rtol; 131*a312c225SMatthew G Knepley /* test convergence */ 132*a312c225SMatthew G Knepley ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 133*a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 134*a312c225SMatthew G Knepley 135*a312c225SMatthew G Knepley #if 0 136*a312c225SMatthew G Knepley /* Barry: What the heck is this part doing? */ 137*a312c225SMatthew G Knepley /* determine optimal scale factor -- slow code */ 138*a312c225SMatthew G Knepley ierr = VecDuplicate(P, &y);CHKERRQ(ierr); 139*a312c225SMatthew G Knepley ierr = VecDuplicate(P, &w);CHKERRQ(ierr); 140*a312c225SMatthew G Knepley ierr = MatMult(Amat, Pold, y);CHKERRQ(ierr); 141*a312c225SMatthew G Knepley /*ierr = KSP_PCApplyBAorAB(ksp,Pold,y,w);CHKERRQ(ierr); */ /* y = BAp */ 142*a312c225SMatthew G Knepley ierr = VecDotNorm2(Pold, y, &rdot, &abr);CHKERRQ(ierr); /* rdot = (p)^T(BAp); abr = (BAp)^T (BAp) */ 143*a312c225SMatthew G Knepley ierr = VecDestroy(&y);CHKERRQ(ierr); 144*a312c225SMatthew G Knepley ierr = VecDestroy(&w);CHKERRQ(ierr); 145*a312c225SMatthew G Knepley A0 = rdot/abr; 146*a312c225SMatthew G Knepley ierr = VecAXPY(X,A0,Pold);CHKERRQ(ierr); /* x <- x + scale p */ 147*a312c225SMatthew G Knepley #endif 148*a312c225SMatthew G Knepley 149*a312c225SMatthew G Knepley /* Loop over batches of directions */ 150*a312c225SMatthew G Knepley for(k = 0; k < snes->max_its; k += ngmres->msize) { 151*a312c225SMatthew G Knepley /* Loop over updates for this batch */ 152*a312c225SMatthew G Knepley /* TODO: Incorporate the variant which use the analytic Jacobian */ 153*a312c225SMatthew G Knepley /* TODO: Incorporate criteria for restarting from paper */ 154*a312c225SMatthew G Knepley for(i = 0; i < ngmres->msize && k+i < snes->max_its; ++i) { 155*a312c225SMatthew G Knepley ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); /* r = F(x) */ 156*a312c225SMatthew G Knepley #if 0 157*a312c225SMatthew G Knepley ierr = SNESSolve(snes->pc, F, P);CHKERRQ(ierr); /* p = P(r) */ 158*a312c225SMatthew G Knepley #else 159*a312c225SMatthew G Knepley ierr = VecCopy(F, P);CHKERRQ(ierr); /* p = r */ 160*a312c225SMatthew G Knepley #endif 161*a312c225SMatthew G Knepley ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm = ||r|| */ 162*a312c225SMatthew G Knepley SNESLogConvHistory(snes, fnorm, 0); 163*a312c225SMatthew G Knepley ierr = SNESMonitor(snes, 0, fnorm);CHKERRQ(ierr); 164*a312c225SMatthew G Knepley ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 165*a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 166*a312c225SMatthew G Knepley 167*a312c225SMatthew G Knepley for(j = 0; j < i; ++j) { /* p = \prod_i (I + v_i w^T_i) p */ 168*a312c225SMatthew G Knepley ierr = VecDot(W[j], P, &wdot);CHKERRQ(ierr); 169*a312c225SMatthew G Knepley ierr = VecAXPY(P, wdot, V[j]);CHKERRQ(ierr); 170*a312c225SMatthew G Knepley } 171*a312c225SMatthew G Knepley ierr = VecCopy(Pold, W[i]);CHKERRQ(ierr); /* w_i = p_{old} */ 172*a312c225SMatthew G Knepley 173*a312c225SMatthew G Knepley ierr = VecAXPY(Pold, -1.0, P);CHKERRQ(ierr); /* v_i = P */ 174*a312c225SMatthew G Knepley ierr = VecDot(W[i], Pold, &wdot);CHKERRQ(ierr); /* ------------------- */ 175*a312c225SMatthew G Knepley ierr = VecCopy(P, V[i]);CHKERRQ(ierr); /* w^T_i (p_{old} - p) */ 176*a312c225SMatthew G Knepley ierr = VecScale(V[i], 1.0/wdot);CHKERRQ(ierr); 177*a312c225SMatthew G Knepley 178*a312c225SMatthew G Knepley ierr = VecDot(W[i], P, &wdot);CHKERRQ(ierr); /* p = (I + v_i w^T_i) p */ 179*a312c225SMatthew G Knepley ierr = VecAXPY(P, wdot, V[i]);CHKERRQ(ierr); 180*a312c225SMatthew G Knepley ierr = VecCopy(P, Pold);CHKERRQ(ierr); /* p_{old} = p */ 181*a312c225SMatthew G Knepley 182*a312c225SMatthew G Knepley ierr = VecAXPY(X, 1.0, P);CHKERRQ(ierr); /* x = x + p */ 183*a312c225SMatthew G Knepley } 184*a312c225SMatthew G Knepley } 185*a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 186*a312c225SMatthew G Knepley PetscFunctionReturn(0); 187*a312c225SMatthew G Knepley } 188*a312c225SMatthew G Knepley 189*a312c225SMatthew G Knepley /*MC 190*a312c225SMatthew G Knepley SNESNGMRES - The Nonlinear Generalized Minimum Residual (NGMRES) method of Oosterlee and Washio. 191*a312c225SMatthew G Knepley 192*a312c225SMatthew G Knepley Level: beginner 193*a312c225SMatthew G Knepley 194*a312c225SMatthew G Knepley Notes: Supports only left preconditioning 195*a312c225SMatthew G Knepley 196*a312c225SMatthew G Knepley "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 197*a312c225SMatthew G Knepley SIAM Journal on Scientific Computing, 21(5), 2000. 198*a312c225SMatthew G Knepley 199*a312c225SMatthew G Knepley .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 200*a312c225SMatthew G Knepley M*/ 201*a312c225SMatthew G Knepley EXTERN_C_BEGIN 202*a312c225SMatthew G Knepley #undef __FUNCT__ 203*a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 204*a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes) 205*a312c225SMatthew G Knepley { 206*a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 207*a312c225SMatthew G Knepley PetscErrorCode ierr; 208*a312c225SMatthew G Knepley 209*a312c225SMatthew G Knepley PetscFunctionBegin; 210*a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 211*a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 212*a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 213*a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 214*a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 215*a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 216*a312c225SMatthew G Knepley 217*a312c225SMatthew G Knepley ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr); 218*a312c225SMatthew G Knepley snes->data = (void*) ngmres; 219*a312c225SMatthew G Knepley ngmres->msize = 30; 220*a312c225SMatthew G Knepley ngmres->csize = 0; 221*a312c225SMatthew G Knepley #if 0 222*a312c225SMatthew G Knepley if (ksp->pc_side != PC_LEFT) {ierr = PetscInfo(ksp,"WARNING! Setting PC_SIDE for NGMRES to left!\n");CHKERRQ(ierr);} 223*a312c225SMatthew G Knepley snes->pc_side = PC_LEFT; 224*a312c225SMatthew G Knepley #endif 225*a312c225SMatthew G Knepley PetscFunctionReturn(0); 226*a312c225SMatthew G Knepley } 227*a312c225SMatthew G Knepley EXTERN_C_END 228