Skip to content

Commit 1500295

Browse files
committed
refactor lmder1 example
1 parent 2eb6fbf commit 1500295

File tree

1 file changed

+76
-74
lines changed

1 file changed

+76
-74
lines changed

examples/example_lmder1.f90

Lines changed: 76 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,95 @@
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
442

3+
use minpack_module, only: wp, enorm, lmder1, chkder
4+
use iso_fortran_env, only: nwrite => output_unit
455

46-
program example_lmder1
47-
use minpack_module, only: enorm, lmder1, chkder
48-
use testmod_der1, only: dp, fcn
496
implicit none
507

8+
integer, parameter :: n = 3
9+
integer, parameter :: m = 15
10+
integer, parameter :: lwa = 5*n+m
11+
5112
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)
5516

5617
! 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]
5819

5920
call check_deriv()
6021

6122
! Set tol to the square root of the machine precision. Unless high precision
6223
! solutions are required, this is the recommended setting.
63-
tol = sqrt(epsilon(1._dp))
24+
tol = sqrt(epsilon(1._wp))
6425

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
7332

7433
contains
7534

7635
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
9294

9395
end program

0 commit comments

Comments
 (0)