xref: /petsc/src/snes/impls/ncg/snesncg.c (revision 41a8cb507f1adb4f8b2f57c2cdf970788f4b78fa)
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 
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;
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) {
941a4f838cSPeter Brune       ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHCP);CHKERRQ(ierr);
959e764e56SPeter Brune     } else {
961a4f838cSPeter Brune       ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);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 */
251e4ed7901SPeter 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     }
257e4ed7901SPeter Brune   } else {
258e4ed7901SPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
259e4ed7901SPeter Brune   }
260e4ed7901SPeter 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");
264e4ed7901SPeter Brune   } else {
265e4ed7901SPeter Brune     fnorm = snes->norm_init;
266e4ed7901SPeter Brune     snes->norm_init_set = PETSC_FALSE;
267e4ed7901SPeter 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);
289217b9c2eSPeter Brune     ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr);
290217b9c2eSPeter Brune     ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr);
29129c94e34SPeter Brune     ierr = SNESSolve(snes->pc, B, dX);CHKERRQ(ierr);
292fef7b6d8SPeter Brune     ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
29351e86f29SPeter Brune     if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) {
294fef7b6d8SPeter Brune       snes->reason = SNES_DIVERGED_INNER;
295fef7b6d8SPeter Brune       PetscFunctionReturn(0);
296fef7b6d8SPeter Brune     }
29729c94e34SPeter Brune     ierr = VecAYPX(dX,-1.0,X);CHKERRQ(ierr);
2985d10c001SPeter Brune   } else {
29929c94e34SPeter Brune     ierr = VecCopy(F, dX);CHKERRQ(ierr);
300fef7b6d8SPeter Brune   }
30129c94e34SPeter Brune   ierr = VecCopy(dX, lX);CHKERRQ(ierr);
302bbd5d0b3SPeter Brune   ierr = VecDot(F, dX, &dXdotF);CHKERRQ(ierr);
303bbd5d0b3SPeter Brune   /*
30488d374b2SPeter Brune   } else {
3058c40d5fbSBarry Smith     ierr = SNESNCGComputeYtJtF_Private(snes, X, F, dX, W, G, &dXdotF);CHKERRQ(ierr);
30688d374b2SPeter Brune   }
307bbd5d0b3SPeter Brune    */
30809c08436SPeter Brune   for(i = 1; i < maxits + 1; i++) {
309fef7b6d8SPeter Brune     lsSuccess = PETSC_TRUE;
31029c94e34SPeter Brune     /* some update types require the old update direction or conjugate direction */
31129c94e34SPeter Brune     if (ncg->betatype == 1 || ncg->betatype == 2 || ncg->betatype == 3 || ncg->betatype == 4) { /* prp, hs, dy, cd need dXold*/
3125d115551SPeter Brune       ierr = VecCopy(F, Fold);CHKERRQ(ierr);
31388d374b2SPeter Brune     }
314f1c6b773SPeter Brune     ierr = SNESLineSearchApply(linesearch, X, F, &fnorm, lX);CHKERRQ(ierr);
315f1c6b773SPeter Brune     ierr = SNESLineSearchGetSuccess(linesearch, &lsSuccess);CHKERRQ(ierr);
316fef7b6d8SPeter Brune     if (!lsSuccess) {
317fef7b6d8SPeter Brune       if (++snes->numFailures >= snes->maxFailures) {
318fef7b6d8SPeter Brune         snes->reason = SNES_DIVERGED_LINE_SEARCH;
3195d10c001SPeter Brune         PetscFunctionReturn(0);
320fef7b6d8SPeter Brune       }
321fef7b6d8SPeter Brune     }
322fef7b6d8SPeter Brune     if (snes->nfuncs >= snes->max_funcs) {
323fef7b6d8SPeter Brune       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
3245d10c001SPeter Brune       PetscFunctionReturn(0);
325fef7b6d8SPeter Brune     }
326fef7b6d8SPeter Brune     if (snes->domainerror) {
327fef7b6d8SPeter Brune       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
328fef7b6d8SPeter Brune       PetscFunctionReturn(0);
329fef7b6d8SPeter Brune     }
330f1c6b773SPeter Brune     ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr);
331fef7b6d8SPeter Brune     /* Monitor convergence */
332fef7b6d8SPeter Brune     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
333169e2be8SPeter Brune     snes->iter = i;
334fef7b6d8SPeter Brune     snes->norm = fnorm;
335fef7b6d8SPeter Brune     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
336fef7b6d8SPeter Brune     SNESLogConvHistory(snes,snes->norm,0);
337fef7b6d8SPeter Brune     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
338302dbbaeSPeter Brune 
339fef7b6d8SPeter Brune     /* Test for convergence */
340fef7b6d8SPeter Brune     ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
3415d10c001SPeter Brune     if (snes->reason) PetscFunctionReturn(0);
342302dbbaeSPeter Brune 
343302dbbaeSPeter Brune     /* Call general purpose update function */
344302dbbaeSPeter Brune     if (snes->ops->update) {
345302dbbaeSPeter Brune       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
346302dbbaeSPeter Brune     }
34783947a81SPeter Brune     if (snes->pc) {
348302dbbaeSPeter Brune       ierr = VecCopy(X,dX);CHKERRQ(ierr);
349217b9c2eSPeter Brune       ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr);
350217b9c2eSPeter Brune       ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr);
351cf949ffaSPeter Brune       ierr = SNESSolve(snes->pc, B, dX);CHKERRQ(ierr);
352302dbbaeSPeter Brune       ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
35351e86f29SPeter Brune       if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) {
354302dbbaeSPeter Brune         snes->reason = SNES_DIVERGED_INNER;
355302dbbaeSPeter Brune         PetscFunctionReturn(0);
356302dbbaeSPeter Brune       }
357eb1825c3SPeter Brune       ierr = VecAYPX(dX,-1.0,X);CHKERRQ(ierr);
358a3685310SPeter Brune     } else {
359a3685310SPeter Brune       ierr = VecCopy(F, dX);CHKERRQ(ierr);
360302dbbaeSPeter Brune     }
361302dbbaeSPeter Brune 
36229c94e34SPeter Brune     /* compute the conjugate direction lX = dX + beta*lX with beta = ((dX, dX) / (dX_old, dX_old) (Fletcher-Reeves update)*/
363dfb256c7SPeter Brune     switch(ncg->betatype) {
364dfb256c7SPeter Brune     case 0: /* Fletcher-Reeves */
3655d115551SPeter Brune       dXolddotFold = dXdotF;
366bbd5d0b3SPeter Brune       ierr = VecDot(dX, dX, &dXdotF);CHKERRQ(ierr);
3675d115551SPeter Brune       beta = PetscRealPart(dXdotF / dXolddotFold);
368dfb256c7SPeter Brune       break;
369dfb256c7SPeter Brune     case 1: /* Polak-Ribiere-Poylak */
3705d115551SPeter Brune       dXolddotFold = dXdotF;
37115f0db4aSPeter Brune       ierr = VecDotBegin(F, dX, &dXdotF);CHKERRQ(ierr);
37215f0db4aSPeter Brune       ierr = VecDotBegin(Fold, dX, &dXdotFold);CHKERRQ(ierr);
37315f0db4aSPeter Brune       ierr = VecDotEnd(F, dX, &dXdotF);CHKERRQ(ierr);
37415f0db4aSPeter Brune       ierr = VecDotEnd(Fold, dX, &dXdotFold);CHKERRQ(ierr);
3755d115551SPeter Brune       beta = PetscRealPart(((dXdotF - dXdotFold) / dXolddotFold));
376dfb256c7SPeter Brune       if (beta < 0.0) beta = 0.0; /* restart */
377dfb256c7SPeter Brune       break;
378dfb256c7SPeter Brune     case 2: /* Hestenes-Stiefel */
37915f0db4aSPeter Brune       ierr = VecDotBegin(dX, F, &dXdotF);CHKERRQ(ierr);
38015f0db4aSPeter Brune       ierr = VecDotBegin(dX, Fold, &dXdotFold);CHKERRQ(ierr);
38115f0db4aSPeter Brune       ierr = VecDotBegin(lX, F, &lXdotF);CHKERRQ(ierr);
38215f0db4aSPeter Brune       ierr = VecDotBegin(lX, Fold, &lXdotFold);CHKERRQ(ierr);
38315f0db4aSPeter Brune       ierr = VecDotEnd(dX, F, &dXdotF);CHKERRQ(ierr);
38415f0db4aSPeter Brune       ierr = VecDotEnd(dX, Fold, &dXdotFold);CHKERRQ(ierr);
38515f0db4aSPeter Brune       ierr = VecDotEnd(lX, F, &lXdotF);CHKERRQ(ierr);
38615f0db4aSPeter Brune       ierr = VecDotEnd(lX, Fold, &lXdotFold);CHKERRQ(ierr);
3875d115551SPeter Brune       beta = PetscRealPart((dXdotF - dXdotFold) / (lXdotF - lXdotFold));
388dfb256c7SPeter Brune       break;
389dfb256c7SPeter Brune     case 3: /* Dai-Yuan */
39015f0db4aSPeter Brune       ierr = VecDotBegin(dX, F, &dXdotF);CHKERRQ(ierr);
39115f0db4aSPeter Brune       ierr = VecDotBegin(lX, F, &lXdotF);CHKERRQ(ierr);
39215f0db4aSPeter Brune       ierr = VecDotBegin(lX, Fold, &lXdotFold);CHKERRQ(ierr);
39315f0db4aSPeter Brune       ierr = VecDotEnd(dX, F, &dXdotF);CHKERRQ(ierr);
39415f0db4aSPeter Brune       ierr = VecDotEnd(lX, F, &lXdotF);CHKERRQ(ierr);
39515f0db4aSPeter Brune       ierr = VecDotEnd(lX, Fold, &lXdotFold);CHKERRQ(ierr);
3965d115551SPeter Brune       beta = PetscRealPart(dXdotF / (lXdotFold - lXdotF));CHKERRQ(ierr);
397dfb256c7SPeter Brune       break;
398dfb256c7SPeter Brune     case 4: /* Conjugate Descent */
39915f0db4aSPeter Brune       ierr = VecDotBegin(dX, F, &dXdotF);CHKERRQ(ierr);
40015f0db4aSPeter Brune       ierr = VecDotBegin(lX, Fold, &lXdotFold);CHKERRQ(ierr);
40115f0db4aSPeter Brune       ierr = VecDotEnd(dX, F, &dXdotF);CHKERRQ(ierr);
40215f0db4aSPeter Brune       ierr = VecDotEnd(lX, Fold, &lXdotFold);CHKERRQ(ierr);
4035d115551SPeter Brune       beta = PetscRealPart(dXdotF / lXdotFold);CHKERRQ(ierr);
404dfb256c7SPeter Brune       break;
405dfb256c7SPeter Brune     }
406dfb256c7SPeter Brune     if (ncg->monitor) {
407646217ecSPeter Brune       ierr = PetscViewerASCIIPrintf(ncg->monitor, "beta = %e\n", beta);CHKERRQ(ierr);
408dfb256c7SPeter Brune     }
409dfb256c7SPeter Brune     ierr = VecAYPX(lX, beta, dX);CHKERRQ(ierr);
410fef7b6d8SPeter Brune   }
411fef7b6d8SPeter Brune   ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr);
412fef7b6d8SPeter Brune   if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
413fef7b6d8SPeter Brune   PetscFunctionReturn(0);
414fef7b6d8SPeter Brune }
415fef7b6d8SPeter Brune 
416fef7b6d8SPeter Brune /*MC
417fef7b6d8SPeter Brune   SNESNCG - Nonlinear Conjugate-Gradient method for the solution of general nonlinear systems.
418fef7b6d8SPeter Brune 
419fef7b6d8SPeter Brune   Level: beginner
420fef7b6d8SPeter Brune 
421fef7b6d8SPeter Brune   Options Database:
4221867fe5bSPeter Brune +   -snes_ncg_type <fr, prp, dy, hs, cd> - Choice of conjugate-gradient update parameter.
423*41a8cb50SPeter Brune .   -snes_linesearch_type <cp,l2,basic> - Line search type.
4241867fe5bSPeter Brune -   -snes_ncg_monitor - Print relevant information about the ncg iteration.
425fef7b6d8SPeter Brune 
426fef7b6d8SPeter Brune Notes: This solves the nonlinear system of equations F(x) = 0 using the nonlinear generalization of the conjugate
427fef7b6d8SPeter Brune gradient method.  This may be used with a nonlinear preconditioner used to pick the new search directions, but otherwise
428fef7b6d8SPeter Brune chooses the initial search direction as F(x) for the initial guess x.
429fef7b6d8SPeter Brune 
430fef7b6d8SPeter Brune 
431fef7b6d8SPeter Brune .seealso:  SNESCreate(), SNES, SNESSetType(), SNESLS, SNESTR, SNESNGMRES, SNESNQN
432fef7b6d8SPeter Brune M*/
433fef7b6d8SPeter Brune EXTERN_C_BEGIN
434fef7b6d8SPeter Brune #undef __FUNCT__
435fef7b6d8SPeter Brune #define __FUNCT__ "SNESCreate_NCG"
436fef7b6d8SPeter Brune PetscErrorCode  SNESCreate_NCG(SNES snes)
437fef7b6d8SPeter Brune {
438fef7b6d8SPeter Brune   PetscErrorCode   ierr;
439ea630c6eSPeter Brune   SNES_NCG * neP;
440fef7b6d8SPeter Brune 
441fef7b6d8SPeter Brune   PetscFunctionBegin;
442fef7b6d8SPeter Brune   snes->ops->destroy         = SNESDestroy_NCG;
443fef7b6d8SPeter Brune   snes->ops->setup           = SNESSetUp_NCG;
444fef7b6d8SPeter Brune   snes->ops->setfromoptions  = SNESSetFromOptions_NCG;
445fef7b6d8SPeter Brune   snes->ops->view            = SNESView_NCG;
446fef7b6d8SPeter Brune   snes->ops->solve           = SNESSolve_NCG;
447fef7b6d8SPeter Brune   snes->ops->reset           = SNESReset_NCG;
448fef7b6d8SPeter Brune 
449fef7b6d8SPeter Brune   snes->usesksp              = PETSC_FALSE;
450fef7b6d8SPeter Brune   snes->usespc               = PETSC_TRUE;
451fef7b6d8SPeter Brune 
45288976e71SPeter Brune   if (!snes->tolerancesset) {
4530e444f03SPeter Brune     snes->max_funcs = 30000;
4540e444f03SPeter Brune     snes->max_its   = 10000;
45588976e71SPeter Brune   }
4560e444f03SPeter Brune 
457fef7b6d8SPeter Brune   ierr = PetscNewLog(snes, SNES_NCG, &neP);CHKERRQ(ierr);
458fef7b6d8SPeter Brune   snes->data = (void*) neP;
459dfb256c7SPeter Brune   neP->monitor = PETSC_NULL;
4601867fe5bSPeter Brune   neP->betatype = 1;
461fef7b6d8SPeter Brune   PetscFunctionReturn(0);
462fef7b6d8SPeter Brune }
463fef7b6d8SPeter Brune EXTERN_C_END
464