Skip to content

memmett/tfortran

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tfortran: Simple pre-processor to help write multi-dimensional Fortran
codes.

Basic usage
===========

To transform ``input`` and write to ``output``::

  $ tfortran [-d DIMENSION] [-i] [-r] [-c] input output

The default dimension is 3.


Known issues
============

#. Error reporting during the transformation process is non-existant.

#. I'm not sure I've settled on the notation... suggestions are welcome.


Transformations
===============

A few simple transforms, by example:

#. Basic indexing (order is preserved)::

   With three indexes:

     1d: <{ nx, ny, nz }>  ->  nx
     2d: <{ nx, ny, nz }>  ->  nx, ny
     3d: <{ nx, ny, nz }>  ->  nx, ny, nz

   With components:

     1d: <{ i, j, k; c }>  ->  i, c
     2d: <{ i, j, k; c }>  ->  i, j, c
     3d: <{ i, j, k; c }>  ->  i, j, k, c

   Auto expansion:

     1d: <{ n }>  ->  n1
     2d: <{ n }>  ->  n1, n2
     3d: <{ n }>  ->  n1, n2, n3

   Auto expansion with components:

     1d: <{ n; c }>  ->  n1, c
     2d: <{ n; c }>  ->  n1, n2, c
     3d: <{ n; c }>  ->  n1, n2, n3, c


   One-dimensional compression (``compress``): if true, a ``1`` or
   ``.`` in the component slot is supressed when the dimension is 1::

       1d: <{ i, j, k; 1 }>  ->  i
       1d: <{ i, j, k; . }>  ->  i
       1d: <{ i, j, k; c }>  ->  i, c
       2d: <{ i, j, k; 1 }>  ->  i, j, 1
       2d: <{ i, j, k; c }>  ->  i, j, c

   This is enabled by default (disable with ``-c``).


#. Modified indexing (order depends on modifiers):

   This is the same as basic indexing (above), except using ``{{`` and
   ``}}``.  Modified indexing is subject to several modifiers:

   #. Interleaved components (``interleave``): if true the component
      piece is moved to the front::

       2d: {{ i, j, k; c }}  ->  c, i, j
       3d: {{ i, j, k; c }}  ->  c, i, j, k

       The is disabled by default (enable with ``-i``).

   #. C/row-major storage (``row_major``): if true the spatial indexes
      are transposed::

       2d: {{ i, j, k; c }}  ->  j, i, c
       3d: {{ i, j, k; c }}  ->  k, j, i, c

      This is disabled by default (enable with ``-r``).

   Note that if both ``row_major`` and ``interleave`` are true, then::

       2d: {{ i, j, k; c }}  ->  c, j, i
       3d: {{ i, j, k; c }}  ->  c, k, j, i


#. Selecting appropriate statements::

     1d: ({ cos(x); cos(x*y); cos(x*y*z) })  ->  cos(x)
     2d: ({ cos(x); cos(x*y); cos(x*y*z) })  ->  cos(x*y)
     3d: ({ cos(x); cos(x*y); cos(x*y*z) })  ->  cos(x*y*z)


#. Concatenation::

     1d: [{ x**2; + y**2; + z**2 }]  ->  x**2
     2d: [{ x**2; + y**2; + z**2 }]  ->  x**2 + y**2
     3d: [{ x**2; + y**2; + z**2 }]  ->  x**2 + y**2 + z**2


#. Multiple do loops::

     do multi(i, j, k; nx, ny, nz)
       ! body
     end do multi

   transforms into

     do i = 1, nx
       do j = 1, ny
         do k = 1, nz
           ! body
         end do
       end do
     end do

   You can optionally supply to/from ranges as well:

     do multi(i, j, k; -L, -L, -L; L, L, L)
       ! body
     end do multi

   transforms into

     do i = -L, L
       do j = -L, L
         do k = -L, L
           ! body
         end do
       end do
     end do


Example
=======

Consider the following subroutine::

  subroutine gradient(f, <{n}>, h, gradf) bind(c, name="divergence")
    real(c_double), intent(in)        :: f({{n}})
    integer(c_int), intent(in), value :: <{n}>
    real(c_double), intent(in), value :: h
    real(c_double), intent(out)       :: gradf({{n;.}})

    integer :: {{ i, j, k }}

    do multi(<{i, j, k}>; <{n}>)
      {[
        gradf({{i,j,k;1}}) = f({{i,j,k}});
        gradf({{i,j,k;2}}) = f({{i,j,k}});
        gradf({{i,j,k;3}}) = f({{i,j,k}})
      ]}
    end do multi
  end subroutine divergence


In two dimensions with interleaved, row-major storage, the above
becomes::

  subroutine gradient(f, n1, n2, h, gradf) bind(c, name="divergence")
    real(c_double), intent(in)        :: f(n2, n1)
    integer(c_int), intent(in), value :: n1, n2
    real(c_double), intent(in), value :: h
    real(c_double), intent(out)       :: gradf(2, n2, n1)

    integer :: j, i

    do i = 1, n1
      do j = 1, n2
        gradf(1, j, i) = f(j, i)
        gradf(2, j, i) = f(j, i)
      end do
    end do
  end subroutine divergence

About

Templated Fortran

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published