F90 Subroutine that accepts any array of any dimension

In summary,In C, you can do this pretty cleanly.In Fortran, you lose the ability to address the elements in a multidimentional way.An alternative would be to compile a C subroutine and link that into calculate the position in the FORTRAN array.
  • #1
Yascho Bob
1
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
  • #2
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
 
  • #3
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.
 
  • #4
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.
 
  • #5
DrClaude: what you wrote will work in F90, but it will not be what the OP is asking ;-)
 
  • #6
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.
 
  • #7
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 DrClaude

FAQ: F90 Subroutine that accepts any array of any dimension

1. What is a F90 subroutine?

A F90 subroutine is a section of code that performs a specific task and can be called multiple times from different parts of a program. It is written in the Fortran 90 programming language.

2. What does it mean for a subroutine to accept any array of any dimension?

This means that the subroutine can take in arrays of any size and shape, as long as they are compatible with the Fortran 90 standard. The subroutine will be able to handle arrays with any number of dimensions, from 1D to n-dimensional.

3. How is an array passed into a F90 subroutine?

In Fortran 90, arrays are passed by reference, meaning that the subroutine has access to the original array in the main program. This allows for efficient memory usage and allows the subroutine to modify the original array if needed.

4. Can a F90 subroutine handle different data types within the same array?

Yes, a F90 subroutine can handle arrays with different data types as long as they are declared and used correctly. Fortran 90 is a strongly typed language, so the data types of all elements in an array must be the same, but different arrays can have different data types.

5. How can I use a F90 subroutine that accepts any array of any dimension in my program?

To use a F90 subroutine, you first need to declare it in your program by specifying its name, arguments, and return type. Then, you can call the subroutine from any part of your program by passing in the array(s) as arguments. Make sure to pass in the correct number and type of arguments as specified in the subroutine declaration.

Similar threads

Replies
5
Views
7K
Replies
8
Views
3K
Replies
5
Views
12K
Replies
4
Views
2K
Replies
5
Views
3K
Replies
22
Views
3K
Replies
4
Views
2K
Replies
2
Views
3K
Replies
18
Views
6K
Replies
2
Views
8K
Back
Top