CooT
CooT

Reputation: 51

Fortran minimization of a function with additional arguments

In fortran I have an external optimization routine that takes as an input the function f(x) and the starting point and returns the value for local minimum. For example if the function is called minimum:

minimum(f,x0,xopt)

The problem is that the function I need to minimize depends on some additional arguments that are not part of the minimization routine: f(x,data).

How can I overcome this issue. In matlab I would use anonymous function

g=@(x) f(x,data)

minimum(g, x0, xopt)

However as I understant in fortran 90 there are no anonymous function.

Thanks.

Upvotes: 5

Views: 1499

Answers (2)

You don't need anonymous functions for this. Your Matlab example is also not anonymous in the end, it has a name g.

Fortran internal functions are of great use here (Fortran 2008 feature, but supported in gfortran and ifort, not supported in Solaris Studio):

call minimum(g, x0, xopt)

contains

  real function g(x)
    real, intent(in) :: x
    g = f(x,data)
  end function

end

Upvotes: 7

TroyHaskin
TroyHaskin

Reputation: 8401

You have the right idea from MATLAB in that you can create another function that returns f's value while encapsulating data. Two options come to mind.

If data is fixed at compile-time, you can wrap f in a module that uses it:

Module Foo
    type(blah) :: data = ...
    Contains
        Real Function f(x)
          ! data is visible here.
        End Function f
End Module Foo

If data is more dynamic through user-input or calculation, you can define a function that returns data and call it from within f:

Real Function f(x)
  ...
  Type(blah), Save :: data
  Logical, Save :: data_not_loaded = .True.
  If data_not_loaded Then
    data = load_data(...)
    data_not_loaded = .False.
  End If
  ...
End Function f

Instead of a load_data() function, you could also make a registry-like subroutine to first set the value of data earlier in the program and then retrieve data from within f. However, the logic in f won't change that much.

There might also be a method using procedure pointers, but I've never used that feature in Fortran, so I may be wrong.

Upvotes: 2

Related Questions