# Interface Fortran 2003

Tasmanian 7.1 comes with new Fortran 2003 interface generated by [Swig-Fortran](https://github.com/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 new module is called `Tasmanian` (without the sg suffix), and it is incompatible with the Fortran 90/95, i.e., use one or the other but not both. A `TasmanianSparseGrid` type is introduced as before, but the interface is fully object-oriented. Currently, only the raw-array interface of the Tasmanian Sparse Grid module has been implemented, but Dream and Addon modules are under development.

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
(work in progress)

### 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., `grid%makeGlobalGrid()`.

The static array API works with allocatable variables but requires user allocation of memory and is not very expressive. Helper methods are provided that return ready allocated pointer variables:
```
    real(C_DOUBLE), dimension(:,:), pointer :: points
    ...
    points => tsgGetPoints(grid)
    ...
    deallocate(points)
```
The helper function are:
```
    points => tsgGetLoadedPoints(grid) ->  grid%getLoadedPoints(points)
    points => tsgGetNeededPoints(grid) ->  grid%getNeededPoints(points)
    points => tsgGetLoaded(grid)       ->  grid%getPoints(points)

    weights => tsgGetQuadratureWeights(grid) -> grid%getQuadratureWeights(weights)
```
