Fortran array shape vs size - fortran

In the case of a vector (a plain sequence of numbers) I don't understand the difference between size and shape.
The enclosed script returns 10 twice, as it should, however the return from size has rank 0 (one number) whereas the return from shape has rank 1?
Program main
implicit none
integer (kind=4) :: numbers(10)=(/0,1,2,3,4,5,6,7,8,9/)
integer (kind=4) :: nsize,nshape(1)
nsize=size(numbers)
nshape=shape(numbers)
print *,nsize,nshape
End Program main

In case someone is still interested:
sizeof is the size of the object in memory measured in bytes. Exists for all objects. Caution: if the object is of a derived type that contains allocatable objects, their size does not count.
size is the number of scalar units in an array-type object irrespective of its dimension(...). Exists for array-type objects.
shape is in essence that what was written in dimension(...) when declaring the object. Exists for array-type objects.
Example:
integer(8),dimension(2,3,4) :: arr
print *, &
sizeof(arr).eq.2*3*4*8, &
size(arr).eq.2*3*4, &
all(shape(arr).eq.(/2,3,4/))
must return T T T

Related

Use an allocatable array that is not allocated in an array assignment [duplicate]

This question already has answers here:
Automatic array allocation upon assignment in Fortran
(2 answers)
Closed 4 years ago.
In Fortran, if I use an allocatable array that is not allocated in an array assignment, I expect that there will appear some runtime errors.
But it turns out that the allocatable array got allocated during the assignment. This seems to be a dangerous design. Could someone explain the reason for this design? An example code is as follows:
module yj_mod
real,dimension(:,:),allocatable :: den_i_right
end module yj_mod
program main
call p()
end program main
subroutine p()
use yj_mod,only : den_i_right
implicit none
real :: a(3,4)
a=3.0
den_i_right=a
write(*,*) size(den_i_right,1), size(den_i_right,2)
end subroutine p
I compiled the above code with gfortran. Running the code indicates den_i_right becomes an array of the same shape as a
It is informally called (..... wait for it .....) (re-)allocation on assignment. The specific language from the Fortran 2003 standard using variable=expr
"If variable is an allocated allocatable variable, it is deallocated if expr is an array of different shape or any of the corresponding length type parameter values of variable and expr differ. If variable is or becomes an unallocated allocatable variable, then it is allocated with each deferred type parameter equal to the corresponding type parameters of expr, with the shape of expr, and with each lower bound equal to the corresponding element of LBOUND(expr)."

How do I read a parameter from a text file in a FORTRAN module? [duplicate]

In Fortran, is the PARAMETER attribute set at runtime or compilation time?
I was wondering if I can pass in the size the of the array at run time and have this set as PARAMETER.
Can this be done? If so, how? If not, why?
Yes, as repeatedly answered, a named constant (an object with the parameter attribute) must have its initial value "known at compile time". However, as you talk about the size of arrays I'll note something else.
When declaring the shape of an array there are many times when the bounds needn't be given by constant expressions (of which a simple named constant is one example). So, in the main program or a module
implicit none
...
integer, dimension(n) :: array ! Not allowed unless n is a named constant.
end program
the n must be a constant. In many other contexts, though, n need only be a specification expression.
implicit none
integer n
read(*,*) n
block
! n is valid specification expression in the block construct
integer, dimension(n) :: array1
call hello(n)
end block
contains
subroutine hello(n)
integer, intent(in) :: n ! Again, n is a specification expression.
integer, dimension(2*n) :: array2
end subroutine
end program
That is, array1 and array2 are explicit shape automatic objects. For many purposes one doesn't really need a named constant.
Beyond the array size, the following is certainly not allowed, though.
implicit none
integer n, m
read(*,*) n, m
block
! n and m are specifications expression in the block construct
integer(kind=m), dimension(n) :: array ! But the kind needs a constant expression.
...
end block
You need dynamic allocation if the size of your array is to be defined as runtime. All parameter (constants) must be defined as compiling time.
The value of a parameter is set at compile time.
A declaration such as
integer, parameter :: number_of_widgets = numwidge
requires that numwidge be known at compile time, indeed known before it is encountered on the rhs of the declaration.

Fortran array allocating different size in different dimension [duplicate]

I want to store something in 2 dimensional array in my code and later want to scan that array. There are N_{1} rows (number of first indices, say i) in the array. However, for a given value of i, number of j values is not fixed though I know the maximum possible value of j (say that it is N_{2}).
I can of course create array of size (N_{1},N_{2}) to store my data. This, however seems wastage of space because my N_{2} values fluctuate a lot and the total number of elements in my array is also very large. Is is possible to create a 2D array that can have different number of j values depending on i value? Alternatively, even if I could create many-many 1D arrays by a single Fortran command and allocate them properly, that is also OK with me.
As you suggest that the answer to another question, looking at ragged arrays may be what you want, I'll briefly mention a usability extension to that answer (hinted at in comment by Doug Lipinski).
For a base type, representing the variable-length dimension, given by High Performance Mark
type :: vector
integer, dimension(:), allocatable :: elements
end type vector
and a type for an array of those
type :: ragged_array
type(vector), dimension(:), allocatable :: vectors
end type ragged_array
one has the allocation steps
type(ragged_array) :: ragarr
allocate(ragarr%vectors(5))
allocate(ragarr%vectors(1)%elements(3))
! etc.
[Alternatively, one may be tempted to just have an array of type(vector).]
For the usability aspect one could create a structure constructor which does the numerous allocations, or even rely on automatic allocation for the variable length components.
In the latter case, which makes sense if the values, not just the extents, are known at creation.
allocate(ragarr%vectors(5))
ragarr%vectors(1)%elements = [1, 6, 13]
! etc.
For the former case, something like
module ragged
implicit none
type :: vector
integer, dimension(:), allocatable :: elements
end type vector
type :: ragged_array
type(vector), dimension(:), allocatable :: vectors
end type ragged_array
interface ragged_array
module procedure ragged_constructor
end interface ragged_array
contains
function ragged_constructor(sizes) result(ra)
integer, intent(in) :: sizes(:)
type(ragged_array) ra
integer i
allocate(ra%vectors(SIZE(sizes)))
do i=1,SIZE(sizes)
allocate(ra%vectors(i)%elements(sizes(i)))
end do
end function ragged_constructor
end module ragged
program test
use ragged
implicit none
type(ragged_array) :: ra
ra = ragged_array([3,4,6,1,12])
end program

Fortran PARAMETER variable initialized from input

In Fortran, is the PARAMETER attribute set at runtime or compilation time?
I was wondering if I can pass in the size the of the array at run time and have this set as PARAMETER.
Can this be done? If so, how? If not, why?
Yes, as repeatedly answered, a named constant (an object with the parameter attribute) must have its initial value "known at compile time". However, as you talk about the size of arrays I'll note something else.
When declaring the shape of an array there are many times when the bounds needn't be given by constant expressions (of which a simple named constant is one example). So, in the main program or a module
implicit none
...
integer, dimension(n) :: array ! Not allowed unless n is a named constant.
end program
the n must be a constant. In many other contexts, though, n need only be a specification expression.
implicit none
integer n
read(*,*) n
block
! n is valid specification expression in the block construct
integer, dimension(n) :: array1
call hello(n)
end block
contains
subroutine hello(n)
integer, intent(in) :: n ! Again, n is a specification expression.
integer, dimension(2*n) :: array2
end subroutine
end program
That is, array1 and array2 are explicit shape automatic objects. For many purposes one doesn't really need a named constant.
Beyond the array size, the following is certainly not allowed, though.
implicit none
integer n, m
read(*,*) n, m
block
! n and m are specifications expression in the block construct
integer(kind=m), dimension(n) :: array ! But the kind needs a constant expression.
...
end block
You need dynamic allocation if the size of your array is to be defined as runtime. All parameter (constants) must be defined as compiling time.
The value of a parameter is set at compile time.
A declaration such as
integer, parameter :: number_of_widgets = numwidge
requires that numwidge be known at compile time, indeed known before it is encountered on the rhs of the declaration.

2D array in Fortran 95 array with one dimension variable

I want to store something in 2 dimensional array in my code and later want to scan that array. There are N_{1} rows (number of first indices, say i) in the array. However, for a given value of i, number of j values is not fixed though I know the maximum possible value of j (say that it is N_{2}).
I can of course create array of size (N_{1},N_{2}) to store my data. This, however seems wastage of space because my N_{2} values fluctuate a lot and the total number of elements in my array is also very large. Is is possible to create a 2D array that can have different number of j values depending on i value? Alternatively, even if I could create many-many 1D arrays by a single Fortran command and allocate them properly, that is also OK with me.
As you suggest that the answer to another question, looking at ragged arrays may be what you want, I'll briefly mention a usability extension to that answer (hinted at in comment by Doug Lipinski).
For a base type, representing the variable-length dimension, given by High Performance Mark
type :: vector
integer, dimension(:), allocatable :: elements
end type vector
and a type for an array of those
type :: ragged_array
type(vector), dimension(:), allocatable :: vectors
end type ragged_array
one has the allocation steps
type(ragged_array) :: ragarr
allocate(ragarr%vectors(5))
allocate(ragarr%vectors(1)%elements(3))
! etc.
[Alternatively, one may be tempted to just have an array of type(vector).]
For the usability aspect one could create a structure constructor which does the numerous allocations, or even rely on automatic allocation for the variable length components.
In the latter case, which makes sense if the values, not just the extents, are known at creation.
allocate(ragarr%vectors(5))
ragarr%vectors(1)%elements = [1, 6, 13]
! etc.
For the former case, something like
module ragged
implicit none
type :: vector
integer, dimension(:), allocatable :: elements
end type vector
type :: ragged_array
type(vector), dimension(:), allocatable :: vectors
end type ragged_array
interface ragged_array
module procedure ragged_constructor
end interface ragged_array
contains
function ragged_constructor(sizes) result(ra)
integer, intent(in) :: sizes(:)
type(ragged_array) ra
integer i
allocate(ra%vectors(SIZE(sizes)))
do i=1,SIZE(sizes)
allocate(ra%vectors(i)%elements(sizes(i)))
end do
end function ragged_constructor
end module ragged
program test
use ragged
implicit none
type(ragged_array) :: ra
ra = ragged_array([3,4,6,1,12])
end program