Allocation of dereferenced pointer in Fortran - fortran

I am trying to create an array of pointers in Fortran 90, as described here. Each pointer in this array is then associated with an array of floats, to be allocated at run time by dereferencing the pointer. See the below example:
program test
type ptr
double precision, pointer :: p(:)
end type ptr
integer :: i, n=5
type(ptr), dimension(3) :: ptrs
double precision, pointer :: a(:), b(:), c(:)
ptrs(1)%p => a
ptrs(2)%p => b
ptrs(3)%p => c
do i=1,3
allocate(ptrs(i)%p(n))
ptrs(i)%p = 0d0
enddo
write(6, *) ptrs(1)%p
write(6, *) a
end program test
Result:
$ gfortran -o test test.f90 && ./test
0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
At line 20 of file test.f90 (unit = 6, file = 'stdout')
Internal Error: list_formatted_write(): Bad type
The error is thrown because a is not allocated. In an ideal world, ptrs(1)%p and a should be identical, but apparently this world is flawed. My question: How do I correctly allocate a, b, and c?

I suggest to always nullify your pointers. That way you won't hit the undefined behaviour cased by undefined pointers so easily.
With the derived type you can use default initialization
type ptr
double precision, pointer :: p(:) => null()
end type ptr
double precision, pointer :: a(:), b(:), c(:)
The pointer a points to some undefined garbage address.
ptrs(1)%p => a
Now ptrs(1)%p points to the same garbage address.
allocate(ptrs(i)%p(n))
Now a new target is allocated and ptrs(1)%p points there. a is unaffected.
Instead, you now have to point a to that new address as well.
a => ptrs(1)%p
It is important not to consider a and ptrs(1)%p to be two aliases to the same thing. They are not. Both are pointers and both point somewhere. It is your responsibility to make sure they point always to the same address.

The important thing to note here is that with
allocate(ptrs(i)%p(n))
you are not allocating (according to the question title) a dereferenced pointer. That is, the allocation does not affect the pointer's target allocation status. Instead, this allocation creates a new target for ptrs(i)%p.
In the answer linked from the question, the target arrays are not themselves pointer or allocatable objects, they are explicit shape arrays. This leads to a subtle difference in what approaches are open to you.
If you want to use dynamic association with the targets of the component pointers, then you can point the pointer to the target after the target is itself allocated. Something like:
allocate(a(n))
ptrs(1)%p => a
Alternatively, you could consider just using allocatable components:
type ptr
double precision, allocatable :: p(:)
end type ptr

Related

intent(out) and allocatable Fortran arrays: what is really done?

I read on many posts on Stack Overflow that an allocatable array is deallocated when it is passed in a subroutine where the dummy argument is intent(out).
If I consider the following code :
program main
real, dimension(:), allocatable :: myArray
integer :: L=8
allocate(myArray(1:L))
call initArray(myArray)
print *, myArray
contains
subroutine initArray(myArray)
real, dimension(:), intent(out) :: myArray
myArray(:) = 10.0
end subroutine initArray
end program main
the output is right. So, when deallocation occurs, memory is released but the array shape is kept. Is it exact ? Any detailed explanation would be appreciated.
I read different posts on the subject (Can I use allocatable array as an intent(out) matrix in Fortran?, What is the effect of passing an allocatable variable into a subroutine with non-allocatable argument?, ...). So I understand that the array is deallocated but I would like to understand what does it mean because in my code, the size is kept and I am also surprised that this code works.
You are slightly misunderstanding what happens here.
Arrays which are deallocated on entry to a procedure with intent(out) are those allocatable arrays which correspond to an allocatable dummy.
What intent(out) means for an argument depends entirely on the characteristics of the dummy not actual argument.
Allocatable actual arguments which correspond to ordinary dummy arguments are not deallocated. (If they were, the dummy argument which is not allocatable would have to be not allocated!)
Instead, the allocation status of the actual argument remains unchanged and the shape of the assumed (not deferred) shape dummy argument remains the same.
The dummy argument becomes undefined, as an intent(out). For the ordinary dummy argument here, that refers simply to its value (which is immediately defined in that assignment statement).
The deallocation happens when the dummy argument is allocatable and intent(out). Try
real, dimension(:), intent(out), allocatable :: myArray
to achieve that.
The fact that the actual argument in the main program is allocatable is immaterial to a subroutine without an allocatable dummy argument (such as yours).
I strongly suggest to name the array in the main program and the argument in the subroutine differently to better see the difference.
program main
real, dimension(:), allocatable :: mainArray
integer :: L=8
allocate(mainArray(1:L))
call initArray(mainArray)
print *, mainArray
contains
subroutine initArray(argArray)
real, dimension(:), intent(out) :: argArray
argArray(:) = 10.0
end subroutine initArray
end program main
Now, mainArray is the actual argument, argArray is the dummy argument. The dummy argument must be allocatable for deallocation to happen.

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)."

Proper way to pass pointers into many subroutines

I'm not a very good programmer and I'm just trying to interface with a model that provides data as pointers. These pointers are passed down through several subroutines before data is written to them. I'm not sure how to do this so that I avoid memory leaks.
Let's say I have an array pointer A that is passed to several subroutines before being written to, how do I handle the declarations, allocations, and deallocations?
module data
implicit none
contains
subroutine s1(a)
real, pointer, intent(out) :: a(5,5)
call s2(a)
end subroutine s1
subroutine s2(a)
real, pointer, intent(out) :: a(5,5)
integer :: i
do i = 1,5
a(:,i) = 5.0
end do
end subroutine s2
end module data
Program test
use data, only : s1, s2
real, pointer, dimension(:,:) :: A => NULL()
allocate(A(5,5))
call s1(A)
write(*,*) A
deallocate(A)
end Program test
Please note that your code is not Fortran 90. The intent attribute for dummy (formal) arguments that are pointers was introduced in Fortran 2003.
The intent refers to the association status of the pointer, not to its target. Also, if the argument is a derived type with
pointer components, the intent applies to the type object itself, not the targets of the pointers. That is, if, for example, intent(in) is used, the data area that the pointer is targeted at can be modified:
module MyType_mod
implicit none
private
type, public :: MyType
integer, pointer :: ptr(:)
contains
procedure :: sub => my_type_sub
end type MyType
contains
subroutine my_type_sub(self)
! Dummy argument
class(MyType), intent(in) :: self
! The following is perfectly legal,
! even though intent(in) was specified
self%ptr = 42
end subroutine my_type_sub
end module MyType_mod
program main
use MyType_mod, only: &
MyType
implicit none
type(MyType) :: foo
integer :: alloc_stat
allocate( integer :: foo%ptr(100), stat=alloc_stat )
call foo%sub()
end program main
Even though not required, in a case such as the previous example, it is better to state intent(inout) to indicate to the reader that modification of data is taking place.
On another note, you may find this answer useful Fortran subroutine returning wrong values

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

Is it necessary to allocate an allocatable array?

I have a simple question regarding derived types and allocated arrays.
Suppose we have defined the type
type demo_type
real(kind=8),allocatable :: a(:)
end type demo_type
and the function
function demo_fill(n) result(b)
integer, intent(in) :: n
real(kind=8) :: b(n)
b = 1.d0
end function demo_fill
Is it correct to write in the main program
type(demo_type) :: DT
DT%a = demo_fill(3)
Or is it necessary to first allocate DT%a to prevent accidentally overwriting other variables in memory?
type(demo_type) :: DT
allocate(DT%a(3))
DT%a = demo_fill(3)
They both compile, but I am wondering which is the correct way. Thanks!
In Fortran 2003 any allocatable array can be allocated automatically on assignment.
In your case
DT%a = demo_fill(3)
causes DT%a to be automatically allocated to the shape of the right hand side, which is the result of the function, if it has not been allocated to this shape previously.
This behavior is standard, but some compilers do not enable it by default, notably the Intel Fortran. You must use special compiler flags to enable it (-standard-semantics, -assume realloc_lhs)
As a side note, kind=8 does not mean 8-byte reals on all compilers, and this usage is frowned upon (see https://stackoverflow.com/a/856243/721644).