Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

function that returns 0-bound array converts it do a 1-bound array.

JAlexiou
New Contributor I
517 Views

I have a function that initializes a 0-bound array of a custom type. This is for a simulation, and the function returns an array of results, with the first item (0 index) being the initial conditions.

    function model3_run(this, end_time, steps) result(sol)
    class(model3), intent(inout) :: this
    real(8), intent(in) :: end_time
    integer, intent(in) :: steps    
    type(state3), allocatable :: sol(:)
    real(8) :: time_step
    integer :: i
        allocate(sol(0:steps))  !  allocate the 0-bound array
        sol(0) = this%initial_state
        time_step = end_time / steps
        do i=1,steps
            sol(i) = this%step(sol(i-1), time_step)
        end do
    end function

when I use `lbound(sol)` and `ubound(sol)` here I get the expected results.

Now the main program runs this code, and stores the results in an allocatable array.

    type(model3) :: sim
    type(state3), allocatable :: solution(:)

        solution = sim%run(0.1d0, 10)        

The problem is that `solution` is no longer a 0-bound array. The first element is stored in index=1.

So my question is as follows: if I am doing it wrong, what is the correct way to allocate a 0-bound dynamic array in a function an use it outside from the main program?

 

[Intel Parallel Fortran XE 2018 update 5, Windows 7 64-bit, Visual Studio 2017 15.9.14]

0 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
517 Views

That is the correct behavior, as the function return is just a value. The only way to maintain bounds in the case of a function return is to return a pointer and use pointer assignment in the main program. Rather than use a function you could make it a subroutine and pass the allocatable array as an intent(out) argument.

View solution in original post

0 Kudos
4 Replies
Steve_Lionel
Honored Contributor III
518 Views

That is the correct behavior, as the function return is just a value. The only way to maintain bounds in the case of a function return is to return a pointer and use pointer assignment in the main program. Rather than use a function you could make it a subroutine and pass the allocatable array as an intent(out) argument.

0 Kudos
JAlexiou
New Contributor I
517 Views

Steve Lionel (Ret.) (Blackbelt) wrote:

That is the correct behavior, as the function return is just a value. The only way to maintain bounds in the case of a function return is to return a pointer and use pointer assignment in the main program. Rather than use a function you could make it a subroutine and pass the allocatable array as an intent(out) argument.

I understand. I like the `solution = sim%run(0.1d0, 10)` semantics, but for Fortran that is a copy operation and the copy does not preserve bounds. I hope I understand correctly that for Fortran `B=A` means make a copy of `A` into `B`.

What if I allocate my array as 0-bound before the function return, will in then produce the result I expect?

 

    allocate(solution(0:n))
    solution = sim%run(0.d0, 10)

 

0 Kudos
FortranFan
Honored Contributor II
517 Views

JAlexiou wrote:

..

What if I allocate my array as 0-bound before the function return, will in then produce the result I expect? ..

You may want to be careful: if the expression (e.g., the result of sim%run(0.0d0, 10)) can end up with a different shape than used in your ALLOCATE statement and your compiler conforms to current standard, the assignment (solution = .. ) - assuming it's intrinsic - can lead to deallocation of the variable and reallocation with the shape of the expression.  Under this circumstance, the lower bound of LHS will become 1.

If the use of a lower bound other than 1 is important to you and you have scenarios where the function result can have different shapes, you may want to look into defined assignment and evaluate this option toward your coding needs involving variables with the ALLOCATABLE attribute.

0 Kudos
Steve_Lionel
Honored Contributor III
517 Views

JAlexiou wrote:

 

What if I allocate my array as 0-bound before the function return, will in then produce the result I expect?

 

    allocate(solution(0:n))
    solution = sim%run(0.d0, 10)

 

Yes, that should work., but it's still a copy, which you said you were concerned about. Because the variable and the result have the same shape (number of elements in each dimension), the variable doesn't get reallocated.

0 Kudos
Reply