|
1 |
| -module testmod_der1 |
2 |
| -implicit none |
3 |
| -private |
4 |
| -public fcn, dp |
5 |
| - |
6 |
| -integer, parameter :: dp=kind(0d0) |
7 |
| - |
8 |
| -contains |
9 |
| - |
10 |
| -subroutine fcn(m, n, x, fvec, fjac, ldfjac, iflag) |
11 |
| -integer, intent(in) :: m, n, ldfjac |
12 |
| -integer, intent(inout) :: iflag |
13 |
| -real(dp), intent(in) :: x(n) |
14 |
| -real(dp), intent(inout) :: fvec(m), fjac(ldfjac, n) |
15 |
| - |
16 |
| -integer :: i |
17 |
| -real(dp) :: tmp1, tmp2, tmp3, tmp4, y(15) |
18 |
| -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, & |
19 |
| - 3.7D-1, 5.8D-1, 7.3D-1, 9.6D-1, 1.34D0, 2.1D0, 4.39D0] |
20 |
| - |
21 |
| -if (iflag == 1) then |
22 |
| - do i = 1, 15 |
23 |
| - tmp1 = i |
24 |
| - tmp2 = 16 - i |
25 |
| - tmp3 = tmp1 |
26 |
| - if (i > 8) tmp3 = tmp2 |
27 |
| - fvec(i) = y(i) - (x(1) + tmp1/(x(2)*tmp2 + x(3)*tmp3)) |
28 |
| - end do |
29 |
| -else |
30 |
| - do i = 1, 15 |
31 |
| - tmp1 = i |
32 |
| - tmp2 = 16 - i |
33 |
| - tmp3 = tmp1 |
34 |
| - if (i > 8) tmp3 = tmp2 |
35 |
| - tmp4 = (x(2)*tmp2 + x(3)*tmp3)**2 |
36 |
| - fjac(i,1) = -1.D0 |
37 |
| - fjac(i,2) = tmp1*tmp2/tmp4 |
38 |
| - fjac(i,3) = tmp1*tmp3/tmp4 |
39 |
| - end do |
40 |
| -end if |
41 |
| -end subroutine |
42 |
| - |
43 |
| -end module |
| 1 | +program example_lmder1 |
44 | 2 |
|
| 3 | +use minpack_module, only: wp, enorm, lmder1, chkder |
| 4 | +use iso_fortran_env, only: nwrite => output_unit |
45 | 5 |
|
46 |
| -program example_lmder1 |
47 |
| -use minpack_module, only: enorm, lmder1, chkder |
48 |
| -use testmod_der1, only: dp, fcn |
49 | 6 | implicit none
|
50 | 7 |
|
| 8 | +integer, parameter :: n = 3 |
| 9 | +integer, parameter :: m = 15 |
| 10 | +integer, parameter :: lwa = 5*n+m |
| 11 | + |
51 | 12 | integer :: info
|
52 |
| -real(dp) :: tol, x(3), fvec(15), fjac(size(fvec), size(x)) |
53 |
| -integer :: ipvt(size(x)) |
54 |
| -real(dp), allocatable :: wa(:) |
| 13 | +real(wp) :: tol, x(n), fvec(m), fjac(m,n) |
| 14 | +integer :: ipvt(n) |
| 15 | +real(wp) :: wa(lwa) |
55 | 16 |
|
56 | 17 | ! The following starting values provide a rough fit.
|
57 |
| -x = [1._dp, 1._dp, 1._dp] |
| 18 | +x = [1.0_wp, 1.0_wp, 1.0_wp] |
58 | 19 |
|
59 | 20 | call check_deriv()
|
60 | 21 |
|
61 | 22 | ! Set tol to the square root of the machine precision. Unless high precision
|
62 | 23 | ! solutions are required, this is the recommended setting.
|
63 |
| -tol = sqrt(epsilon(1._dp)) |
| 24 | +tol = sqrt(epsilon(1._wp)) |
64 | 25 |
|
65 |
| -allocate(wa(5*size(x) + size(fvec))) |
66 |
| -call lmder1(fcn, size(fvec), size(x), x, fvec, fjac, size(fjac, 1), tol, & |
67 |
| - info, ipvt, wa, size(wa)) |
68 |
| -print 1000, enorm(size(fvec), fvec), info, x |
69 |
| -1000 format(5x, 'FINAL L2 NORM OF THE RESIDUALS', d15.7 // & |
70 |
| - 5x, 'EXIT PARAMETER', 16x, i10 // & |
71 |
| - 5x, 'FINAL APPROXIMATE SOLUTION' // & |
72 |
| - 5x, 3d15.7) |
| 26 | +call lmder1(fcn, m, n, x, fvec, fjac, m, tol, info, ipvt, wa, lwa) |
| 27 | + |
| 28 | +write(nwrite, '(5x,a,d15.7//,5x,a,16x,i10//,5x,a//(5x,3d15.7))') & |
| 29 | + 'FINAL L2 NORM OF THE RESIDUALS', enorm(m, fvec), & |
| 30 | + 'EXIT PARAMETER', info, & |
| 31 | + 'FINAL APPROXIMATE SOLUTION', x |
73 | 32 |
|
74 | 33 | contains
|
75 | 34 |
|
76 | 35 | subroutine check_deriv()
|
77 |
| -integer :: iflag |
78 |
| -real(dp) :: xp(size(x)), fvecp(size(fvec)), err(size(fvec)) |
79 |
| -call chkder(size(fvec), size(x), x, fvec, fjac, size(fjac, 1), xp, fvecp, & |
80 |
| - 1, err) |
81 |
| -iflag = 1 |
82 |
| -call fcn(size(fvec), size(x), x, fvec, fjac, size(fjac, 1), iflag) |
83 |
| -iflag = 2 |
84 |
| -call fcn(size(fvec), size(x), x, fvec, fjac, size(fjac, 1), iflag) |
85 |
| -iflag = 1 |
86 |
| -call fcn(size(fvec), size(x), xp, fvecp, fjac, size(fjac, 1), iflag) |
87 |
| -call chkder(size(fvec), size(x), x, fvec, fjac, size(fjac, 1), xp, fvecp, & |
88 |
| - 2, err) |
89 |
| -print *, "Derivatives check (1.0 is correct, 0.0 is incorrect):" |
90 |
| -print *, err |
91 |
| -end subroutine |
| 36 | + |
| 37 | + integer :: iflag |
| 38 | + real(wp) :: xp(n), fvecp(m), err(m) |
| 39 | + |
| 40 | + call chkder(m, n, x, fvec, fjac, m, xp, fvecp, 1, err) |
| 41 | + iflag = 1 |
| 42 | + call fcn(m, n, x, fvec, fjac, m, iflag) |
| 43 | + iflag = 2 |
| 44 | + call fcn(m, n, x, fvec, fjac, m, iflag) |
| 45 | + iflag = 1 |
| 46 | + call fcn(m, n, xp, fvecp, fjac, m, iflag) |
| 47 | + call chkder(m, n, x, fvec, fjac, m, xp, fvecp, 2, err) |
| 48 | + |
| 49 | + write(nwrite, '(a)') 'Derivatives check (1.0 is correct, 0.0 is incorrect):' |
| 50 | + write(nwrite,'(1p,(5x,3d15.7))') err |
| 51 | + if (any(abs(err-1.0_wp)>epsilon(1.0_wp))) error stop 'Derivative check failed' |
| 52 | + |
| 53 | +end subroutine check_deriv |
| 54 | + |
| 55 | +subroutine fcn(m, n, x, fvec, fjac, ldfjac, iflag) |
| 56 | + |
| 57 | + integer, intent(in) :: m |
| 58 | + integer, intent(in) :: n |
| 59 | + real(wp), intent(in) :: x(n) |
| 60 | + real(wp), intent(inout) :: fvec(m) |
| 61 | + real(wp), intent(inout) :: fjac(ldfjac, n) |
| 62 | + integer, intent(in) :: ldfjac |
| 63 | + integer, intent(inout) :: iflag |
| 64 | + |
| 65 | + integer :: i |
| 66 | + real(wp) :: tmp1, tmp2, tmp3, tmp4 |
| 67 | + |
| 68 | + 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, & |
| 69 | + 3.2e-1_wp, 3.5e-1_wp, 3.9e-1_wp, 3.7e-1_wp, 5.8e-1_wp, & |
| 70 | + 7.3e-1_wp, 9.6e-1_wp, 1.34e0_wp, 2.1e0_wp, 4.39e0_wp] |
| 71 | + |
| 72 | + if (iflag == 1) then |
| 73 | + do i = 1, 15 |
| 74 | + tmp1 = i |
| 75 | + tmp2 = 16 - i |
| 76 | + tmp3 = tmp1 |
| 77 | + if (i > 8) tmp3 = tmp2 |
| 78 | + fvec(i) = y(i) - (x(1) + tmp1/(x(2)*tmp2 + x(3)*tmp3)) |
| 79 | + end do |
| 80 | + else |
| 81 | + do i = 1, 15 |
| 82 | + tmp1 = i |
| 83 | + tmp2 = 16 - i |
| 84 | + tmp3 = tmp1 |
| 85 | + if (i > 8) tmp3 = tmp2 |
| 86 | + tmp4 = (x(2)*tmp2 + x(3)*tmp3)**2 |
| 87 | + fjac(i,1) = -1.0_wp |
| 88 | + fjac(i,2) = tmp1*tmp2/tmp4 |
| 89 | + fjac(i,3) = tmp1*tmp3/tmp4 |
| 90 | + end do |
| 91 | + end if |
| 92 | + |
| 93 | + end subroutine fcn |
92 | 94 |
|
93 | 95 | end program
|
0 commit comments