NLSL
mnbrak.f90
Go to the documentation of this file.
1  subroutine mnbrak(ax,bx,cx,fa,fb,fc,func,iflag,bound)
2 c
3  use errmsg
4 c
5  implicit none
6  double precision ax,bx,cx,fa,fb,fc,func,bound
7  integer iflag
8  external func
9 c
10  double precision dum,fu,plim,r,q,u,ulim
11 c
12  double precision GLIMIT,GOLD,TINY
13  parameter(gold=1.618034d0,glimit=100.0d0,tiny=1.0d-20)
14 c
15 c -- Evaluate function at points a and b
16 c
17  fa=func(ax,iflag)
18  if (iflag.lt.0) return
19 c
20  fb=func(bx,iflag)
21  if (iflag.lt.0) return
22 c
23 c -- Rearrange the two points so that a to b is always "downhill"
24 c Set parameter search boundary along this direction
25 c
26  if(fb.gt.fa)then
27  dum=ax
28  ax=bx
29  bx=dum
30  dum=fb
31  fb=fa
32  fa=dum
33  plim=bx+sign(bound,bx-ax)
34  else
35  plim=ax+sign(bound,bx-ax)
36  end if
37 c
38 c Choose a third point using golden ratio
39 c
40  cx=bx+gold*(bx-ax)
41 c
42  fc=func(cx,iflag)
43  if (iflag.lt.0) return
44 c
45 c==================================================
46 c Main loop: do while f(B) > f(C)
47 c (if f(B) < f(C), we're done!)
48 c==================================================
49 c
50  1 if (fb.ge.fc) then
51 c
52 c ----------------------------------------------------
53 c Check that the point with the lowest function value
54 c does not go beyond the initial step bound
55 c ----------------------------------------------------
56  if ((cx-ax)*(plim-cx).le.0.) then
57  iflag=nomin
58  return
59  end if
60 c
61 c -----------------------------------------------
62 c Take parabolic step based on three known points
63 c -----------------------------------------------
64  r=(bx-ax)*(fb-fc)
65  q=(bx-cx)*(fb-fa)
66  u=bx-((bx-cx)*q-(bx-ax)*r)/(2.*sign(max(abs(q-r),tiny),q-r))
67 c
68 c ---------------------------------------------------------------
69 c Choose a limit that is the smaller of the parabolic step limit
70 c and the step bound from the initial point (ax)
71 c ----------------------------------------------------------------
72  ulim=bx+glimit*(cx-bx)
73  if ((ulim-ax)*(plim-ulim).lt.0.) ulim=plim
74 c
75 c --------------------------------
76 c Step is between B and C: try it
77 c --------------------------------
78  if((bx-u)*(u-cx).gt.0.)then
79  fu=func(u,iflag)
80  if (iflag.lt.0) return
81 c
82 c ---------------------------------------
83 c U is a minimum: bracket is B,U,C (exit)
84 c ---------------------------------------
85  if(fu.lt.fc)then
86  ax=bx
87  fa=fb
88  bx=u
89  fb=fu
90  go to 1
91 c
92 c -----------------------------------
93 c f(U)>f(B): bracket is A,B,U (exit)
94 c -----------------------------------
95  else if(fu.gt.fb)then
96  cx=u
97  fc=fu
98  go to 1
99  endif
100 c
101 c ------------------------------------------------------
102 c Have f(A) > f(B) > f(U) > f(C). Try stepping further.
103 c ------------------------------------------------------
104  u=cx+gold*(cx-bx)
105  fu=func(u,iflag)
106  if (iflag.lt.0) return
107 c
108 c ------------------------------------------------
109 c Step is between C and its allowed limit: try it
110 c ------------------------------------------------
111  else if((cx-u)*(u-ulim).gt.0.)then
112  fu=func(u,iflag)
113  if (iflag.lt.0) return
114 c
115 c -------------------------------------------------------
116 c Have f(A) > f(B) > f(C) > f(U): reset upper bound to B
117 c -------------------------------------------------------
118  if(fu.lt.fc)then
119  bx=cx
120  cx=u
121  u=cx+gold*(cx-bx)
122  fb=fc
123  fc=fu
124  fu=func(u,iflag)
125  if (iflag.lt.0) return
126  endif
127 c
128 c -----------------------------------------------------------
129 c Step went beyond the limiting value: try function at limit
130 c -----------------------------------------------------------
131  else if((u-ulim)*(ulim-cx).ge.0.)then
132  u=ulim
133  fu=func(u,iflag)
134  if (iflag.lt.0) return
135 c
136 c ------------------------------------------------------------
137 c Reject parabolic step and use golden section magnification
138 c ------------------------------------------------------------
139  else
140  u=cx+gold*(cx-bx)
141  if ((u-ulim)*(ulim-cx).ge.0.) u=ulim
142  fu=func(u,iflag)
143  if (iflag.lt.0) return
144  endif
145 c
146 c ---------------------------------
147 c Discard oldest point and continue
148 c ---------------------------------
149  ax=bx
150  bx=cx
151  cx=u
152  fa=fb
153  fb=fc
154  fc=fu
155  go to 1
156  endif
157 c
158  iflag=0
159  return
160  end
integer, parameter nomin
Definition: errmsg.f90:51
subroutine mnbrak(ax, bx, cx, fa, fb, fc, func, iflag, bound)
Definition: mnbrak.f90:2