xref: /petsc/src/snes/impls/ncg/snesncg.c (revision bbd5d0b317af04eb83c39e72581bf86c64bd741a)
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