4.2. The FunctionModule wrapper.

To enable the legacy integrator to evaluate functions that are not defined in the same fashion as the FunctionModule above (i.e., such that they define the eval method or equivalent interface that takes a FunctionParams_t argument and a real argument) is to create another FunctionModule that allows a FunctionPort to be used for the function evaluation.

file: $STUDENT_SRC/legacy/f90/FunctionModuleWrapper.f90
module FunctionModule

  ! This module replaces the FunctionModule used by the legacy integrator. 
  ! Thus, we need to makes sure that this module is first in the module
  ! search path when building the integrator component.
  
  ! We need to include the function port definitions
  use function_FunctionPort_type                           (1)
  use function_FunctionPort

  implicit none

  type FunctionParams_t
     sequence              ! required for component version
     type(function_FunctionPort_t) funcPort                (2)
  end type FunctionParams_t

  interface eval                                           (3)
     ! This is the one called by the legacy Integrator
     module procedure evalFunction
  end interface

contains

  subroutine setFunctionPort(params, port)
    type(FunctionParams_t),        intent(OUT) :: params
    type(function_FunctionPort_t), intent(IN)  :: port

    params%funcPort = port
  end subroutine setFunctionPort
    
  real function evalFunction(params, x)
    use function_FunctionPort
    ! input parameters:
    type(FunctionParams_t), intent(IN) :: params
    real,                   intent(IN) :: x

    ! local variablesreal 
    real (selected_real_kind(15, 307)) :: xx
    real (selected_real_kind(15, 307)) :: retval

    ! Compute value by calling the function evaluation in FunctionModule
    xx = x
    call evaluate(params%funcPort, xx, retval)             (4)
    evalFunction = retval

  end function evalFunction

end module FunctionModule

Notes on the FunctionModuleWrapper.f90 file

1

The FunctionModuleWrapper module uses (includes) the FunctionPort_type and FunctionPort modules (in $STUDENT_SRC/ports/function/f90, whose definitions were automatically generated by Babel from the SIDL definition of function.FunctionPort ($STUDENT_SRC/ports/sidl/function.sidl).

2

The FunctionParams_t type that was originally defined in LegacyFunctionModule.f90.

3

The legacy FunctionModule contained the eval function; in our wrapper implementation, we create an eval interface that contains the new evaluation function, evalFunction.

4

This is the call to the evaluate subroutine of the FunctionPort, using the parameters passed to the evalFunction. Note that the params%funcPort is supposed to have already been set by the caller by using the setFunctionPort subroutine defined in this module.

[Note] Note

In one of the first steps of this tutorial, the entire tutorial tree was built (see Appendix C, Building the Tutorial and Student Code Trees), including the sources in the $STUDENT_SRC/legacy/f90 directory and its subdirectories. Two distinct libraries were created, one containing only legacy codes (lib/libLegacyIntegrator.a), and another one (lib/libWrappedLegacyIntegrator.a) containing the FunctionModule definition in FunctionModuleWrapper.f90 instead of the FunctionModule definition definition contained in LegacyFunctionModule.f90. Also, the compiled modules for each version (legacy and wrapped) are put in separate include directories: include for the legacy code, and include_w for the wrapped version. While the simple application example (in simpleApp/Main.f90) uses only the legacy codes, the include_w directory and the lib/libWrappedLegacyIntegrator.a are used in the compilation of the Midpoint integrator component that you will write in the steps that follow.