V3FIT
lmpar.f
1  SUBROUTINE lmpar (n, r, ldr, ipvt, diag, qtb, delta, par, x,
2  1 sdiag, wa1, wa2)
3  USE stel_kinds
4  IMPLICIT NONE
5 C-----------------------------------------------
6 C D u m m y A r g u m e n t s
7 C-----------------------------------------------
8  INTEGER, INTENT(in) :: n, ldr, ipvt(n)
9  REAL(rprec), INTENT(in) :: delta
10  REAL(rprec), INTENT(inout) :: par
11  REAL(rprec), DIMENSION(ldr,n), INTENT(inout) :: r
12  REAL(rprec), DIMENSION(n) :: wa1, wa2
13  REAL(rprec), DIMENSION(n), INTENT(in) :: diag, qtb
14  REAL(rprec), DIMENSION(n), INTENT(out) :: x, sdiag
15 C-----------------------------------------------
16 C L o c a l P a r a m e t e r s
17 C-----------------------------------------------
18  REAL(rprec), PARAMETER :: p1=0.1_dp, zero = 0,
19  1 p001 = 0.001_dp
20 C-----------------------------------------------
21 C L o c a l V a r i a b l e s
22 C-----------------------------------------------
23  INTEGER :: iter, j, jm1, jp1, k, l, nsing
24  REAL(rprec) :: dxnorm, dwarf, fp, gnorm, parc, parl, paru,
25  1 sum0, enorm, dpmpar, temp, epsmch
26 C-----------------------------------------------
27 C E x t e r n a l F u n c t i o n s
28 C-----------------------------------------------
29  EXTERNAL dpmpar, enorm
30 C-----------------------------------------------
31 c
32 c SUBROUTINE lmpar
33 c
34 c given an m by n matrix a, an n by n nonsingular diagonal
35 c matrix d, an m-vector b, and a positive number delta,
36 c the problem is to determine a value for the parameter
37 c par such that IF x solves the system
38 c
39 c a*x = b , SQRT(par)*d*x = 0 ,
40 c
41 c in the least squares sense, and dxnorm is the euclidean
42 c norm of d*x, THEN either par is zero and
43 c
44 c (dxnorm-delta) .le. 0.1*delta ,
45 c
46 c or par is positive and
47 c
48 c ABS(dxnorm-delta) .le. 0.1*delta .
49 c
50 c this SUBROUTINE completes the solution of the problem
51 c IF it is provided with the necessary information from the
52 c qr factorization, with column pivoting, of a. that is, IF
53 c a*p = q*r, WHERE p is a permutation matrix, q has orthogonal
54 c columns, and r is an upper triangular matrix with diagonal
55 c elements of nonincreasing magnitude, THEN lmpar EXPects
56 c the full upper triangle of r, the permutation matrix p,
57 c and the first n components of (q TRANSPOSE)*b. on output
58 c lmpar also provides an upper triangular matrix s such that
59 c
60 c t t t
61 c p *(a *a + par*d*d)*p = s *s .
62 c
63 c s is employed within lmpar and may be of separate interest.
64 c
65 c ONLY a few iterations are generally needed for convergence
66 c of the algorithm. IF, however, the limit of 10 iterations
67 c is reached, THEN the output par will contain the best
68 c value obtained so far.
69 c
70 c the SUBROUTINE statement is
71 c
72 c SUBROUTINE lmpar(n,r,ldr,ipvt,diag,qtb,delta,par,x,sdiag,
73 c wa1,wa2)
74 c
75 c WHERE
76 c
77 c n is a positive INTEGER input variable set to the order of r.
78 c
79 c r is an n by n array. on input the full upper triangle
80 c must contain the full upper triangle of the matrix r.
81 c on output the full upper triangle is unaltered, and the
82 c strict lower triangle CONTAINS the strict upper triangle
83 c (transposed) of the upper triangular matrix s.
84 c
85 c ldr is a positive INTEGER input variable not less than n
86 c which specifies the leading DIMENSION of the array r.
87 c
88 c ipvt is an INTEGER input array of length n which defines the
89 c permutation matrix p such that a*p = q*r. column j of p
90 c is column ipvt(j) of the identity matrix.
91 c
92 c diag is an input array of length n which must contain the
93 c diagonal elements of the matrix d.
94 c
95 c qtb is an input array of length n which must contain the first
96 c n elements of the vector (q TRANSPOSE)*b.
97 c
98 c delta is a positive input variable which specifies an upper
99 c bound on the euclidean norm of d*x.
100 c
101 c par is a nonnegative variable. on input par CONTAINS an
102 c initial estimate of the levenberg-marquardt PARAMETER.
103 c on output par CONTAINS the final estimate.
104 c
105 c x is an output array of length n which CONTAINS the least
106 c squares solution of the system a*x = b, SQRT(par)*d*x = 0,
107 c for the output par.
108 c
109 c sdiag is an output array of length n which CONTAINS the
110 c diagonal elements of the upper triangular matrix s.
111 c
112 c wa1 and wa2 are work arrays of length n.
113 c
114 c subprograms called
115 c
116 c MINpack-supplied ... dpmpar,enorm,qrsolv
117 c
118 c fortran-supplied ... ABS,max,min,sqrt
119 c
120 c argonne national laboratory. MINpack project. march 1980.
121 c burton s. garbow, kenneth e. hillstrom, jorge j. more
122 c
123 c **********
124 
125 c
126 c dwarf is the smallest positive magnitude.
127 c
128  dwarf = dpmpar(2)
129  epsmch = sqrt(dpmpar(1)) !SPH: Gives better lower bound for r(j,j)
130 c
131 c compute and store in x the gauss-newton direction. IF the
132 c jacobian is rank-deficient, obtain a least squares solution.
133 c
134  nsing = n
135  DO j = 1, n
136  wa1(j) = qtb(j)
137 !SPH IF (r(j,j).eq.zero .and. nsing.eq.n) nsing = j - 1
138  IF (abs(r(j,j)).le.epsmch .and. nsing.eq.n) nsing = j - 1
139  IF (nsing .lt. n) wa1(j) = zero
140  END DO
141  IF (nsing .ge. 1) THEN
142  DO k = 1, nsing
143  j = nsing - k + 1
144  wa1(j) = wa1(j)/r(j,j)
145  temp = wa1(j)
146  jm1 = j - 1
147  IF (jm1 .ge. 1) THEN
148  wa1(:jm1) = wa1(:jm1) - r(:jm1,j)*temp
149  END IF
150  END DO
151  END IF
152  DO j = 1, n
153  l = ipvt(j)
154  x(l) = wa1(j)
155  END DO
156 c
157 c initialize the iteration counter.
158 c evaluate the FUNCTION at the origin, and test
159 c for acceptance of the gauss-newton direction.
160 c
161  wa2 = diag * x
162  dxnorm = enorm(n,wa2)
163  fp = dxnorm - delta
164 
165  IF (fp .le. p1*delta) THEN
166  par = zero
167  RETURN
168  END IF
169 
170 c
171 c BEGIN GAUSS-NEWTON STEP
172 c
173 c IF the jacobian is not rank deficient, the newton
174 c step provides a lower bound, parl, for the zero of
175 c the FUNCTION. otherwise set this bound to zero.
176 c
177  parl = zero
178  IF (nsing .ge. n) THEN
179  wa1 = diag(ipvt)*(wa2(ipvt)/dxnorm)
180  DO j = 1, n
181  sum0 = zero
182  jm1 = j - 1
183  IF (jm1 .ge. 1) sum0 = sum(r(:jm1,j)*wa1(:jm1))
184  wa1(j) = (wa1(j)-sum0)/r(j,j)
185  END DO
186  temp = enorm(n,wa1)
187  parl = ((fp/delta)/temp)/temp
188  END IF
189 c
190 c calculate an upper bound, paru, for the zero of the FUNCTION.
191 c
192  DO j = 1, n
193  sum0 = sum(r(:j,j)*qtb(:j))
194  l = ipvt(j)
195  wa1(j) = sum0/diag(l)
196  END DO
197  gnorm = enorm(n,wa1)
198  paru = gnorm/delta
199  IF (paru .eq. zero) paru = dwarf/min(delta,p1)
200 c
201 c IF the input par lies outside of the interval (parl,paru),
202 c set par to the CLOSEr ENDpoint.
203 c
204  par = max(par,parl)
205  par = min(par,paru)
206  IF (par .eq. zero) par = gnorm/dxnorm
207 
208 c
209 c beginning of an iteration loop.
210 c
211  DO iter = 1, 10
212 c
213 c evaluate the FUNCTION at the current value of par.
214 c
215  IF (par .le. zero) par = max(dwarf,p001*paru)
216  temp = sqrt(par)
217 
218  wa1 = temp*diag
219  CALL qrsolv (n, r, ldr, ipvt, wa1, qtb, x, sdiag, wa2)
220  wa2 = diag*x
221  dxnorm = enorm(n,wa2)
222  temp = fp
223  fp = dxnorm - delta
224 c
225 c If the function is small enough, accept the current value
226 c of par. also test for the exceptional cases where parl
227 c is zero or the number of iterations has reached 10.
228 c
229  IF (abs(fp).le.p1*delta .or. parl.eq.zero .and.
230  1 fp.le.temp .and. temp.lt.zero .or. iter.eq.10) EXIT
231 c
232 c compute the newton correction.
233 c
234  wa1 = diag(ipvt)*(wa2(ipvt)/dxnorm)
235  DO j = 1, n
236  wa1(j) = wa1(j)/sdiag(j)
237  temp = wa1(j)
238  jp1 = j + 1
239  IF (n .ge. jp1) wa1(jp1:n) = wa1(jp1:n) - r(jp1:n,j)*temp
240  END DO
241  temp = enorm(n,wa1)
242  parc = ((fp/delta)/temp)/temp
243 c
244 c depending on the sign of the FUNCTION, update parl or paru.
245 c
246  IF (fp .gt. zero) parl = max(parl,par)
247  IF (fp .lt. zero) paru = min(paru,par)
248 c
249 c compute an improved estimate for par.
250 c
251  par = max(parl,par + parc)
252 
253  END DO !!end of an iteration.
254 
255  END SUBROUTINE lmpar