-
Notifications
You must be signed in to change notification settings - Fork 63
BMI Fortran
To enable Fortran integration functionality, the CMake build system has to be generated with the NGEN_WITH_BMI_FORTRAN
CMake variable set to ON
.
Nextgen takes advantage of the Fortran iso_c_binding
module to achieve interoperability with Fortran modules. In short, this works through use of an intermediate middleware module maintained within Nextgen. This module handles the (majority of the) binding through proxy functions that make use of the actual external BMI Fortran module.
The middleware module source is located in extern/iso_c_fortran_bmi/.
The proxy functions require an opaque handle to a created BMI Fortran object to be provided as an argument, so such an object and its opaque handle must be setup and returned via a
register_bmi
function.
Because of the use of iso_c_bindings
, integrating with a Fortran BMI module works very similarly to integrating with a C BMI module, where a shared library is dynamically loaded. An extra bootstrapping registration function is also, again, required.
As with C, a registration function must be provided by the module, beyond what is implemented for BMI. It should look very similar to the example below. In fact, it is likely sufficient to simply modify the use bminoahowp
and type(bmi_noahowp), target, save :: bmi_model
lines to suit the module in question.
This function should receive an opaque pointer and set it to point to a created BMI object of the appropriate type for the module. Note that while save
is being used in a way that persists only the initial object, since this will be used within the scope of a dynamic library loaded specifically for working with a particular catchment formulation, it should not cause issues.
function register_bmi(this) result(bmi_status) bind(C, name="register_bmi")
use, intrinsic:: iso_c_binding, only: c_ptr, c_loc, c_int
use bminoahowp
implicit none
type(c_ptr) :: this ! If not value, then from the C perspective `this` is a void**
integer(kind=c_int) :: bmi_status
!Create the momdel instance to use
type(bmi_noahowp), target, save :: bmi_model !should be safe, since this will only be used once within scope of dynamically loaded library
!Create a simple pointer wrapper
type(box), pointer :: bmi_box
!allocate the pointer box
allocate(bmi_box)
!allocate(bmi_box%ptr, source=bmi_model)
bmi_box%foobar = 42
!associate the wrapper pointer the created model instance
bmi_box%ptr => bmi_model
!Return the pointer to box
this = c_loc(bmi_box)
bmi_status = BMI_SUCCESS
end function register_bmi
An example implementation for an appropriate BMI model as a Fortran module/derived type is provided in the project.
Tutorial
Getting Started
Configuration
Technical References