Skip to content

Commit 4717189

Browse files
Merge pull request #63 from jacobwilliams/62-modernize-examples
Modernize the examples
2 parents e26542b + 0ce2ed7 commit 4717189

File tree

5 files changed

+243
-253
lines changed

5 files changed

+243
-253
lines changed

examples/example_hybrd.f90

+43-53
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,41 @@
55
!> -x(8) + (3-2*x(9))*x(9) = -1
66
program example_hybrd
77

8-
use minpack_module, only: hybrd, enorm, dpmpar
9-
implicit none
10-
integer j, n, maxfev, ml, mu, mode, nprint, info, nfev, ldfjac, lr, nwrite
11-
double precision xtol, epsfcn, factor, fnorm
12-
double precision x(9), fvec(9), diag(9), fjac(9, 9), r(45), qtf(9), &
13-
wa1(9), wa2(9), wa3(9), wa4(9)
14-
15-
!> Logical output unit is assumed to be number 6.
16-
data nwrite/6/
8+
use minpack_module, only: wp, hybrd, enorm, dpmpar
9+
use iso_fortran_env, only: nwrite => output_unit
1710

18-
n = 9
19-
20-
!> The following starting values provide a rough solution.
21-
do j = 1, 9
22-
x(j) = -1.0d0
23-
end do
11+
implicit none
2412

25-
ldfjac = 9
26-
lr = 45
13+
integer,parameter :: n = 9
14+
integer,parameter :: ldfjac = n
15+
integer,parameter :: lr = (n*(n+1))/2
2716

28-
!> Set xtol to the square root of the machine precision.
29-
!> unless high precision solutions are required,
30-
!> this is the recommended setting.
31-
xtol = dsqrt(dpmpar(1))
17+
integer :: maxfev, ml, mu, mode, nprint, info, nfev
18+
real(wp) :: epsfcn, factor, fnorm, xtol
19+
real(wp) :: x(n), fvec(n), diag(n), fjac(n, n), r(lr), qtf(n), &
20+
wa1(n), wa2(n), wa3(n), wa4(n)
3221

22+
xtol = sqrt(dpmpar(1)) ! square root of the machine precision.
3323
maxfev = 2000
3424
ml = 1
3525
mu = 1
36-
epsfcn = 0.0d0
26+
epsfcn = 0.0_wp
3727
mode = 2
38-
do j = 1, 9
39-
diag(j) = 1.0d0
40-
end do
41-
factor = 1.0d2
28+
factor = 100.0_wp
4229
nprint = 0
30+
diag = 1.0_wp
31+
x = -1.0_wp ! starting values to provide a rough solution.
4332

4433
call hybrd(fcn, n, x, fvec, xtol, maxfev, ml, mu, epsfcn, diag, &
4534
mode, factor, nprint, info, nfev, fjac, ldfjac, &
4635
r, lr, qtf, wa1, wa2, wa3, wa4)
4736
fnorm = enorm(n, fvec)
48-
write (nwrite, 1000) fnorm, nfev, info, (x(j), j=1, n)
4937

50-
1000 format(5x, "FINAL L2 NORM OF THE RESIDUALS", d15.7// &
51-
5x, "NUMBER OF FUNCTION EVALUATIONS", i10// &
52-
5x, "EXIT PARAMETER", 16x, i10// &
53-
5x, "FINAL APPROXIMATE SOLUTION"//(5x, 3d15.7))
38+
write (nwrite, '(5x,a,d15.7//5x,a,i10//5x,a,16x,i10//5x,a//(5x,3d15.7))') &
39+
"FINAL L2 NORM OF THE RESIDUALS", fnorm, &
40+
"NUMBER OF FUNCTION EVALUATIONS", nfev, &
41+
"EXIT PARAMETER", info, &
42+
"FINAL APPROXIMATE SOLUTION", x
5443

5544
!> Results obtained with different compilers or machines
5645
!> may be slightly different.
@@ -75,28 +64,29 @@ subroutine fcn(n, x, fvec, iflag)
7564
implicit none
7665
integer, intent(in) :: n
7766
integer, intent(inout) :: iflag
78-
double precision, intent(in) :: x(n)
79-
double precision, intent(out) :: fvec(n)
80-
81-
integer k
82-
double precision one, temp, temp1, temp2, three, two, zero
83-
data zero, one, two, three/0.0d0, 1.0d0, 2.0d0, 3.0d0/
84-
85-
if (iflag /= 0) go to 5
86-
87-
!! Insert print statements here when nprint is positive.
88-
89-
return
90-
5 continue
91-
do k = 1, n
92-
temp = (three - two*x(k))*x(k)
93-
temp1 = zero
94-
if (k /= 1) temp1 = x(k - 1)
95-
temp2 = zero
96-
if (k /= n) temp2 = x(k + 1)
97-
fvec(k) = temp - temp1 - two*temp2 + one
98-
end do
99-
return
67+
real(wp), intent(in) :: x(n)
68+
real(wp), intent(out) :: fvec(n)
69+
70+
integer :: k !! counter
71+
real(wp) :: temp, temp1, temp2
72+
73+
real(wp),parameter :: zero = 0.0_wp
74+
real(wp),parameter :: one = 1.0_wp
75+
real(wp),parameter :: two = 2.0_wp
76+
real(wp),parameter :: three = 3.0_wp
77+
78+
if (iflag == 0) then
79+
!! Insert print statements here when nprint is positive.
80+
else
81+
do k = 1, n
82+
temp = (three - two*x(k))*x(k)
83+
temp1 = zero
84+
if (k /= 1) temp1 = x(k - 1)
85+
temp2 = zero
86+
if (k /= n) temp2 = x(k + 1)
87+
fvec(k) = temp - temp1 - two*temp2 + one
88+
end do
89+
end if
10090

10191
end subroutine fcn
10292

examples/example_hybrd1.f90

+23-23
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,33 @@
66
!> -x(8) + (3-2*x(9))*x(9) = -1
77
program example_hybrd1
88

9-
use minpack_module, only: hybrd1, dpmpar, enorm
9+
use minpack_module, only: wp, hybrd1, dpmpar, enorm
10+
use iso_fortran_env, only: nwrite => output_unit
11+
1012
implicit none
11-
integer j, n, info, lwa, nwrite
12-
double precision tol, fnorm
13-
double precision x(9), fvec(9), wa(180)
1413

15-
!> Logical output unit is assumed to be number 6.
16-
data nwrite/6/
14+
integer,parameter :: n = 9
15+
integer,parameter :: lwa = (n*(3*n+13))/2
1716

18-
n = 9
17+
integer :: j, info
18+
real(wp) :: tol, fnorm
19+
real(wp) :: x(n), fvec(n), wa(lwa)
1920

2021
!> The following starting values provide a rough solution.
21-
do j = 1, 9
22-
x(j) = -1.d0
23-
end do
24-
25-
lwa = 180
22+
x = -1.0_wp
2623

2724
!> Set tol to the square root of the machine precision.
2825
!> unless high precision solutions are required,
2926
!> this is the recommended setting.
30-
tol = dsqrt(dpmpar(1))
27+
tol = sqrt(dpmpar(1))
3128

3229
call hybrd1(fcn, n, x, fvec, tol, info, wa, lwa)
3330
fnorm = enorm(n, fvec)
34-
write (nwrite, 1000) fnorm, info, (x(j), j=1, n)
3531

36-
1000 format(5x, "FINAL L2 NORM OF THE RESIDUALS", d15.7// &
37-
5x, "EXIT PARAMETER", 16x, i10// &
38-
5x, "FINAL APPROXIMATE SOLUTION"// &
39-
(5x, 3d15.7))
32+
write (nwrite, '(5x,a,d15.7//5x,a,16x,i10//5x,a//(5x,3d15.7))') &
33+
"FINAL L2 NORM OF THE RESIDUALS", fnorm, &
34+
"EXIT PARAMETER", info, &
35+
"FINAL APPROXIMATE SOLUTION", x
4036

4137
!> Results obtained with different compilers or machines
4238
!> may be slightly different.
@@ -59,12 +55,16 @@ subroutine fcn(n, x, fvec, iflag)
5955
implicit none
6056
integer, intent(in) :: n
6157
integer, intent(inout) :: iflag
62-
double precision, intent(in) :: x(n)
63-
double precision, intent(out) :: fvec(n)
58+
real(wp), intent(in) :: x(n)
59+
real(wp), intent(out) :: fvec(n)
60+
61+
integer :: k
62+
real(wp) :: temp, temp1, temp2
6463

65-
integer k
66-
double precision one, temp, temp1, temp2, three, two, zero
67-
data zero, one, two, three/0.0d0, 1.0d0, 2.0d0, 3.0d0/
64+
real(wp),parameter :: zero = 0.0_wp
65+
real(wp),parameter :: one = 1.0_wp
66+
real(wp),parameter :: two = 2.0_wp
67+
real(wp),parameter :: three = 3.0_wp
6868

6969
do k = 1, n
7070
temp = (three - two*x(k))*x(k)

examples/example_lmder1.f90

+76-74
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)