How to initialize two-dimensional arrays in Fortran

我怕爱的太早我们不能终老 提交于 2019-12-17 05:03:09

问题


In C you can easily initialize an array using the curly braces syntax, if I remember correctly:

int* a = new int[] { 1, 2, 3, 4 };

How can you do the same in Fortran for two-dimensional arrays when you wish to initialize a matrix with specific test values for mathematical purposes? (Without having to doubly index every element on separate statements)

The array is either defined by

real, dimension(3, 3) :: a

or

real, dimension(:), allocatable :: a

回答1:


You can do that using reshape and shape intrinsics. Something like:

INTEGER, DIMENSION(3, 3) :: array
array = reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array))

But remember the column-major order. The array will be

1   4   7
2   5   8
3   6   9

after reshaping.

So to get:

1   2   3
4   5   6
7   8   9

you also need transpose intrinsic:

array = transpose(reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array)))

For more general example (allocatable 2D array with different dimensions), one needs size intrinsic:

PROGRAM main

  IMPLICIT NONE

  INTEGER, DIMENSION(:, :), ALLOCATABLE :: array

  ALLOCATE (array(2, 3))

  array = transpose(reshape((/ 1, 2, 3, 4, 5, 6 /),                            &
    (/ size(array, 2), size(array, 1) /)))

  DEALLOCATE (array)

END PROGRAM main



回答2:


For multidimensional (rank>1) arrays, the Fortran way for initialization differs from the C solution because in C multidimensional arrays are just arrays of arrays of etc.

In Fortran, each rank corresponds to a different attribute of the modified data type. But there is only one array constructor, for rank-1 arrays. From these two reasons, initialization through array constructor requires the RESHAPE intrisic function.

In addition to what has already been answered, there is a more direct way of entering the value of a matrix by row instead as by column: reshape has an optional argument ORDER which can be used to modify the order of filling the element of the multidimensional array with the entries of the array constructor.

For instance, in the case of the example in the first answer, one could write:

INTEGER, DIMENSION(3, 3) :: array=reshape( (/ 1, 2, 3, &
                                              4, 5, 6, &
                                              7, 8, 9 /), &
                                           shape(array), order=(/2,1/) )

obtaining the filling of the matrix array exactly in the order shown by the lines of code.

The array (/2, 1/) forces the column index (2) to have precedence on the row index (1), giving the desired effect.




回答3:


Array initialization can be done in the array declaration statement itself, as shown below:

program test
 real:: x(3) = (/1,2,3/)
 real:: y(3,3) = reshape((/1,2,3,4,5,6,7,8,9/), (/3,3/))
 integer:: i(3,2,2) = reshape((/1,2,3,4,5,6,7,8,9,10,11,12/), (/3,2,2/))

end program test

It surprises me that

 real:: y(3,3) = (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/)

is not accepted by the compiler (tried g95, gfortran). It turns out that the shape of (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/) is 9 and not 3 3!



来源:https://stackoverflow.com/questions/3708307/how-to-initialize-two-dimensional-arrays-in-fortran

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!