Doxygen 1.15.0
Toolkit for Adaptive Stochastic Modeling and Non-Intrusive ApproximatioN: Tasmanian v8.2
Loading...
Searching...
No Matches
Interface Fortran 2003

Tasmanian comes with Fortran 2003 interface generated by Swig-Fortran. The automatic generation makes the code easy to maintain and support, and the generation process is done off-line by the development team; hence, users are not required to install Swig and can use the interface with just a regular Fortran compiler. Furthermore, the 2003 standard support objects which allows for the OOP interface of Tasmanian C++ to be duplicated similar to Python and thus the on-line C++ Doxygen documentation is now relevant to Fortran as well.

The module is called Tasmanian and requires Fortran 2003 and a class TasmanianSparseGrid type is used. Currently, the Tasmanian Sparse Grid module has been implemented together with the MPI Addons; the Dream module and the remainder of the Addon templates are not supported (possibly in the future).

Simple example:

program tasmanian_demo
use Tasmanian
use, intrinsic :: iso_c_binding
implicit none
type(TasmanianSparseGrid) :: grid
real(C_DOUBLE), dimension(:,:), allocatable :: points
integer :: i, j
grid = TasmanianSparseGrid()
call grid%makeGlobalGrid(2, 1, 1, tsg_type_level, tsg_rule_clenshawcurtis)
allocate(points(grid%getNumDimensions(), grid%getNumPoints()))
call grid%getPoints(points(:, 1))
do i = 1, grid%getNumDimensions()
do j = 1, grid%getNumPoints()
write(*,*) points(i, j)
enddo
enddo
deallocate(points)
call grid%release()
end program tasmanian_demo

Line by line:

  • The TasmanianSparseGrid object must be initialized and deleted with the commands
    grid = TasmanianSparseGrid()
    call grid%release()
  • The make-grid commands have the same syntax as C++ with the enumerate types replaced by integer constants with identical names and the tsg_ prefix.
  • The double-precision type used in all calls is real(C_DOUBLE) but it could easily be the Fortran native DOUBLE PRECISION so long as the type is compatible with C_DOUBLE.
  • The organization of the points is in two dimensional matrix, where each column corresponds to the coordinates of a single point; however, the API accepts only single dimensional arrays (c-style), hence the conversion
    call grid%getPoints(points(:, 1))

See the Included Examples

Several Fortran examples are provided that duplicate the functionality in C++ and Python, which makes it easy to compare and contrast.

Filenames and Strings

Strings works differently between the Fortran, C and C++ languages. Tasmanian I/O methods accept C-style of null-terminated character arrays, but Fortran character arrays are often padded with white spaces. The Fortran trim() command can be used to remove trailing white spaces from the filenames and avoid confusion with C++. See the following example that assumes a file with the name "123" is holding a valid Tasmanian sparse grid and we want to read the grid into a Tasmanian object:

character(len = 3), parameter :: filename = "123"
character(len = 4), parameter :: padded = "123"
grid = TasmanianSparseGrid()
grid%read(filename) ! OK, reads from "123"
! grid%read(padded) ! Bad, tries to read from "123 "
grid%read(trim(padded)) ! OK, removes the extra space

Row-vs-Column Format

C and C++-14 standards do not have a native two dimensional data-structure and many of the inputs and outputs for Tasmanain are logically organized in strips of data with a fixed stride. When interfacing with a language that supports two dimensional data (e.g., matrix type) it is beneficial to make the translation, but without a copy or manual transposing of the data to avoid performance degradation. Therefore, the strips of data are aligned to the dimension of the fastest index, e.g., the rows for a row-major language (Python-numpy) and columns for a column-major one (Fortran). The Matlab interface uses row-major format due to the ascii file standard used in the background.

The five point Clenshaw-Curtis grid has 5 points, (0,0), (0,-1), (0,1), (-1,0) and (1,0). The matrix generated by Fortran will have the organization:

0 0 0 -1 1
0 -1 1 0 0

while the Python and Matlab equivalents would be:

0 0
0 -1
0 1
-1 0
1 0

Factory and Helper Methods and Namespaces

Fortran 2003 does not support namespaces and the wrapper API works directly with user allocated matrices. The make***Grid() factory methods have been replaced with:

TasGrid::makeGlobalGrid => TasmanianGlobalGrid
TasGrid::makeSequenceGrid => TasmanianSequenceGrid
TasGrid::makeLocalPolynomialGrid => TasmanianLocalPolynomialGrid
TasGrid::makeFourierGrid => TasmanianFourierGrid
TasGrid::makeWaveletGrid => TasmanianWaveletGrid
TasGrid::readGrid => TasmanianReadGrid
TasGrid::copyGrid => TasmanianCopyGrid

Although the methods do not support array API and hence anisotropic weights and level limits still require the use of the member functions, e.g., makeGlobalGrid().

The static array API works with allocatable variables but requires user allocation of memory and is not very expressive. Functions that return pointers to pre-allocated data are preferable; however, functions and subroutines cannot share names in generic overloads. Thus, the Fortran functions use alternative names that start with return as opposed to get, e.g.,

real(C_DOUBLE), dimension(:,:), pointer :: points
...
points => grid%returnPoints()
...
deallocate(points)

The helper function are:

points => grid%returnLoadedPoints()
points => grid%returnNeededPoints()
points => grid%returnPoints()
weight => grid%returnQuadratureWeights()
coeffs => grid%returnHierarchicalCoefficients()
coeffs => grid%returnComplexHierarchicalCoefficients()

See the next section for complex numbers.

Complex numbers

Tasmanian Fourier grids utilize complex numbers in the background which is usually opaque to the user. However, the methods to set and get hierarchical coefficients do use complex numbers, see the C++ API for details. The C++ API returns raw pointers which cannot be manipulated directly from within Fortran; hence the C++ methods are replaced with methods that accept and return copies of the data and utilize the complex format (similar to Python and MATLAB). The two methods are:

complex(C_DOUBLE), dimension(:, :), pointer :: coeffs, new_coeffs
...
coeffs => grid%returnComplexHierarchicalCoefficients()
grid%setComplexHierarchicalCoefficients(new_coeffs)

MPI Fortran Capabilities

If Tasmanian has been compiled with MPI support, a second Tasmanian module will be included that contains Fortran wrappers for the MPI C++ templates. The module is called Tasmanian_mpi and must be used in conjunction with Tasmanian, e.g.,

use Tasmanian
use Tasmanian_mpi
use mpi

The Tasmanian_mpi module instantiates the templates as Fortran functions and pre-pends tsg to the names to avoid possible namespace conflicts, e.g.,

ierr = tsgMPIGridSend(grid, destination, tag, comm)
ierr = tsgMPIGridRecv(grid, source, tag, comm)
ierr = tsgMPIGridBcast(grid, root, comm)
ierr = tsgMPIGridScatterOutputs(grid, subgrid, root, tag, comm)

Note, each methods returns the MPI error code returned by C++ which is different from the way MPI usually works under Fortran, but that is due to the way Swig instantiates the templates and the fact that the error comes from MPI call in the C++ section of the code. The templates always work in binary communication mode, since the ASCII mode is mostly for debugging purposes on the C++ side.