Table of Contents
In this exercise, you will wrap an existing (“legacy”) software library as a CCA component (i.e. “componentize” it). The CCA is designed to make it as easy as possible to componentize existing software, and a significant fraction of CCA components are created in this way. While this specific example is minimal, the techniques used to produce a component that uses an existing library with minimal or no modifications to legacy code is applicable for large legacy codes.
The integrator components are Fortran90 wrappers over an existing legacy integrator library. For the purposes of this exercise, the legacy library is located in the student-src/legacy/f90 directory. The Integrator.f90 code implements a midpoint rule integration approach. Our goal is to create an integrator component that uses the legacy implementation to compute the integral of a function.
Our Fortran legacy library (in student-src/legacy/f90) contains an integration algorithm, which can be invoked as follows:
call integrate_mp(functionParams, lowBound, upBound, count)
where functionParams is a variable of type FunctionParams_t. This type is used to store various function-specific attributes, such as the constant coefficients. The definition of this type is in the FunctionModule module, in the LegacyFunctionModule.f90 file:
file: student-src/legacy/f90/LegacyFunctionModule.f90
module FunctionModule
implicit none
type FunctionParams_t
private
real, dimension(3) :: coef
end type FunctionParams_t
contains
subroutine init(params, coefficients)
! !INPUT PARAMETERS:
type(FunctionParams_t), intent(INOUT) :: params
real, dimension(:), intent(IN) :: coefficients
integer :: i
do i = 1 ,3
params%coef(i) = coefficients(i)
end do
end subroutine init
real function eval(params, x)
! !INPUT PARAMETERS:
type(FunctionParams_t), intent(IN) :: params
real, intent(IN) :: x
eval = 2 * x
end function eval
end module FunctionModule
The legacy integrator (in Integrator.f90) uses the midpoint integration algorithm to integrate an arbitrary function that has an eval function and uses FunctionParams_t to store its state. The complete code for the legacy integrator follows.
file: student-src/legacy/f90/Integrator.f90 module Integrator use FunctionModuleimplicit none contains real function integrate_mp(functionParams, lowBound, upBound, count) implicit none ! !INPUT PARAMETERS: type(FunctionParams_t),intent(IN) :: functionParams
real, intent(IN) :: lowBound real, intent(IN) :: upBound integer, intent(IN) :: count ! !LOCAL VARIABLES: real :: sum, h, x, dcount, func_val integer :: i integrate_mp = -1 ! Compute integral sum = 0.0 h = (upBound - lowBound) / count do i = 0, count x = lowBound + h * (i + 0.5) func_val = eval(functionParams, x)
sum = sum + func_val end do integrate_mp = sum * h end function integrate_mp end module Integrator
Notes on the Integrator.f90 file
![]() |
The Integrator module uses the FunctionModule, which means that the integrator can only evaluate functions defined in this FunctionModule, or other Fortran modules that "extend" it. |
![]() |
The functionParamsargument of the integrator is the only way function parameters can be passed through to the function being evaluated. |
![]() |
This evaluates the function given the parameters passed into the Integrator. |