F90 Subroutine that accepts any array of any dimension

Click For Summary

Discussion Overview

The discussion revolves around creating a Fortran subroutine that can accept arrays of any dimension and size, similar to a C function. Participants explore various approaches and limitations inherent to Fortran's handling of arrays and pointers.

Discussion Character

  • Technical explanation
  • Debate/contested

Main Points Raised

  • One participant seeks advice on writing a Fortran subroutine that can handle arrays of any dimension, referencing a C implementation as a model.
  • Another participant suggests that while Fortran can handle multidimensional arrays, it may not allow addressing elements in a multidimensional way as easily as C.
  • A participant notes that Fortran pointers are type-specific and dimension-specific, which complicates the creation of a generic array handler.
  • There is a discussion about the need to pass all dimensions and calculate positions in a one-dimensional array, highlighting the difference in how Fortran and C handle array indexing.
  • One participant provides formulas for calculating the position of elements in multidimensional arrays based on their dimensions.
  • A later reply introduces the concept of using Fortran 90 generic interfaces to handle arrays, although it acknowledges that the dimensions must be declared beforehand.

Areas of Agreement / Disagreement

Participants express differing views on the feasibility and methods of creating a generic array handler in Fortran. There is no consensus on a single approach, and various methods are proposed and debated.

Contextual Notes

Limitations include the need for specific type and dimension declarations in Fortran, which may restrict the flexibility sought by the original poster. The discussion also highlights the differences in array indexing between Fortran and C.

Yascho Bob
Messages
1
Reaction score
0
Hi,

I need to write a subroutine that accepts as an argument an array of any number of dimensions, where each dimensions has any size. The array is contiguously allocated.

In C, I can do this pretty cleanly.

void array_func(int ndims, int *dims, int *array)
{
// do stuff with the array
// in C, using *array is okay so long as the array was allocated contiguously.
}

Any advice on how to do this with fortran? I'm a total newb at Fortran.
 
Technology news on Phys.org
You can do the same in Fortran, although you lose the ability to address the elements in a multidimentional way.
Fortran:
subroutine foobar(ndims, dims, array)

  implicit none

  integer, intent(in) :: ndims
  integer, dimension(ndims), intent(in) :: dims
  integer, dimension(:), intent(inout) :: array

  ! Your code here
end subroutine foobar
 
Fortran was not quite designed like and on purpose; so, you cannot have some kind of generic array or pointer that can accept an incoming matrix of any number of dimensions. In Fortran, pointers have specific targets that are declared by type and number of dimensions if arrays.

Having said that, I think I saw a paper somewhere where they explain some acrobatics with type definitions where they manage to do a couple of good tricks, but I can't quite recall what. Let's see if I remember.
 
gsal said:
In Fortran, pointers have specific targets that are declared by type and number of dimensions if arrays.
You're right, what I wrote won't work in F90.
 
DrClaude: what you wrote will work in F90, but it will not be what the OP is asking ;-)
 
You have to pass all the dimensions and calculate the proper position in the array as a one-dimensional array. Keep in mind that FORTRAN runs through the first dimension fastest. It is the opposite of C, which runs through the last dimension fastest.

The (i,j) position in an array of dimensions dim1, dim2 is at (j-1)*dim1 + i
The (i,j,k) position in an array of dimensions dim1, dim2, dim3 is at (k-1)*dim2*dim1 + (j-1)*dim1 + i
The (i,j,k.l) position in an array of dimensions dim1, dim2, dim3, dim4 is at
(l-1)*dim3*dim2*dim1 + (k-1)*dim2*dim1 + (j-1)*dim1 + i

You can see how you can handle any number of indices.
An alternative would be to compile a C subroutine and link that into calculate the position in the FORTRAN array. Keep in mind the reversed order of index progression in C versus FORTRAN.
 
Example using Fortran90 Generic Interfaces.

This may not be exactly what the OP wants as, again, the argument needs to have been declared ahead of time with the correct number of dimensions. The calling of the subruotine, though, kind of meets what the OP requests...a single "subroutine" call that takes a matrix of "any" number of dimensions:

Fortran:
module multi
    interface mdarray
        module procedure m1d, m2d, m3d, m4d, m5d
    end interface
   
contains

    subroutine m1d(m)
        real, dimension(:) :: m
        write(*,'(5f6.1)') m
    end subroutine m1d
   
    subroutine m2d(m)
        real, dimension(:,:) :: m
        write(*,'(5f6.1)') m
    end subroutine m2d
   
    subroutine m3d(m)
        real, dimension(:,:,:) :: m
        write(*,'(5f6.1)') m
    end subroutine m3d
   
    subroutine m4d(m)
        real, dimension(:,:,:,:) :: m
        write(*,'(5f6.1)') m
    end subroutine m4d
   
    subroutine m5d(m)
        real, dimension(:,:,:,:,:) :: m
        write(*,'(5f6.1)') m
    end subroutine m5d
   
end module multi

program crazy
    use multi
   
    real :: a1d(2)    , a2d(2,2)  , a3d(2,2,2), a4d(2,2,2,2), a5d(2,2,2,2,2)    

    a1d = 1.0  ; call mdarray(a1d) ; write(*,*)
    a2d = 2.0  ; call mdarray(a2d) ; write(*,*)
    a3d = 3.0  ; call mdarray(a3d) ; write(*,*)
    a4d = 4.0  ; call mdarray(a4d) ; write(*,*)
    a5d = 5.0  ; call mdarray(a5d) ; write(*,*)
   
end program crazy
 
  • Like
Likes   Reactions: DrClaude

Similar threads

  • · Replies 5 ·
Replies
5
Views
8K
  • · Replies 8 ·
Replies
8
Views
4K
  • · Replies 5 ·
Replies
5
Views
13K
  • · Replies 4 ·
Replies
4
Views
3K
  • · Replies 5 ·
Replies
5
Views
4K
  • · Replies 22 ·
Replies
22
Views
3K
  • · Replies 4 ·
Replies
4
Views
3K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 18 ·
Replies
18
Views
7K
  • · Replies 2 ·
Replies
2
Views
9K