Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] A Modern Fortran Interface #233

Closed
wants to merge 14 commits into from
Closed

Conversation

ivan-pi
Copy link

@ivan-pi ivan-pi commented Nov 13, 2018

Hello Steven,

I have been working on a modern Fortran interface for NLopt that is based upon the Fortran/C interoperability features defined in the newer Fortran language standards (> 2003). The new interface is a large improvement over the old interface that uses an integer*8 as an opaque pointer to the "opt" class. Instead a derived-type opt is created that encapsulates the "opt" class as a C pointer and directly calls the C routines for access to the internals. It is quite similar to the C++ interface actually. The only thing missing at this point is the mechanism for returning error codes and the tutorial and API description are not finished completely.

An adaptor strategy is used in order to hide implementation details of the C interface, particularly passing data to the callback functions (the objectives and constraints). The new Fortran way of doing this is based upon a "functor" pattern and expects the users to extend an abstract type. Alternatively the data can be safely passed as a c_ptr and must be unpacked "manually" by the user.

I would be happy to get some input from you and other developers on what changes should I make that both preserve the philosophy of NLopt but are familiar to the modern Fortran programmer, before you would consider merging.

Looking forward to your response.

Sincerely,

Ivan

@jschueller
Copy link
Collaborator

jschueller commented Nov 14, 2018

The tests will need some updating, see #234.

@ivan-pi
Copy link
Author

ivan-pi commented Nov 15, 2018

Thank you Julien for preparing the CMake.

I have added a procedural test case where I access the C API directly and a second object-oriented example where I make use of derived-type extension in order to package the callback functions and required data together. I followed this discussion to get a minimal working Fortran CMake. To my dismay, I just noticed that the adaptor pattern introduces a memory leak; this happens after a call to remove_inequality/equality_constraints() as the memory allocated in Fortran becomes lost. For the objective function I added an type(adaptor) instance into my opt class and edited the finalizer. In order to fix the constraints I currently see no other option than to keep a linked list of the Fortran-allocated constraint functions on the Fortran side.

A few more design choices I would like to discuss are:

  • The name of the "opt" derived-type could be changed to opt_type or nlopt_opt, so that the user does not need to prepend "my". Example:
use nlopt
implicit none
type(opt_type) :: opt
! ... do stuff with opt ...
end
  • Currently the user can obtain the integer return flags as optional arguments to most functions. Error checking is completely left to the user. Maybe a basic "mythrow" mechanism, similar to the C++ API would be more helpful.
  • I have provided two ways to pass callback functions for the objectives and constraints. One mechanism is with a c_ptr instance (just like in the C API), and the other one is the extended type mechanism (that currently causes a memory leak). Does any other mechanism make sense?
  • Personally I would like to have the algorithm integers and error and success flags directly accesible from the nlopt module. Then I only need to import one module. The current automatically generated nlopt.f file is missing the public keyword in order for me to simply include it. This however interferes with the existing Fortran interface.

@ivan-pi
Copy link
Author

ivan-pi commented Nov 15, 2018

The tests are compiled and run succesfully on osx, but the linux build fails due to an old version of gfortran (4.8.4) that does not support finalizers. I have built the Fortran interface successfully with gfortran-5 (5.4.0, there are some harmless compiler messages due to a bug in the compiler concerning finalization), or even better with gfortran-8 (8.1.0).

I don't have much experience with Travis, but according to these guidelines I just need to include ubuntu-toolchain-r-test as a source and replace gfortran with gfortran-5 or higher. Would this affect the other packages?

@ivan-pi ivan-pi changed the title A Modern Fortran Interface [WIP] A Modern Fortran Interface Nov 15, 2018
@stevengj
Copy link
Owner

Would it be a lot of trouble to have a cmake test to detect whether a supported Fortran compiler is available, and disable this API if not?

@aitap
Copy link
Contributor

aitap commented Apr 14, 2019

Excuse me for butting in, but one way to accomplish that would be to explicitly test whether a dummy program using the least frequently supported feature can be compiled:

include(CheckFortranSourceCompiles)
CHECK_Fortran_SOURCE_COMPILES(
	"module mod_test_finalizers
	 type test_finalizers
	  contains
	  final :: finalizer
	 end type
	 contains
	 subroutine finalizer(x)
	  type(test_finalizers) :: x
	 end subroutine
	end module
	program program_test_finalizer
	 use mod_test_finalizers
	 type(test_finalizers) :: x
	end program"
	HAVE_F03_FINALIZERS
	SRC_EXT "f90"
)

@gabrielgggg
Copy link

This would be very very helpful!

@ivan-pi
Copy link
Author

ivan-pi commented Aug 12, 2021

Hi @gabrielgggg, you might want to check out the new Fortran bindings: https://github.com/grimme-lab/nlopt-f

I will close this issue in favor of that project.

@ivan-pi ivan-pi closed this Aug 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants