Skip to content

Commit 1976de2

Browse files
committed
Add hybrd interface and example.
1 parent be736da commit 1976de2

File tree

5 files changed

+139
-6
lines changed

5 files changed

+139
-6
lines changed

examples/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
include_directories(${PROJECT_BINARY_DIR}/src)
22

3+
add_executable(example_hybrd example_hybrd.f90)
4+
target_link_libraries(example_hybrd minpack)
5+
36
add_executable(example_hybrd1 example_hybrd1.f90)
47
target_link_libraries(example_hybrd1 minpack)
58

examples/example_hybrd.f90

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
!> The problem is to determine the values of x(1), x(2), ..., x(9)
2+
!> which solve the system of tridiagonal equations
3+
!> (3-2*x(1))*x(1) -2*x(2) = -1
4+
!> -x(i-1) + (3-2*x(i))*x(i) -2*x(i+1) = -1, i=2-8
5+
!> -x(8) + (3-2*x(9))*x(9) = -1
6+
program example_hybrd
7+
8+
use minpack, 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/
17+
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
24+
25+
ldfjac = 9
26+
lr = 45
27+
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))
32+
33+
maxfev = 2000
34+
ml = 1
35+
mu = 1
36+
epsfcn = 0.0d0
37+
mode = 2
38+
do j = 1, 9
39+
diag(j) = 1.0d0
40+
end do
41+
factor = 1.0d2
42+
nprint = 0
43+
44+
call hybrd(fcn, n, x, fvec, xtol, maxfev, ml, mu, epsfcn, diag, &
45+
mode, factor, nprint, info, nfev, fjac, ldfjac, &
46+
r, lr, qtf, wa1, wa2, wa3, wa4)
47+
fnorm = enorm(n, fvec)
48+
write (nwrite, 1000) fnorm, nfev, info, (x(j), j=1, n)
49+
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))
54+
55+
!> Results obtained with different compilers or machines
56+
!> may be slightly different.
57+
!>
58+
!>> FINAL L2 NORM OF THE RESIDUALS 0.1192636D-07
59+
!>>
60+
!>> NUMBER OF FUNCTION EVALUATIONS 14
61+
!>>
62+
!>> EXIT PARAMETER 1
63+
!>>
64+
!>> FINAL APPROXIMATE SOLUTION
65+
!>>
66+
!>> -0.5706545D+00 -0.6816283D+00 -0.7017325D+00
67+
!>> -0.7042129D+00 -0.7013690D+00 -0.6918656D+00
68+
!>> -0.6657920D+00 -0.5960342D+00 -0.4164121D+00
69+
70+
contains
71+
72+
!> Subroutine fcn for hybrd example.
73+
subroutine fcn(n, x, fvec, iflag)
74+
75+
implicit none
76+
integer n, iflag
77+
double precision x(n), fvec(n)
78+
79+
integer k
80+
double precision one, temp, temp1, temp2, three, two, zero
81+
data zero, one, two, three/0.0d0, 1.0d0, 2.0d0, 3.0d0/
82+
83+
if (iflag /= 0) go to 5
84+
85+
!! Insert print statements here when nprint is positive.
86+
87+
return
88+
5 continue
89+
do k = 1, n
90+
temp = (three - two*x(k))*x(k)
91+
temp1 = zero
92+
if (k /= 1) temp1 = x(k - 1)
93+
temp2 = zero
94+
if (k /= n) temp2 = x(k + 1)
95+
fvec(k) = temp - temp1 - two*temp2 + one
96+
end do
97+
return
98+
99+
end subroutine fcn
100+
101+
end program example_hybrd

examples/example_hybrd1.f90

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
!> which solve the system of tridiagonal equations.
33
!>
44
!> (3-2*x(1))*x(1) -2*x(2) = -1
5-
!> -x(i-1) + (3-2*x(i))*x(i) -2*x(i+1) = -1, i=2-8
6-
!> -x(8) + (3-2*x(9))*x(9) = -1
5+
!> -x(i-1) + (3-2*x(i))*x(i) -2*x(i+1) = -1, i=2-8
6+
!> -x(8) + (3-2*x(9))*x(9) = -1
77
program example_hybrd1
88

9-
use minpack, only: hybrd1
9+
use minpack, only: hybrd1, dpmpar, enorm
1010
implicit none
1111
integer j, n, info, lwa, nwrite
1212
double precision tol, fnorm
1313
double precision x(9), fvec(9), wa(180)
14-
double precision enorm, dpmpar
1514

15+
!> Logical output unit is assumed to be number 6.
1616
data nwrite/6/
1717

1818
n = 9
@@ -23,6 +23,10 @@ program example_hybrd1
2323
end do
2424

2525
lwa = 180
26+
27+
!> Set tol to the square root of the machine precision.
28+
!> unless high precision solutions are required,
29+
!> this is the recommended setting.
2630
tol = dsqrt(dpmpar(1))
2731

2832
call hybrd1(fcn, n, x, fvec, tol, info, wa, lwa)
@@ -35,7 +39,7 @@ program example_hybrd1
3539
(5x, 3d15.7))
3640

3741
!> Results obtained with different compilers or machines
38-
!> may be slightly different.
42+
!> may be slightly different.
3943
!>
4044
!>> FINAL L2 NORM OF THE RESIDUALS 0.1192636D-07
4145
!>>
@@ -49,7 +53,7 @@ program example_hybrd1
4953

5054
contains
5155

52-
!> subroutine fcn for hybrd1 example.
56+
!> Subroutine fcn for hybrd1 example.
5357
subroutine fcn(n, x, fvec, iflag)
5458

5559
implicit none

fpm.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ auto-examples = false
1717
[install]
1818
library = false
1919

20+
[[ example ]]
21+
name = "example_hybrd"
22+
source-dir = "examples"
23+
main = "example_hybrd.f90"
24+
2025
[[ example ]]
2126
name = "example_hybrd1"
2227
source-dir = "examples"

src/minpack.f90

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,26 @@ double precision function enorm(n,x)
1212
double precision x(n)
1313
end function
1414

15+
!> The purpose of `hybrd` is to find a zero of a system of N non-
16+
!> linear functions in N variables by a modification of the Powell
17+
!> hybrid method. The user must provide a subroutine which calcu-
18+
!> lates the functions. The Jacobian is then calculated by a for-
19+
!> ward-difference approximation.
20+
subroutine hybrd(fcn,n,x,fvec,xtol,maxfev,ml,mu,epsfcn,diag, &
21+
mode,factor,nprint,info,nfev,fjac,ldfjac, &
22+
r,lr,qtf,wa1,wa2,wa3,wa4)
23+
integer n,maxfev,ml,mu,mode,nprint,info,nfev,ldfjac,lr
24+
double precision xtol,epsfcn,factor
25+
double precision x(n),fvec(n),diag(n),fjac(ldfjac,n),r(lr),qtf(n), &
26+
wa1(n),wa2(n),wa3(n),wa4(n)
27+
interface
28+
subroutine fcn(n,x,fvec,iflag)
29+
integer n,iflag
30+
double precision x(n),fvec(n)
31+
end subroutine fcn
32+
end interface
33+
end subroutine hybrd
34+
1535
!> The purpose of `hybrd1` is to find a zero of a system of
1636
!> n nonlinear functions in n variables by a modification
1737
!> of the powell hybrid method.

0 commit comments

Comments
 (0)