xref: /petsc/src/snes/impls/ncg/snesncg.c (revision dced61a5cfeeeda68dfa4ee3e53b34d3cfb8da9f)
1 #include <../src/snes/impls/ncg/snesncgimpl.h> /*I "petscsnes.h" I*/
2 const char *const SNESNCGTypes[] = {"FR","PRP","HS","DY","CD","SNESNCGType","SNES_NCG_",0};
3 
4 #undef __FUNCT__
5 #define __FUNCT__ "SNESReset_NCG"
6 PetscErrorCode SNESReset_NCG(SNES snes)
7 {
8   PetscFunctionBegin;
9   PetscFunctionReturn(0);
10 }
11 
12 #define SNESLINESEARCHNCGLINEAR "ncglinear"
13 
14 /*
15   SNESDestroy_NCG - Destroys the private SNES_NCG context that was created with SNESCreate_NCG().
16 
17   Input Parameter:
18 . snes - the SNES context
19 
20   Application Interface Routine: SNESDestroy()
21 */
22 #undef __FUNCT__
23 #define __FUNCT__ "SNESDestroy_NCG"
24 PetscErrorCode SNESDestroy_NCG(SNES snes)
25 {
26   PetscErrorCode ierr;
27 
28   PetscFunctionBegin;
29   ierr = PetscFree(snes->data);CHKERRQ(ierr);
30   PetscFunctionReturn(0);
31 }
32 
33 /*
34    SNESSetUp_NCG - Sets up the internal data structures for the later use
35    of the SNESNCG nonlinear solver.
36 
37    Input Parameters:
38 +  snes - the SNES context
39 -  x - the solution vector
40 
41    Application Interface Routine: SNESSetUp()
42  */
43 
44 PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_NCGLinear(SNESLineSearch);
45 
46 #undef __FUNCT__
47 #define __FUNCT__ "SNESSetUp_NCG"
48 PetscErrorCode SNESSetUp_NCG(SNES snes)
49 {
50   PetscErrorCode ierr;
51 
52   PetscFunctionBegin;
53   ierr = SNESSetWorkVecs(snes,2);CHKERRQ(ierr);
54   if (snes->pcside == PC_RIGHT) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNESNCG only supports left preconditioning");
55   if (snes->functype == SNES_FUNCTION_DEFAULT) snes->functype = SNES_FUNCTION_UNPRECONDITIONED;
56   PetscFunctionReturn(0);
57 }
58 /*
59   SNESSetFromOptions_NCG - Sets various parameters for the SNESNCG method.
60 
61   Input Parameter:
62 . snes - the SNES context
63 
64   Application Interface Routine: SNESSetFromOptions()
65 */
66 #undef __FUNCT__
67 #define __FUNCT__ "SNESSetFromOptions_NCG"
68 static PetscErrorCode SNESSetFromOptions_NCG(PetscOptions *PetscOptionsObject,SNES snes)
69 {
70   SNES_NCG       *ncg = (SNES_NCG*)snes->data;
71   PetscErrorCode ierr;
72   PetscBool      debug = PETSC_FALSE;
73   SNESLineSearch linesearch;
74   SNESNCGType    ncgtype=ncg->type;
75 
76   PetscFunctionBegin;
77   ierr = PetscOptionsHead(PetscOptionsObject,"SNES NCG options");CHKERRQ(ierr);
78   ierr = PetscOptionsBool("-snes_ncg_monitor","Monitor NCG iterations","SNES",ncg->monitor ? PETSC_TRUE : PETSC_FALSE, &debug, NULL);CHKERRQ(ierr);
79   if (debug) {
80     ncg->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr);
81   }
82   ierr = PetscOptionsEnum("-snes_ncg_type","NCG Beta type used","SNESNCGSetType",SNESNCGTypes,(PetscEnum)ncg->type,(PetscEnum*)&ncgtype,NULL);CHKERRQ(ierr);
83   ierr = SNESNCGSetType(snes, ncgtype);CHKERRQ(ierr);
84   ierr = PetscOptionsTail();CHKERRQ(ierr);
85   if (!snes->linesearch) {
86     ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr);
87     if (!snes->pc) {
88       ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHCP);CHKERRQ(ierr);
89     } else {
90       ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr);
91     }
92   }
93   ierr = SNESLineSearchRegister(SNESLINESEARCHNCGLINEAR, SNESLineSearchCreate_NCGLinear);CHKERRQ(ierr);
94   PetscFunctionReturn(0);
95 }
96 
97 /*
98   SNESView_NCG - Prints info from the SNESNCG data structure.
99 
100   Input Parameters:
101 + SNES - the SNES context
102 - viewer - visualization context
103 
104   Application Interface Routine: SNESView()
105 */
106 #undef __FUNCT__
107 #define __FUNCT__ "SNESView_NCG"
108 static PetscErrorCode SNESView_NCG(SNES snes, PetscViewer viewer)
109 {
110   SNES_NCG      *ncg = (SNES_NCG *) snes->data;
111   PetscBool      iascii;
112   PetscErrorCode ierr;
113 
114   PetscFunctionBegin;
115   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
116   if (iascii) {
117     ierr = PetscViewerASCIIPrintf(viewer, "ncg type: %s\n", SNESNCGTypes[ncg->type]);CHKERRQ(ierr);
118   }
119   PetscFunctionReturn(0);
120 }
121 
122 #undef __FUNCT__
123 #define __FUNCT__ "SNESLineSearchApply_NCGLinear"
124 PetscErrorCode SNESLineSearchApply_NCGLinear(SNESLineSearch linesearch)
125 {
126   PetscScalar    alpha, ptAp;
127   Vec            X, Y, F, W;
128   SNES           snes;
129   PetscErrorCode ierr;
130   PetscReal      *fnorm, *xnorm, *ynorm;
131 
132   PetscFunctionBegin;
133   ierr  = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr);
134   X     = linesearch->vec_sol;
135   W     = linesearch->vec_sol_new;
136   F     = linesearch->vec_func;
137   Y     = linesearch->vec_update;
138   fnorm = &linesearch->fnorm;
139   xnorm = &linesearch->xnorm;
140   ynorm = &linesearch->ynorm;
141 
142   if (!snes->jacobian) {
143     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
144   }
145 
146   /*
147 
148    The exact step size for unpreconditioned linear CG is just:
149    alpha = (r, r) / (p, Ap) = (f, f) / (y, Jy)
150    */
151   ierr  = SNESComputeJacobian(snes, X, snes->jacobian, snes->jacobian_pre);CHKERRQ(ierr);
152   ierr  = VecDot(F, F, &alpha);CHKERRQ(ierr);
153   ierr  = MatMult(snes->jacobian, Y, W);CHKERRQ(ierr);
154   ierr  = VecDot(Y, W, &ptAp);CHKERRQ(ierr);
155   alpha = alpha / ptAp;
156   ierr  = VecAXPY(X,-alpha,Y);CHKERRQ(ierr);
157   ierr  = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
158 
159   ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);
160   ierr = VecNorm(X,NORM_2,xnorm);CHKERRQ(ierr);
161   ierr = VecNorm(Y,NORM_2,ynorm);CHKERRQ(ierr);
162   PetscFunctionReturn(0);
163 }
164 
165 #undef __FUNCT__
166 #define __FUNCT__ "SNESLineSearchCreate_NCGLinear"
167 PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_NCGLinear(SNESLineSearch linesearch)
168 {
169   PetscFunctionBegin;
170   linesearch->ops->apply          = SNESLineSearchApply_NCGLinear;
171   linesearch->ops->destroy        = NULL;
172   linesearch->ops->setfromoptions = NULL;
173   linesearch->ops->reset          = NULL;
174   linesearch->ops->view           = NULL;
175   linesearch->ops->setup          = NULL;
176   PetscFunctionReturn(0);
177 }
178 
179 #undef __FUNCT__
180 #define __FUNCT__ "SNESNCGComputeYtJtF_Private"
181 /*
182 
183  Assuming F = SNESComputeFunction(X) compute Y^tJ^tF using a simple secant approximation of the jacobian.
184 
185  */
186 PetscErrorCode SNESNCGComputeYtJtF_Private(SNES snes, Vec X, Vec F, Vec Y, Vec W, Vec G, PetscScalar * ytJtf)
187 {
188   PetscErrorCode ierr;
189   PetscScalar    ftf, ftg, fty, h;
190 
191   PetscFunctionBegin;
192   ierr   = VecDot(F, F, &ftf);CHKERRQ(ierr);
193   ierr   = VecDot(F, Y, &fty);CHKERRQ(ierr);
194   h      = 1e-5*fty / fty;
195   ierr   = VecCopy(X, W);CHKERRQ(ierr);
196   ierr   = VecAXPY(W, -h, Y);CHKERRQ(ierr);          /* this is arbitrary */
197   ierr   = SNESComputeFunction(snes, W, G);CHKERRQ(ierr);
198   ierr   = VecDot(G, F, &ftg);CHKERRQ(ierr);
199   *ytJtf = (ftg - ftf) / h;
200   PetscFunctionReturn(0);
201 }
202 
203 #undef __FUNCT__
204 #define __FUNCT__ "SNESNCGSetType"
205 /*@
206     SNESNCGSetType - Sets the conjugate update type for SNESNCG.
207 
208     Logically Collective on SNES
209 
210     Input Parameters:
211 +   snes - the iterative context
212 -   btype - update type
213 
214     Options Database:
215 .   -snes_ncg_type<prp,fr,hs,dy,cd>
216 
217     Level: intermediate
218 
219     SNESNCGSelectTypes:
220 +   SNES_NCG_FR - Fletcher-Reeves update
221 .   SNES_NCG_PRP - Polak-Ribiere-Polyak update
222 .   SNES_NCG_HS - Hestenes-Steifel update
223 .   SNES_NCG_DY - Dai-Yuan update
224 -   SNES_NCG_CD - Conjugate Descent update
225 
226    Notes:
227    PRP is the default, and the only one that tolerates generalized search directions.
228 
229 .keywords: SNES, SNESNCG, selection, type, set
230 @*/
231 PetscErrorCode SNESNCGSetType(SNES snes, SNESNCGType btype)
232 {
233   PetscErrorCode ierr;
234 
235   PetscFunctionBegin;
236   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
237   ierr = PetscTryMethod(snes,"SNESNCGSetType_C",(SNES,SNESNCGType),(snes,btype));CHKERRQ(ierr);
238   PetscFunctionReturn(0);
239 }
240 
241 #undef __FUNCT__
242 #define __FUNCT__ "SNESNCGSetType_NCG"
243 PetscErrorCode SNESNCGSetType_NCG(SNES snes, SNESNCGType btype)
244 {
245   SNES_NCG *ncg = (SNES_NCG*)snes->data;
246 
247   PetscFunctionBegin;
248   ncg->type = btype;
249   PetscFunctionReturn(0);
250 }
251 
252 /*
253   SNESSolve_NCG - Solves a nonlinear system with the Nonlinear Conjugate Gradient method.
254 
255   Input Parameters:
256 . snes - the SNES context
257 
258   Output Parameter:
259 . outits - number of iterations until termination
260 
261   Application Interface Routine: SNESSolve()
262 */
263 #undef __FUNCT__
264 #define __FUNCT__ "SNESSolve_NCG"
265 PetscErrorCode SNESSolve_NCG(SNES snes)
266 {
267   SNES_NCG             *ncg = (SNES_NCG*)snes->data;
268   Vec                  X,dX,lX,F,dXold;
269   PetscReal            fnorm, ynorm, xnorm, beta = 0.0;
270   PetscScalar          dXdotdX, dXolddotdXold, dXdotdXold, lXdotdX, lXdotdXold;
271   PetscInt             maxits, i;
272   PetscErrorCode       ierr;
273   SNESLineSearchReason lsresult = SNES_LINESEARCH_SUCCEEDED;
274   SNESLineSearch       linesearch;
275   SNESConvergedReason  reason;
276 
277   PetscFunctionBegin;
278 
279   if (snes->xl || snes->xu || snes->ops->computevariablebounds) {
280     SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name);
281   }
282 
283   ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr);
284   snes->reason = SNES_CONVERGED_ITERATING;
285 
286   maxits = snes->max_its;            /* maximum number of iterations */
287   X      = snes->vec_sol;            /* X^n */
288   dXold  = snes->work[0];            /* The previous iterate of X */
289   dX     = snes->work[1];            /* the preconditioned direction */
290   lX     = snes->vec_sol_update;     /* the conjugate direction */
291   F      = snes->vec_func;           /* residual vector */
292 
293   ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr);
294 
295   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
296   snes->iter = 0;
297   snes->norm = 0.;
298   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
299 
300   /* compute the initial function and preconditioned update dX */
301 
302   if (snes->pc && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
303     ierr = SNESApplyNPC(snes,X,NULL,dX);CHKERRQ(ierr);
304     ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
305     if (reason < 0  && reason != SNES_DIVERGED_MAX_IT) {
306       snes->reason = SNES_DIVERGED_INNER;
307       PetscFunctionReturn(0);
308     }
309     ierr = VecCopy(dX,F);CHKERRQ(ierr);
310     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
311   } else {
312     if (!snes->vec_func_init_set) {
313       ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
314     } else snes->vec_func_init_set = PETSC_FALSE;
315 
316     /* convergence test */
317     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);
318     SNESCheckFunctionNorm(snes,fnorm);
319     ierr = VecCopy(F,dX);CHKERRQ(ierr);
320   }
321   if (snes->pc) {
322     if (snes->functype == SNES_FUNCTION_UNPRECONDITIONED) {
323       ierr = SNESApplyNPC(snes,X,F,dX);CHKERRQ(ierr);
324       ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
325       if (reason < 0  && reason != SNES_DIVERGED_MAX_IT) {
326         snes->reason = SNES_DIVERGED_INNER;
327         PetscFunctionReturn(0);
328       }
329     }
330   }
331   ierr = VecCopy(dX,lX);CHKERRQ(ierr);
332   ierr = VecDot(dX, dX, &dXdotdX);CHKERRQ(ierr);
333 
334 
335   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
336   snes->norm = fnorm;
337   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
338   ierr       = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr);
339   ierr       = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
340 
341   /* test convergence */
342   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
343   if (snes->reason) PetscFunctionReturn(0);
344 
345   /* Call general purpose update function */
346   if (snes->ops->update) {
347     ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
348   }
349 
350   /* first update -- just use the (preconditioned) residual direction for the initial conjugate direction */
351 
352   for (i = 1; i < maxits + 1; i++) {
353     /* some update types require the old update direction or conjugate direction */
354     if (ncg->type != SNES_NCG_FR) {
355       ierr = VecCopy(dX, dXold);CHKERRQ(ierr);
356     }
357     ierr = SNESLineSearchApply(linesearch,X,F,&fnorm,lX);CHKERRQ(ierr);
358     ierr = SNESLineSearchGetReason(linesearch, &lsresult);CHKERRQ(ierr);
359     ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr);
360     if (lsresult) {
361       if (++snes->numFailures >= snes->maxFailures) {
362         snes->reason = SNES_DIVERGED_LINE_SEARCH;
363         PetscFunctionReturn(0);
364       }
365     }
366     if (snes->nfuncs >= snes->max_funcs) {
367       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
368       PetscFunctionReturn(0);
369     }
370     /* Monitor convergence */
371     ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
372     snes->iter = i;
373     snes->norm = fnorm;
374     ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
375     ierr       = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr);
376     ierr       = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
377 
378     /* Test for convergence */
379     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
380     if (snes->reason) PetscFunctionReturn(0);
381 
382     /* Call general purpose update function */
383     if (snes->ops->update) {
384       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
385     }
386     if (snes->pc) {
387       if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
388         ierr = SNESApplyNPC(snes,X,NULL,dX);CHKERRQ(ierr);
389         ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
390         if (reason < 0  && reason != SNES_DIVERGED_MAX_IT) {
391           snes->reason = SNES_DIVERGED_INNER;
392           PetscFunctionReturn(0);
393         }
394         ierr = VecCopy(dX,F);CHKERRQ(ierr);
395       } else {
396         ierr = SNESApplyNPC(snes,X,F,dX);CHKERRQ(ierr);
397         ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr);
398         if (reason < 0  && reason != SNES_DIVERGED_MAX_IT) {
399           snes->reason = SNES_DIVERGED_INNER;
400           PetscFunctionReturn(0);
401         }
402       }
403     } else {
404       ierr = VecCopy(F,dX);CHKERRQ(ierr);
405     }
406 
407     /* compute the conjugate direction lX = dX + beta*lX with beta = ((dX, dX) / (dX_old, dX_old) (Fletcher-Reeves update)*/
408     switch (ncg->type) {
409     case SNES_NCG_FR: /* Fletcher-Reeves */
410       dXolddotdXold= dXdotdX;
411       ierr         = VecDot(dX, dX, &dXdotdX);CHKERRQ(ierr);
412       beta         = PetscRealPart(dXdotdX / dXolddotdXold);
413       break;
414     case SNES_NCG_PRP: /* Polak-Ribiere-Poylak */
415       dXolddotdXold= dXdotdX;
416       ierr         = VecDotBegin(dX, dX, &dXdotdXold);CHKERRQ(ierr);
417       ierr         = VecDotBegin(dXold, dX, &dXdotdXold);CHKERRQ(ierr);
418       ierr         = VecDotEnd(dX, dX, &dXdotdX);CHKERRQ(ierr);
419       ierr         = VecDotEnd(dXold, dX, &dXdotdXold);CHKERRQ(ierr);
420       beta         = PetscRealPart(((dXdotdX - dXdotdXold) / dXolddotdXold));
421       if (beta < 0.0) beta = 0.0; /* restart */
422       break;
423     case SNES_NCG_HS: /* Hestenes-Stiefel */
424       ierr = VecDotBegin(dX, dX, &dXdotdX);CHKERRQ(ierr);
425       ierr = VecDotBegin(dX, dXold, &dXdotdXold);CHKERRQ(ierr);
426       ierr = VecDotBegin(lX, dX, &lXdotdX);CHKERRQ(ierr);
427       ierr = VecDotBegin(lX, dXold, &lXdotdXold);CHKERRQ(ierr);
428       ierr = VecDotEnd(dX, dX, &dXdotdX);CHKERRQ(ierr);
429       ierr = VecDotEnd(dX, dXold, &dXdotdXold);CHKERRQ(ierr);
430       ierr = VecDotEnd(lX, dX, &lXdotdX);CHKERRQ(ierr);
431       ierr = VecDotEnd(lX, dXold, &lXdotdXold);CHKERRQ(ierr);
432       beta = PetscRealPart((dXdotdX - dXdotdXold) / (lXdotdX - lXdotdXold));
433       break;
434     case SNES_NCG_DY: /* Dai-Yuan */
435       ierr = VecDotBegin(dX, dX, &dXdotdX);CHKERRQ(ierr);
436       ierr = VecDotBegin(lX, dX, &lXdotdX);CHKERRQ(ierr);
437       ierr = VecDotBegin(lX, dXold, &lXdotdXold);CHKERRQ(ierr);
438       ierr = VecDotEnd(dX, dX, &dXdotdX);CHKERRQ(ierr);
439       ierr = VecDotEnd(lX, dX, &lXdotdX);CHKERRQ(ierr);
440       ierr = VecDotEnd(lX, dXold, &lXdotdXold);CHKERRQ(ierr);
441       beta = PetscRealPart(dXdotdX / (lXdotdXold - lXdotdX));CHKERRQ(ierr);
442       break;
443     case SNES_NCG_CD: /* Conjugate Descent */
444       ierr = VecDotBegin(dX, dX, &dXdotdX);CHKERRQ(ierr);
445       ierr = VecDotBegin(lX, dXold, &lXdotdXold);CHKERRQ(ierr);
446       ierr = VecDotEnd(dX, dX, &dXdotdX);CHKERRQ(ierr);
447       ierr = VecDotEnd(lX, dXold, &lXdotdXold);CHKERRQ(ierr);
448       beta = PetscRealPart(dXdotdX / lXdotdXold);CHKERRQ(ierr);
449       break;
450     }
451     if (ncg->monitor) {
452       ierr = PetscViewerASCIIPrintf(ncg->monitor, "beta = %e\n", (double)beta);CHKERRQ(ierr);
453     }
454     ierr = VecAYPX(lX, beta, dX);CHKERRQ(ierr);
455   }
456   ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr);
457   if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
458   PetscFunctionReturn(0);
459 }
460 
461 
462 
463 /*MC
464   SNESNCG - Nonlinear Conjugate-Gradient method for the solution of general nonlinear systems.
465 
466   Level: beginner
467 
468   Options Database:
469 +   -snes_ncg_type <fr, prp, dy, hs, cd> - Choice of conjugate-gradient update parameter.
470 .   -snes_linesearch_type <cp,l2,basic> - Line search type.
471 -   -snes_ncg_monitor - Print relevant information about the ncg iteration.
472 
473 Notes: This solves the nonlinear system of equations F(x) = 0 using the nonlinear generalization of the conjugate
474 gradient method.  This may be used with a nonlinear preconditioner used to pick the new search directions, but otherwise
475 chooses the initial search direction as F(x) for the initial guess x.
476 
477 The default type is PRP.
478 
479 
480 .seealso:  SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESNEWTONTR, SNESNGMRES, SNESNQN
481 M*/
482 #undef __FUNCT__
483 #define __FUNCT__ "SNESCreate_NCG"
484 PETSC_EXTERN PetscErrorCode SNESCreate_NCG(SNES snes)
485 {
486   PetscErrorCode ierr;
487   SNES_NCG       * neP;
488 
489   PetscFunctionBegin;
490   snes->ops->destroy        = SNESDestroy_NCG;
491   snes->ops->setup          = SNESSetUp_NCG;
492   snes->ops->setfromoptions = SNESSetFromOptions_NCG;
493   snes->ops->view           = SNESView_NCG;
494   snes->ops->solve          = SNESSolve_NCG;
495   snes->ops->reset          = SNESReset_NCG;
496 
497   snes->usesksp = PETSC_FALSE;
498   snes->usespc  = PETSC_TRUE;
499   snes->pcside  = PC_LEFT;
500 
501   if (!snes->tolerancesset) {
502     snes->max_funcs = 30000;
503     snes->max_its   = 10000;
504     snes->stol      = 1e-20;
505   }
506 
507   ierr         = PetscNewLog(snes,&neP);CHKERRQ(ierr);
508   snes->data   = (void*) neP;
509   neP->monitor = NULL;
510   neP->type    = SNES_NCG_PRP;
511   ierr         = PetscObjectComposeFunction((PetscObject)snes,"SNESNCGSetType_C", SNESNCGSetType_NCG);CHKERRQ(ierr);
512   PetscFunctionReturn(0);
513 }
514