|
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