3

If I want to create an allocatable multidimensional array, I can say:

program test
    real, dimension(:,:), allocatable :: x
    integer :: i,j

    allocate(x(5, 5))

    do i = 1,size(x,1)
        do j = 1,size(x,2)
            x(i,j) = i*j
        end do
    end do

    write(*,*) x

end program test

However, what if I don't know how many dimension x will be. Is there a way to accommodate that?

user1543042
  • 3,422
  • 1
  • 17
  • 31
  • 1
    I wonder if you can use `RESHAPE()` to flatten, assign values, and then give it the original shape again. – John Alexiou Aug 12 '15 at 21:13
  • 1
    What will govern the number of ranks? And how will you use the array? – francescalus Aug 12 '15 at 21:28
  • @francescalus, I will set the rank using a `integer, parameter :: ND = ` a number between 1 and 3. The use is a scalar field (voltage) which I want to solve Poisson's equation (https://en.wikipedia.org/wiki/Poisson%27s_equation) using the finite difference method. So if I knew the rank (the number of dimensions) I could just say for example if `ND = 2`, `V(2:size(V,1)-1, 2:size(V,2)-1) = V(2:size(V,1), 2:size(V,2)-1) + V(1:size(V,1)-1, 2:size(V,2)-1) + V(2:size(V,1)-1, 2:size(V,2)) + V(2:size(V,1), 1:size(V,2)-1)`. – user1543042 Aug 17 '15 at 16:27
  • possible duplicate of [Fortran: set array's rank at runtime](http://stackoverflow.com/questions/7500920/fortran-set-arrays-rank-at-runtime) – francescalus Aug 20 '15 at 16:13

2 Answers2

4

Newer compilers allow the use of assumed-rank objects for interoperability. I think that is what you are looking for. But this is for call to functions or subroutines. The function or subroutine declares the dummy argument as assumed-rank and the actual rank is passed with the actual argument at runtime.

Example from IBM website:

REAL :: a0
REAL :: a1(10)
REAL :: a2(10, 20)
REAL, POINTER :: a3(:,:,:)

CALL sub1(a0)
CALL sub1(a1)
CALL sub1(a2)
CALL sub1(a3)

CONTAINS
    SUBROUTINE sub1(a)
        REAL :: a(..)
        PRINT *, RANK(a)
    END

END

follow this or that for more details

innoSPG
  • 4,588
  • 1
  • 29
  • 42
  • 2
    Note that assumed-rank is part of TS 29113:2012 and included in the Fortran2015 draft. Recent versions of gfortran and ifort should also support this but support is probably relatively recent e.g. in the last 3 years at most. – casey Aug 12 '15 at 20:54
  • I tried with both ifort 14 and 15. Both of them spit out `error #5082: Syntax error, found '.' when expecting one of: REAL :: a(..) ---------------------------^ test.f90(8): error #6634: The shape matching rules of actual arguments and dummy arguments have been violated. [A1] CALL sub1(a1) ------------------^` – user1543042 Aug 17 '15 at 16:30
  • @user1543042 It looks like ifort 16 is required for assumed rank support. – francescalus Aug 17 '15 at 16:34
  • @user1543042, you do not have the latest compiler to use the feature. Either you re-think your design or you upgrade your compiler. It is important to answer for yourself the comment of francescalus: "What will govern the number of ranks? And how will you use the array?" – innoSPG Aug 17 '15 at 17:12
1

It looks to me like you're trying to carry out stencil computations across an array of rank-1, -2 or -3 -- this isn't quite the same as needing arrays of arbitrary rank. And assumed-rank arrays are really only applicable when passing an array argument to a routine, there's no mechanism even in the forthcoming standard for declaring an array to have a rank determined at run-time.

If you're impatient to get on with your code and your compiler doesn't yet implement TS 29113:2012 perhaps the following approach will appeal to you.

   real, dimension(:,:,:), allocatable :: voltage_field

   if (nd == 1) allocate(voltage_field(nx,1,1))
   if (nd == 2) allocate(voltage_field(nx,ny,1))       
   if (nd == 3) allocate(voltage_field(nx,ny,nz))

Your current approach faces the problem of not knowing, in advance of knowing the number of dimensions in the field, how many nearest-neighbours to consider in the stencil, so you might find yourself writing 3 versions of each stencil update. If you simply abuse a rank-3 array of size nx*1*1 to represent a 1D problem (mutatis mutandis a 2D problem) you always have 3 sets of nearest-neighbours in each stencil calculation. It's just that in the flattened dimensions the nearest neighbour is, well, either a ghost cell containing a boundary value, or the cell itself if your space wraps round.

Writing your code to work always in 3 dimensions but to make no assumptions about the extent of at least two of them will, I think, be easier than writing rank-sensitive code. But I haven't given the matter a lot of thought and I haven't really thought too much about its impact on your f-d scheme.

High Performance Mark
  • 77,191
  • 7
  • 105
  • 161