Actual source code: umls.c
1: /*$Id: umls.c,v 1.112 2001/08/07 21:31:11 bsmith Exp $*/
3: #include src/snes/impls/umls/umls.h
5: EXTERN int SNESStep(SNES,PetscReal*,PetscReal*,PetscReal*,PetscReal*,
6: PetscReal*,PetscReal*,PetscReal*,PetscReal*,PetscReal*);
8: /*
9: Implements Newton's Method with a line search approach
10: for solving unconstrained minimization problems.
12: Note:
13: The line search algorithm is taken from More and Thuente,
14: "Line search algorithms with guaranteed sufficient decrease",
15: Argonne National Laboratory, Technical Report MCS-P330-1092.
16: */
18: static int SNESSolve_UM_LS(SNES snes,int *outits)
19: {
20: SNES_UM_LS *neP = (SNES_UM_LS*)snes->data;
21: int maxits,success,iters,i,global_dim,ierr,kspmaxit;
22: PetscReal snorm,*f,*gnorm,two = 2.0,tnorm;
23: PetscScalar neg_one = -1.0;
24: Vec G,X,RHS,S,W;
25: SLES sles;
26: KSP ksp;
27: MatStructure flg = DIFFERENT_NONZERO_PATTERN;
28: SNESConvergedReason reason;
29: KSPConvergedReason kreason;
32: snes->reason = SNES_CONVERGED_ITERATING;
34: maxits = snes->max_its; /* maximum number of iterations */
35: X = snes->vec_sol; /* solution vector */
36: G = snes->vec_func; /* gradient vector */
37: RHS = snes->work[0]; /* work vectors */
38: S = snes->work[1]; /* step vector */
39: W = snes->work[2]; /* work vector */
40: f = &(snes->fc); /* function to minimize */
41: gnorm = &(snes->norm); /* gradient norm */
43: PetscObjectTakeAccess(snes);
44: snes->iter = 0;
45: PetscObjectGrantAccess(snes);
46: SNESComputeMinimizationFunction(snes,X,f); /* f(X) */
47: SNESComputeGradient(snes,X,G); /* G(X) <- gradient */
49: PetscObjectTakeAccess(snes);
50: VecNorm(G,NORM_2,gnorm); /* gnorm = || G || */
51: PetscObjectGrantAccess(snes);
52: SNESLogConvHistory(snes,*gnorm,0);
53: SNESMonitor(snes,0,*gnorm);
55: SNESGetSLES(snes,&sles);
56: SLESGetKSP(sles,&ksp);
57: VecGetSize(X,&global_dim);
58: kspmaxit = neP->max_kspiter_factor * ((int)sqrt((PetscReal)global_dim));
59: KSPSetTolerances(ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,kspmaxit);
61: for (i=0; i<maxits; i++) {
62: PetscObjectTakeAccess(snes);
63: snes->iter = i+1;
64: PetscObjectGrantAccess(snes);
65: neP->gamma = neP->gamma_factor*(*gnorm);
66: success = 0;
67: VecCopy(G,RHS);
68: VecScale(&neg_one,RHS);
69: SNESComputeHessian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);
70: SLESSetOperators(snes->sles,snes->jacobian,snes->jacobian_pre,flg);
71: while (!success) {
72: SLESSolve(snes->sles,RHS,S,&iters);
73: snes->linear_its += iters;
74: KSPGetConvergedReason(ksp,&kreason);
75: if ((int)kreason < 0 || (iters >= kspmaxit)) { /* Modify diagonal of Hessian */
76: neP->gamma_factor *= two;
77: neP->gamma = neP->gamma_factor*(*gnorm);
78: #if !defined(PETSC_USE_COMPLEX)
79: PetscLogInfo(snes,"SNESSolve_UM_LS: modify diagonal (assume same nonzero structure), gamma_factor=%g, gamma=%gn",
80: neP->gamma_factor,neP->gamma);
81: #else
82: PetscLogInfo(snes,"SNESSolve_UM_LS: modify diagonal (asuume same nonzero structure), gamma_factor=%g, gamma=%gn",
83: neP->gamma_factor,PetscRealPart(neP->gamma));
84: #endif
85: MatShift(&neP->gamma,snes->jacobian);
86: if ((snes->jacobian_pre != snes->jacobian) && (flg != SAME_PRECONDITIONER)){
87: MatShift(&neP->gamma,snes->jacobian_pre);
88: }
89: /* We currently assume that all diagonal elements were allocated in
90: original matrix, so that nonzero pattern is same ... should fix this */
91: SLESSetOperators(snes->sles,snes->jacobian,snes->jacobian_pre,
92: SAME_NONZERO_PATTERN);
93: } else {
94: success = 1;
95: }
96: }
97: VecNorm(S,NORM_2,&snorm);
99: /* Line search */
100: neP->step = 1.0;
101: (*neP->LineSearch)(snes,X,G,S,W,f,&(neP->step),&tnorm,&(neP->line));
102: PetscObjectTakeAccess(snes);
103: snes->norm = tnorm;
104: PetscObjectGrantAccess(snes);
105: if (neP->line != 1) snes->numFailures++;
107: SNESLogConvHistory(snes,*gnorm,iters);
108: SNESMonitor(snes,i+1,*gnorm);
109: PetscLogInfo(snes,"SNESSolve_UM_LS: %d: f=%g, gnorm=%g, snorm=%g, step=%g, KSP iters=%dn",
110: snes->iter,*f,*gnorm,snorm,neP->step,iters);
112: /* Test for convergence */
113: (*snes->converged)(snes,snorm,*gnorm,*f,&reason,snes->cnvP);
114: if (reason) break;
115: neP->gamma_factor /= two;
116: }
117: /* Verify solution is in correct location */
118: if (X != snes->vec_sol) {
119: VecCopy(X,snes->vec_sol);
120: snes->vec_sol_always = snes->vec_sol;
121: snes->vec_func_always = snes->vec_func;
122: }
123: if (i == maxits) {
124: PetscLogInfo(snes,"SNESSolve_UM_LS: Maximum number of iterations reached: %dn",maxits);
125: i--;
126: reason = SNES_DIVERGED_MAX_IT;
127: }
128: PetscObjectTakeAccess(snes);
129: snes->reason = reason;
130: PetscObjectGrantAccess(snes);
131: *outits = i+1;
132: return(0);
133: }
134: /* ---------------------------------------------------------- */
135: static int SNESSetUp_UM_LS(SNES snes)
136: {
137: int ierr;
138: PetscTruth ilu,bjacobi;
139: SLES sles;
140: PC pc;
143: snes->nwork = 4;
144: VecDuplicateVecs(snes->vec_sol,snes->nwork,&snes->work);
145: PetscLogObjectParents(snes,snes->nwork,snes->work);
146: snes->vec_sol_update_always = snes->work[3];
148: /*
149: If PC was set by default to ILU then change it to Jacobi
150: */
151: SNESGetSLES(snes,&sles);
152: SLESGetPC(sles,&pc);
153: PetscTypeCompare((PetscObject)pc,PCILU,&ilu);
154: if (ilu) {
155: PCSetType(pc,PCJACOBI);
156: } else {
157: PetscTypeCompare((PetscObject)pc,PCBJACOBI,&bjacobi);
158: if (bjacobi) {
159: /* cannot do this; since PC may not have been setup yet */
160: /* PCBJacobiGetSubSLES(pc,0,0,&subsles);
161: SLESGetPC(*subsles,&subpc);
162: PetscTypeCompare((PetscObject)subpc,PCILU,&ilu);
163: if (ilu) {
164: PCSetType(pc,PCJACOBI);
165: } */
166: /* don't really want to do this, since user may have selected BJacobi plus something
167: that is symmetric on each processor; really only want to catch the default ILU */
168: PCSetType(pc,PCJACOBI);
169: }
170: }
172: return(0);
173: }
174: /*------------------------------------------------------------*/
175: static int SNESDestroy_UM_LS(SNES snes)
176: {
177: int ierr;
180: if (snes->nwork) {
181: VecDestroyVecs(snes->work,snes->nwork);
182: }
183: PetscFree(snes->data);
184: return(0);
185: }
186: /*------------------------------------------------------------*/
187: static int SNESSetFromOptions_UM_LS(SNES snes)
188: {
189: SNES_UM_LS *ctx = (SNES_UM_LS *)snes->data;
190: int ierr;
191: SLES sles;
192: PC pc;
193: PetscTruth ismatshell,nopcset;
194: Mat pmat;
197: PetscOptionsHead("SNES trust region options for minimization");
198: PetscOptionsReal("-snes_um_ls_gamma_factor","Damping parameter","None",ctx->gamma_factor,&ctx->gamma_factor,0);
199: PetscOptionsInt("-snes_um_ls_maxfev","Max function evaluation in line search","None",ctx->maxfev,&ctx->maxfev,0);
200: PetscOptionsReal("-snes_um_ls_ftol","Tolerance for sufficient decrease","None",ctx->ftol,&ctx->ftol,0);
201: PetscOptionsReal("-snes_um_ls_gtol","Tolerance for curvature condition","None",ctx->gtol,&ctx->gtol,0);
202: PetscOptionsReal("-snes_um_ls_rtol","Relative tolerance for acceptable step","None",ctx->rtol,&ctx->rtol,0);
203: PetscOptionsReal("-snes_um_ls_stepmin","Lower bound for step","None",ctx->stepmin,&ctx->stepmin,0);
204: PetscOptionsReal("-snes_um_ls_stepmax","upper bound for step","None",ctx->stepmax,&ctx->stepmax,0);
205: PetscOptionsTail();
206: /* if preconditioner has not been set yet, and not using a matrix shell then
207: set preconditioner to Jacobi. This is to prevent PCSetFromOptions() from
208: setting a default of ILU or block Jacobi-ILU which won't work since TR
209: requires a symmetric preconditioner
210: */
211: SNESGetSLES(snes,&sles);
212: SLESGetPC(sles,&pc);
213: PetscTypeCompare((PetscObject)pc,0,&nopcset);
214: if (nopcset) {
215: PCGetOperators(pc,PETSC_NULL,&pmat,PETSC_NULL);
216: if (pmat) {
217: PetscTypeCompare((PetscObject)pmat,MATSHELL,&ismatshell);
218: if (!ismatshell) {
219: PCSetType(pc,PCJACOBI);
220: }
221: }
222: }
223: return(0);
224: }
226: /*------------------------------------------------------------*/
227: static int SNESView_UM_LS(SNES snes,PetscViewer viewer)
228: {
229: SNES_UM_LS *ls = (SNES_UM_LS *)snes->data;
230: int ierr;
231: PetscTruth isascii;
234: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
235: if (isascii) {
236: PetscViewerASCIIPrintf(viewer," gamma_f=%g, maxf=%d, maxkspf=%d, ftol=%g, rtol=%g, gtol=%gn",
237: ls->gamma_factor,ls->maxfev,ls->max_kspiter_factor,ls->ftol,ls->rtol,ls->gtol);
238: } else {
239: SETERRQ1(1,"Viewer type %s not supported for SNES UM LS",((PetscObject)viewer)->type_name);
240: }
241: return(0);
242: }
243: /* ---------------------------------------------------------- */
244: /*@C
245: SNESConverged_UM_LS - Monitors the convergence of the SNESSolve_UM_LS()
246: routine (default).
248: Collective on SNES
250: Input Parameters:
251: + snes - the SNES context
252: . xnorm - 2-norm of current iterate
253: . gnorm - 2-norm of current gradient
254: . f - objective function value
255: - dummy - unused dummy context
257: Output Parameter:
258: . reason - one of
259: $ SNES_CONVERGED_FNORM_ABS (F < F_minabs),
260: $ SNES_CONVERGED_GNORM_ABS (grad F < grad),
261: $ SNES_DIVERGED_FUNCTION_COUNT (nfunc > max_func),
262: $ SNES_DIVERGED_LS_FAILURE (line search attempt failed)
263: $ SNES_DIVERGED_FNORM_NAN (f = NaN),
264: $ SNES_CONVERGED_ITERATING otherwise
266: where
267: + atol - absolute gradient norm tolerance, set with SNESSetTolerances()
268: . fmin - lower bound on function value, set with SNESSetMinimizationFunctionTolerance()
269: . max_func - maximum number of function evaluations, set with SNESSetTolerances()
270: - nfunc - number of function evaluations
272: Level: intermediate
274: @*/
275: int SNESConverged_UM_LS(SNES snes,PetscReal xnorm,PetscReal gnorm,PetscReal f,SNESConvergedReason *reason,void *dummy)
276: {
277: SNES_UM_LS *neP = (SNES_UM_LS*)snes->data;
281: if (f != f) {
282: PetscLogInfo(snes,"SNESConverged_UM_LS:Failed to converged, function is NaNn");
283: *reason = SNES_DIVERGED_FNORM_NAN;
284: } else if (f < snes->fmin) {
285: PetscLogInfo(snes,"SNESConverged_UM_LS: Converged due to function value %g < minimum function value %gn",
286: f,snes->fmin);
287: *reason = SNES_CONVERGED_FNORM_ABS ;
288: } else if (gnorm < snes->atol) {
289: PetscLogInfo(snes,"SNESConverged_UM_LS: Converged due to gradient norm %g < %gn",gnorm,snes->atol);
290: *reason = SNES_CONVERGED_GNORM_ABS;
291: } else if (snes->nfuncs > snes->max_funcs) {
292: PetscLogInfo(snes,"SNESConverged_UM_LS: Exceeded maximum number of function evaluations: %d > %dn",
293: snes->nfuncs,snes->max_funcs);
294: *reason = SNES_DIVERGED_FUNCTION_COUNT;
295: } else if (neP->line != 1) {
296: PetscLogInfo(snes,"SNESConverged_UM_LS: Line search failed for above reasonn");
297: *reason = SNES_DIVERGED_LS_FAILURE;
298: } else {
299: *reason = SNES_CONVERGED_ITERATING;
300: }
301: return(0);
302: }
303: /* ---------------------------------------------------------- */
304: /* @ SNESMoreLineSearch - This routine performs a line search algorithm,
305: taken from More and Thuente, "Line search algorithms with
306: guaranteed sufficient decrease", Argonne National Laboratory",
307: Technical Report MCS-P330-1092.
309: Input Parameters:
310: + snes - SNES context
311: . X - current iterate (on output X contains new iterate, X + step*S)
312: . S - search direction
313: . f - objective function evaluated at X
314: . G - gradient evaluated at X
315: . W - work vector
316: - step - initial estimate of step length
318: Output parameters:
319: + f - objective function evaluated at new iterate, X + step*S
320: . G - gradient evaluated at new iterate, X + step*S
321: . X - new iterate
322: . gnorm - 2-norm of G
323: - step - final step length
325: Info is set to one of:
326: . 1 - the line search succeeds; the sufficient decrease
327: condition and the directional derivative condition hold
329: negative number if an input parameter is invalid
330: . -1 - step < 0
331: . -2 - ftol < 0
332: . -3 - rtol < 0
333: . -4 - gtol < 0
334: . -5 - stepmin < 0
335: . -6 - stepmax < stepmin
336: - -7 - maxfev < 0
338: positive number > 1 if the line search otherwise terminates
339: + 2 - Relative width of the interval of uncertainty is
340: at most rtol.
341: . 3 - Maximum number of function evaluations (maxfev) has
342: been reached.
343: . 4 - Step is at the lower bound, stepmin.
344: . 5 - Step is at the upper bound, stepmax.
345: . 6 - Rounding errors may prevent further progress.
346: There may not be a step that satisfies the
347: sufficient decrease and curvature conditions.
348: Tolerances may be too small.
349: + 7 - Search direction is not a descent direction.
351: Notes:
352: This routine is used within the SNESUMLS method.
353: @ */
354: int SNESMoreLineSearch(SNES snes,Vec X,Vec G,Vec S,Vec W,PetscReal *f,
355: PetscReal *step,PetscReal *gnorm,int *info)
356: {
357: SNES_UM_LS *neP = (SNES_UM_LS*)snes->data;
358: PetscReal zero = 0.0,two = 2.0,p5 = 0.5,p66 = 0.66,xtrapf = 4.0;
359: PetscReal finit,width,width1,dginit,fm,fxm,fym,dgm,dgxm,dgym;
360: PetscReal dgx,dgy,dg,fx,fy,stx,sty,dgtest,ftest1;
361: int ierr,i,stage1;
362: #if defined(PETSC_USE_COMPLEX)
363: PetscScalar cdginit,cdg,cstep = 0.0;
364: #endif
367: /* neP->stepmin - lower bound for step */
368: /* neP->stepmax - upper bound for step */
369: /* neP->rtol - relative tolerance for an acceptable step */
370: /* neP->ftol - tolerance for sufficient decrease condition */
371: /* neP->gtol - tolerance for curvature condition */
372: /* neP->nfev - number of function evaluations */
373: /* neP->maxfev - maximum number of function evaluations */
375: /* Check input parameters for errors */
376: if (*step < zero) {
377: PetscLogInfo(snes,"SNESMoreLineSearch:Line search error: step (%g) < 0n",*step);
378: *info = -1; return(0);
379: } else if (neP->ftol < zero) {
380: PetscLogInfo(snes,"SNESMoreLineSearch:Line search error: ftol (%g) < 0n",neP->ftol);
381: *info = -2; return(0);
382: } else if (neP->rtol < zero) {
383: PetscLogInfo(snes,"SNESMoreLineSearch:Line search error: rtol (%g) < 0n",neP->rtol);
384: *info = -3; return(0);
385: } else if (neP->gtol < zero) {
386: PetscLogInfo(snes,"SNESMoreLineSearch:Line search error: gtol (%g) < 0n",neP->gtol);
387: *info = -4; return(0);
388: } else if (neP->stepmin < zero) {
389: PetscLogInfo(snes,"SNESMoreLineSearch:Line search error: stepmin (%g) < 0n",neP->stepmin);
390: *info = -5; return(0);
391: } else if (neP->stepmax < neP->stepmin) {
392: PetscLogInfo(snes,"SNESMoreLineSearch:Line search error: stepmax (%g) < stepmin (%g)n",
393: neP->stepmax,neP->stepmin);
394: *info = -6; return(0);
395: } else if (neP->maxfev < zero) {
396: PetscLogInfo(snes,"SNESMoreLineSearch:Line search error: maxfev (%d) < 0n",neP->maxfev);
397: *info = -7; return(0);
398: }
400: /* Check that search direction is a descent direction */
401: #if defined(PETSC_USE_COMPLEX)
402: VecDot(G,S,&cdginit); dginit = PetscRealPart(cdginit);
403: #else
404: VecDot(G,S,&dginit); /* dginit = G^T S */
405: #endif
406: if (dginit >= zero) {
407: PetscLogInfo(snes,"SNESMoreLineSearch:Search direction not a descent directionn");
408: *info = 7; return(0);
409: }
411: /* Initialization */
412: neP->bracket = 0;
413: *info = 0;
414: stage1 = 1;
415: finit = *f;
416: dgtest = neP->ftol * dginit;
417: width = neP->stepmax - neP->stepmin;
418: width1 = width * two;
419: VecCopy(X,W);
420: /* Variable dictionary:
421: stx, fx, dgx - the step, function, and derivative at the best step
422: sty, fy, dgy - the step, function, and derivative at the other endpoint
423: of the interval of uncertainty
424: step, f, dg - the step, function, and derivative at the current step */
426: stx = zero;
427: fx = finit;
428: dgx = dginit;
429: sty = zero;
430: fy = finit;
431: dgy = dginit;
432:
433: neP->nfev = 0;
434: for (i=0; i< neP->maxfev; i++) {
435: /* Set min and max steps to correspond to the interval of uncertainty */
436: if (neP->bracket) {
437: neP->stepmin = PetscMin(stx,sty);
438: neP->stepmax = PetscMax(stx,sty);
439: } else {
440: neP->stepmin = stx;
441: neP->stepmax = *step + xtrapf * (*step - stx);
442: }
444: /* Force the step to be within the bounds */
445: *step = PetscMax(*step,neP->stepmin);
446: *step = PetscMin(*step,neP->stepmax);
448: /* If an unusual termination is to occur, then let step be the lowest
449: point obtained thus far */
450: if (((neP->bracket) && (*step <= neP->stepmin || *step >= neP->stepmax)) ||
451: ((neP->bracket) && (neP->stepmax - neP->stepmin <= neP->rtol * neP->stepmax)) ||
452: (neP->nfev >= neP->maxfev - 1) || (neP->infoc == 0))
453: *step = stx;
455: #if defined(PETSC_USE_COMPLEX)
456: cstep = *step;
457: VecWAXPY(&cstep,S,W,X);
458: #else
459: VecWAXPY(step,S,W,X); /* X = W + step*S */
460: #endif
461: SNESComputeMinimizationFunction(snes,X,f);
462: neP->nfev++;
463: SNESComputeGradient(snes,X,G);
464: #if defined(PETSC_USE_COMPLEX)
465: VecDot(G,S,&cdg); dg = PetscRealPart(cdg);
466: #else
467: VecDot(G,S,&dg); /* dg = G^T S */
468: #endif
469: ftest1 = finit + *step * dgtest;
470:
471: /* Convergence testing */
472: if (((neP->bracket) && (*step <= neP->stepmin||*step >= neP->stepmax)) || (!neP->infoc)) {
473: *info = 6;
474: PetscLogInfo(snes,"SNESMoreLineSearch:Rounding errors may prevent further progress. May not be a step satisfyingn");
475: PetscLogInfo(snes,"SNESMoreLineSearch:sufficient decrease and curvature conditions. Tolerances may be too small.n");
476: }
477: if ((*step == neP->stepmax) && (*f <= ftest1) && (dg <= dgtest)) {
478: PetscLogInfo(snes,"SNESMoreLineSearch:Step is at the upper bound, stepmax (%g)n",neP->stepmax);
479: *info = 5;
480: }
481: if ((*step == neP->stepmin) && (*f >= ftest1) && (dg >= dgtest)) {
482: PetscLogInfo(snes,"SNESMoreLineSearch:Step is at the lower bound, stepmin (%g)n",neP->stepmin);
483: *info = 4;
484: }
485: if (neP->nfev >= neP->maxfev) {
486: PetscLogInfo(snes,"SNESMoreLineSearch:Number of line search function evals (%d) > maximum (%d)n",neP->nfev,neP->maxfev);
487: *info = 3;
488: }
489: if ((neP->bracket) && (neP->stepmax - neP->stepmin <= neP->rtol*neP->stepmax)){
490: PetscLogInfo(snes,"SNESMoreLineSearch:Relative width of interval of uncertainty is at most rtol (%g)n",neP->rtol);
491: *info = 2;
492: }
493: if ((*f <= ftest1) && (PetscAbsReal(dg) <= neP->gtol*(-dginit))) {
494: PetscLogInfo(snes,"SNESMoreLineSearch:Line search success: Sufficient decrease and directional deriv conditions holdn");
495: *info = 1;
496: }
497: if (*info) break;
499: /* In the first stage, we seek a step for which the modified function
500: has a nonpositive value and nonnegative derivative */
501: if ((stage1) && (*f <= ftest1) && (dg >= dginit * PetscMin(neP->ftol,neP->gtol)))
502: stage1 = 0;
504: /* A modified function is used to predict the step only if we
505: have not obtained a step for which the modified function has a
506: nonpositive function value and nonnegative derivative, and if a
507: lower function value has been obtained but the decrease is not
508: sufficient */
510: if ((stage1) && (*f <= fx) && (*f > ftest1)) {
511: fm = *f - *step * dgtest; /* Define modified function */
512: fxm = fx - stx * dgtest; /* and derivatives */
513: fym = fy - sty * dgtest;
514: dgm = dg - dgtest;
515: dgxm = dgx - dgtest;
516: dgym = dgy - dgtest;
518: /* Update the interval of uncertainty and compute the new step */
519: SNESStep(snes,&stx,&fxm,&dgxm,&sty,&fym,&dgym,step,&fm,&dgm);
521: fx = fxm + stx * dgtest; /* Reset the function and */
522: fy = fym + sty * dgtest; /* gradient values */
523: dgx = dgxm + dgtest;
524: dgy = dgym + dgtest;
525: } else {
526: /* Update the interval of uncertainty and compute the new step */
527: SNESStep(snes,&stx,&fx,&dgx,&sty,&fy,&dgy,step,f,&dg);
528: }
530: /* Force a sufficient decrease in the interval of uncertainty */
531: if (neP->bracket) {
532: if (PetscAbsReal(sty - stx) >= p66 * width1) *step = stx + p5*(sty - stx);
533: width1 = width;
534: width = PetscAbsReal(sty - stx);
535: }
536: }
538: /* Finish computations */
539: PetscLogInfo(snes,"SNESMoreLineSearch:%d function evals in line search, step = %10.4fn",neP->nfev,neP->step);
540: VecNorm(G,NORM_2,gnorm);
541: return(0);
542: }
544: EXTERN_C_BEGIN
545: int SNESLineSearchGetDampingParameter_UM_LS(SNES snes,PetscScalar *damp)
546: {
547: SNES_UM_LS *neP;
550: neP = (SNES_UM_LS*)snes->data;
551: *damp = neP->gamma;
552: return(0);
553: }
554: EXTERN_C_END
556: /* ---------------------------------------------------------- */
557: EXTERN_C_BEGIN
558: int SNESCreate_UM_LS(SNES snes)
559: {
560: SNES_UM_LS *neP;
561: int ierr;
564: if (snes->method_class != SNES_UNCONSTRAINED_MINIMIZATION) {
565: SETERRQ(PETSC_ERR_ARG_WRONG,"For SNES_UNCONSTRAINED_MINIMIZATION only");
566: }
567: snes->setup = SNESSetUp_UM_LS;
568: snes->solve = SNESSolve_UM_LS;
569: snes->destroy = SNESDestroy_UM_LS;
570: snes->converged = SNESConverged_UM_LS;
571: snes->view = SNESView_UM_LS;
572: snes->setfromoptions = SNESSetFromOptions_UM_LS;
573: snes->nwork = 0;
575: ierr = PetscNew(SNES_UM_LS,&neP);
576: PetscLogObjectMemory(snes,sizeof(SNES_UM_LS));
577: snes->data = (void*)neP;
578: neP->LineSearch = SNESMoreLineSearch;
579: neP->gamma = 0.0;
580: neP->gamma_factor = 0.005;
581: neP->max_kspiter_factor = 5;
582: neP->step = 1.0;
583: neP->ftol = 0.001;
584: neP->rtol = 1.0e-10;
585: neP->gtol = 0.90;
586: neP->stepmin = 1.0e-20;
587: neP->stepmax = 1.0e+20;
588: neP->nfev = 0;
589: neP->bracket = 0;
590: neP->infoc = 1;
591: neP->maxfev = 30;
593: PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchGetDampingParameter_C",
594: "SNESLineSearchGetDampingParameter_UM_LS",
595: SNESLineSearchGetDampingParameter_UM_LS);
597: return(0);
598: }
599: EXTERN_C_END
602: /* @
603: SNESLineSearchGetDampingParameter - Gets the damping parameter used within
604: the line search method SNESUMLS for unconstrained minimization.
606: Input Parameter:
607: . type - SNES method
609: Output Parameter:
610: . damp - the damping parameter
612: .keywords: SNES, nonlinear, get, line search, damping parameter
613: @ */
614: int SNESLineSearchGetDampingParameter(SNES snes,PetscScalar *damp)
615: {
616: int ierr,(*f)(SNES,PetscScalar *);
621: PetscObjectQueryFunction((PetscObject)snes,"SNESLineSearchGetDampingParameter_C",(void (**)(void))&f);
622: if (f) {
623: (*f)(snes,damp);
624: } else {
625: SETERRQ(1,"Can only get line search damping when line search algorithm used");
626: }
627: return(0);
628: }