xref: /petsc/src/snes/impls/ncg/snesncg.c (revision 63e7833ae58c359c2a0b3235ce285a042bc82d50)
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 
121a4f838cSPeter Brune #define SNESLINESEARCHNCGLINEAR "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);
571a4f838cSPeter Brune   ierr = SNESLineSearchRegisterDynamic(SNESLINESEARCHNCGLINEAR, 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;
74fef7b6d8SPeter Brune   PetscErrorCode     ierr;
750a844d1aSPeter Brune   PetscBool          debug;
76f1c6b773SPeter Brune   SNESLineSearch     linesearch;
77a11d90f7SPeter Brune   SNESNCGType        ncgtype=ncg->type;
78fef7b6d8SPeter Brune 
79fef7b6d8SPeter Brune   PetscFunctionBegin;
80fef7b6d8SPeter Brune   ierr = PetscOptionsHead("SNES NCG options");CHKERRQ(ierr);
81dfb256c7SPeter Brune   ierr = PetscOptionsBool("-snes_ncg_monitor","Monitor NCG iterations","SNES",ncg->monitor ? PETSC_TRUE: PETSC_FALSE, &debug, PETSC_NULL);CHKERRQ(ierr);
820a844d1aSPeter Brune   ierr = PetscOptionsEnum("-snes_ncg_type","NCG Beta type used","SNESNCGSetType",SNESNCGTypes,(PetscEnum)ncg->type,(PetscEnum*)&ncgtype,PETSC_NULL);CHKERRQ(ierr);
830a844d1aSPeter Brune   ierr = SNESNCGSetType(snes, ncgtype);CHKERRQ(ierr);
84dfb256c7SPeter Brune   if (debug) {
85dfb256c7SPeter Brune     ncg->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr);
86dfb256c7SPeter Brune   }
87fef7b6d8SPeter Brune   ierr = PetscOptionsTail();CHKERRQ(ierr);
889e764e56SPeter Brune   if (!snes->linesearch) {
89f1c6b773SPeter Brune     ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
909e764e56SPeter Brune     if (!snes->pc) {
911a4f838cSPeter Brune       ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHCP);CHKERRQ(ierr);
929e764e56SPeter Brune     } else {
931a4f838cSPeter Brune       ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr);
949e764e56SPeter Brune     }
959e764e56SPeter Brune   }
96fef7b6d8SPeter Brune   PetscFunctionReturn(0);
97fef7b6d8SPeter Brune }
98fef7b6d8SPeter Brune 
99fef7b6d8SPeter Brune /*
100fef7b6d8SPeter Brune   SNESView_NCG - Prints info from the SNESNCG data structure.
101fef7b6d8SPeter Brune 
102fef7b6d8SPeter Brune   Input Parameters:
103fef7b6d8SPeter Brune + SNES - the SNES context
104fef7b6d8SPeter Brune - viewer - visualization context
105fef7b6d8SPeter Brune 
106fef7b6d8SPeter Brune   Application Interface Routine: SNESView()
107fef7b6d8SPeter Brune */
108fef7b6d8SPeter Brune #undef __FUNCT__
109fef7b6d8SPeter Brune #define __FUNCT__ "SNESView_NCG"
110fef7b6d8SPeter Brune static PetscErrorCode SNESView_NCG(SNES snes, PetscViewer viewer)
111fef7b6d8SPeter Brune {
112fef7b6d8SPeter Brune   PetscBool        iascii;
113fef7b6d8SPeter Brune   PetscErrorCode   ierr;
114fef7b6d8SPeter Brune 
115fef7b6d8SPeter Brune   PetscFunctionBegin;
116251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
117fef7b6d8SPeter Brune   if (iascii) {
118fef7b6d8SPeter Brune   }
119fef7b6d8SPeter Brune   PetscFunctionReturn(0);
120fef7b6d8SPeter Brune }
121fef7b6d8SPeter Brune 
122fef7b6d8SPeter Brune #undef __FUNCT__
123f1c6b773SPeter Brune #define __FUNCT__ "SNESLineSearchApply_NCGLinear"
124f1c6b773SPeter Brune PetscErrorCode SNESLineSearchApply_NCGLinear(SNESLineSearch linesearch)
125ea630c6eSPeter Brune {
126ea630c6eSPeter Brune   PetscScalar      alpha, ptAp;
127bbd5d0b3SPeter Brune   Vec              X, Y, F, W;
128bbd5d0b3SPeter Brune   SNES             snes;
129ea630c6eSPeter Brune   PetscErrorCode   ierr;
130bbd5d0b3SPeter Brune   PetscReal        *fnorm, *xnorm, *ynorm;
131ea630c6eSPeter Brune   MatStructure     flg = DIFFERENT_NONZERO_PATTERN;
132ea630c6eSPeter Brune 
133ea630c6eSPeter Brune   PetscFunctionBegin;
134f1c6b773SPeter Brune   ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr);
135bbd5d0b3SPeter Brune   X = linesearch->vec_sol;
136bbd5d0b3SPeter Brune   W = linesearch->vec_sol_new;
137bbd5d0b3SPeter Brune   F = linesearch->vec_func;
138bbd5d0b3SPeter Brune   Y = linesearch->vec_update;
139bbd5d0b3SPeter Brune   fnorm = &linesearch->fnorm;
140bbd5d0b3SPeter Brune   xnorm = &linesearch->xnorm;
141bbd5d0b3SPeter Brune   ynorm = &linesearch->ynorm;
142bbd5d0b3SPeter 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;
153d9fe6452SJed Brown   ierr = PetscPrintf(((PetscObject)snes)->comm, "alpha: %G\n", PetscRealPart(alpha));CHKERRQ(ierr);
154bbd5d0b3SPeter Brune   ierr = VecAXPY(X, alpha, Y);CHKERRQ(ierr);
155bbd5d0b3SPeter Brune   ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr);
156bbd5d0b3SPeter Brune 
157bbd5d0b3SPeter Brune   ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr);
158bbd5d0b3SPeter Brune   ierr = VecNorm(X, NORM_2, xnorm);CHKERRQ(ierr);
159bbd5d0b3SPeter Brune   ierr = VecNorm(Y, NORM_2, ynorm);CHKERRQ(ierr);
160ea630c6eSPeter Brune  PetscFunctionReturn(0);
161ea630c6eSPeter Brune }
162ea630c6eSPeter Brune 
163bbd5d0b3SPeter Brune EXTERN_C_BEGIN
164bbd5d0b3SPeter Brune #undef __FUNCT__
165f1c6b773SPeter Brune #define __FUNCT__ "SNESLineSearchCreate_NCGLinear"
166bbd5d0b3SPeter Brune 
167f1c6b773SPeter Brune PetscErrorCode SNESLineSearchCreate_NCGLinear(SNESLineSearch linesearch)
168bbd5d0b3SPeter Brune {
169bbd5d0b3SPeter Brune   PetscFunctionBegin;
170f1c6b773SPeter Brune   linesearch->ops->apply          = SNESLineSearchApply_NCGLinear;
171bbd5d0b3SPeter Brune   linesearch->ops->destroy        = PETSC_NULL;
172bbd5d0b3SPeter Brune   linesearch->ops->setfromoptions = PETSC_NULL;
173bbd5d0b3SPeter Brune   linesearch->ops->reset          = PETSC_NULL;
174bbd5d0b3SPeter Brune   linesearch->ops->view           = PETSC_NULL;
175bbd5d0b3SPeter Brune   linesearch->ops->setup          = PETSC_NULL;
176bbd5d0b3SPeter Brune   PetscFunctionReturn(0);
177bbd5d0b3SPeter Brune }
178bbd5d0b3SPeter Brune EXTERN_C_END
179bbd5d0b3SPeter Brune 
18088d374b2SPeter Brune #undef __FUNCT__
1818c40d5fbSBarry Smith #define __FUNCT__ "SNESNCGComputeYtJtF_Private"
18288d374b2SPeter Brune /*
18388d374b2SPeter Brune 
18488d374b2SPeter Brune  Assuming F = SNESComputeFunction(X) compute Y^tJ^tF using a simple secant approximation of the jacobian.
18588d374b2SPeter Brune 
18688d374b2SPeter Brune  */
18767392de3SBarry Smith PetscErrorCode SNESNCGComputeYtJtF_Private(SNES snes, Vec X, Vec F, Vec Y, Vec W, Vec G, PetscScalar * ytJtf)
18867392de3SBarry Smith  {
18988d374b2SPeter Brune   PetscErrorCode ierr;
19088d374b2SPeter Brune   PetscScalar    ftf, ftg, fty, h;
19167392de3SBarry Smith 
19288d374b2SPeter Brune   PetscFunctionBegin;
19388d374b2SPeter Brune   ierr = VecDot(F, F, &ftf);CHKERRQ(ierr);
19488d374b2SPeter Brune   ierr = VecDot(F, Y, &fty);CHKERRQ(ierr);
19588d374b2SPeter Brune   h = 1e-5*fty / fty;
19688d374b2SPeter Brune   ierr = VecCopy(X, W);CHKERRQ(ierr);
19788d374b2SPeter Brune   ierr = VecAXPY(W, -h, Y);CHKERRQ(ierr);            /* this is arbitrary */
19888d374b2SPeter Brune   ierr = SNESComputeFunction(snes, W, G);CHKERRQ(ierr);
19988d374b2SPeter Brune   ierr = VecDot(G, F, &ftg);CHKERRQ(ierr);
20088d374b2SPeter Brune   *ytJtf = (ftg - ftf) / h;
20188d374b2SPeter Brune   PetscFunctionReturn(0);
20288d374b2SPeter Brune }
20388d374b2SPeter Brune 
2040a844d1aSPeter Brune #undef __FUNCT__
2050a844d1aSPeter Brune #define __FUNCT__ "SNESNCGSetType"
2060a844d1aSPeter Brune /*@
2070a844d1aSPeter Brune     SNESNCGSetType - Sets the conjugate update type for SNESNCG.
2080a844d1aSPeter Brune 
2090a844d1aSPeter Brune     Logically Collective on SNES
2100a844d1aSPeter Brune 
2110a844d1aSPeter Brune     Input Parameters:
2120a844d1aSPeter Brune +   snes - the iterative context
2130a844d1aSPeter Brune -   btype - update type
2140a844d1aSPeter Brune 
2150a844d1aSPeter Brune     Options Database:
2160a844d1aSPeter Brune .   -snes_ncg_type<prp,fr,hs,dy,cd>
2170a844d1aSPeter Brune 
2180a844d1aSPeter Brune     Level: intermediate
2190a844d1aSPeter Brune 
2200a844d1aSPeter Brune     SNESNCGSelectTypes:
2210a844d1aSPeter Brune +   SNES_NCG_FR - Fletcher-Reeves update
2220a844d1aSPeter Brune .   SNES_NCG_PRP - Polak-Ribiere-Polyak update
2230a844d1aSPeter Brune .   SNES_NCG_HS - Hestenes-Steifel update
2240a844d1aSPeter Brune .   SNES_NCG_DY - Dai-Yuan update
2250a844d1aSPeter Brune -   SNES_NCG_CD - Conjugate Descent update
2260a844d1aSPeter Brune 
2270a844d1aSPeter Brune    Notes:
2280a844d1aSPeter Brune    PRP is the default, and the only one that tolerates generalized search directions.
2290a844d1aSPeter Brune 
2300a844d1aSPeter Brune .keywords: SNES, SNESNCG, selection, type, set
2310a844d1aSPeter Brune @*/
2320adebc6cSBarry Smith PetscErrorCode SNESNCGSetType(SNES snes, SNESNCGType btype)
2330adebc6cSBarry Smith {
2340a844d1aSPeter Brune   PetscErrorCode ierr;
2356e111a19SKarl Rupp 
2360a844d1aSPeter Brune   PetscFunctionBegin;
2370a844d1aSPeter Brune   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
2380a844d1aSPeter Brune   ierr = PetscTryMethod(snes,"SNESNCGSetType_C",(SNES,SNESNCGType),(snes,btype));CHKERRQ(ierr);
2390a844d1aSPeter Brune   PetscFunctionReturn(0);
2400a844d1aSPeter Brune }
2410a844d1aSPeter Brune 
2420a844d1aSPeter Brune 
2430a844d1aSPeter Brune EXTERN_C_BEGIN
2440a844d1aSPeter Brune #undef __FUNCT__
2450a844d1aSPeter Brune #define __FUNCT__ "SNESNCGSetType_NCG"
2460adebc6cSBarry Smith PetscErrorCode SNESNCGSetType_NCG(SNES snes, SNESNCGType btype)
2470adebc6cSBarry Smith {
2480a844d1aSPeter Brune   SNES_NCG *ncg = (SNES_NCG *)snes->data;
2496e111a19SKarl Rupp 
2500a844d1aSPeter Brune   PetscFunctionBegin;
2510a844d1aSPeter Brune   ncg->type = btype;
2520a844d1aSPeter Brune   PetscFunctionReturn(0);
2530a844d1aSPeter Brune }
2540a844d1aSPeter Brune EXTERN_C_END
2550a844d1aSPeter Brune 
256fef7b6d8SPeter Brune /*
257fef7b6d8SPeter Brune   SNESSolve_NCG - Solves a nonlinear system with the Nonlinear Conjugate Gradient method.
258fef7b6d8SPeter Brune 
259fef7b6d8SPeter Brune   Input Parameters:
260fef7b6d8SPeter Brune . snes - the SNES context
261fef7b6d8SPeter Brune 
262fef7b6d8SPeter Brune   Output Parameter:
263fef7b6d8SPeter Brune . outits - number of iterations until termination
264fef7b6d8SPeter Brune 
265fef7b6d8SPeter Brune   Application Interface Routine: SNESSolve()
266fef7b6d8SPeter Brune */
267fef7b6d8SPeter Brune #undef __FUNCT__
268fef7b6d8SPeter Brune #define __FUNCT__ "SNESSolve_NCG"
269fef7b6d8SPeter Brune PetscErrorCode SNESSolve_NCG(SNES snes)
270fef7b6d8SPeter Brune {
271dfb256c7SPeter Brune   SNES_NCG            *ncg = (SNES_NCG *)snes->data;
272bbd5d0b3SPeter Brune   Vec                 X, dX, lX, F, B, Fold;
273bbd5d0b3SPeter Brune   PetscReal           fnorm, ynorm, xnorm, beta = 0.0;
2745d115551SPeter Brune   PetscScalar         dXdotF, dXolddotFold, dXdotFold, lXdotF, lXdotFold;
275fef7b6d8SPeter Brune   PetscInt            maxits, i;
276fef7b6d8SPeter Brune   PetscErrorCode      ierr;
277fef7b6d8SPeter Brune   SNESConvergedReason reason;
278fef7b6d8SPeter Brune   PetscBool           lsSuccess = PETSC_TRUE;
279f1c6b773SPeter Brune   SNESLineSearch     linesearch;
28088d374b2SPeter Brune 
281fef7b6d8SPeter Brune   PetscFunctionBegin;
282fef7b6d8SPeter Brune   snes->reason = SNES_CONVERGED_ITERATING;
283fef7b6d8SPeter Brune 
284fef7b6d8SPeter Brune   maxits = snes->max_its;            /* maximum number of iterations */
285fef7b6d8SPeter Brune   X      = snes->vec_sol;            /* X^n */
2865d115551SPeter Brune   Fold   = snes->work[0];            /* The previous iterate of X */
28788d374b2SPeter Brune   dX     = snes->work[1];            /* the preconditioned direction */
288169e2be8SPeter Brune   lX     = snes->vec_sol_update;     /* the conjugate direction */
289fef7b6d8SPeter Brune   F      = snes->vec_func;           /* residual vector */
290302dbbaeSPeter Brune   B      = snes->vec_rhs;            /* the right hand side */
291fef7b6d8SPeter Brune 
292f1c6b773SPeter Brune   ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
2939e764e56SPeter Brune 
294fef7b6d8SPeter Brune   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
295fef7b6d8SPeter Brune   snes->iter = 0;
296fef7b6d8SPeter Brune   snes->norm = 0.;
297fef7b6d8SPeter Brune   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
298fef7b6d8SPeter Brune 
299bbd5d0b3SPeter Brune   /* compute the initial function and preconditioned update dX */
300e4ed7901SPeter Brune   if (!snes->vec_func_init_set) {
301fef7b6d8SPeter Brune     ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
302fef7b6d8SPeter Brune     if (snes->domainerror) {
303fef7b6d8SPeter Brune       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
304fef7b6d8SPeter Brune       PetscFunctionReturn(0);
305fef7b6d8SPeter Brune     }
306e4ed7901SPeter Brune   } else {
307e4ed7901SPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
308e4ed7901SPeter Brune   }
309e4ed7901SPeter Brune   if (!snes->norm_init_set) {
310fef7b6d8SPeter Brune   /* convergence test */
311fef7b6d8SPeter Brune     ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F||  */
312fef7b6d8SPeter Brune     if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
313e4ed7901SPeter Brune   } else {
314e4ed7901SPeter Brune     fnorm = snes->norm_init;
315e4ed7901SPeter Brune     snes->norm_init_set = PETSC_FALSE;
316e4ed7901SPeter Brune   }
317fef7b6d8SPeter Brune   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
318fef7b6d8SPeter Brune   snes->norm = fnorm;
319fef7b6d8SPeter Brune   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
320fef7b6d8SPeter Brune   SNESLogConvHistory(snes,fnorm,0);
321fef7b6d8SPeter Brune   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
322fef7b6d8SPeter Brune 
323fef7b6d8SPeter Brune   /* set parameter for default relative tolerance convergence test */
324fef7b6d8SPeter Brune   snes->ttol = fnorm*snes->rtol;
325fef7b6d8SPeter Brune   /* test convergence */
326fef7b6d8SPeter Brune   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
327fef7b6d8SPeter Brune   if (snes->reason) PetscFunctionReturn(0);
328fef7b6d8SPeter Brune 
329fef7b6d8SPeter Brune   /* Call general purpose update function */
330fef7b6d8SPeter Brune   if (snes->ops->update) {
331fef7b6d8SPeter Brune     ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
332fef7b6d8SPeter Brune  }
333fef7b6d8SPeter Brune 
334fef7b6d8SPeter Brune   /* first update -- just use the (preconditioned) residual direction for the initial conjugate direction */
335bbd5d0b3SPeter Brune 
336c40d0f55SPeter Brune   if (snes->pc && snes->pcside == PC_RIGHT) {
33729c94e34SPeter Brune     ierr = VecCopy(X, dX);CHKERRQ(ierr);
338217b9c2eSPeter Brune     ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr);
339217b9c2eSPeter Brune     ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr);
340*63e7833aSPeter Brune 
341*63e7833aSPeter Brune     ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,dX,B,0);CHKERRQ(ierr);
34229c94e34SPeter Brune     ierr = SNESSolve(snes->pc, B, dX);CHKERRQ(ierr);
343*63e7833aSPeter Brune     ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,dX,B,0);CHKERRQ(ierr);
344*63e7833aSPeter Brune 
345fef7b6d8SPeter Brune     ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
34651e86f29SPeter Brune     if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) {
347fef7b6d8SPeter Brune       snes->reason = SNES_DIVERGED_INNER;
348fef7b6d8SPeter Brune       PetscFunctionReturn(0);
349fef7b6d8SPeter Brune     }
35029c94e34SPeter Brune     ierr = VecAYPX(dX,-1.0,X);CHKERRQ(ierr);
3515d10c001SPeter Brune   } else {
35229c94e34SPeter Brune     ierr = VecCopy(F, dX);CHKERRQ(ierr);
353fef7b6d8SPeter Brune   }
35429c94e34SPeter Brune   ierr = VecCopy(dX, lX);CHKERRQ(ierr);
355bbd5d0b3SPeter Brune   ierr = VecDot(F, dX, &dXdotF);CHKERRQ(ierr);
356bbd5d0b3SPeter Brune   /*
35788d374b2SPeter Brune   } else {
3588c40d5fbSBarry Smith     ierr = SNESNCGComputeYtJtF_Private(snes, X, F, dX, W, G, &dXdotF);CHKERRQ(ierr);
35988d374b2SPeter Brune   }
360bbd5d0b3SPeter Brune    */
36109c08436SPeter Brune   for (i = 1; i < maxits + 1; i++) {
362fef7b6d8SPeter Brune     lsSuccess = PETSC_TRUE;
36329c94e34SPeter Brune     /* some update types require the old update direction or conjugate direction */
3640a844d1aSPeter Brune     if (ncg->type != SNES_NCG_FR) {
3655d115551SPeter Brune       ierr = VecCopy(F, Fold);CHKERRQ(ierr);
36688d374b2SPeter Brune     }
367f1c6b773SPeter Brune     ierr = SNESLineSearchApply(linesearch, X, F, &fnorm, lX);CHKERRQ(ierr);
368f1c6b773SPeter Brune     ierr = SNESLineSearchGetSuccess(linesearch, &lsSuccess);CHKERRQ(ierr);
369fef7b6d8SPeter Brune     if (!lsSuccess) {
370fef7b6d8SPeter Brune       if (++snes->numFailures >= snes->maxFailures) {
371fef7b6d8SPeter Brune         snes->reason = SNES_DIVERGED_LINE_SEARCH;
3725d10c001SPeter Brune         PetscFunctionReturn(0);
373fef7b6d8SPeter Brune       }
374fef7b6d8SPeter Brune     }
375fef7b6d8SPeter Brune     if (snes->nfuncs >= snes->max_funcs) {
376fef7b6d8SPeter Brune       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
3775d10c001SPeter Brune       PetscFunctionReturn(0);
378fef7b6d8SPeter Brune     }
379fef7b6d8SPeter Brune     if (snes->domainerror) {
380fef7b6d8SPeter Brune       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
381fef7b6d8SPeter Brune       PetscFunctionReturn(0);
382fef7b6d8SPeter Brune     }
383f1c6b773SPeter Brune     ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr);
384fef7b6d8SPeter Brune     /* Monitor convergence */
385fef7b6d8SPeter Brune     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
386169e2be8SPeter Brune     snes->iter = i;
387fef7b6d8SPeter Brune     snes->norm = fnorm;
388fef7b6d8SPeter Brune     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
389fef7b6d8SPeter Brune     SNESLogConvHistory(snes,snes->norm,0);
390fef7b6d8SPeter Brune     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
391302dbbaeSPeter Brune 
392fef7b6d8SPeter Brune     /* Test for convergence */
393d484d688SPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
3945d10c001SPeter Brune     if (snes->reason) PetscFunctionReturn(0);
395302dbbaeSPeter Brune 
396302dbbaeSPeter Brune     /* Call general purpose update function */
397302dbbaeSPeter Brune     if (snes->ops->update) {
398302dbbaeSPeter Brune       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
399302dbbaeSPeter Brune     }
400c40d0f55SPeter Brune     if (snes->pc && snes->pcside == PC_RIGHT) {
401302dbbaeSPeter Brune       ierr = VecCopy(X,dX);CHKERRQ(ierr);
402217b9c2eSPeter Brune       ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr);
403217b9c2eSPeter Brune       ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr);
404cf949ffaSPeter Brune       ierr = SNESSolve(snes->pc, B, dX);CHKERRQ(ierr);
405302dbbaeSPeter Brune       ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
40651e86f29SPeter Brune       if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) {
407302dbbaeSPeter Brune         snes->reason = SNES_DIVERGED_INNER;
408302dbbaeSPeter Brune         PetscFunctionReturn(0);
409302dbbaeSPeter Brune       }
410eb1825c3SPeter Brune       ierr = VecAYPX(dX,-1.0,X);CHKERRQ(ierr);
411a3685310SPeter Brune     } else {
412a3685310SPeter Brune       ierr = VecCopy(F, dX);CHKERRQ(ierr);
413302dbbaeSPeter Brune     }
414302dbbaeSPeter Brune 
41529c94e34SPeter Brune     /* compute the conjugate direction lX = dX + beta*lX with beta = ((dX, dX) / (dX_old, dX_old) (Fletcher-Reeves update)*/
4160a844d1aSPeter Brune     switch (ncg->type) {
4170a844d1aSPeter Brune     case SNES_NCG_FR: /* Fletcher-Reeves */
4185d115551SPeter Brune       dXolddotFold = dXdotF;
419bbd5d0b3SPeter Brune       ierr = VecDot(dX, dX, &dXdotF);CHKERRQ(ierr);
4205d115551SPeter Brune       beta = PetscRealPart(dXdotF / dXolddotFold);
421dfb256c7SPeter Brune       break;
4220a844d1aSPeter Brune     case SNES_NCG_PRP: /* Polak-Ribiere-Poylak */
4235d115551SPeter Brune       dXolddotFold = dXdotF;
42415f0db4aSPeter Brune       ierr = VecDotBegin(F, dX, &dXdotF);CHKERRQ(ierr);
42515f0db4aSPeter Brune       ierr = VecDotBegin(Fold, dX, &dXdotFold);CHKERRQ(ierr);
42615f0db4aSPeter Brune       ierr = VecDotEnd(F, dX, &dXdotF);CHKERRQ(ierr);
42715f0db4aSPeter Brune       ierr = VecDotEnd(Fold, dX, &dXdotFold);CHKERRQ(ierr);
4285d115551SPeter Brune       beta = PetscRealPart(((dXdotF - dXdotFold) / dXolddotFold));
429dfb256c7SPeter Brune       if (beta < 0.0) beta = 0.0; /* restart */
430dfb256c7SPeter Brune       break;
4310a844d1aSPeter Brune     case SNES_NCG_HS: /* Hestenes-Stiefel */
43215f0db4aSPeter Brune       ierr = VecDotBegin(dX, F, &dXdotF);CHKERRQ(ierr);
43315f0db4aSPeter Brune       ierr = VecDotBegin(dX, Fold, &dXdotFold);CHKERRQ(ierr);
43415f0db4aSPeter Brune       ierr = VecDotBegin(lX, F, &lXdotF);CHKERRQ(ierr);
43515f0db4aSPeter Brune       ierr = VecDotBegin(lX, Fold, &lXdotFold);CHKERRQ(ierr);
43615f0db4aSPeter Brune       ierr = VecDotEnd(dX, F, &dXdotF);CHKERRQ(ierr);
43715f0db4aSPeter Brune       ierr = VecDotEnd(dX, Fold, &dXdotFold);CHKERRQ(ierr);
43815f0db4aSPeter Brune       ierr = VecDotEnd(lX, F, &lXdotF);CHKERRQ(ierr);
43915f0db4aSPeter Brune       ierr = VecDotEnd(lX, Fold, &lXdotFold);CHKERRQ(ierr);
4405d115551SPeter Brune       beta = PetscRealPart((dXdotF - dXdotFold) / (lXdotF - lXdotFold));
441dfb256c7SPeter Brune       break;
4420a844d1aSPeter Brune     case SNES_NCG_DY: /* Dai-Yuan */
44315f0db4aSPeter Brune       ierr = VecDotBegin(dX, F, &dXdotF);CHKERRQ(ierr);
44415f0db4aSPeter Brune       ierr = VecDotBegin(lX, F, &lXdotF);CHKERRQ(ierr);
44515f0db4aSPeter Brune       ierr = VecDotBegin(lX, Fold, &lXdotFold);CHKERRQ(ierr);
44615f0db4aSPeter Brune       ierr = VecDotEnd(dX, F, &dXdotF);CHKERRQ(ierr);
44715f0db4aSPeter Brune       ierr = VecDotEnd(lX, F, &lXdotF);CHKERRQ(ierr);
44815f0db4aSPeter Brune       ierr = VecDotEnd(lX, Fold, &lXdotFold);CHKERRQ(ierr);
4495d115551SPeter Brune       beta = PetscRealPart(dXdotF / (lXdotFold - lXdotF));CHKERRQ(ierr);
450dfb256c7SPeter Brune       break;
4510a844d1aSPeter Brune     case SNES_NCG_CD: /* Conjugate Descent */
45215f0db4aSPeter Brune       ierr = VecDotBegin(dX, F, &dXdotF);CHKERRQ(ierr);
45315f0db4aSPeter Brune       ierr = VecDotBegin(lX, Fold, &lXdotFold);CHKERRQ(ierr);
45415f0db4aSPeter Brune       ierr = VecDotEnd(dX, F, &dXdotF);CHKERRQ(ierr);
45515f0db4aSPeter Brune       ierr = VecDotEnd(lX, Fold, &lXdotFold);CHKERRQ(ierr);
4565d115551SPeter Brune       beta = PetscRealPart(dXdotF / lXdotFold);CHKERRQ(ierr);
457dfb256c7SPeter Brune       break;
458dfb256c7SPeter Brune     }
459dfb256c7SPeter Brune     if (ncg->monitor) {
460646217ecSPeter Brune       ierr = PetscViewerASCIIPrintf(ncg->monitor, "beta = %e\n", beta);CHKERRQ(ierr);
461dfb256c7SPeter Brune     }
462dfb256c7SPeter Brune     ierr = VecAYPX(lX, beta, dX);CHKERRQ(ierr);
463fef7b6d8SPeter Brune   }
464fef7b6d8SPeter Brune   ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr);
465fef7b6d8SPeter Brune   if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
466fef7b6d8SPeter Brune   PetscFunctionReturn(0);
467fef7b6d8SPeter Brune }
468fef7b6d8SPeter Brune 
4690a844d1aSPeter Brune 
4700a844d1aSPeter Brune 
471fef7b6d8SPeter Brune /*MC
472fef7b6d8SPeter Brune   SNESNCG - Nonlinear Conjugate-Gradient method for the solution of general nonlinear systems.
473fef7b6d8SPeter Brune 
474fef7b6d8SPeter Brune   Level: beginner
475fef7b6d8SPeter Brune 
476fef7b6d8SPeter Brune   Options Database:
4771867fe5bSPeter Brune +   -snes_ncg_type <fr, prp, dy, hs, cd> - Choice of conjugate-gradient update parameter.
47841a8cb50SPeter Brune .   -snes_linesearch_type <cp,l2,basic> - Line search type.
4791867fe5bSPeter Brune -   -snes_ncg_monitor - Print relevant information about the ncg iteration.
480fef7b6d8SPeter Brune 
481fef7b6d8SPeter Brune Notes: This solves the nonlinear system of equations F(x) = 0 using the nonlinear generalization of the conjugate
482fef7b6d8SPeter Brune gradient method.  This may be used with a nonlinear preconditioner used to pick the new search directions, but otherwise
483fef7b6d8SPeter Brune chooses the initial search direction as F(x) for the initial guess x.
484fef7b6d8SPeter Brune 
485fef7b6d8SPeter Brune 
48604d7464bSBarry Smith .seealso:  SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNEWTONTR, SNESNGMRES, SNESNQN
487fef7b6d8SPeter Brune M*/
488fef7b6d8SPeter Brune EXTERN_C_BEGIN
489fef7b6d8SPeter Brune #undef __FUNCT__
490fef7b6d8SPeter Brune #define __FUNCT__ "SNESCreate_NCG"
491fef7b6d8SPeter Brune PetscErrorCode  SNESCreate_NCG(SNES snes)
492fef7b6d8SPeter Brune {
493fef7b6d8SPeter Brune   PetscErrorCode   ierr;
494ea630c6eSPeter Brune   SNES_NCG * neP;
495fef7b6d8SPeter Brune 
496fef7b6d8SPeter Brune   PetscFunctionBegin;
497fef7b6d8SPeter Brune   snes->ops->destroy         = SNESDestroy_NCG;
498fef7b6d8SPeter Brune   snes->ops->setup           = SNESSetUp_NCG;
499fef7b6d8SPeter Brune   snes->ops->setfromoptions  = SNESSetFromOptions_NCG;
500fef7b6d8SPeter Brune   snes->ops->view            = SNESView_NCG;
501fef7b6d8SPeter Brune   snes->ops->solve           = SNESSolve_NCG;
502fef7b6d8SPeter Brune   snes->ops->reset           = SNESReset_NCG;
503fef7b6d8SPeter Brune 
504fef7b6d8SPeter Brune   snes->usesksp              = PETSC_FALSE;
505fef7b6d8SPeter Brune   snes->usespc               = PETSC_TRUE;
506fef7b6d8SPeter Brune 
50788976e71SPeter Brune   if (!snes->tolerancesset) {
5080e444f03SPeter Brune     snes->max_funcs = 30000;
5090e444f03SPeter Brune     snes->max_its   = 10000;
510c522fa08SPeter Brune     snes->stol      = 1e-20;
51188976e71SPeter Brune   }
5120e444f03SPeter Brune 
513fef7b6d8SPeter Brune   ierr = PetscNewLog(snes, SNES_NCG, &neP);CHKERRQ(ierr);
514fef7b6d8SPeter Brune   snes->data = (void*) neP;
515dfb256c7SPeter Brune   neP->monitor = PETSC_NULL;
5160a844d1aSPeter Brune   neP->type = SNES_NCG_PRP;
5170a844d1aSPeter Brune   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESNCGSetType_C","SNESNCGSetType_NCG", SNESNCGSetType_NCG);CHKERRQ(ierr);
518fef7b6d8SPeter Brune   PetscFunctionReturn(0);
519fef7b6d8SPeter Brune }
520fef7b6d8SPeter Brune EXTERN_C_END
521