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 { 7*bbd5d0b3SPeter Brune PetscErrorCode ierr; 8*bbd5d0b3SPeter Brune SNES_NCG *ncg = (SNES_NCG *)snes->data; 9fef7b6d8SPeter Brune 10fef7b6d8SPeter Brune PetscFunctionBegin; 11*bbd5d0b3SPeter Brune ierr = LineSearchDestroy(&ncg->linesearch);CHKERRQ(ierr); 12fef7b6d8SPeter Brune PetscFunctionReturn(0); 13fef7b6d8SPeter Brune } 14fef7b6d8SPeter Brune 15*bbd5d0b3SPeter Brune #define LINESEARCHNCGLINEAR "linear" 16*bbd5d0b3SPeter Brune 17fef7b6d8SPeter Brune /* 18fef7b6d8SPeter Brune SNESDestroy_NCG - Destroys the private SNES_NCG context that was created with SNESCreate_NCG(). 19fef7b6d8SPeter Brune 20fef7b6d8SPeter Brune Input Parameter: 21fef7b6d8SPeter Brune . snes - the SNES context 22fef7b6d8SPeter Brune 23fef7b6d8SPeter Brune Application Interface Routine: SNESDestroy() 24fef7b6d8SPeter Brune */ 25fef7b6d8SPeter Brune #undef __FUNCT__ 26fef7b6d8SPeter Brune #define __FUNCT__ "SNESDestroy_NCG" 27fef7b6d8SPeter Brune PetscErrorCode SNESDestroy_NCG(SNES snes) 28fef7b6d8SPeter Brune { 29fef7b6d8SPeter Brune PetscErrorCode ierr; 30fef7b6d8SPeter Brune 31fef7b6d8SPeter Brune PetscFunctionBegin; 32fef7b6d8SPeter Brune ierr = PetscFree(snes->data);CHKERRQ(ierr); 33fef7b6d8SPeter Brune PetscFunctionReturn(0); 34fef7b6d8SPeter Brune } 35fef7b6d8SPeter Brune 36fef7b6d8SPeter Brune /* 37fef7b6d8SPeter Brune SNESSetUp_NCG - Sets up the internal data structures for the later use 38fef7b6d8SPeter Brune of the SNESNCG nonlinear solver. 39fef7b6d8SPeter Brune 40fef7b6d8SPeter Brune Input Parameters: 41fef7b6d8SPeter Brune + snes - the SNES context 42fef7b6d8SPeter Brune - x - the solution vector 43fef7b6d8SPeter Brune 44fef7b6d8SPeter Brune Application Interface Routine: SNESSetUp() 45fef7b6d8SPeter Brune */ 46*bbd5d0b3SPeter Brune 47*bbd5d0b3SPeter Brune EXTERN_C_BEGIN; 48*bbd5d0b3SPeter Brune extern PetscErrorCode LineSearchCreate_NCGLinear(LineSearch); 49*bbd5d0b3SPeter Brune EXTERN_C_END; 50*bbd5d0b3SPeter Brune 51fef7b6d8SPeter Brune #undef __FUNCT__ 52fef7b6d8SPeter Brune #define __FUNCT__ "SNESSetUp_NCG" 53fef7b6d8SPeter Brune PetscErrorCode SNESSetUp_NCG(SNES snes) 54fef7b6d8SPeter Brune { 55fef7b6d8SPeter Brune PetscErrorCode ierr; 56*bbd5d0b3SPeter Brune SNES_NCG *ncg = (SNES_NCG *)snes->data; 57*bbd5d0b3SPeter Brune const char *optionsprefix; 58fef7b6d8SPeter Brune 59fef7b6d8SPeter Brune PetscFunctionBegin; 60*bbd5d0b3SPeter Brune ierr = SNESDefaultGetWork(snes,2);CHKERRQ(ierr); 61*bbd5d0b3SPeter Brune ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); 62*bbd5d0b3SPeter Brune ierr = LineSearchRegisterDynamic(LINESEARCHNCGLINEAR, PETSC_NULL,"LineSearchCreate_NCGLinear", LineSearchCreate_NCGLinear);CHKERRQ(ierr); 63*bbd5d0b3SPeter Brune ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 64*bbd5d0b3SPeter Brune ierr = LineSearchCreate(((PetscObject)snes)->comm, &ncg->linesearch);CHKERRQ(ierr); 65*bbd5d0b3SPeter Brune ierr = LineSearchSetSNES(ncg->linesearch, snes);CHKERRQ(ierr); 66*bbd5d0b3SPeter Brune if (snes->pc) { 67*bbd5d0b3SPeter Brune ierr = LineSearchSetType(ncg->linesearch, LINESEARCHCP);CHKERRQ(ierr); 68*bbd5d0b3SPeter Brune } else { 69*bbd5d0b3SPeter Brune ierr = LineSearchSetType(ncg->linesearch, LINESEARCHL2);CHKERRQ(ierr); 70*bbd5d0b3SPeter Brune } 71*bbd5d0b3SPeter Brune ierr = LineSearchAppendOptionsPrefix(ncg->linesearch, optionsprefix);CHKERRQ(ierr); 72*bbd5d0b3SPeter Brune ierr = LineSearchSetFromOptions(ncg->linesearch);CHKERRQ(ierr); 73*bbd5d0b3SPeter Brune 74fef7b6d8SPeter Brune PetscFunctionReturn(0); 75fef7b6d8SPeter Brune } 76fef7b6d8SPeter Brune /* 7705b53524SPeter Brune SNESSetFromOptions_NCG - Sets various parameters for the SNESNCG method. 78fef7b6d8SPeter Brune 79fef7b6d8SPeter Brune Input Parameter: 80fef7b6d8SPeter Brune . snes - the SNES context 81fef7b6d8SPeter Brune 82fef7b6d8SPeter Brune Application Interface Routine: SNESSetFromOptions() 83fef7b6d8SPeter Brune */ 84fef7b6d8SPeter Brune #undef __FUNCT__ 85fef7b6d8SPeter Brune #define __FUNCT__ "SNESSetFromOptions_NCG" 86fef7b6d8SPeter Brune static PetscErrorCode SNESSetFromOptions_NCG(SNES snes) 87fef7b6d8SPeter Brune { 88dfb256c7SPeter Brune SNES_NCG *ncg = (SNES_NCG *)snes->data; 89dfb256c7SPeter Brune const char *betas[] = {"FR","PRP","HS", "DY", "CD"}; 90fef7b6d8SPeter Brune PetscErrorCode ierr; 91dfb256c7SPeter Brune PetscBool debug, flg; 92dfb256c7SPeter Brune PetscInt indx; 93fef7b6d8SPeter Brune 94fef7b6d8SPeter Brune PetscFunctionBegin; 95fef7b6d8SPeter Brune ierr = PetscOptionsHead("SNES NCG options");CHKERRQ(ierr); 96dfb256c7SPeter Brune ierr = PetscOptionsBool("-snes_ncg_monitor", "Monitor NCG iterations", "SNES", ncg->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);CHKERRQ(ierr); 97dfb256c7SPeter Brune ierr = PetscOptionsEList("-snes_ncg_type","Nonlinear CG update used","", betas, 5, "FR",&indx, &flg);CHKERRQ(ierr); 98dfb256c7SPeter Brune if (flg) { 99dfb256c7SPeter Brune ncg->betatype = indx; 100dfb256c7SPeter Brune } 101dfb256c7SPeter Brune if (debug) { 102dfb256c7SPeter Brune ncg->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 103dfb256c7SPeter Brune } 104fef7b6d8SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 105fef7b6d8SPeter Brune PetscFunctionReturn(0); 106fef7b6d8SPeter Brune } 107fef7b6d8SPeter Brune 108fef7b6d8SPeter Brune /* 109fef7b6d8SPeter Brune SNESView_NCG - Prints info from the SNESNCG data structure. 110fef7b6d8SPeter Brune 111fef7b6d8SPeter Brune Input Parameters: 112fef7b6d8SPeter Brune + SNES - the SNES context 113fef7b6d8SPeter Brune - viewer - visualization context 114fef7b6d8SPeter Brune 115fef7b6d8SPeter Brune Application Interface Routine: SNESView() 116fef7b6d8SPeter Brune */ 117fef7b6d8SPeter Brune #undef __FUNCT__ 118fef7b6d8SPeter Brune #define __FUNCT__ "SNESView_NCG" 119fef7b6d8SPeter Brune static PetscErrorCode SNESView_NCG(SNES snes, PetscViewer viewer) 120fef7b6d8SPeter Brune { 121fef7b6d8SPeter Brune PetscBool iascii; 122fef7b6d8SPeter Brune PetscErrorCode ierr; 123*bbd5d0b3SPeter Brune SNES_NCG *ncg = (SNES_NCG *)snes->data; 124fef7b6d8SPeter Brune 125fef7b6d8SPeter Brune PetscFunctionBegin; 126fef7b6d8SPeter Brune ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 127fef7b6d8SPeter Brune if (iascii) { 128*bbd5d0b3SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," line search type variant: %s\n", ((PetscObject)ncg->linesearch)->type_name);CHKERRQ(ierr); 129fef7b6d8SPeter Brune } 130fef7b6d8SPeter Brune PetscFunctionReturn(0); 131fef7b6d8SPeter Brune } 132fef7b6d8SPeter Brune 133fef7b6d8SPeter Brune #undef __FUNCT__ 134*bbd5d0b3SPeter Brune #define __FUNCT__ "LineSearchApply_NCGLinear" 135*bbd5d0b3SPeter Brune PetscErrorCode LineSearchApply_NCGLinear(LineSearch linesearch) 136ea630c6eSPeter Brune { 137ea630c6eSPeter Brune PetscScalar alpha, ptAp; 138*bbd5d0b3SPeter Brune Vec X, Y, F, W; 139*bbd5d0b3SPeter Brune SNES snes; 140ea630c6eSPeter Brune PetscErrorCode ierr; 141*bbd5d0b3SPeter Brune PetscReal *fnorm, *xnorm, *ynorm; 142ea630c6eSPeter Brune MatStructure flg = DIFFERENT_NONZERO_PATTERN; 143ea630c6eSPeter Brune 144ea630c6eSPeter Brune PetscFunctionBegin; 145*bbd5d0b3SPeter Brune 146*bbd5d0b3SPeter Brune ierr = LineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr); 147*bbd5d0b3SPeter Brune X = linesearch->vec_sol; 148*bbd5d0b3SPeter Brune W = linesearch->vec_sol_new; 149*bbd5d0b3SPeter Brune F = linesearch->vec_func; 150*bbd5d0b3SPeter Brune Y = linesearch->vec_update; 151*bbd5d0b3SPeter Brune fnorm = &linesearch->fnorm; 152*bbd5d0b3SPeter Brune xnorm = &linesearch->xnorm; 153*bbd5d0b3SPeter Brune ynorm = &linesearch->ynorm; 154*bbd5d0b3SPeter Brune 155ea630c6eSPeter Brune /* 156ea630c6eSPeter Brune 157d2140ca3SPeter Brune The exact step size for unpreconditioned linear CG is just: 158ea630c6eSPeter Brune alpha = (r, r) / (p, Ap) = (f, f) / (y, Jy) 159ea630c6eSPeter Brune */ 160a5892487SPeter Brune ierr = SNESComputeJacobian(snes, X, &snes->jacobian, &snes->jacobian_pre, &flg);CHKERRQ(ierr); 161ea630c6eSPeter Brune ierr = VecDot(F, F, &alpha);CHKERRQ(ierr); 162ea630c6eSPeter Brune ierr = MatMult(snes->jacobian, Y, W);CHKERRQ(ierr); 163ea630c6eSPeter Brune ierr = VecDot(Y, W, &ptAp);CHKERRQ(ierr); 164ea630c6eSPeter Brune alpha = alpha / ptAp; 165d9fe6452SJed Brown ierr = PetscPrintf(((PetscObject)snes)->comm, "alpha: %G\n", PetscRealPart(alpha));CHKERRQ(ierr); 166*bbd5d0b3SPeter Brune ierr = VecAXPY(X, alpha, Y);CHKERRQ(ierr); 167*bbd5d0b3SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 168*bbd5d0b3SPeter Brune 169*bbd5d0b3SPeter Brune ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr); 170*bbd5d0b3SPeter Brune ierr = VecNorm(X, NORM_2, xnorm);CHKERRQ(ierr); 171*bbd5d0b3SPeter Brune ierr = VecNorm(Y, NORM_2, ynorm);CHKERRQ(ierr); 172*bbd5d0b3SPeter Brune 173ea630c6eSPeter Brune PetscFunctionReturn(0); 174ea630c6eSPeter Brune } 175ea630c6eSPeter Brune 176*bbd5d0b3SPeter Brune EXTERN_C_BEGIN 177*bbd5d0b3SPeter Brune #undef __FUNCT__ 178*bbd5d0b3SPeter Brune #define __FUNCT__ "LineSearchCreate_NCGLinear" 179*bbd5d0b3SPeter Brune 180*bbd5d0b3SPeter Brune PetscErrorCode LineSearchCreate_NCGLinear(LineSearch linesearch) 181*bbd5d0b3SPeter Brune { 182*bbd5d0b3SPeter Brune PetscFunctionBegin; 183*bbd5d0b3SPeter Brune linesearch->ops->apply = LineSearchApply_NCGLinear; 184*bbd5d0b3SPeter Brune linesearch->ops->destroy = PETSC_NULL; 185*bbd5d0b3SPeter Brune linesearch->ops->setfromoptions = PETSC_NULL; 186*bbd5d0b3SPeter Brune linesearch->ops->reset = PETSC_NULL; 187*bbd5d0b3SPeter Brune linesearch->ops->view = PETSC_NULL; 188*bbd5d0b3SPeter Brune linesearch->ops->setup = PETSC_NULL; 189*bbd5d0b3SPeter Brune PetscFunctionReturn(0); 190*bbd5d0b3SPeter Brune } 191*bbd5d0b3SPeter Brune EXTERN_C_END 192*bbd5d0b3SPeter Brune 19388d374b2SPeter Brune #undef __FUNCT__ 19488d374b2SPeter Brune #define __FUNCT__ "ComputeYtJtF_Private" 19588d374b2SPeter Brune /* 19688d374b2SPeter Brune 19788d374b2SPeter Brune Assuming F = SNESComputeFunction(X) compute Y^tJ^tF using a simple secant approximation of the jacobian. 19888d374b2SPeter Brune 19988d374b2SPeter Brune */ 20088d374b2SPeter Brune PetscErrorCode ComputeYtJtF_Private(SNES snes, Vec X, Vec F, Vec Y, Vec W, Vec G, PetscScalar * ytJtf) { 20188d374b2SPeter Brune PetscErrorCode ierr; 20288d374b2SPeter Brune PetscScalar ftf, ftg, fty, h; 20388d374b2SPeter Brune PetscFunctionBegin; 20488d374b2SPeter Brune ierr = VecDot(F, F, &ftf);CHKERRQ(ierr); 20588d374b2SPeter Brune ierr = VecDot(F, Y, &fty);CHKERRQ(ierr); 20688d374b2SPeter Brune h = 1e-5*fty / fty; 20788d374b2SPeter Brune ierr = VecCopy(X, W);CHKERRQ(ierr); 20888d374b2SPeter Brune ierr = VecAXPY(W, -h, Y);CHKERRQ(ierr); /* this is arbitrary */ 20988d374b2SPeter Brune ierr = SNESComputeFunction(snes, W, G);CHKERRQ(ierr); 21088d374b2SPeter Brune ierr = VecDot(G, F, &ftg);CHKERRQ(ierr); 21188d374b2SPeter Brune *ytJtf = (ftg - ftf) / h; 21288d374b2SPeter Brune PetscFunctionReturn(0); 21388d374b2SPeter Brune } 21488d374b2SPeter Brune 215fef7b6d8SPeter Brune /* 216fef7b6d8SPeter Brune SNESSolve_NCG - Solves a nonlinear system with the Nonlinear Conjugate Gradient method. 217fef7b6d8SPeter Brune 218fef7b6d8SPeter Brune Input Parameters: 219fef7b6d8SPeter Brune . snes - the SNES context 220fef7b6d8SPeter Brune 221fef7b6d8SPeter Brune Output Parameter: 222fef7b6d8SPeter Brune . outits - number of iterations until termination 223fef7b6d8SPeter Brune 224fef7b6d8SPeter Brune Application Interface Routine: SNESSolve() 225fef7b6d8SPeter Brune */ 226fef7b6d8SPeter Brune #undef __FUNCT__ 227fef7b6d8SPeter Brune #define __FUNCT__ "SNESSolve_NCG" 228fef7b6d8SPeter Brune PetscErrorCode SNESSolve_NCG(SNES snes) 229fef7b6d8SPeter Brune { 230dfb256c7SPeter Brune SNES_NCG *ncg = (SNES_NCG *)snes->data; 231*bbd5d0b3SPeter Brune Vec X, dX, lX, F, B, Fold; 232*bbd5d0b3SPeter Brune PetscReal fnorm, ynorm, xnorm, beta = 0.0; 2335d115551SPeter Brune PetscScalar dXdotF, dXolddotFold, dXdotFold, lXdotF, lXdotFold; 234fef7b6d8SPeter Brune PetscInt maxits, i; 235fef7b6d8SPeter Brune PetscErrorCode ierr; 236fef7b6d8SPeter Brune SNESConvergedReason reason; 237fef7b6d8SPeter Brune PetscBool lsSuccess = PETSC_TRUE; 23888d374b2SPeter Brune 239fef7b6d8SPeter Brune PetscFunctionBegin; 240fef7b6d8SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 241fef7b6d8SPeter Brune 242fef7b6d8SPeter Brune maxits = snes->max_its; /* maximum number of iterations */ 243fef7b6d8SPeter Brune X = snes->vec_sol; /* X^n */ 2445d115551SPeter Brune Fold = snes->work[0]; /* The previous iterate of X */ 24588d374b2SPeter Brune dX = snes->work[1]; /* the preconditioned direction */ 246169e2be8SPeter Brune lX = snes->vec_sol_update; /* the conjugate direction */ 247fef7b6d8SPeter Brune F = snes->vec_func; /* residual vector */ 248302dbbaeSPeter Brune B = snes->vec_rhs; /* the right hand side */ 249fef7b6d8SPeter Brune 250fef7b6d8SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 251fef7b6d8SPeter Brune snes->iter = 0; 252fef7b6d8SPeter Brune snes->norm = 0.; 253fef7b6d8SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 254fef7b6d8SPeter Brune 255*bbd5d0b3SPeter Brune /* compute the initial function and preconditioned update dX */ 256fef7b6d8SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 257fef7b6d8SPeter Brune if (snes->domainerror) { 258fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 259fef7b6d8SPeter Brune PetscFunctionReturn(0); 260fef7b6d8SPeter Brune } 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"); 264fef7b6d8SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 265fef7b6d8SPeter Brune snes->norm = fnorm; 266fef7b6d8SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 267fef7b6d8SPeter Brune SNESLogConvHistory(snes,fnorm,0); 268fef7b6d8SPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 269fef7b6d8SPeter Brune 270fef7b6d8SPeter Brune /* set parameter for default relative tolerance convergence test */ 271fef7b6d8SPeter Brune snes->ttol = fnorm*snes->rtol; 272fef7b6d8SPeter Brune /* test convergence */ 273fef7b6d8SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 274fef7b6d8SPeter Brune if (snes->reason) PetscFunctionReturn(0); 275fef7b6d8SPeter Brune 276fef7b6d8SPeter Brune /* Call general purpose update function */ 277fef7b6d8SPeter Brune if (snes->ops->update) { 278fef7b6d8SPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 279fef7b6d8SPeter Brune } 280fef7b6d8SPeter Brune 281fef7b6d8SPeter Brune /* first update -- just use the (preconditioned) residual direction for the initial conjugate direction */ 282*bbd5d0b3SPeter Brune 28383947a81SPeter Brune if (snes->pc) { 28429c94e34SPeter Brune ierr = VecCopy(X, dX);CHKERRQ(ierr); 28529c94e34SPeter Brune ierr = SNESSolve(snes->pc, B, dX);CHKERRQ(ierr); 286fef7b6d8SPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 28751e86f29SPeter Brune if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) { 288fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_INNER; 289fef7b6d8SPeter Brune PetscFunctionReturn(0); 290fef7b6d8SPeter Brune } 29129c94e34SPeter Brune ierr = VecAYPX(dX,-1.0,X);CHKERRQ(ierr); 2925d10c001SPeter Brune } else { 29329c94e34SPeter Brune ierr = VecCopy(F, dX);CHKERRQ(ierr); 294fef7b6d8SPeter Brune } 29529c94e34SPeter Brune ierr = VecCopy(dX, lX);CHKERRQ(ierr); 296*bbd5d0b3SPeter Brune ierr = VecDot(F, dX, &dXdotF);CHKERRQ(ierr); 297*bbd5d0b3SPeter Brune /* 29888d374b2SPeter Brune } else { 29988d374b2SPeter Brune ierr = ComputeYtJtF_Private(snes, X, F, dX, W, G, &dXdotF);CHKERRQ(ierr); 30088d374b2SPeter Brune } 301*bbd5d0b3SPeter Brune */ 30209c08436SPeter Brune for(i = 1; i < maxits + 1; i++) { 303fef7b6d8SPeter Brune lsSuccess = PETSC_TRUE; 30429c94e34SPeter Brune /* some update types require the old update direction or conjugate direction */ 30529c94e34SPeter Brune if (ncg->betatype == 1 || ncg->betatype == 2 || ncg->betatype == 3 || ncg->betatype == 4) { /* prp, hs, dy, cd need dXold*/ 3065d115551SPeter Brune ierr = VecCopy(F, Fold);CHKERRQ(ierr); 30788d374b2SPeter Brune } 308*bbd5d0b3SPeter Brune ierr = LineSearchApply(ncg->linesearch, X, F, &fnorm, lX);CHKERRQ(ierr); 309*bbd5d0b3SPeter Brune ierr = LineSearchGetSuccess(ncg->linesearch, &lsSuccess);CHKERRQ(ierr); 310fef7b6d8SPeter Brune if (!lsSuccess) { 311fef7b6d8SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 312fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 3135d10c001SPeter Brune PetscFunctionReturn(0); 314fef7b6d8SPeter Brune } 315fef7b6d8SPeter Brune } 316fef7b6d8SPeter Brune if (snes->nfuncs >= snes->max_funcs) { 317fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 3185d10c001SPeter Brune PetscFunctionReturn(0); 319fef7b6d8SPeter Brune } 320fef7b6d8SPeter Brune if (snes->domainerror) { 321fef7b6d8SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 322fef7b6d8SPeter Brune PetscFunctionReturn(0); 323fef7b6d8SPeter Brune } 324*bbd5d0b3SPeter Brune ierr = LineSearchGetNorms(ncg->linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr); 325fef7b6d8SPeter Brune /* Monitor convergence */ 326fef7b6d8SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 327169e2be8SPeter Brune snes->iter = i; 328fef7b6d8SPeter Brune snes->norm = fnorm; 329fef7b6d8SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 330fef7b6d8SPeter Brune SNESLogConvHistory(snes,snes->norm,0); 331fef7b6d8SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 332302dbbaeSPeter Brune 333fef7b6d8SPeter Brune /* Test for convergence */ 334fef7b6d8SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 3355d10c001SPeter Brune if (snes->reason) PetscFunctionReturn(0); 336302dbbaeSPeter Brune 337302dbbaeSPeter Brune /* Call general purpose update function */ 338302dbbaeSPeter Brune if (snes->ops->update) { 339302dbbaeSPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 340302dbbaeSPeter Brune } 34183947a81SPeter Brune if (snes->pc) { 342302dbbaeSPeter Brune ierr = VecCopy(X,dX);CHKERRQ(ierr); 343cf949ffaSPeter Brune ierr = SNESSolve(snes->pc, B, dX);CHKERRQ(ierr); 344302dbbaeSPeter Brune ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 34551e86f29SPeter Brune if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) { 346302dbbaeSPeter Brune snes->reason = SNES_DIVERGED_INNER; 347302dbbaeSPeter Brune PetscFunctionReturn(0); 348302dbbaeSPeter Brune } 349eb1825c3SPeter Brune ierr = VecAYPX(dX,-1.0,X);CHKERRQ(ierr); 350a3685310SPeter Brune } else { 351a3685310SPeter Brune ierr = VecCopy(F, dX);CHKERRQ(ierr); 352302dbbaeSPeter Brune } 353302dbbaeSPeter Brune 35429c94e34SPeter Brune /* compute the conjugate direction lX = dX + beta*lX with beta = ((dX, dX) / (dX_old, dX_old) (Fletcher-Reeves update)*/ 355dfb256c7SPeter Brune switch(ncg->betatype) { 356dfb256c7SPeter Brune case 0: /* Fletcher-Reeves */ 3575d115551SPeter Brune dXolddotFold = dXdotF; 358*bbd5d0b3SPeter Brune ierr = VecDot(dX, dX, &dXdotF);CHKERRQ(ierr); 3595d115551SPeter Brune beta = PetscRealPart(dXdotF / dXolddotFold); 360dfb256c7SPeter Brune break; 361dfb256c7SPeter Brune case 1: /* Polak-Ribiere-Poylak */ 3625d115551SPeter Brune dXolddotFold = dXdotF; 3635d115551SPeter Brune ierr = VecDot(F, dX, &dXdotF);CHKERRQ(ierr); 3645d115551SPeter Brune ierr = VecDot(Fold, dX, &dXdotFold);CHKERRQ(ierr); 3655d115551SPeter Brune beta = PetscRealPart(((dXdotF - dXdotFold) / dXolddotFold)); 366dfb256c7SPeter Brune if (beta < 0.0) beta = 0.0; /* restart */ 367dfb256c7SPeter Brune break; 368dfb256c7SPeter Brune case 2: /* Hestenes-Stiefel */ 3695d115551SPeter Brune ierr = VecDot(dX, F, &dXdotF);CHKERRQ(ierr); 3705d115551SPeter Brune ierr = VecDot(dX, Fold, &dXdotFold);CHKERRQ(ierr); 3715d115551SPeter Brune ierr = VecDot(lX, F, &lXdotF);CHKERRQ(ierr); 3725d115551SPeter Brune ierr = VecDot(lX, Fold, &lXdotFold);CHKERRQ(ierr); 3735d115551SPeter Brune beta = PetscRealPart((dXdotF - dXdotFold) / (lXdotF - lXdotFold)); 374dfb256c7SPeter Brune break; 375dfb256c7SPeter Brune case 3: /* Dai-Yuan */ 3765d115551SPeter Brune ierr = VecDot(dX, F, &dXdotF);CHKERRQ(ierr); 377*bbd5d0b3SPeter Brune ierr = VecDot(lX, F, &lXdotF);CHKERRQ(ierr); 378*bbd5d0b3SPeter Brune ierr = VecDot(lX, Fold, &lXdotFold);CHKERRQ(ierr); 3795d115551SPeter Brune beta = PetscRealPart(dXdotF / (lXdotFold - lXdotF));CHKERRQ(ierr); 380dfb256c7SPeter Brune break; 381dfb256c7SPeter Brune case 4: /* Conjugate Descent */ 38201fcfa61SPeter Brune ierr = VecDot(dX, F, &dXdotF);CHKERRQ(ierr); 38388d374b2SPeter Brune ierr = VecDot(lX, Fold, &lXdotFold);CHKERRQ(ierr); 3845d115551SPeter Brune beta = PetscRealPart(dXdotF / lXdotFold);CHKERRQ(ierr); 385dfb256c7SPeter Brune break; 386dfb256c7SPeter Brune } 387dfb256c7SPeter Brune if (ncg->monitor) { 388646217ecSPeter Brune ierr = PetscViewerASCIIPrintf(ncg->monitor, "beta = %e\n", beta);CHKERRQ(ierr); 389dfb256c7SPeter Brune } 390dfb256c7SPeter Brune ierr = VecAYPX(lX, beta, dX);CHKERRQ(ierr); 391fef7b6d8SPeter Brune } 392fef7b6d8SPeter Brune ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 393fef7b6d8SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 394fef7b6d8SPeter Brune PetscFunctionReturn(0); 395fef7b6d8SPeter Brune } 396fef7b6d8SPeter Brune 397fef7b6d8SPeter Brune /*MC 398fef7b6d8SPeter Brune SNESNCG - Nonlinear Conjugate-Gradient method for the solution of general nonlinear systems. 399fef7b6d8SPeter Brune 400fef7b6d8SPeter Brune Level: beginner 401fef7b6d8SPeter Brune 402fef7b6d8SPeter Brune Options Database: 4031867fe5bSPeter Brune + -snes_ncg_type <fr, prp, dy, hs, cd> - Choice of conjugate-gradient update parameter. 404f3aaf736SPeter Brune . -snes_ls <basic,basicnormnorms,quadratic,critical,test> - Line search type. 4051867fe5bSPeter Brune - -snes_ncg_monitor - Print relevant information about the ncg iteration. 406fef7b6d8SPeter Brune 407fef7b6d8SPeter Brune Notes: This solves the nonlinear system of equations F(x) = 0 using the nonlinear generalization of the conjugate 408fef7b6d8SPeter Brune gradient method. This may be used with a nonlinear preconditioner used to pick the new search directions, but otherwise 409fef7b6d8SPeter Brune chooses the initial search direction as F(x) for the initial guess x. 410fef7b6d8SPeter Brune 411fef7b6d8SPeter Brune 412fef7b6d8SPeter Brune .seealso: SNESCreate(), SNES, SNESSetType(), SNESLS, SNESTR, SNESNGMRES, SNESNQN 413fef7b6d8SPeter Brune M*/ 414fef7b6d8SPeter Brune EXTERN_C_BEGIN 415fef7b6d8SPeter Brune #undef __FUNCT__ 416fef7b6d8SPeter Brune #define __FUNCT__ "SNESCreate_NCG" 417fef7b6d8SPeter Brune PetscErrorCode SNESCreate_NCG(SNES snes) 418fef7b6d8SPeter Brune { 419fef7b6d8SPeter Brune PetscErrorCode ierr; 420ea630c6eSPeter Brune SNES_NCG * neP; 421fef7b6d8SPeter Brune 422fef7b6d8SPeter Brune PetscFunctionBegin; 423fef7b6d8SPeter Brune snes->ops->destroy = SNESDestroy_NCG; 424fef7b6d8SPeter Brune snes->ops->setup = SNESSetUp_NCG; 425fef7b6d8SPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_NCG; 426fef7b6d8SPeter Brune snes->ops->view = SNESView_NCG; 427fef7b6d8SPeter Brune snes->ops->solve = SNESSolve_NCG; 428fef7b6d8SPeter Brune snes->ops->reset = SNESReset_NCG; 429fef7b6d8SPeter Brune 430fef7b6d8SPeter Brune snes->usesksp = PETSC_FALSE; 431fef7b6d8SPeter Brune snes->usespc = PETSC_TRUE; 432fef7b6d8SPeter Brune 4330e444f03SPeter Brune snes->max_funcs = 30000; 4340e444f03SPeter Brune snes->max_its = 10000; 4350e444f03SPeter Brune 436fef7b6d8SPeter Brune ierr = PetscNewLog(snes, SNES_NCG, &neP);CHKERRQ(ierr); 437fef7b6d8SPeter Brune snes->data = (void*) neP; 438dfb256c7SPeter Brune neP->monitor = PETSC_NULL; 4391867fe5bSPeter Brune neP->betatype = 1; 440fef7b6d8SPeter Brune PetscFunctionReturn(0); 441fef7b6d8SPeter Brune } 442fef7b6d8SPeter Brune EXTERN_C_END 443