1fef7b6d8SPeter Brune #include <../src/snes/impls/ncg/snesncgimpl.h> 2fef7b6d8SPeter Brune 3fef7b6d8SPeter Brune #undef __FUNCT__ 4fef7b6d8SPeter Brune #define __FUNCT__ "SNESReset_NCG" 5fef7b6d8SPeter Brune PetscErrorCode SNESReset_NCG(SNES snes) 6fef7b6d8SPeter Brune { 7fef7b6d8SPeter Brune 8fef7b6d8SPeter Brune PetscFunctionBegin; 9fef7b6d8SPeter Brune PetscFunctionReturn(0); 10fef7b6d8SPeter Brune } 11fef7b6d8SPeter Brune 12f1c6b773SPeter Brune #define SNES_LINESEARCH_NCGLINEAR "linear" 13bbd5d0b3SPeter Brune 14fef7b6d8SPeter Brune /* 15fef7b6d8SPeter Brune SNESDestroy_NCG - Destroys the private SNES_NCG context that was created with SNESCreate_NCG(). 16fef7b6d8SPeter Brune 17fef7b6d8SPeter Brune Input Parameter: 18fef7b6d8SPeter Brune . snes - the SNES context 19fef7b6d8SPeter Brune 20fef7b6d8SPeter Brune Application Interface Routine: SNESDestroy() 21fef7b6d8SPeter Brune */ 22fef7b6d8SPeter Brune #undef __FUNCT__ 23fef7b6d8SPeter Brune #define __FUNCT__ "SNESDestroy_NCG" 24fef7b6d8SPeter Brune PetscErrorCode SNESDestroy_NCG(SNES snes) 25fef7b6d8SPeter Brune { 26fef7b6d8SPeter Brune PetscErrorCode ierr; 27fef7b6d8SPeter Brune 28fef7b6d8SPeter Brune PetscFunctionBegin; 29fef7b6d8SPeter Brune ierr = PetscFree(snes->data);CHKERRQ(ierr); 30fef7b6d8SPeter Brune PetscFunctionReturn(0); 31fef7b6d8SPeter Brune } 32fef7b6d8SPeter Brune 33fef7b6d8SPeter Brune /* 34fef7b6d8SPeter Brune SNESSetUp_NCG - Sets up the internal data structures for the later use 35fef7b6d8SPeter Brune of the SNESNCG nonlinear solver. 36fef7b6d8SPeter Brune 37fef7b6d8SPeter Brune Input Parameters: 38fef7b6d8SPeter Brune + snes - the SNES context 39fef7b6d8SPeter Brune - x - the solution vector 40fef7b6d8SPeter Brune 41fef7b6d8SPeter Brune Application Interface Routine: SNESSetUp() 42fef7b6d8SPeter Brune */ 43bbd5d0b3SPeter Brune 445dc0b524SSatish Balay EXTERN_C_BEGIN 45f1c6b773SPeter Brune extern PetscErrorCode SNESLineSearchCreate_NCGLinear(SNESLineSearch); 465dc0b524SSatish Balay EXTERN_C_END 47bbd5d0b3SPeter Brune 48fef7b6d8SPeter Brune #undef __FUNCT__ 49fef7b6d8SPeter Brune #define __FUNCT__ "SNESSetUp_NCG" 50fef7b6d8SPeter Brune PetscErrorCode SNESSetUp_NCG(SNES snes) 51fef7b6d8SPeter Brune { 52fef7b6d8SPeter Brune PetscErrorCode ierr; 53fef7b6d8SPeter Brune 54fef7b6d8SPeter Brune PetscFunctionBegin; 55bbd5d0b3SPeter Brune ierr = SNESDefaultGetWork(snes,2);CHKERRQ(ierr); 56bbd5d0b3SPeter Brune ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); 57f1c6b773SPeter Brune ierr = SNESLineSearchRegisterDynamic(SNES_LINESEARCH_NCGLINEAR, PETSC_NULL,"SNESLineSearchCreate_NCGLinear", SNESLineSearchCreate_NCGLinear);CHKERRQ(ierr); 58bbd5d0b3SPeter Brune 59fef7b6d8SPeter Brune PetscFunctionReturn(0); 60fef7b6d8SPeter Brune } 61fef7b6d8SPeter Brune /* 6205b53524SPeter Brune SNESSetFromOptions_NCG - Sets various parameters for the SNESNCG method. 63fef7b6d8SPeter Brune 64fef7b6d8SPeter Brune Input Parameter: 65fef7b6d8SPeter Brune . snes - the SNES context 66fef7b6d8SPeter Brune 67fef7b6d8SPeter Brune Application Interface Routine: SNESSetFromOptions() 68fef7b6d8SPeter Brune */ 69fef7b6d8SPeter Brune #undef __FUNCT__ 70fef7b6d8SPeter Brune #define __FUNCT__ "SNESSetFromOptions_NCG" 71fef7b6d8SPeter Brune static PetscErrorCode SNESSetFromOptions_NCG(SNES snes) 72fef7b6d8SPeter Brune { 73dfb256c7SPeter Brune SNES_NCG *ncg = (SNES_NCG *)snes->data; 74dfb256c7SPeter Brune const char *betas[] = {"FR","PRP","HS", "DY", "CD"}; 75fef7b6d8SPeter Brune PetscErrorCode ierr; 76dfb256c7SPeter Brune PetscBool debug, flg; 77dfb256c7SPeter Brune PetscInt indx; 78f1c6b773SPeter Brune SNESLineSearch linesearch; 79fef7b6d8SPeter Brune 80fef7b6d8SPeter Brune PetscFunctionBegin; 81fef7b6d8SPeter Brune ierr = PetscOptionsHead("SNES NCG options");CHKERRQ(ierr); 82dfb256c7SPeter Brune ierr = PetscOptionsBool("-snes_ncg_monitor", "Monitor NCG iterations", "SNES", ncg->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);CHKERRQ(ierr); 83dfb256c7SPeter Brune ierr = PetscOptionsEList("-snes_ncg_type","Nonlinear CG update used","", betas, 5, "FR",&indx, &flg);CHKERRQ(ierr); 84dfb256c7SPeter Brune if (flg) { 85dfb256c7SPeter Brune ncg->betatype = indx; 86dfb256c7SPeter Brune } 87dfb256c7SPeter Brune if (debug) { 88dfb256c7SPeter Brune ncg->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 89dfb256c7SPeter Brune } 90fef7b6d8SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 919e764e56SPeter Brune if (!snes->linesearch) { 92f1c6b773SPeter Brune ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr); 939e764e56SPeter Brune if (!snes->pc) { 94f1c6b773SPeter Brune ierr = SNESLineSearchSetType(linesearch, SNES_LINESEARCH_CP);CHKERRQ(ierr); 959e764e56SPeter Brune } else { 96f1c6b773SPeter Brune ierr = SNESLineSearchSetType(linesearch, SNES_LINESEARCH_L2);CHKERRQ(ierr); 979e764e56SPeter Brune } 989e764e56SPeter Brune } 99fef7b6d8SPeter Brune PetscFunctionReturn(0); 100fef7b6d8SPeter Brune } 101fef7b6d8SPeter Brune 102fef7b6d8SPeter Brune /* 103fef7b6d8SPeter Brune SNESView_NCG - Prints info from the SNESNCG data structure. 104fef7b6d8SPeter Brune 105fef7b6d8SPeter Brune Input Parameters: 106fef7b6d8SPeter Brune + SNES - the SNES context 107fef7b6d8SPeter Brune - viewer - visualization context 108fef7b6d8SPeter Brune 109fef7b6d8SPeter Brune Application Interface Routine: SNESView() 110fef7b6d8SPeter Brune */ 111fef7b6d8SPeter Brune #undef __FUNCT__ 112fef7b6d8SPeter Brune #define __FUNCT__ "SNESView_NCG" 113fef7b6d8SPeter Brune static PetscErrorCode SNESView_NCG(SNES snes, PetscViewer viewer) 114fef7b6d8SPeter Brune { 115fef7b6d8SPeter Brune PetscBool iascii; 116fef7b6d8SPeter Brune PetscErrorCode ierr; 117fef7b6d8SPeter Brune 118fef7b6d8SPeter Brune PetscFunctionBegin; 119fef7b6d8SPeter Brune ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 120fef7b6d8SPeter Brune if (iascii) { 121fef7b6d8SPeter Brune } 122fef7b6d8SPeter Brune PetscFunctionReturn(0); 123fef7b6d8SPeter Brune } 124fef7b6d8SPeter Brune 125fef7b6d8SPeter Brune #undef __FUNCT__ 126f1c6b773SPeter Brune #define __FUNCT__ "SNESLineSearchApply_NCGLinear" 127f1c6b773SPeter Brune PetscErrorCode SNESLineSearchApply_NCGLinear(SNESLineSearch linesearch) 128ea630c6eSPeter Brune { 129ea630c6eSPeter Brune PetscScalar alpha, ptAp; 130bbd5d0b3SPeter Brune Vec X, Y, F, W; 131bbd5d0b3SPeter Brune SNES snes; 132ea630c6eSPeter Brune PetscErrorCode ierr; 133bbd5d0b3SPeter Brune PetscReal *fnorm, *xnorm, *ynorm; 134ea630c6eSPeter Brune MatStructure flg = DIFFERENT_NONZERO_PATTERN; 135ea630c6eSPeter Brune 136ea630c6eSPeter Brune PetscFunctionBegin; 137bbd5d0b3SPeter Brune 138f1c6b773SPeter Brune ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr); 139bbd5d0b3SPeter Brune X = linesearch->vec_sol; 140bbd5d0b3SPeter Brune W = linesearch->vec_sol_new; 141bbd5d0b3SPeter Brune F = linesearch->vec_func; 142bbd5d0b3SPeter Brune Y = linesearch->vec_update; 143bbd5d0b3SPeter Brune fnorm = &linesearch->fnorm; 144bbd5d0b3SPeter Brune xnorm = &linesearch->xnorm; 145bbd5d0b3SPeter Brune ynorm = &linesearch->ynorm; 146bbd5d0b3SPeter Brune 147ea630c6eSPeter Brune /* 148ea630c6eSPeter Brune 149d2140ca3SPeter Brune The exact step size for unpreconditioned linear CG is just: 150ea630c6eSPeter Brune alpha = (r, r) / (p, Ap) = (f, f) / (y, Jy) 151ea630c6eSPeter Brune */ 152a5892487SPeter Brune ierr = SNESComputeJacobian(snes, X, &snes->jacobian, &snes->jacobian_pre, &flg);CHKERRQ(ierr); 153ea630c6eSPeter Brune ierr = VecDot(F, F, &alpha);CHKERRQ(ierr); 154ea630c6eSPeter Brune ierr = MatMult(snes->jacobian, Y, W);CHKERRQ(ierr); 155ea630c6eSPeter Brune ierr = VecDot(Y, W, &ptAp);CHKERRQ(ierr); 156ea630c6eSPeter Brune alpha = alpha / ptAp; 157d9fe6452SJed Brown ierr = PetscPrintf(((PetscObject)snes)->comm, "alpha: %G\n", PetscRealPart(alpha));CHKERRQ(ierr); 158bbd5d0b3SPeter Brune ierr = VecAXPY(X, alpha, Y);CHKERRQ(ierr); 159bbd5d0b3SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 160bbd5d0b3SPeter Brune 161bbd5d0b3SPeter Brune ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr); 162bbd5d0b3SPeter Brune ierr = VecNorm(X, NORM_2, xnorm);CHKERRQ(ierr); 163bbd5d0b3SPeter Brune ierr = VecNorm(Y, NORM_2, ynorm);CHKERRQ(ierr); 164bbd5d0b3SPeter Brune 165ea630c6eSPeter Brune PetscFunctionReturn(0); 166ea630c6eSPeter Brune } 167ea630c6eSPeter Brune 168bbd5d0b3SPeter Brune EXTERN_C_BEGIN 169bbd5d0b3SPeter Brune #undef __FUNCT__ 170f1c6b773SPeter Brune #define __FUNCT__ "SNESLineSearchCreate_NCGLinear" 171bbd5d0b3SPeter Brune 172f1c6b773SPeter Brune PetscErrorCode SNESLineSearchCreate_NCGLinear(SNESLineSearch linesearch) 173bbd5d0b3SPeter Brune { 174bbd5d0b3SPeter Brune PetscFunctionBegin; 175f1c6b773SPeter Brune linesearch->ops->apply = SNESLineSearchApply_NCGLinear; 176bbd5d0b3SPeter Brune linesearch->ops->destroy = PETSC_NULL; 177bbd5d0b3SPeter Brune linesearch->ops->setfromoptions = PETSC_NULL; 178bbd5d0b3SPeter Brune linesearch->ops->reset = PETSC_NULL; 179bbd5d0b3SPeter Brune linesearch->ops->view = PETSC_NULL; 180bbd5d0b3SPeter Brune linesearch->ops->setup = PETSC_NULL; 181bbd5d0b3SPeter Brune PetscFunctionReturn(0); 182bbd5d0b3SPeter Brune } 183bbd5d0b3SPeter Brune EXTERN_C_END 184bbd5d0b3SPeter Brune 18588d374b2SPeter Brune #undef __FUNCT__ 1868c40d5fbSBarry Smith #define __FUNCT__ "SNESNCGComputeYtJtF_Private" 18788d374b2SPeter Brune /* 18888d374b2SPeter Brune 18988d374b2SPeter Brune Assuming F = SNESComputeFunction(X) compute Y^tJ^tF using a simple secant approximation of the jacobian. 19088d374b2SPeter Brune 19188d374b2SPeter Brune */ 1928c40d5fbSBarry Smith PetscErrorCode SNESNCGComputeYtJtF_Private(SNES snes, Vec X, Vec F, Vec Y, Vec W, Vec G, PetscScalar * ytJtf) { 19388d374b2SPeter Brune PetscErrorCode ierr; 19488d374b2SPeter Brune PetscScalar ftf, ftg, fty, h; 19588d374b2SPeter Brune PetscFunctionBegin; 19688d374b2SPeter Brune ierr = VecDot(F, F, &ftf);CHKERRQ(ierr); 19788d374b2SPeter Brune ierr = VecDot(F, Y, &fty);CHKERRQ(ierr); 19888d374b2SPeter Brune h = 1e-5*fty / fty; 19988d374b2SPeter Brune ierr = VecCopy(X, W);CHKERRQ(ierr); 20088d374b2SPeter Brune ierr = VecAXPY(W, -h, Y);CHKERRQ(ierr); /* this is arbitrary */ 20188d374b2SPeter Brune ierr = SNESComputeFunction(snes, W, G);CHKERRQ(ierr); 20288d374b2SPeter Brune ierr = VecDot(G, F, &ftg);CHKERRQ(ierr); 20388d374b2SPeter Brune *ytJtf = (ftg - ftf) / h; 20488d374b2SPeter Brune PetscFunctionReturn(0); 20588d374b2SPeter Brune } 20688d374b2SPeter Brune 207fef7b6d8SPeter Brune /* 208fef7b6d8SPeter Brune SNESSolve_NCG - Solves a nonlinear system with the Nonlinear Conjugate Gradient method. 209fef7b6d8SPeter Brune 210fef7b6d8SPeter Brune Input Parameters: 211fef7b6d8SPeter Brune . snes - the SNES context 212fef7b6d8SPeter Brune 213fef7b6d8SPeter Brune Output Parameter: 214fef7b6d8SPeter Brune . outits - number of iterations until termination 215fef7b6d8SPeter Brune 216fef7b6d8SPeter Brune Application Interface Routine: SNESSolve() 217fef7b6d8SPeter Brune */ 218fef7b6d8SPeter Brune #undef __FUNCT__ 219fef7b6d8SPeter Brune #define __FUNCT__ "SNESSolve_NCG" 220fef7b6d8SPeter Brune PetscErrorCode SNESSolve_NCG(SNES snes) 221fef7b6d8SPeter Brune { 222dfb256c7SPeter Brune SNES_NCG *ncg = (SNES_NCG *)snes->data; 223bbd5d0b3SPeter Brune Vec X, dX, lX, F, B, Fold; 224bbd5d0b3SPeter Brune PetscReal fnorm, ynorm, xnorm, beta = 0.0; 2255d115551SPeter Brune PetscScalar dXdotF, dXolddotFold, dXdotFold, lXdotF, lXdotFold; 226fef7b6d8SPeter Brune PetscInt maxits, i; 227fef7b6d8SPeter Brune PetscErrorCode ierr; 228fef7b6d8SPeter Brune SNESConvergedReason reason; 229fef7b6d8SPeter Brune PetscBool lsSuccess = PETSC_TRUE; 230f1c6b773SPeter Brune SNESLineSearch linesearch; 23188d374b2SPeter Brune 232fef7b6d8SPeter Brune PetscFunctionBegin; 233fef7b6d8SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 234fef7b6d8SPeter Brune 235fef7b6d8SPeter Brune maxits = snes->max_its; /* maximum number of iterations */ 236fef7b6d8SPeter Brune X = snes->vec_sol; /* X^n */ 2375d115551SPeter Brune Fold = snes->work[0]; /* The previous iterate of X */ 23888d374b2SPeter Brune dX = snes->work[1]; /* the preconditioned direction */ 239169e2be8SPeter Brune lX = snes->vec_sol_update; /* the conjugate direction */ 240fef7b6d8SPeter Brune F = snes->vec_func; /* residual vector */ 241302dbbaeSPeter Brune B = snes->vec_rhs; /* the right hand side */ 242fef7b6d8SPeter Brune 243f1c6b773SPeter Brune ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr); 2449e764e56SPeter Brune 245fef7b6d8SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 246fef7b6d8SPeter Brune snes->iter = 0; 247fef7b6d8SPeter Brune snes->norm = 0.; 248fef7b6d8SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 249fef7b6d8SPeter Brune 250bbd5d0b3SPeter Brune /* compute the initial function and preconditioned update dX */ 251*e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 252fef7b6d8SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 253fef7b6d8SPeter Brune if (snes->domainerror) { 254fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 255fef7b6d8SPeter Brune PetscFunctionReturn(0); 256fef7b6d8SPeter Brune } 257*e4ed7901SPeter Brune } else { 258*e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 259*e4ed7901SPeter Brune } 260*e4ed7901SPeter Brune if (!snes->norm_init_set) { 261fef7b6d8SPeter Brune /* convergence test */ 262fef7b6d8SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 263fef7b6d8SPeter Brune if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 264*e4ed7901SPeter Brune } else { 265*e4ed7901SPeter Brune fnorm = snes->norm_init; 266*e4ed7901SPeter Brune snes->norm_init_set = PETSC_FALSE; 267*e4ed7901SPeter Brune } 268fef7b6d8SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 269fef7b6d8SPeter Brune snes->norm = fnorm; 270fef7b6d8SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 271fef7b6d8SPeter Brune SNESLogConvHistory(snes,fnorm,0); 272fef7b6d8SPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 273fef7b6d8SPeter Brune 274fef7b6d8SPeter Brune /* set parameter for default relative tolerance convergence test */ 275fef7b6d8SPeter Brune snes->ttol = fnorm*snes->rtol; 276fef7b6d8SPeter Brune /* test convergence */ 277fef7b6d8SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 278fef7b6d8SPeter Brune if (snes->reason) PetscFunctionReturn(0); 279fef7b6d8SPeter Brune 280fef7b6d8SPeter Brune /* Call general purpose update function */ 281fef7b6d8SPeter Brune if (snes->ops->update) { 282fef7b6d8SPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 283fef7b6d8SPeter Brune } 284fef7b6d8SPeter Brune 285fef7b6d8SPeter Brune /* first update -- just use the (preconditioned) residual direction for the initial conjugate direction */ 286bbd5d0b3SPeter Brune 28783947a81SPeter Brune if (snes->pc) { 28829c94e34SPeter Brune ierr = VecCopy(X, dX);CHKERRQ(ierr); 28929c94e34SPeter Brune ierr = SNESSolve(snes->pc, B, dX);CHKERRQ(ierr); 290fef7b6d8SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 29151e86f29SPeter Brune if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) { 292fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_INNER; 293fef7b6d8SPeter Brune PetscFunctionReturn(0); 294fef7b6d8SPeter Brune } 29529c94e34SPeter Brune ierr = VecAYPX(dX,-1.0,X);CHKERRQ(ierr); 2965d10c001SPeter Brune } else { 29729c94e34SPeter Brune ierr = VecCopy(F, dX);CHKERRQ(ierr); 298fef7b6d8SPeter Brune } 29929c94e34SPeter Brune ierr = VecCopy(dX, lX);CHKERRQ(ierr); 300bbd5d0b3SPeter Brune ierr = VecDot(F, dX, &dXdotF);CHKERRQ(ierr); 301bbd5d0b3SPeter Brune /* 30288d374b2SPeter Brune } else { 3038c40d5fbSBarry Smith ierr = SNESNCGComputeYtJtF_Private(snes, X, F, dX, W, G, &dXdotF);CHKERRQ(ierr); 30488d374b2SPeter Brune } 305bbd5d0b3SPeter Brune */ 30609c08436SPeter Brune for(i = 1; i < maxits + 1; i++) { 307fef7b6d8SPeter Brune lsSuccess = PETSC_TRUE; 30829c94e34SPeter Brune /* some update types require the old update direction or conjugate direction */ 30929c94e34SPeter Brune if (ncg->betatype == 1 || ncg->betatype == 2 || ncg->betatype == 3 || ncg->betatype == 4) { /* prp, hs, dy, cd need dXold*/ 3105d115551SPeter Brune ierr = VecCopy(F, Fold);CHKERRQ(ierr); 31188d374b2SPeter Brune } 312f1c6b773SPeter Brune ierr = SNESLineSearchApply(linesearch, X, F, &fnorm, lX);CHKERRQ(ierr); 313f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(linesearch, &lsSuccess);CHKERRQ(ierr); 314fef7b6d8SPeter Brune if (!lsSuccess) { 315fef7b6d8SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 316fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 3175d10c001SPeter Brune PetscFunctionReturn(0); 318fef7b6d8SPeter Brune } 319fef7b6d8SPeter Brune } 320fef7b6d8SPeter Brune if (snes->nfuncs >= snes->max_funcs) { 321fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 3225d10c001SPeter Brune PetscFunctionReturn(0); 323fef7b6d8SPeter Brune } 324fef7b6d8SPeter Brune if (snes->domainerror) { 325fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 326fef7b6d8SPeter Brune PetscFunctionReturn(0); 327fef7b6d8SPeter Brune } 328f1c6b773SPeter Brune ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr); 329fef7b6d8SPeter Brune /* Monitor convergence */ 330fef7b6d8SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 331169e2be8SPeter Brune snes->iter = i; 332fef7b6d8SPeter Brune snes->norm = fnorm; 333fef7b6d8SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 334fef7b6d8SPeter Brune SNESLogConvHistory(snes,snes->norm,0); 335fef7b6d8SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 336302dbbaeSPeter Brune 337fef7b6d8SPeter Brune /* Test for convergence */ 338fef7b6d8SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 3395d10c001SPeter Brune if (snes->reason) PetscFunctionReturn(0); 340302dbbaeSPeter Brune 341302dbbaeSPeter Brune /* Call general purpose update function */ 342302dbbaeSPeter Brune if (snes->ops->update) { 343302dbbaeSPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 344302dbbaeSPeter Brune } 34583947a81SPeter Brune if (snes->pc) { 346302dbbaeSPeter Brune ierr = VecCopy(X,dX);CHKERRQ(ierr); 347cf949ffaSPeter Brune ierr = SNESSolve(snes->pc, B, dX);CHKERRQ(ierr); 348302dbbaeSPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 34951e86f29SPeter Brune if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) { 350302dbbaeSPeter Brune snes->reason = SNES_DIVERGED_INNER; 351302dbbaeSPeter Brune PetscFunctionReturn(0); 352302dbbaeSPeter Brune } 353eb1825c3SPeter Brune ierr = VecAYPX(dX,-1.0,X);CHKERRQ(ierr); 354a3685310SPeter Brune } else { 355a3685310SPeter Brune ierr = VecCopy(F, dX);CHKERRQ(ierr); 356302dbbaeSPeter Brune } 357302dbbaeSPeter Brune 35829c94e34SPeter Brune /* compute the conjugate direction lX = dX + beta*lX with beta = ((dX, dX) / (dX_old, dX_old) (Fletcher-Reeves update)*/ 359dfb256c7SPeter Brune switch(ncg->betatype) { 360dfb256c7SPeter Brune case 0: /* Fletcher-Reeves */ 3615d115551SPeter Brune dXolddotFold = dXdotF; 362bbd5d0b3SPeter Brune ierr = VecDot(dX, dX, &dXdotF);CHKERRQ(ierr); 3635d115551SPeter Brune beta = PetscRealPart(dXdotF / dXolddotFold); 364dfb256c7SPeter Brune break; 365dfb256c7SPeter Brune case 1: /* Polak-Ribiere-Poylak */ 3665d115551SPeter Brune dXolddotFold = dXdotF; 3675d115551SPeter Brune ierr = VecDot(F, dX, &dXdotF);CHKERRQ(ierr); 3685d115551SPeter Brune ierr = VecDot(Fold, dX, &dXdotFold);CHKERRQ(ierr); 3695d115551SPeter Brune beta = PetscRealPart(((dXdotF - dXdotFold) / dXolddotFold)); 370dfb256c7SPeter Brune if (beta < 0.0) beta = 0.0; /* restart */ 371dfb256c7SPeter Brune break; 372dfb256c7SPeter Brune case 2: /* Hestenes-Stiefel */ 3735d115551SPeter Brune ierr = VecDot(dX, F, &dXdotF);CHKERRQ(ierr); 3745d115551SPeter Brune ierr = VecDot(dX, Fold, &dXdotFold);CHKERRQ(ierr); 3755d115551SPeter Brune ierr = VecDot(lX, F, &lXdotF);CHKERRQ(ierr); 3765d115551SPeter Brune ierr = VecDot(lX, Fold, &lXdotFold);CHKERRQ(ierr); 3775d115551SPeter Brune beta = PetscRealPart((dXdotF - dXdotFold) / (lXdotF - lXdotFold)); 378dfb256c7SPeter Brune break; 379dfb256c7SPeter Brune case 3: /* Dai-Yuan */ 3805d115551SPeter Brune ierr = VecDot(dX, F, &dXdotF);CHKERRQ(ierr); 381bbd5d0b3SPeter Brune ierr = VecDot(lX, F, &lXdotF);CHKERRQ(ierr); 382bbd5d0b3SPeter Brune ierr = VecDot(lX, Fold, &lXdotFold);CHKERRQ(ierr); 3835d115551SPeter Brune beta = PetscRealPart(dXdotF / (lXdotFold - lXdotF));CHKERRQ(ierr); 384dfb256c7SPeter Brune break; 385dfb256c7SPeter Brune case 4: /* Conjugate Descent */ 38601fcfa61SPeter Brune ierr = VecDot(dX, F, &dXdotF);CHKERRQ(ierr); 38788d374b2SPeter Brune ierr = VecDot(lX, Fold, &lXdotFold);CHKERRQ(ierr); 3885d115551SPeter Brune beta = PetscRealPart(dXdotF / lXdotFold);CHKERRQ(ierr); 389dfb256c7SPeter Brune break; 390dfb256c7SPeter Brune } 391dfb256c7SPeter Brune if (ncg->monitor) { 392646217ecSPeter Brune ierr = PetscViewerASCIIPrintf(ncg->monitor, "beta = %e\n", beta);CHKERRQ(ierr); 393dfb256c7SPeter Brune } 394dfb256c7SPeter Brune ierr = VecAYPX(lX, beta, dX);CHKERRQ(ierr); 395fef7b6d8SPeter Brune } 396fef7b6d8SPeter Brune ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 397fef7b6d8SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 398fef7b6d8SPeter Brune PetscFunctionReturn(0); 399fef7b6d8SPeter Brune } 400fef7b6d8SPeter Brune 401fef7b6d8SPeter Brune /*MC 402fef7b6d8SPeter Brune SNESNCG - Nonlinear Conjugate-Gradient method for the solution of general nonlinear systems. 403fef7b6d8SPeter Brune 404fef7b6d8SPeter Brune Level: beginner 405fef7b6d8SPeter Brune 406fef7b6d8SPeter Brune Options Database: 4071867fe5bSPeter Brune + -snes_ncg_type <fr, prp, dy, hs, cd> - Choice of conjugate-gradient update parameter. 408f3aaf736SPeter Brune . -snes_ls <basic,basicnormnorms,quadratic,critical,test> - Line search type. 4091867fe5bSPeter Brune - -snes_ncg_monitor - Print relevant information about the ncg iteration. 410fef7b6d8SPeter Brune 411fef7b6d8SPeter Brune Notes: This solves the nonlinear system of equations F(x) = 0 using the nonlinear generalization of the conjugate 412fef7b6d8SPeter Brune gradient method. This may be used with a nonlinear preconditioner used to pick the new search directions, but otherwise 413fef7b6d8SPeter Brune chooses the initial search direction as F(x) for the initial guess x. 414fef7b6d8SPeter Brune 415fef7b6d8SPeter Brune 416fef7b6d8SPeter Brune .seealso: SNESCreate(), SNES, SNESSetType(), SNESLS, SNESTR, SNESNGMRES, SNESNQN 417fef7b6d8SPeter Brune M*/ 418fef7b6d8SPeter Brune EXTERN_C_BEGIN 419fef7b6d8SPeter Brune #undef __FUNCT__ 420fef7b6d8SPeter Brune #define __FUNCT__ "SNESCreate_NCG" 421fef7b6d8SPeter Brune PetscErrorCode SNESCreate_NCG(SNES snes) 422fef7b6d8SPeter Brune { 423fef7b6d8SPeter Brune PetscErrorCode ierr; 424ea630c6eSPeter Brune SNES_NCG * neP; 425fef7b6d8SPeter Brune 426fef7b6d8SPeter Brune PetscFunctionBegin; 427fef7b6d8SPeter Brune snes->ops->destroy = SNESDestroy_NCG; 428fef7b6d8SPeter Brune snes->ops->setup = SNESSetUp_NCG; 429fef7b6d8SPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_NCG; 430fef7b6d8SPeter Brune snes->ops->view = SNESView_NCG; 431fef7b6d8SPeter Brune snes->ops->solve = SNESSolve_NCG; 432fef7b6d8SPeter Brune snes->ops->reset = SNESReset_NCG; 433fef7b6d8SPeter Brune 434fef7b6d8SPeter Brune snes->usesksp = PETSC_FALSE; 435fef7b6d8SPeter Brune snes->usespc = PETSC_TRUE; 436fef7b6d8SPeter Brune 43788976e71SPeter Brune if (!snes->tolerancesset) { 4380e444f03SPeter Brune snes->max_funcs = 30000; 4390e444f03SPeter Brune snes->max_its = 10000; 44088976e71SPeter Brune } 4410e444f03SPeter Brune 442fef7b6d8SPeter Brune ierr = PetscNewLog(snes, SNES_NCG, &neP);CHKERRQ(ierr); 443fef7b6d8SPeter Brune snes->data = (void*) neP; 444dfb256c7SPeter Brune neP->monitor = PETSC_NULL; 4451867fe5bSPeter Brune neP->betatype = 1; 446fef7b6d8SPeter Brune PetscFunctionReturn(0); 447fef7b6d8SPeter Brune } 448fef7b6d8SPeter Brune EXTERN_C_END 449