Calling Fortran routine within Jump objective function

Hello,
I have a question regarding the call of Fortran routines within a Jump objective function. With the help of several forum posts, I managed to write Julia and Fortran code so I can call the Fortran routine from Julia outside of a Jump objective function.
In this case, the Julia code looks like this

ffreturn = zeros(Float64,1)
xx = zeros(Float64,2)
xx[1] = 2.0
xx[2] = 4.2
ccall((:FCN, "C:/Users/.../Subroutine.dll"),
 Cvoid, (Ptr{Array{Float64,2}},Ptr{Array{Float64,1}}),xx,ffreturn)
println(ffreturn[1])

and on the Fortran side, the code is

module objective
  implicit none
  private
  public :: FCN

contains

  subroutine FCN(x,fvalue) bind(C,name="FCN")
    use, intrinsic :: iso_c_binding, only: c_double
    implicit none

    real(c_double), intent(in) :: x(2)
    real(c_double), intent(inout) :: fvalue(1)

    fvalue(1) = (x(1)-2.)**2 + (x(2)-3.)**2

  end subroutine FCN

end module objective

in this setup, everything works fine. However, when I try to call the Fortran routine from within a Jump objective function, the code is still running and the optimizer finishes, however, the Fortran routine only receives zeros as input values for x(1) and x(2) throughout the optimization. In this case, the the Julia side looks like this:

using JuMP
using Ipopt

myModel = Model(solver=IpoptSolver())
@variable(myModel, x[1:2]) 

function my_function(x)
    freturn = zeros(Float64,1)
    ccall((:FCN, "C:/Users/.../Subroutine.dll"),
      Cvoid, (Ptr{Array{Float64,2}},Ptr{Array{Float64,1}}),x,freturn)
    fvalue = freturn[1]
    return fvalue
end

@objective(myModel, Min, my_function(x))
status = solve(myModel)

Is this not working because of Jumps automatic differentiation approach and because of this, x is actually some sort of overloaded structure? The result of typeof(x) only returns Variable. Or do I need to change something on the Fortran side?

Thank you in advance for any helpful suggestions!

  1. You will need to register your function. See: https://www.juliaopt.org/JuMP.jl/v0.20.0/nlp/#User-defined-Functions-1.
  2. You’ll also need to change your function to remove the vector input. See: https://www.juliaopt.org/JuMP.jl/v0.20.0/nlp/#User-defined-functions-with-vector-inputs-1
  3. Since JuMP can’t automatically differentiate your fortran code, you will also need to supply a gradient. There is an example in the user-defined function section. If you can’t supply a gradient, JuMP isn’t the right tool for the job. You should look at NLopt.jl or Optim.jl.
2 Likes

Thank you for your feedback! I will try it out.