diff --git a/src/minpack.f90 b/src/minpack.f90 index 7cf47d3..61c5528 100644 --- a/src/minpack.f90 +++ b/src/minpack.f90 @@ -22,7 +22,7 @@ module minpack_module real(wp), parameter, private :: zero = 0.0_wp abstract interface - subroutine func(n, x, fvec, iflag) + subroutine func(n, x, fvec, iflag, udata) !! user-supplied subroutine for [[hybrd]], [[hybrd1]], and [[fdjac1]] import :: wp implicit none @@ -30,9 +30,10 @@ subroutine func(n, x, fvec, iflag) real(wp), intent(in) :: x(n) !! independant variable vector real(wp), intent(out) :: fvec(n) !! value of function at `x` integer, intent(inout) :: iflag !! set to <0 to terminate execution + class(*), intent(inout), optional :: udata !! user data end subroutine func - subroutine func2(m, n, x, fvec, iflag) + subroutine func2(m, n, x, fvec, iflag, udata) !! user-supplied subroutine for [[fdjac2]], [[lmdif]], and [[lmdif1]] import :: wp implicit none @@ -43,9 +44,10 @@ subroutine func2(m, n, x, fvec, iflag) integer, intent(inout) :: iflag !! the value of iflag should not be changed unless !! the user wants to terminate execution of lmdif. !! in this case set iflag to a negative integer. + class(*), intent(inout), optional :: udata !! user data end subroutine func2 - subroutine fcn_hybrj(n, x, fvec, fjac, ldfjac, iflag) + subroutine fcn_hybrj(n, x, fvec, fjac, ldfjac, iflag, udata) !! user-supplied subroutine for [[hybrj]] and [[hybrj1]] import :: wp implicit none @@ -62,9 +64,10 @@ subroutine fcn_hybrj(n, x, fvec, fjac, ldfjac, iflag) !! the value of iflag should not be changed by fcn unless !! the user wants to terminate execution of hybrj. !! in this case set iflag to a negative integer. + class(*), intent(inout), optional :: udata !! user data end subroutine fcn_hybrj - subroutine fcn_lmder(m, n, x, fvec, fjac, ldfjac, iflag) + subroutine fcn_lmder(m, n, x, fvec, fjac, ldfjac, iflag, udata) !! user-supplied subroutine for [[lmder]] and [[lmder1]] import :: wp implicit none @@ -82,9 +85,10 @@ subroutine fcn_lmder(m, n, x, fvec, fjac, ldfjac, iflag) real(wp), intent(in) :: x(n) !! independant variable vector real(wp), intent(inout) :: fvec(m) !! value of function at `x` real(wp), intent(inout) :: fjac(ldfjac, n) !! jacobian matrix at `x` + class(*), intent(inout), optional :: udata !! user data end subroutine fcn_lmder - subroutine fcn_lmstr(m, n, x, fvec, fjrow, iflag) + subroutine fcn_lmstr(m, n, x, fvec, fjrow, iflag, udata) import :: wp implicit none integer, intent(in) :: m !! the number of functions. @@ -100,6 +104,7 @@ subroutine fcn_lmstr(m, n, x, fvec, fjrow, iflag) real(wp) :: x(n) !! independant variable vector real(wp) :: fvec(m) !! value of function at `x` real(wp) :: fjrow(n) !! jacobian row + class(*), intent(inout), optional :: udata !! user data end subroutine fcn_lmstr end interface @@ -431,7 +436,7 @@ end function enorm ! a banded form, then function evaluations are saved by only ! approximating the nonzero terms. - subroutine fdjac1(fcn, n, x, Fvec, Fjac, Ldfjac, Iflag, Ml, Mu, Epsfcn, Wa1, Wa2) + subroutine fdjac1(fcn, n, x, Fvec, Fjac, Ldfjac, Iflag, Ml, Mu, Epsfcn, Wa1, Wa2, udata) implicit none @@ -467,6 +472,7 @@ subroutine fdjac1(fcn, n, x, Fvec, Fjac, Ldfjac, Iflag, Ml, Mu, Epsfcn, Wa1, Wa2 real(wp), intent(inout) :: Wa2(n) !! work array of length n. if ml + mu + 1 is at !! least n, then the jacobian is considered dense, and wa2 is !! not referenced. + class(*), intent(inout), optional :: udata !! user data integer :: i, j, k, msum real(wp) :: eps, h, temp @@ -483,7 +489,7 @@ subroutine fdjac1(fcn, n, x, Fvec, Fjac, Ldfjac, Iflag, Ml, Mu, Epsfcn, Wa1, Wa2 x(j) = Wa2(j) + h end do Iflag = 1 ! JW added - call fcn(n, x, Wa1, Iflag) + call fcn(n, x, Wa1, Iflag, udata) if (Iflag < 0) return do j = k, n, msum x(j) = Wa2(j) @@ -503,7 +509,7 @@ subroutine fdjac1(fcn, n, x, Fvec, Fjac, Ldfjac, Iflag, Ml, Mu, Epsfcn, Wa1, Wa2 if (h == zero) h = eps x(j) = temp + h Iflag = 1 ! JW added - call fcn(n, x, Wa1, Iflag) + call fcn(n, x, Wa1, Iflag, udata) if (Iflag < 0) return x(j) = temp do i = 1, n @@ -521,7 +527,7 @@ end subroutine fdjac1 ! to the m by n jacobian matrix associated with a specified ! problem of m functions in n variables. - subroutine fdjac2(fcn, m, n, x, Fvec, Fjac, Ldfjac, Iflag, Epsfcn, Wa) + subroutine fdjac2(fcn, m, n, x, Fvec, Fjac, Ldfjac, Iflag, Epsfcn, Wa, udata) implicit none @@ -548,6 +554,7 @@ subroutine fdjac2(fcn, m, n, x, Fvec, Fjac, Ldfjac, Iflag, Epsfcn, Wa) real(wp), intent(out) :: Fjac(Ldfjac, n) !! an output m by n array which contains the !! approximation to the jacobian matrix evaluated at x. real(wp), intent(inout) :: Wa(m) !! a work array of length m. + class(*), intent(inout), optional :: udata !! user data integer :: i, j real(wp) :: eps, h, temp @@ -558,7 +565,7 @@ subroutine fdjac2(fcn, m, n, x, Fvec, Fjac, Ldfjac, Iflag, Epsfcn, Wa) h = eps*abs(temp) if (h == zero) h = eps x(j) = temp + h - call fcn(m, n, x, Wa, Iflag) + call fcn(m, n, x, Wa, Iflag, udata) if (Iflag < 0) return x(j) = temp do i = 1, m @@ -579,7 +586,7 @@ end subroutine fdjac2 subroutine hybrd(fcn, n, x, Fvec, Xtol, Maxfev, Ml, Mu, Epsfcn, Diag, Mode, & Factor, Nprint, Info, Nfev, Fjac, Ldfjac, r, Lr, Qtf, Wa1, & - Wa2, Wa3, Wa4) + Wa2, Wa3, Wa4, udata) implicit none @@ -666,6 +673,7 @@ subroutine hybrd(fcn, n, x, Fvec, Xtol, Maxfev, Ml, Mu, Epsfcn, Diag, Mode, & real(wp), intent(inout) :: wa2(n) !! work array real(wp), intent(inout) :: wa3(n) !! work array real(wp), intent(inout) :: wa4(n) !! work array + class(*), intent(inout), optional :: udata !! user data integer :: i, iflag, iter, j, jm1, l, msum, ncfail, ncsuc, nslow1, nslow2 integer :: iwa(1) @@ -695,7 +703,7 @@ subroutine hybrd(fcn, n, x, Fvec, Xtol, Maxfev, Ml, Mu, Epsfcn, Diag, Mode, & ! and calculate its norm. iflag = 1 - call fcn(n, x, Fvec, iflag) + call fcn(n, x, Fvec, iflag, udata) Nfev = 1 if (iflag < 0) goto 300 fnorm = enorm(n, Fvec) @@ -720,7 +728,7 @@ subroutine hybrd(fcn, n, x, Fvec, Xtol, Maxfev, Ml, Mu, Epsfcn, Diag, Mode, & ! calculate the jacobian matrix. iflag = 2 - call fdjac1(fcn, n, x, Fvec, Fjac, Ldfjac, iflag, Ml, Mu, Epsfcn, Wa1, Wa2) + call fdjac1(fcn, n, x, Fvec, Fjac, Ldfjac, iflag, Ml, Mu, Epsfcn, Wa1, Wa2, udata) Nfev = Nfev + msum if (iflag < 0) goto 300 @@ -800,7 +808,7 @@ subroutine hybrd(fcn, n, x, Fvec, Xtol, Maxfev, Ml, Mu, Epsfcn, Diag, Mode, & 200 if (Nprint > 0) then iflag = 0 - if (mod(iter - 1, Nprint) == 0) call fcn(n, x, Fvec, iflag) + if (mod(iter - 1, Nprint) == 0) call fcn(n, x, Fvec, iflag, udata) if (iflag < 0) goto 300 end if @@ -824,7 +832,7 @@ subroutine hybrd(fcn, n, x, Fvec, Xtol, Maxfev, Ml, Mu, Epsfcn, Diag, Mode, & ! evaluate the function at x + p and calculate its norm. iflag = 1 - call fcn(n, Wa2, Wa4, iflag) + call fcn(n, Wa2, Wa4, iflag, udata) Nfev = Nfev + 1 if (iflag >= 0) then fnorm1 = enorm(n, Wa4) @@ -941,7 +949,7 @@ subroutine hybrd(fcn, n, x, Fvec, Xtol, Maxfev, Ml, Mu, Epsfcn, Diag, Mode, & 300 if (iflag < 0) Info = iflag iflag = 0 - if (Nprint > 0) call fcn(n, x, Fvec, iflag) + if (Nprint > 0) call fcn(n, x, Fvec, iflag, udata) end subroutine hybrd !***************************************************************************************** @@ -956,7 +964,7 @@ end subroutine hybrd ! the jacobian is then calculated by a forward-difference ! approximation. - subroutine hybrd1(fcn, n, x, Fvec, Tol, Info, Wa, Lwa) + subroutine hybrd1(fcn, n, x, Fvec, Tol, Info, Wa, Lwa, udata) implicit none @@ -987,6 +995,7 @@ subroutine hybrd1(fcn, n, x, Fvec, Tol, Info, Wa, Lwa) integer, intent(in) :: Lwa !! a positive integer input variable not less than !! (n*(3*n+13))/2. real(wp), intent(inout) :: Wa(Lwa) !! a work array of length lwa. + class(*), intent(inout), optional :: udata !! user data integer :: index, j, lr, maxfev, ml, mode, mu, nfev, nprint real(wp) :: epsfcn, xtol @@ -1013,7 +1022,8 @@ subroutine hybrd1(fcn, n, x, Fvec, Tol, Info, Wa, Lwa) index = 6*n + lr call hybrd(fcn, n, x, Fvec, xtol, maxfev, ml, mu, epsfcn, Wa(1), mode, & factor, nprint, Info, nfev, Wa(index + 1), n, Wa(6*n + 1), lr, & - Wa(n + 1), Wa(2*n + 1), Wa(3*n + 1), Wa(4*n + 1), Wa(5*n + 1)) + Wa(n + 1), Wa(2*n + 1), Wa(3*n + 1), Wa(4*n + 1), Wa(5*n + 1), & + udata) if (Info == 5) Info = 4 end if @@ -1029,7 +1039,7 @@ end subroutine hybrd1 subroutine hybrj(fcn, n, x, Fvec, Fjac, Ldfjac, Xtol, Maxfev, Diag, Mode, & Factor, Nprint, Info, Nfev, Njev, r, Lr, Qtf, Wa1, Wa2, & - Wa3, Wa4) + Wa3, Wa4, udata) implicit none @@ -1107,6 +1117,7 @@ subroutine hybrj(fcn, n, x, Fvec, Fjac, Ldfjac, Xtol, Maxfev, Diag, Mode, & real(wp), intent(inout) :: Wa2(n) !! work array of length n. real(wp), intent(inout) :: Wa3(n) !! work array of length n. real(wp), intent(inout) :: Wa4(n) !! work array of length n. + class(*), intent(inout), optional :: udata !! user data integer :: i, iflag, iter, j, jm1, l, ncfail, ncsuc, nslow1, nslow2 integer :: iwa(1) @@ -1137,7 +1148,7 @@ subroutine hybrj(fcn, n, x, Fvec, Fjac, Ldfjac, Xtol, Maxfev, Diag, Mode, & ! and calculate its norm. iflag = 1 - call fcn(n, x, Fvec, Fjac, Ldfjac, iflag) + call fcn(n, x, Fvec, Fjac, Ldfjac, iflag, udata) Nfev = 1 if (iflag < 0) goto 300 fnorm = enorm(n, Fvec) @@ -1157,7 +1168,7 @@ subroutine hybrj(fcn, n, x, Fvec, Fjac, Ldfjac, Xtol, Maxfev, Diag, Mode, & ! calculate the jacobian matrix. iflag = 2 - call fcn(n, x, Fvec, Fjac, Ldfjac, iflag) + call fcn(n, x, Fvec, Fjac, Ldfjac, iflag, udata) Njev = Njev + 1 if (iflag < 0) goto 300 @@ -1240,7 +1251,7 @@ subroutine hybrj(fcn, n, x, Fvec, Fjac, Ldfjac, Xtol, Maxfev, Diag, Mode, & 200 if (Nprint > 0) then iflag = 0 if (mod(iter - 1, Nprint) == 0) & - call fcn(n, x, Fvec, Fjac, Ldfjac, iflag) + call fcn(n, x, Fvec, Fjac, Ldfjac, iflag, udata) if (iflag < 0) goto 300 end if @@ -1264,7 +1275,7 @@ subroutine hybrj(fcn, n, x, Fvec, Fjac, Ldfjac, Xtol, Maxfev, Diag, Mode, & ! evaluate the function at x + p and calculate its norm. iflag = 1 - call fcn(n, Wa2, Wa4, Fjac, Ldfjac, iflag) + call fcn(n, Wa2, Wa4, Fjac, Ldfjac, iflag, udata) Nfev = Nfev + 1 if (iflag >= 0) then fnorm1 = enorm(n, Wa4) @@ -1382,7 +1393,7 @@ subroutine hybrj(fcn, n, x, Fvec, Fjac, Ldfjac, Xtol, Maxfev, Diag, Mode, & 300 if (iflag < 0) Info = iflag iflag = 0 - if (Nprint > 0) call fcn(n, x, Fvec, Fjac, Ldfjac, iflag) + if (Nprint > 0) call fcn(n, x, Fvec, Fjac, Ldfjac, iflag, udata) end subroutine hybrj !***************************************************************************************** @@ -1396,7 +1407,7 @@ end subroutine hybrj ! must provide a subroutine which calculates the functions ! and the jacobian. - subroutine hybrj1(fcn, n, x, Fvec, Fjac, Ldfjac, Tol, Info, Wa, Lwa) + subroutine hybrj1(fcn, n, x, Fvec, Fjac, Ldfjac, Tol, Info, Wa, Lwa, udata) implicit none @@ -1433,6 +1444,7 @@ subroutine hybrj1(fcn, n, x, Fvec, Fjac, Ldfjac, Tol, Info, Wa, Lwa) !! orthogonal matrix q produced by the qr factorization !! of the final approximate jacobian. real(wp), intent(inout) :: Wa(Lwa) !! a work array of length lwa. + class(*), intent(inout), optional :: udata !! user data integer :: j, lr, maxfev, mode, nfev, njev, nprint real(wp) :: xtol @@ -1455,7 +1467,7 @@ subroutine hybrj1(fcn, n, x, Fvec, Fjac, Ldfjac, Tol, Info, Wa, Lwa) lr = (n*(n + 1))/2 call hybrj(fcn, n, x, Fvec, Fjac, Ldfjac, xtol, maxfev, Wa(1), mode, & factor, nprint, Info, nfev, njev, Wa(6*n + 1), lr, Wa(n + 1), & - Wa(2*n + 1), Wa(3*n + 1), Wa(4*n + 1), Wa(5*n + 1)) + Wa(2*n + 1), Wa(3*n + 1), Wa(4*n + 1), Wa(5*n + 1), udata) if (Info == 5) Info = 4 end if @@ -1471,7 +1483,7 @@ end subroutine hybrj1 subroutine lmder(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & Diag, Mode, Factor, Nprint, Info, Nfev, Njev, Ipvt, Qtf, & - Wa1, Wa2, Wa3, Wa4) + Wa1, Wa2, Wa3, Wa4, udata) implicit none @@ -1577,6 +1589,7 @@ subroutine lmder(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & real(wp), intent(inout) :: Wa2(n) !! work array of length n. real(wp), intent(inout) :: Wa3(n) !! work array of length n. real(wp), intent(inout) :: Wa4(m) !! work array of length n. + class(*), intent(inout), optional :: udata !! user data integer :: i, iflag, iter, j, l real(wp) :: actred, delta, dirder, fnorm, fnorm1, gnorm, par, & @@ -1608,7 +1621,7 @@ subroutine lmder(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & ! and calculate its norm. iflag = 1 - call fcn(m, n, x, Fvec, Fjac, Ldfjac, iflag) + call fcn(m, n, x, Fvec, Fjac, Ldfjac, iflag, udata) Nfev = 1 if (iflag >= 0) then fnorm = enorm(m, Fvec) @@ -1623,7 +1636,7 @@ subroutine lmder(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & ! calculate the jacobian matrix. 20 iflag = 2 - call fcn(m, n, x, Fvec, Fjac, Ldfjac, iflag) + call fcn(m, n, x, Fvec, Fjac, Ldfjac, iflag, udata) Njev = Njev + 1 if (iflag >= 0) then @@ -1632,7 +1645,7 @@ subroutine lmder(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & if (Nprint > 0) then iflag = 0 if (mod(iter - 1, Nprint) == 0) & - call fcn(m, n, x, Fvec, Fjac, Ldfjac, iflag) + call fcn(m, n, x, Fvec, Fjac, Ldfjac, iflag, udata) if (iflag < 0) goto 100 end if @@ -1734,7 +1747,7 @@ subroutine lmder(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & ! evaluate the function at x + p and calculate its norm. iflag = 1 - call fcn(m, n, Wa2, Wa4, Fjac, Ldfjac, iflag) + call fcn(m, n, Wa2, Wa4, Fjac, Ldfjac, iflag, udata) Nfev = Nfev + 1 if (iflag >= 0) then fnorm1 = enorm(m, Wa4) @@ -1826,7 +1839,7 @@ subroutine lmder(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & 100 if (iflag < 0) Info = iflag iflag = 0 - if (Nprint > 0) call fcn(m, n, x, Fvec, Fjac, Ldfjac, iflag) + if (Nprint > 0) call fcn(m, n, x, Fvec, Fjac, Ldfjac, iflag, udata) end subroutine lmder !***************************************************************************************** @@ -1839,7 +1852,7 @@ end subroutine lmder ! general least-squares solver lmder. the user must provide a ! subroutine which calculates the functions and the jacobian. - subroutine lmder1(fcn, m, n, x, Fvec, Fjac, Ldfjac, Tol, Info, Ipvt, Wa, Lwa) + subroutine lmder1(fcn, m, n, x, Fvec, Fjac, Ldfjac, Tol, Info, Ipvt, Wa, Lwa, udata) implicit none procedure(fcn_lmder) :: fcn !! user-supplied subroutine which @@ -1899,6 +1912,7 @@ subroutine lmder1(fcn, m, n, x, Fvec, Fjac, Ldfjac, Tol, Info, Ipvt, Wa, Lwa) !! part of fjac contains information generated during !! the computation of r. real(wp), intent(inout) :: Wa(Lwa) !! a work array of length lwa. + class(*), intent(inout), optional :: udata !! user data integer :: maxfev, mode, nfev, njev, nprint real(wp) :: ftol, gtol, xtol @@ -1920,7 +1934,7 @@ subroutine lmder1(fcn, m, n, x, Fvec, Fjac, Ldfjac, Tol, Info, Ipvt, Wa, Lwa) nprint = 0 call lmder(fcn, m, n, x, Fvec, Fjac, Ldfjac, ftol, xtol, gtol, maxfev, & & Wa(1), mode, factor, nprint, Info, nfev, njev, Ipvt, Wa(n + 1)& - & , Wa(2*n + 1), Wa(3*n + 1), Wa(4*n + 1), Wa(5*n + 1)) + & , Wa(2*n + 1), Wa(3*n + 1), Wa(4*n + 1), Wa(5*n + 1), udata) if (Info == 8) Info = 4 end if @@ -1937,7 +1951,7 @@ end subroutine lmder1 subroutine lmdif(fcn, m, n, x, Fvec, Ftol, Xtol, Gtol, Maxfev, Epsfcn, Diag, & Mode, Factor, Nprint, Info, Nfev, Fjac, Ldfjac, Ipvt, & - Qtf, Wa1, Wa2, Wa3, Wa4) + Qtf, Wa1, Wa2, Wa3, Wa4, udata) implicit none procedure(func2) :: fcn !! the user-supplied subroutine which @@ -2046,6 +2060,7 @@ subroutine lmdif(fcn, m, n, x, Fvec, Ftol, Xtol, Gtol, Maxfev, Epsfcn, Diag, & real(wp), intent(inout) :: Wa2(n) !! work array of length n. real(wp), intent(inout) :: Wa3(n) !! work array of length n. real(wp), intent(inout) :: Wa4(m) !! work array of length n. + class(*), intent(inout), optional :: udata !! user data integer :: i, iflag, iter, j, l real(wp) :: actred, delta, dirder, fnorm, & @@ -2077,7 +2092,7 @@ subroutine lmdif(fcn, m, n, x, Fvec, Ftol, Xtol, Gtol, Maxfev, Epsfcn, Diag, & ! and calculate its norm. iflag = 1 - call fcn(m, n, x, Fvec, iflag) + call fcn(m, n, x, Fvec, iflag, udata) Nfev = 1 if (iflag >= 0) then fnorm = enorm(m, Fvec) @@ -2092,7 +2107,7 @@ subroutine lmdif(fcn, m, n, x, Fvec, Ftol, Xtol, Gtol, Maxfev, Epsfcn, Diag, & ! calculate the jacobian matrix. 20 iflag = 2 - call fdjac2(fcn, m, n, x, Fvec, Fjac, Ldfjac, iflag, Epsfcn, Wa4) + call fdjac2(fcn, m, n, x, Fvec, Fjac, Ldfjac, iflag, Epsfcn, Wa4, udata) Nfev = Nfev + n if (iflag >= 0) then @@ -2101,7 +2116,7 @@ subroutine lmdif(fcn, m, n, x, Fvec, Ftol, Xtol, Gtol, Maxfev, Epsfcn, Diag, & if (Nprint > 0) then iflag = 0 if (mod(iter - 1, Nprint) == 0) & - call fcn(m, n, x, Fvec, iflag) + call fcn(m, n, x, Fvec, iflag, udata) if (iflag < 0) goto 100 end if @@ -2204,7 +2219,7 @@ subroutine lmdif(fcn, m, n, x, Fvec, Ftol, Xtol, Gtol, Maxfev, Epsfcn, Diag, & ! evaluate the function at x + p and calculate its norm. iflag = 1 - call fcn(m, n, Wa2, Wa4, iflag) + call fcn(m, n, Wa2, Wa4, iflag, udata) Nfev = Nfev + 1 if (iflag >= 0) then fnorm1 = enorm(m, Wa4) @@ -2302,7 +2317,7 @@ subroutine lmdif(fcn, m, n, x, Fvec, Ftol, Xtol, Gtol, Maxfev, Epsfcn, Diag, & 100 if (iflag < 0) Info = iflag iflag = 0 - if (Nprint > 0) call fcn(m, n, x, Fvec, iflag) + if (Nprint > 0) call fcn(m, n, x, Fvec, iflag, udata) end subroutine lmdif !***************************************************************************************** @@ -2316,7 +2331,7 @@ end subroutine lmdif ! subroutine which calculates the functions. the jacobian is ! then calculated by a forward-difference approximation. - subroutine lmdif1(fcn, m, n, x, Fvec, Tol, Info, Iwa, Wa, Lwa) + subroutine lmdif1(fcn, m, n, x, Fvec, Tol, Info, Iwa, Wa, Lwa, udata) implicit none procedure(func2) :: fcn !! the user-supplied subroutine which @@ -2358,6 +2373,7 @@ subroutine lmdif1(fcn, m, n, x, Fvec, Tol, Info, Iwa, Wa, Lwa) real(wp), intent(out) :: Fvec(m) !! an output array of length m which contains !! the functions evaluated at the output x. real(wp), intent(inout) :: Wa(Lwa) !! a work array of length lwa. + class(*), intent(inout), optional :: udata !! user data integer :: maxfev, mode, mp5n, nfev, nprint real(wp) :: epsfcn, ftol, gtol, xtol @@ -2382,7 +2398,8 @@ subroutine lmdif1(fcn, m, n, x, Fvec, Tol, Info, Iwa, Wa, Lwa) mp5n = m + 5*n call lmdif(fcn, m, n, x, Fvec, ftol, xtol, gtol, maxfev, epsfcn, Wa(1), & mode, factor, nprint, Info, nfev, Wa(mp5n + 1), m, Iwa, & - Wa(n + 1), Wa(2*n + 1), Wa(3*n + 1), Wa(4*n + 1), Wa(5*n + 1)) + Wa(n + 1), Wa(2*n + 1), Wa(3*n + 1), Wa(4*n + 1), Wa(5*n + 1), & + udata) if (Info == 8) Info = 4 end if @@ -2627,7 +2644,7 @@ end subroutine lmpar subroutine lmstr(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & Diag, Mode, Factor, Nprint, Info, Nfev, Njev, Ipvt, Qtf, & - Wa1, Wa2, Wa3, Wa4) + Wa1, Wa2, Wa3, Wa4, udata) implicit none procedure(fcn_lmstr) :: fcn !! user-supplied subroutine which @@ -2729,6 +2746,7 @@ subroutine lmstr(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & real(wp) :: Wa2(n) !! work array of length n. real(wp) :: Wa3(n) !! work array of length n. real(wp) :: Wa4(m) !! work array of length m. + class(*), intent(inout), optional :: udata !! user data integer :: i, iflag, iter, j, l real(wp) :: actred, delta, dirder, fnorm, & @@ -2762,7 +2780,7 @@ subroutine lmstr(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & ! and calculate its norm. iflag = 1 - call fcn(m, n, x, Fvec, Wa3, iflag) + call fcn(m, n, x, Fvec, Wa3, iflag, udata) Nfev = 1 if (iflag < 0) goto 200 fnorm = enorm(m, Fvec) @@ -2778,7 +2796,7 @@ subroutine lmstr(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & 100 if (Nprint > 0) then iflag = 0 - if (mod(iter - 1, Nprint) == 0) call fcn(m, n, x, Fvec, Wa3, iflag) + if (mod(iter - 1, Nprint) == 0) call fcn(m, n, x, Fvec, Wa3, iflag, udata) if (iflag < 0) goto 200 end if @@ -2795,7 +2813,7 @@ subroutine lmstr(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & end do iflag = 2 do i = 1, m - call fcn(m, n, x, Fvec, Wa3, iflag) + call fcn(m, n, x, Fvec, Wa3, iflag, udata) if (iflag < 0) goto 200 temp = Fvec(i) call rwupdt(n, Fjac, Ldfjac, Wa3, Qtf, temp, Wa1, Wa2) @@ -2902,7 +2920,7 @@ subroutine lmstr(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & ! evaluate the function at x + p and calculate its norm. iflag = 1 - call fcn(m, n, Wa2, Wa4, Wa3, iflag) + call fcn(m, n, Wa2, Wa4, Wa3, iflag, udata) Nfev = Nfev + 1 if (iflag >= 0) then fnorm1 = enorm(m, Wa4) @@ -2998,7 +3016,7 @@ subroutine lmstr(fcn, m, n, x, Fvec, Fjac, Ldfjac, Ftol, Xtol, Gtol, Maxfev, & 200 if (iflag < 0) Info = iflag iflag = 0 - if (Nprint > 0) call fcn(m, n, x, Fvec, Wa3, iflag) + if (Nprint > 0) call fcn(m, n, x, Fvec, Wa3, iflag, udata) end subroutine lmstr !***************************************************************************************** @@ -3012,7 +3030,7 @@ end subroutine lmstr ! lmstr. the user must provide a subroutine which calculates ! the functions and the rows of the jacobian. - subroutine lmstr1(fcn, m, n, x, Fvec, Fjac, Ldfjac, Tol, Info, Ipvt, Wa, Lwa) + subroutine lmstr1(fcn, m, n, x, Fvec, Fjac, Ldfjac, Tol, Info, Ipvt, Wa, Lwa, udata) implicit none procedure(fcn_lmstr) :: fcn !! user-supplied subroutine which @@ -3070,6 +3088,7 @@ subroutine lmstr1(fcn, m, n, x, Fvec, Fjac, Ldfjac, Tol, Info, Ipvt, Wa, Lwa) !! part of fjac contains information generated during !! the computation of r. real(wp), intent(inout) :: Wa(Lwa) !! a work array of length lwa. + class(*), intent(inout), optional :: udata !! user data integer :: maxfev, mode, nfev, njev, nprint real(wp) :: ftol, gtol, xtol @@ -3093,7 +3112,7 @@ subroutine lmstr1(fcn, m, n, x, Fvec, Fjac, Ldfjac, Tol, Info, Ipvt, Wa, Lwa) nprint = 0 call lmstr(fcn, m, n, x, Fvec, Fjac, Ldfjac, ftol, xtol, gtol, maxfev, & Wa(1), mode, factor, nprint, Info, nfev, njev, Ipvt, Wa(n + 1), & - Wa(2*n + 1), Wa(3*n + 1), Wa(4*n + 1), Wa(5*n + 1)) + Wa(2*n + 1), Wa(3*n + 1), Wa(4*n + 1), Wa(5*n + 1), udata) if (Info == 8) Info = 4 end if @@ -3808,4 +3827,4 @@ end subroutine rwupdt !***************************************************************************************** end module minpack_module -!***************************************************************************************** \ No newline at end of file +!***************************************************************************************** diff --git a/test/test_hybrd.f90 b/test/test_hybrd.f90 index 5e017d4..b722c27 100644 --- a/test/test_hybrd.f90 +++ b/test/test_hybrd.f90 @@ -87,11 +87,12 @@ program test end do end program test - subroutine fcn(n,x,Fvec,Iflag) + subroutine fcn(n,x,Fvec,Iflag,udata) implicit none integer n , Iflag double precision x(n) , Fvec(n) + class(*), optional :: udata ! ********** ! ! THE CALLING SEQUENCE OF FCN SHOULD BE IDENTICAL TO THE diff --git a/test/test_hybrj.f90 b/test/test_hybrj.f90 index a1e3213..b412bcb 100644 --- a/test/test_hybrj.f90 +++ b/test/test_hybrj.f90 @@ -93,11 +93,12 @@ program test end do end program test - subroutine fcn(n,x,Fvec,Fjac,Ldfjac,Iflag) + subroutine fcn(n,x,Fvec,Fjac,Ldfjac,Iflag,udata) implicit none integer n , Ldfjac , Iflag double precision x(n) , Fvec(n) , Fjac(Ldfjac,n) + class(*), optional :: udata ! ********** ! ! THE CALLING SEQUENCE OF FCN SHOULD BE IDENTICAL TO THE diff --git a/test/test_lmder.f90 b/test/test_lmder.f90 index 8a11340..6b10676 100644 --- a/test/test_lmder.f90 +++ b/test/test_lmder.f90 @@ -94,7 +94,7 @@ program test ! FUNCTION AND JACOBIAN SUBROUTINES SSQFCN AND SSQJAC WITH ! THE APPROPRIATE VALUE OF PROBLEM NUMBER (NPROB). - subroutine fcn(m, n, x, Fvec, Fjac, Ldfjac, Iflag) + subroutine fcn(m, n, x, Fvec, Fjac, Ldfjac, Iflag, udata) implicit none @@ -112,6 +112,7 @@ subroutine fcn(m, n, x, Fvec, Fjac, Ldfjac, Iflag) real(wp), intent(in) :: x(n) !! independant variable vector real(wp), intent(inout) :: fvec(m) !! value of function at `x` real(wp), intent(inout) :: fjac(ldfjac, n) !! jacobian matrix at `x` + class(*), intent(inout), optional :: udata select case (iflag) case (1) @@ -994,4 +995,4 @@ end subroutine ssqfcn !***************************************************************************************** end program test -!***************************************************************************************** \ No newline at end of file +!***************************************************************************************** diff --git a/test/test_lmdif.f90 b/test/test_lmdif.f90 index 486ad4c..99cc351 100644 --- a/test/test_lmdif.f90 +++ b/test/test_lmdif.f90 @@ -96,11 +96,12 @@ program test end do end program test - subroutine fcn(m,n,x,Fvec,Iflag) + subroutine fcn(m,n,x,Fvec,Iflag,udata) implicit none integer m , n , Iflag double precision x(n) , Fvec(m) + class(*), optional :: udata ! ********** ! ! THE CALLING SEQUENCE OF FCN SHOULD BE IDENTICAL TO THE diff --git a/test/test_lmstr.f90 b/test/test_lmstr.f90 index 85bbefc..b31b36e 100644 --- a/test/test_lmstr.f90 +++ b/test/test_lmstr.f90 @@ -103,11 +103,12 @@ program test end program test - subroutine fcn(m,n,x,Fvec,Fjrow,Iflag) + subroutine fcn(m,n,x,Fvec,Fjrow,Iflag,udata) implicit none integer m , n , Iflag double precision x(n) , Fvec(m) , Fjrow(n) + class(*), optional :: udata ! ********** ! ! THE CALLING SEQUENCE OF FCN SHOULD BE IDENTICAL TO THE