Skip to content

Commit 11d68d0

Browse files
committed
refactor lmdif1 example
1 parent 1500295 commit 11d68d0

File tree

1 file changed

+48
-50
lines changed

1 file changed

+48
-50
lines changed

examples/example_lmdif1.f90

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,59 @@
1-
module testmod_dif1
1+
program example_lmdif1
2+
3+
use minpack_module, only: wp, enorm, lmdif1
4+
use iso_fortran_env, only: nwrite => output_unit
5+
26
implicit none
3-
private
4-
public fcn, dp
57

6-
integer, parameter :: dp=kind(0d0)
8+
integer, parameter :: n = 3
9+
integer, parameter :: m = 15
10+
integer, parameter :: lwa = m*n+5*n+m
11+
12+
integer :: info
13+
real(wp) :: tol, x(n), fvec(m), wa(lwa)
14+
integer :: iwa(n)
15+
16+
! The following starting values provide a rough fit.
17+
x = [1.0_wp, 1.0_wp, 1.0_wp]
18+
19+
! Set tol to the square root of the machine precision. Unless high precision
20+
! solutions are required, this is the recommended setting.
21+
tol = sqrt(epsilon(1.0_wp))
22+
23+
call lmdif1(fcn, m, n, x, fvec, tol, info, iwa, wa, lwa)
24+
25+
write(nwrite, '(5x,a,d15.7//,5x,a,16x,i10//,5x,a//(5x,3d15.7))') &
26+
'FINAL L2 NORM OF THE RESIDUALS', enorm(m, fvec), &
27+
'EXIT PARAMETER', info, &
28+
'FINAL APPROXIMATE SOLUTION', x
729

830
contains
931

1032
subroutine fcn(m, n, x, fvec, iflag)
11-
integer, intent(in) :: m, n
12-
integer, intent(inout) :: iflag
13-
real(dp), intent(in) :: x(n)
14-
real(dp), intent(out) :: fvec(m)
15-
16-
integer :: i
17-
real(dp) :: tmp1, tmp2, tmp3, y(15)
18-
! Suppress compiler warning:
19-
y(1) = iflag
20-
y = [1.4D-1, 1.8D-1, 2.2D-1, 2.5D-1, 2.9D-1, 3.2D-1, 3.5D-1, 3.9D-1, &
21-
3.7D-1, 5.8D-1, 7.3D-1, 9.6D-1, 1.34D0, 2.1D0, 4.39D0]
22-
23-
do i = 1, 15
24-
tmp1 = i
25-
tmp2 = 16 - i
26-
tmp3 = tmp1
27-
if (i > 8) tmp3 = tmp2
28-
fvec(i) = y(i) - (x(1) + tmp1/(x(2)*tmp2 + x(3)*tmp3))
29-
end do
30-
end subroutine
31-
32-
end module
3333

34+
integer, intent(in) :: m
35+
integer, intent(in) :: n
36+
real(wp), intent(in) :: x(n)
37+
real(wp), intent(out) :: fvec(m)
38+
integer, intent(inout) :: iflag
3439

35-
program example_lmdif1
36-
use minpack_module, only: enorm, lmdif1
37-
use testmod_dif1, only: dp, fcn
38-
implicit none
40+
integer :: i
41+
real(wp) :: tmp1, tmp2, tmp3
3942

40-
integer :: info, m, n
41-
real(dp) :: tol, x(3), fvec(15)
42-
integer :: iwa(size(x))
43-
real(dp), allocatable :: wa(:)
43+
real(wp),parameter :: y(15) = [1.4e-1_wp, 1.8e-1_wp, 2.2e-1_wp, 2.5e-1_wp, 2.9e-1_wp, &
44+
3.2e-1_wp, 3.5e-1_wp, 3.9e-1_wp, 3.7e-1_wp, 5.8e-1_wp, &
45+
7.3e-1_wp, 9.6e-1_wp, 1.34e0_wp, 2.1e0_wp, 4.39e0_wp]
4446

45-
! The following starting values provide a rough fit.
46-
x = [1._dp, 1._dp, 1._dp]
47+
if (iflag > 0) then ! just to avoid the compiler warning
48+
do i = 1, 15
49+
tmp1 = i
50+
tmp2 = 16 - i
51+
tmp3 = tmp1
52+
if (i > 8) tmp3 = tmp2
53+
fvec(i) = y(i) - (x(1) + tmp1/(x(2)*tmp2 + x(3)*tmp3))
54+
end do
55+
end if
4756

48-
! Set tol to the square root of the machine precision. Unless high precision
49-
! solutions are required, this is the recommended setting.
50-
tol = sqrt(epsilon(1._dp))
51-
52-
m = size(fvec)
53-
n = size(x)
54-
allocate(wa(m*n + 5*n + m))
55-
call lmdif1(fcn, size(fvec), size(x), x, fvec, tol, info, iwa, wa, size(wa))
56-
print 1000, enorm(size(fvec), fvec), info, x
57-
1000 format(5x, 'FINAL L2 NORM OF THE RESIDUALS', d15.7 // &
58-
5x, 'EXIT PARAMETER', 16x, i10 // &
59-
5x, 'FINAL APPROXIMATE SOLUTION' // &
60-
5x, 3d15.7)
61-
end program
57+
end subroutine fcn
58+
59+
end program example_lmdif1

0 commit comments

Comments
 (0)