xref: /petsc/src/snes/impls/ncg/snesncg.c (revision 9105210e9938473647066099faf9eb790c82c8ad)
10a844d1aSPeter Brune #include <../src/snes/impls/ncg/snesncgimpl.h> /*I "petscsnes.h" I*/
26a6fc655SJed Brown const char *const SNESNCGTypes[] = {"FR","PRP","HS","DY","CD","SNESNCGType","SNES_NCG_",0};
3fef7b6d8SPeter Brune 
4fef7b6d8SPeter Brune #undef __FUNCT__
5fef7b6d8SPeter Brune #define __FUNCT__ "SNESReset_NCG"
6fef7b6d8SPeter Brune PetscErrorCode SNESReset_NCG(SNES snes)
7fef7b6d8SPeter Brune {
8fef7b6d8SPeter Brune   PetscFunctionBegin;
9fef7b6d8SPeter Brune   PetscFunctionReturn(0);
10fef7b6d8SPeter Brune }
11fef7b6d8SPeter Brune 
12*9105210eSPeter Brune #define SNESLINESEARCHNCGLINEAR "ncglinear"
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 
448cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_NCGLinear(SNESLineSearch);
45bbd5d0b3SPeter Brune 
46fef7b6d8SPeter Brune #undef __FUNCT__
47fef7b6d8SPeter Brune #define __FUNCT__ "SNESSetUp_NCG"
48fef7b6d8SPeter Brune PetscErrorCode SNESSetUp_NCG(SNES snes)
49fef7b6d8SPeter Brune {
50fef7b6d8SPeter Brune   PetscErrorCode ierr;
51fef7b6d8SPeter Brune 
52fef7b6d8SPeter Brune   PetscFunctionBegin;
53fa0ddf94SBarry Smith   ierr = SNESSetWorkVecs(snes,2);CHKERRQ(ierr);
54fef7b6d8SPeter Brune   PetscFunctionReturn(0);
55fef7b6d8SPeter Brune }
56fef7b6d8SPeter Brune /*
5705b53524SPeter Brune   SNESSetFromOptions_NCG - Sets various parameters for the SNESNCG method.
58fef7b6d8SPeter Brune 
59fef7b6d8SPeter Brune   Input Parameter:
60fef7b6d8SPeter Brune . snes - the SNES context
61fef7b6d8SPeter Brune 
62fef7b6d8SPeter Brune   Application Interface Routine: SNESSetFromOptions()
63fef7b6d8SPeter Brune */
64fef7b6d8SPeter Brune #undef __FUNCT__
65fef7b6d8SPeter Brune #define __FUNCT__ "SNESSetFromOptions_NCG"
66fef7b6d8SPeter Brune static PetscErrorCode SNESSetFromOptions_NCG(SNES snes)
67fef7b6d8SPeter Brune {
68dfb256c7SPeter Brune   SNES_NCG       *ncg = (SNES_NCG*)snes->data;
69fef7b6d8SPeter Brune   PetscErrorCode ierr;
700a844d1aSPeter Brune   PetscBool      debug;
71f1c6b773SPeter Brune   SNESLineSearch linesearch;
72a11d90f7SPeter Brune   SNESNCGType    ncgtype=ncg->type;
73fef7b6d8SPeter Brune 
74fef7b6d8SPeter Brune   PetscFunctionBegin;
75fef7b6d8SPeter Brune   ierr = PetscOptionsHead("SNES NCG options");CHKERRQ(ierr);
760298fd71SBarry Smith   ierr = PetscOptionsBool("-snes_ncg_monitor","Monitor NCG iterations","SNES",ncg->monitor ? PETSC_TRUE : PETSC_FALSE, &debug, NULL);CHKERRQ(ierr);
770298fd71SBarry Smith   ierr = PetscOptionsEnum("-snes_ncg_type","NCG Beta type used","SNESNCGSetType",SNESNCGTypes,(PetscEnum)ncg->type,(PetscEnum*)&ncgtype,NULL);CHKERRQ(ierr);
780a844d1aSPeter Brune   ierr = SNESNCGSetType(snes, ncgtype);CHKERRQ(ierr);
79dfb256c7SPeter Brune   if (debug) {
80ce94432eSBarry Smith     ncg->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr);
81dfb256c7SPeter Brune   }
82fef7b6d8SPeter Brune   ierr = PetscOptionsTail();CHKERRQ(ierr);
839e764e56SPeter Brune   if (!snes->linesearch) {
847601faf0SJed Brown     ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr);
859e764e56SPeter Brune     if (!snes->pc) {
861a4f838cSPeter Brune       ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHCP);CHKERRQ(ierr);
879e764e56SPeter Brune     } else {
881a4f838cSPeter Brune       ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr);
899e764e56SPeter Brune     }
909e764e56SPeter Brune   }
91*9105210eSPeter Brune   ierr = SNESLineSearchRegister(SNESLINESEARCHNCGLINEAR, SNESLineSearchCreate_NCGLinear);CHKERRQ(ierr);
92fef7b6d8SPeter Brune   PetscFunctionReturn(0);
93fef7b6d8SPeter Brune }
94fef7b6d8SPeter Brune 
95fef7b6d8SPeter Brune /*
96fef7b6d8SPeter Brune   SNESView_NCG - Prints info from the SNESNCG data structure.
97fef7b6d8SPeter Brune 
98fef7b6d8SPeter Brune   Input Parameters:
99fef7b6d8SPeter Brune + SNES - the SNES context
100fef7b6d8SPeter Brune - viewer - visualization context
101fef7b6d8SPeter Brune 
102fef7b6d8SPeter Brune   Application Interface Routine: SNESView()
103fef7b6d8SPeter Brune */
104fef7b6d8SPeter Brune #undef __FUNCT__
105fef7b6d8SPeter Brune #define __FUNCT__ "SNESView_NCG"
106fef7b6d8SPeter Brune static PetscErrorCode SNESView_NCG(SNES snes, PetscViewer viewer)
107fef7b6d8SPeter Brune {
108fef7b6d8SPeter Brune   PetscBool      iascii;
109fef7b6d8SPeter Brune   PetscErrorCode ierr;
110fef7b6d8SPeter Brune 
111fef7b6d8SPeter Brune   PetscFunctionBegin;
112251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
113fef7b6d8SPeter Brune   if (iascii) {
114fef7b6d8SPeter Brune   }
115fef7b6d8SPeter Brune   PetscFunctionReturn(0);
116fef7b6d8SPeter Brune }
117fef7b6d8SPeter Brune 
118fef7b6d8SPeter Brune #undef __FUNCT__
119f1c6b773SPeter Brune #define __FUNCT__ "SNESLineSearchApply_NCGLinear"
120f1c6b773SPeter Brune PetscErrorCode SNESLineSearchApply_NCGLinear(SNESLineSearch linesearch)
121ea630c6eSPeter Brune {
122ea630c6eSPeter Brune   PetscScalar    alpha, ptAp;
123bbd5d0b3SPeter Brune   Vec            X, Y, F, W;
124bbd5d0b3SPeter Brune   SNES           snes;
125ea630c6eSPeter Brune   PetscErrorCode ierr;
126bbd5d0b3SPeter Brune   PetscReal      *fnorm, *xnorm, *ynorm;
127ea630c6eSPeter Brune   MatStructure   flg = DIFFERENT_NONZERO_PATTERN;
128ea630c6eSPeter Brune 
129ea630c6eSPeter Brune   PetscFunctionBegin;
130f1c6b773SPeter Brune   ierr  = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr);
131bbd5d0b3SPeter Brune   X     = linesearch->vec_sol;
132bbd5d0b3SPeter Brune   W     = linesearch->vec_sol_new;
133bbd5d0b3SPeter Brune   F     = linesearch->vec_func;
134bbd5d0b3SPeter Brune   Y     = linesearch->vec_update;
135bbd5d0b3SPeter Brune   fnorm = &linesearch->fnorm;
136bbd5d0b3SPeter Brune   xnorm = &linesearch->xnorm;
137bbd5d0b3SPeter Brune   ynorm = &linesearch->ynorm;
138bbd5d0b3SPeter Brune 
139*9105210eSPeter Brune   if (!snes->jacobian) {
140*9105210eSPeter Brune     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
141*9105210eSPeter Brune   }
142*9105210eSPeter Brune 
143ea630c6eSPeter Brune   /*
144ea630c6eSPeter Brune 
145d2140ca3SPeter Brune    The exact step size for unpreconditioned linear CG is just:
146ea630c6eSPeter Brune    alpha = (r, r) / (p, Ap) = (f, f) / (y, Jy)
147ea630c6eSPeter Brune    */
148a5892487SPeter Brune   ierr  = SNESComputeJacobian(snes, X, &snes->jacobian, &snes->jacobian_pre, &flg);CHKERRQ(ierr);
149ea630c6eSPeter Brune   ierr  = VecDot(F, F, &alpha);CHKERRQ(ierr);
150ea630c6eSPeter Brune   ierr  = MatMult(snes->jacobian, Y, W);CHKERRQ(ierr);
151ea630c6eSPeter Brune   ierr  = VecDot(Y, W, &ptAp);CHKERRQ(ierr);
152ea630c6eSPeter Brune   alpha = alpha / ptAp;
153*9105210eSPeter Brune   ierr  = VecAXPY(X,-alpha,Y);CHKERRQ(ierr);
154bbd5d0b3SPeter Brune   ierr  = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
155bbd5d0b3SPeter Brune 
156bbd5d0b3SPeter Brune   ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);
157bbd5d0b3SPeter Brune   ierr = VecNorm(X,NORM_2,xnorm);CHKERRQ(ierr);
158bbd5d0b3SPeter Brune   ierr = VecNorm(Y,NORM_2,ynorm);CHKERRQ(ierr);
159ea630c6eSPeter Brune   PetscFunctionReturn(0);
160ea630c6eSPeter Brune }
161ea630c6eSPeter Brune 
162bbd5d0b3SPeter Brune #undef __FUNCT__
163f1c6b773SPeter Brune #define __FUNCT__ "SNESLineSearchCreate_NCGLinear"
1648cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_NCGLinear(SNESLineSearch linesearch)
165bbd5d0b3SPeter Brune {
166bbd5d0b3SPeter Brune   PetscFunctionBegin;
167f1c6b773SPeter Brune   linesearch->ops->apply          = SNESLineSearchApply_NCGLinear;
1680298fd71SBarry Smith   linesearch->ops->destroy        = NULL;
1690298fd71SBarry Smith   linesearch->ops->setfromoptions = NULL;
1700298fd71SBarry Smith   linesearch->ops->reset          = NULL;
1710298fd71SBarry Smith   linesearch->ops->view           = NULL;
1720298fd71SBarry Smith   linesearch->ops->setup          = NULL;
173bbd5d0b3SPeter Brune   PetscFunctionReturn(0);
174bbd5d0b3SPeter Brune }
175bbd5d0b3SPeter Brune 
17688d374b2SPeter Brune #undef __FUNCT__
1778c40d5fbSBarry Smith #define __FUNCT__ "SNESNCGComputeYtJtF_Private"
17888d374b2SPeter Brune /*
17988d374b2SPeter Brune 
18088d374b2SPeter Brune  Assuming F = SNESComputeFunction(X) compute Y^tJ^tF using a simple secant approximation of the jacobian.
18188d374b2SPeter Brune 
18288d374b2SPeter Brune  */
18367392de3SBarry Smith PetscErrorCode SNESNCGComputeYtJtF_Private(SNES snes, Vec X, Vec F, Vec Y, Vec W, Vec G, PetscScalar * ytJtf)
18467392de3SBarry Smith {
18588d374b2SPeter Brune   PetscErrorCode ierr;
18688d374b2SPeter Brune   PetscScalar    ftf, ftg, fty, h;
18767392de3SBarry Smith 
18888d374b2SPeter Brune   PetscFunctionBegin;
18988d374b2SPeter Brune   ierr   = VecDot(F, F, &ftf);CHKERRQ(ierr);
19088d374b2SPeter Brune   ierr   = VecDot(F, Y, &fty);CHKERRQ(ierr);
19188d374b2SPeter Brune   h      = 1e-5*fty / fty;
19288d374b2SPeter Brune   ierr   = VecCopy(X, W);CHKERRQ(ierr);
19388d374b2SPeter Brune   ierr   = VecAXPY(W, -h, Y);CHKERRQ(ierr);          /* this is arbitrary */
19488d374b2SPeter Brune   ierr   = SNESComputeFunction(snes, W, G);CHKERRQ(ierr);
19588d374b2SPeter Brune   ierr   = VecDot(G, F, &ftg);CHKERRQ(ierr);
19688d374b2SPeter Brune   *ytJtf = (ftg - ftf) / h;
19788d374b2SPeter Brune   PetscFunctionReturn(0);
19888d374b2SPeter Brune }
19988d374b2SPeter Brune 
2000a844d1aSPeter Brune #undef __FUNCT__
2010a844d1aSPeter Brune #define __FUNCT__ "SNESNCGSetType"
2020a844d1aSPeter Brune /*@
2030a844d1aSPeter Brune     SNESNCGSetType - Sets the conjugate update type for SNESNCG.
2040a844d1aSPeter Brune 
2050a844d1aSPeter Brune     Logically Collective on SNES
2060a844d1aSPeter Brune 
2070a844d1aSPeter Brune     Input Parameters:
2080a844d1aSPeter Brune +   snes - the iterative context
2090a844d1aSPeter Brune -   btype - update type
2100a844d1aSPeter Brune 
2110a844d1aSPeter Brune     Options Database:
2120a844d1aSPeter Brune .   -snes_ncg_type<prp,fr,hs,dy,cd>
2130a844d1aSPeter Brune 
2140a844d1aSPeter Brune     Level: intermediate
2150a844d1aSPeter Brune 
2160a844d1aSPeter Brune     SNESNCGSelectTypes:
2170a844d1aSPeter Brune +   SNES_NCG_FR - Fletcher-Reeves update
2180a844d1aSPeter Brune .   SNES_NCG_PRP - Polak-Ribiere-Polyak update
2190a844d1aSPeter Brune .   SNES_NCG_HS - Hestenes-Steifel update
2200a844d1aSPeter Brune .   SNES_NCG_DY - Dai-Yuan update
2210a844d1aSPeter Brune -   SNES_NCG_CD - Conjugate Descent update
2220a844d1aSPeter Brune 
2230a844d1aSPeter Brune    Notes:
2240a844d1aSPeter Brune    PRP is the default, and the only one that tolerates generalized search directions.
2250a844d1aSPeter Brune 
2260a844d1aSPeter Brune .keywords: SNES, SNESNCG, selection, type, set
2270a844d1aSPeter Brune @*/
2280adebc6cSBarry Smith PetscErrorCode SNESNCGSetType(SNES snes, SNESNCGType btype)
2290adebc6cSBarry Smith {
2300a844d1aSPeter Brune   PetscErrorCode ierr;
2316e111a19SKarl Rupp 
2320a844d1aSPeter Brune   PetscFunctionBegin;
2330a844d1aSPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
2340a844d1aSPeter Brune   ierr = PetscTryMethod(snes,"SNESNCGSetType_C",(SNES,SNESNCGType),(snes,btype));CHKERRQ(ierr);
2350a844d1aSPeter Brune   PetscFunctionReturn(0);
2360a844d1aSPeter Brune }
2370a844d1aSPeter Brune 
2380a844d1aSPeter Brune #undef __FUNCT__
2390a844d1aSPeter Brune #define __FUNCT__ "SNESNCGSetType_NCG"
2400adebc6cSBarry Smith PetscErrorCode SNESNCGSetType_NCG(SNES snes, SNESNCGType btype)
2410adebc6cSBarry Smith {
2420a844d1aSPeter Brune   SNES_NCG *ncg = (SNES_NCG*)snes->data;
2436e111a19SKarl Rupp 
2440a844d1aSPeter Brune   PetscFunctionBegin;
2450a844d1aSPeter Brune   ncg->type = btype;
2460a844d1aSPeter Brune   PetscFunctionReturn(0);
2470a844d1aSPeter Brune }
2480a844d1aSPeter Brune 
249fef7b6d8SPeter Brune /*
250fef7b6d8SPeter Brune   SNESSolve_NCG - Solves a nonlinear system with the Nonlinear Conjugate Gradient method.
251fef7b6d8SPeter Brune 
252fef7b6d8SPeter Brune   Input Parameters:
253fef7b6d8SPeter Brune . snes - the SNES context
254fef7b6d8SPeter Brune 
255fef7b6d8SPeter Brune   Output Parameter:
256fef7b6d8SPeter Brune . outits - number of iterations until termination
257fef7b6d8SPeter Brune 
258fef7b6d8SPeter Brune   Application Interface Routine: SNESSolve()
259fef7b6d8SPeter Brune */
260fef7b6d8SPeter Brune #undef __FUNCT__
261fef7b6d8SPeter Brune #define __FUNCT__ "SNESSolve_NCG"
262fef7b6d8SPeter Brune PetscErrorCode SNESSolve_NCG(SNES snes)
263fef7b6d8SPeter Brune {
264dfb256c7SPeter Brune   SNES_NCG            *ncg = (SNES_NCG*)snes->data;
265bbd5d0b3SPeter Brune   Vec                 X, dX, lX, F, B, Fold;
266bbd5d0b3SPeter Brune   PetscReal           fnorm, ynorm, xnorm, beta = 0.0;
2675d115551SPeter Brune   PetscScalar         dXdotF, dXolddotFold, dXdotFold, lXdotF, lXdotFold;
268fef7b6d8SPeter Brune   PetscInt            maxits, i;
269fef7b6d8SPeter Brune   PetscErrorCode      ierr;
270fef7b6d8SPeter Brune   SNESConvergedReason reason;
271fef7b6d8SPeter Brune   PetscBool           lsSuccess = PETSC_TRUE;
272f1c6b773SPeter Brune   SNESLineSearch      linesearch;
27388d374b2SPeter Brune 
274fef7b6d8SPeter Brune   PetscFunctionBegin;
275fef7b6d8SPeter Brune   snes->reason = SNES_CONVERGED_ITERATING;
276fef7b6d8SPeter Brune 
277fef7b6d8SPeter Brune   maxits = snes->max_its;            /* maximum number of iterations */
278fef7b6d8SPeter Brune   X      = snes->vec_sol;            /* X^n */
2795d115551SPeter Brune   Fold   = snes->work[0];            /* The previous iterate of X */
28088d374b2SPeter Brune   dX     = snes->work[1];            /* the preconditioned direction */
281169e2be8SPeter Brune   lX     = snes->vec_sol_update;     /* the conjugate direction */
282fef7b6d8SPeter Brune   F      = snes->vec_func;           /* residual vector */
283302dbbaeSPeter Brune   B      = snes->vec_rhs;            /* the right hand side */
284fef7b6d8SPeter Brune 
2857601faf0SJed Brown   ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr);
2869e764e56SPeter Brune 
287ce8c27fbSBarry Smith   ierr       = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr);
288fef7b6d8SPeter Brune   snes->iter = 0;
289fef7b6d8SPeter Brune   snes->norm = 0.;
290ce8c27fbSBarry Smith   ierr       = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr);
291fef7b6d8SPeter Brune 
292bbd5d0b3SPeter Brune   /* compute the initial function and preconditioned update dX */
293e4ed7901SPeter Brune   if (!snes->vec_func_init_set) {
294fef7b6d8SPeter Brune     ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
295fef7b6d8SPeter Brune     if (snes->domainerror) {
296fef7b6d8SPeter Brune       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
297fef7b6d8SPeter Brune       PetscFunctionReturn(0);
298fef7b6d8SPeter Brune     }
2991aa26658SKarl Rupp   } else snes->vec_func_init_set = PETSC_FALSE;
3001aa26658SKarl Rupp 
301e4ed7901SPeter Brune   if (!snes->norm_init_set) {
302fef7b6d8SPeter Brune     /* convergence test */
303fef7b6d8SPeter Brune     ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F||  */
304189a9710SBarry Smith     if (PetscIsInfOrNanReal(fnorm)) {
305189a9710SBarry Smith       snes->reason = SNES_DIVERGED_FNORM_NAN;
306189a9710SBarry Smith       PetscFunctionReturn(0);
307189a9710SBarry Smith     }
308e4ed7901SPeter Brune   } else {
309e4ed7901SPeter Brune     fnorm               = snes->norm_init;
310e4ed7901SPeter Brune     snes->norm_init_set = PETSC_FALSE;
311e4ed7901SPeter Brune   }
312ce8c27fbSBarry Smith   ierr       = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr);
313fef7b6d8SPeter Brune   snes->norm = fnorm;
314ce8c27fbSBarry Smith   ierr       = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr);
315a71f0d7dSBarry Smith   ierr       = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr);
316fef7b6d8SPeter Brune   ierr       = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
317fef7b6d8SPeter Brune 
318fef7b6d8SPeter Brune   /* set parameter for default relative tolerance convergence test */
319fef7b6d8SPeter Brune   snes->ttol = fnorm*snes->rtol;
320fef7b6d8SPeter Brune   /* test convergence */
321fef7b6d8SPeter Brune   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
322fef7b6d8SPeter Brune   if (snes->reason) PetscFunctionReturn(0);
323fef7b6d8SPeter Brune 
324fef7b6d8SPeter Brune   /* Call general purpose update function */
325fef7b6d8SPeter Brune   if (snes->ops->update) {
326fef7b6d8SPeter Brune     ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
327fef7b6d8SPeter Brune   }
328fef7b6d8SPeter Brune 
329fef7b6d8SPeter Brune   /* first update -- just use the (preconditioned) residual direction for the initial conjugate direction */
330bbd5d0b3SPeter Brune 
331c40d0f55SPeter Brune   if (snes->pc && snes->pcside == PC_RIGHT) {
33229c94e34SPeter Brune     ierr = VecCopy(X, dX);CHKERRQ(ierr);
333217b9c2eSPeter Brune     ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr);
334217b9c2eSPeter Brune     ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr);
33563e7833aSPeter Brune 
33663e7833aSPeter Brune     ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,dX,B,0);CHKERRQ(ierr);
33729c94e34SPeter Brune     ierr = SNESSolve(snes->pc, B, dX);CHKERRQ(ierr);
33863e7833aSPeter Brune     ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,dX,B,0);CHKERRQ(ierr);
33963e7833aSPeter Brune 
340fef7b6d8SPeter Brune     ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
34151e86f29SPeter Brune     if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) {
342fef7b6d8SPeter Brune       snes->reason = SNES_DIVERGED_INNER;
343fef7b6d8SPeter Brune       PetscFunctionReturn(0);
344fef7b6d8SPeter Brune     }
34529c94e34SPeter Brune     ierr = VecAYPX(dX,-1.0,X);CHKERRQ(ierr);
3465d10c001SPeter Brune   } else {
34729c94e34SPeter Brune     ierr = VecCopy(F, dX);CHKERRQ(ierr);
348fef7b6d8SPeter Brune   }
34929c94e34SPeter Brune   ierr = VecCopy(dX, lX);CHKERRQ(ierr);
350bbd5d0b3SPeter Brune   ierr = VecDot(F, dX, &dXdotF);CHKERRQ(ierr);
351bbd5d0b3SPeter Brune   /*
35288d374b2SPeter Brune   } else {
3538c40d5fbSBarry Smith     ierr = SNESNCGComputeYtJtF_Private(snes, X, F, dX, W, G, &dXdotF);CHKERRQ(ierr);
35488d374b2SPeter Brune   }
355bbd5d0b3SPeter Brune    */
35609c08436SPeter Brune   for (i = 1; i < maxits + 1; i++) {
357fef7b6d8SPeter Brune     lsSuccess = PETSC_TRUE;
35829c94e34SPeter Brune     /* some update types require the old update direction or conjugate direction */
3590a844d1aSPeter Brune     if (ncg->type != SNES_NCG_FR) {
3605d115551SPeter Brune       ierr = VecCopy(F, Fold);CHKERRQ(ierr);
36188d374b2SPeter Brune     }
362f1c6b773SPeter Brune     ierr = SNESLineSearchApply(linesearch, X, F, &fnorm, lX);CHKERRQ(ierr);
363f1c6b773SPeter Brune     ierr = SNESLineSearchGetSuccess(linesearch, &lsSuccess);CHKERRQ(ierr);
364fef7b6d8SPeter Brune     if (!lsSuccess) {
365fef7b6d8SPeter Brune       if (++snes->numFailures >= snes->maxFailures) {
366fef7b6d8SPeter Brune         snes->reason = SNES_DIVERGED_LINE_SEARCH;
3675d10c001SPeter Brune         PetscFunctionReturn(0);
368fef7b6d8SPeter Brune       }
369fef7b6d8SPeter Brune     }
370fef7b6d8SPeter Brune     if (snes->nfuncs >= snes->max_funcs) {
371fef7b6d8SPeter Brune       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
3725d10c001SPeter Brune       PetscFunctionReturn(0);
373fef7b6d8SPeter Brune     }
374fef7b6d8SPeter Brune     if (snes->domainerror) {
375fef7b6d8SPeter Brune       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
376fef7b6d8SPeter Brune       PetscFunctionReturn(0);
377fef7b6d8SPeter Brune     }
378f1c6b773SPeter Brune     ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr);
379fef7b6d8SPeter Brune     /* Monitor convergence */
380ce8c27fbSBarry Smith     ierr       = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr);
381169e2be8SPeter Brune     snes->iter = i;
382fef7b6d8SPeter Brune     snes->norm = fnorm;
383ce8c27fbSBarry Smith     ierr       = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr);
384a71f0d7dSBarry Smith     ierr       = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr);
385fef7b6d8SPeter Brune     ierr       = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
386302dbbaeSPeter Brune 
387fef7b6d8SPeter Brune     /* Test for convergence */
388d484d688SPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
3895d10c001SPeter Brune     if (snes->reason) PetscFunctionReturn(0);
390302dbbaeSPeter Brune 
391302dbbaeSPeter Brune     /* Call general purpose update function */
392302dbbaeSPeter Brune     if (snes->ops->update) {
393302dbbaeSPeter Brune       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
394302dbbaeSPeter Brune     }
395c40d0f55SPeter Brune     if (snes->pc && snes->pcside == PC_RIGHT) {
396302dbbaeSPeter Brune       ierr = VecCopy(X,dX);CHKERRQ(ierr);
397217b9c2eSPeter Brune       ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr);
398217b9c2eSPeter Brune       ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr);
3999d3f82b5SPeter Brune       ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,dX,B,0);CHKERRQ(ierr);
400cf949ffaSPeter Brune       ierr = SNESSolve(snes->pc, B, dX);CHKERRQ(ierr);
4019d3f82b5SPeter Brune       ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,dX,B,0);CHKERRQ(ierr);
402302dbbaeSPeter Brune       ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
40351e86f29SPeter Brune       if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) {
404302dbbaeSPeter Brune         snes->reason = SNES_DIVERGED_INNER;
405302dbbaeSPeter Brune         PetscFunctionReturn(0);
406302dbbaeSPeter Brune       }
407eb1825c3SPeter Brune       ierr = VecAYPX(dX,-1.0,X);CHKERRQ(ierr);
408a3685310SPeter Brune     } else {
409a3685310SPeter Brune       ierr = VecCopy(F, dX);CHKERRQ(ierr);
410302dbbaeSPeter Brune     }
411302dbbaeSPeter Brune 
41229c94e34SPeter Brune     /* compute the conjugate direction lX = dX + beta*lX with beta = ((dX, dX) / (dX_old, dX_old) (Fletcher-Reeves update)*/
4130a844d1aSPeter Brune     switch (ncg->type) {
4140a844d1aSPeter Brune     case SNES_NCG_FR: /* Fletcher-Reeves */
4155d115551SPeter Brune       dXolddotFold = dXdotF;
416bbd5d0b3SPeter Brune       ierr         = VecDot(dX, dX, &dXdotF);CHKERRQ(ierr);
4175d115551SPeter Brune       beta         = PetscRealPart(dXdotF / dXolddotFold);
418dfb256c7SPeter Brune       break;
4190a844d1aSPeter Brune     case SNES_NCG_PRP: /* Polak-Ribiere-Poylak */
4205d115551SPeter Brune       dXolddotFold = dXdotF;
42115f0db4aSPeter Brune       ierr         = VecDotBegin(F, dX, &dXdotF);CHKERRQ(ierr);
42215f0db4aSPeter Brune       ierr         = VecDotBegin(Fold, dX, &dXdotFold);CHKERRQ(ierr);
42315f0db4aSPeter Brune       ierr         = VecDotEnd(F, dX, &dXdotF);CHKERRQ(ierr);
42415f0db4aSPeter Brune       ierr         = VecDotEnd(Fold, dX, &dXdotFold);CHKERRQ(ierr);
4255d115551SPeter Brune       beta         = PetscRealPart(((dXdotF - dXdotFold) / dXolddotFold));
426dfb256c7SPeter Brune       if (beta < 0.0) beta = 0.0; /* restart */
427dfb256c7SPeter Brune       break;
4280a844d1aSPeter Brune     case SNES_NCG_HS: /* Hestenes-Stiefel */
42915f0db4aSPeter Brune       ierr = VecDotBegin(dX, F, &dXdotF);CHKERRQ(ierr);
43015f0db4aSPeter Brune       ierr = VecDotBegin(dX, Fold, &dXdotFold);CHKERRQ(ierr);
43115f0db4aSPeter Brune       ierr = VecDotBegin(lX, F, &lXdotF);CHKERRQ(ierr);
43215f0db4aSPeter Brune       ierr = VecDotBegin(lX, Fold, &lXdotFold);CHKERRQ(ierr);
43315f0db4aSPeter Brune       ierr = VecDotEnd(dX, F, &dXdotF);CHKERRQ(ierr);
43415f0db4aSPeter Brune       ierr = VecDotEnd(dX, Fold, &dXdotFold);CHKERRQ(ierr);
43515f0db4aSPeter Brune       ierr = VecDotEnd(lX, F, &lXdotF);CHKERRQ(ierr);
43615f0db4aSPeter Brune       ierr = VecDotEnd(lX, Fold, &lXdotFold);CHKERRQ(ierr);
4375d115551SPeter Brune       beta = PetscRealPart((dXdotF - dXdotFold) / (lXdotF - lXdotFold));
438dfb256c7SPeter Brune       break;
4390a844d1aSPeter Brune     case SNES_NCG_DY: /* Dai-Yuan */
44015f0db4aSPeter Brune       ierr = VecDotBegin(dX, F, &dXdotF);CHKERRQ(ierr);
44115f0db4aSPeter Brune       ierr = VecDotBegin(lX, F, &lXdotF);CHKERRQ(ierr);
44215f0db4aSPeter Brune       ierr = VecDotBegin(lX, Fold, &lXdotFold);CHKERRQ(ierr);
44315f0db4aSPeter Brune       ierr = VecDotEnd(dX, F, &dXdotF);CHKERRQ(ierr);
44415f0db4aSPeter Brune       ierr = VecDotEnd(lX, F, &lXdotF);CHKERRQ(ierr);
44515f0db4aSPeter Brune       ierr = VecDotEnd(lX, Fold, &lXdotFold);CHKERRQ(ierr);
4465d115551SPeter Brune       beta = PetscRealPart(dXdotF / (lXdotFold - lXdotF));CHKERRQ(ierr);
447dfb256c7SPeter Brune       break;
4480a844d1aSPeter Brune     case SNES_NCG_CD: /* Conjugate Descent */
44915f0db4aSPeter Brune       ierr = VecDotBegin(dX, F, &dXdotF);CHKERRQ(ierr);
45015f0db4aSPeter Brune       ierr = VecDotBegin(lX, Fold, &lXdotFold);CHKERRQ(ierr);
45115f0db4aSPeter Brune       ierr = VecDotEnd(dX, F, &dXdotF);CHKERRQ(ierr);
45215f0db4aSPeter Brune       ierr = VecDotEnd(lX, Fold, &lXdotFold);CHKERRQ(ierr);
4535d115551SPeter Brune       beta = PetscRealPart(dXdotF / lXdotFold);CHKERRQ(ierr);
454dfb256c7SPeter Brune       break;
455dfb256c7SPeter Brune     }
456dfb256c7SPeter Brune     if (ncg->monitor) {
457646217ecSPeter Brune       ierr = PetscViewerASCIIPrintf(ncg->monitor, "beta = %e\n", beta);CHKERRQ(ierr);
458dfb256c7SPeter Brune     }
459dfb256c7SPeter Brune     ierr = VecAYPX(lX, beta, dX);CHKERRQ(ierr);
460fef7b6d8SPeter Brune   }
461fef7b6d8SPeter Brune   ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr);
462fef7b6d8SPeter Brune   if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
463fef7b6d8SPeter Brune   PetscFunctionReturn(0);
464fef7b6d8SPeter Brune }
465fef7b6d8SPeter Brune 
4660a844d1aSPeter Brune 
4670a844d1aSPeter Brune 
468fef7b6d8SPeter Brune /*MC
469fef7b6d8SPeter Brune   SNESNCG - Nonlinear Conjugate-Gradient method for the solution of general nonlinear systems.
470fef7b6d8SPeter Brune 
471fef7b6d8SPeter Brune   Level: beginner
472fef7b6d8SPeter Brune 
473fef7b6d8SPeter Brune   Options Database:
4741867fe5bSPeter Brune +   -snes_ncg_type <fr, prp, dy, hs, cd> - Choice of conjugate-gradient update parameter.
47541a8cb50SPeter Brune .   -snes_linesearch_type <cp,l2,basic> - Line search type.
4761867fe5bSPeter Brune -   -snes_ncg_monitor - Print relevant information about the ncg iteration.
477fef7b6d8SPeter Brune 
478fef7b6d8SPeter Brune Notes: This solves the nonlinear system of equations F(x) = 0 using the nonlinear generalization of the conjugate
479fef7b6d8SPeter Brune gradient method.  This may be used with a nonlinear preconditioner used to pick the new search directions, but otherwise
480fef7b6d8SPeter Brune chooses the initial search direction as F(x) for the initial guess x.
481fef7b6d8SPeter Brune 
482fef7b6d8SPeter Brune 
48304d7464bSBarry Smith .seealso:  SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNEWTONTR, SNESNGMRES, SNESNQN
484fef7b6d8SPeter Brune M*/
485fef7b6d8SPeter Brune #undef __FUNCT__
486fef7b6d8SPeter Brune #define __FUNCT__ "SNESCreate_NCG"
4878cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NCG(SNES snes)
488fef7b6d8SPeter Brune {
489fef7b6d8SPeter Brune   PetscErrorCode ierr;
490ea630c6eSPeter Brune   SNES_NCG       * neP;
491fef7b6d8SPeter Brune 
492fef7b6d8SPeter Brune   PetscFunctionBegin;
493fef7b6d8SPeter Brune   snes->ops->destroy        = SNESDestroy_NCG;
494fef7b6d8SPeter Brune   snes->ops->setup          = SNESSetUp_NCG;
495fef7b6d8SPeter Brune   snes->ops->setfromoptions = SNESSetFromOptions_NCG;
496fef7b6d8SPeter Brune   snes->ops->view           = SNESView_NCG;
497fef7b6d8SPeter Brune   snes->ops->solve          = SNESSolve_NCG;
498fef7b6d8SPeter Brune   snes->ops->reset          = SNESReset_NCG;
499fef7b6d8SPeter Brune 
500fef7b6d8SPeter Brune   snes->usesksp = PETSC_FALSE;
501fef7b6d8SPeter Brune   snes->usespc  = PETSC_TRUE;
502fef7b6d8SPeter Brune 
50388976e71SPeter Brune   if (!snes->tolerancesset) {
5040e444f03SPeter Brune     snes->max_funcs = 30000;
5050e444f03SPeter Brune     snes->max_its   = 10000;
506c522fa08SPeter Brune     snes->stol      = 1e-20;
50788976e71SPeter Brune   }
5080e444f03SPeter Brune 
509fef7b6d8SPeter Brune   ierr         = PetscNewLog(snes, SNES_NCG, &neP);CHKERRQ(ierr);
510fef7b6d8SPeter Brune   snes->data   = (void*) neP;
5110298fd71SBarry Smith   neP->monitor = NULL;
5120a844d1aSPeter Brune   neP->type    = SNES_NCG_PRP;
513bdf89e91SBarry Smith   ierr         = PetscObjectComposeFunction((PetscObject)snes,"SNESNCGSetType_C", SNESNCGSetType_NCG);CHKERRQ(ierr);
514fef7b6d8SPeter Brune   PetscFunctionReturn(0);
515fef7b6d8SPeter Brune }
516