Silverfrost Forums

Welcome to our forums

Beginner programmer: Allocatable in a function

4 Jun 2020 2:50 #25566

Hi all,

I am a beginner programmer and new to Fortran.

I found the following code it has other modules.

When I compile the following code, I get the following message.

Compiling file: module_linear_equations.f90 C:\Users\Gary\Documents\Newton_Test\module_linear_equations.F90(39) : error 456 - ALLOCATABLE is an illegal attribute specifier for a RESULT variable such as (RESULT of ASCEND) C:\Users\Gary\Documents\Newton_Test\module_linear_equations.F90(52) : error 456 - ALLOCATABLE is an illegal attribute specifier for a RESULT variable such as (RESULT of DROP) C:\Users\Gary\Documents\Newton_Test\module_linear_equations.F90(65) : error 456 - ALLOCATABLE is an illegal attribute specifier for a RESULT variable such as (RESULT of RESOL_LU) Compilation failed.

I am unsure what the issue is as it appears to me that the allocatable attribute is implemented correctly. Are the problems due to it being in a function? This compiles successfully in GNU Fortran.

!-----------------------------------------------------------------------
! This module solve linear equations using:
!   1. LU descomposition
!   2. PLU (TODO)
!   3. QR  (TODO)
!
! Licensing: This code is distributed under the GNU GPL license.
! Author: Carlos Planelles Alemany, planelles20(at)gmail(dot)com
!-----------------------------------------------------------------------
module module_linear_equations

implicit none

contains

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! LU descomposition
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

subroutine lu(A, L, U)
    real, intent(in) :: A(:,:)
    real, intent(out), allocatable :: L(:,:), U(:,:)
    integer :: i, j

    allocate(L(size(A,1),size(A,2)), U(size(A,1),size(A,2)))
    forall(i=1:size(A,1)) L(i,i) = 1.0
    do j = 1, size(A,2)
      do i = 1, j
        U(i,j) = A(i,j) - dot_product(L(i,1:i-1), U(1:i-1,j))
      end do
      do i = j+1, size(A,2)
        L(i,j) = (A(i,j) - dot_product(L(i,1:j-1), U(1:j-1,j))) / U(j,j)
      end do
    end do
end subroutine

function ascend(A, b) result(x)
    real, intent(in) :: A(:,:), b(:)
    real, dimension(:), allocatable :: x
    integer :: i, j, n

    n = size(A, 2)
    allocate(x(n))
    x(n) = b(n) / A(n,n)
    do i = n-1, 1, -1
      x(i) = (b(i) - dot_product(A(i,i+1:n), x(i+1:n))) / A(i,i)
    end do
end function

function drop(A, b) result(x)
    real, intent(in) :: A(:,:), b(:)
    real, allocatable :: x(:)
    integer :: i, j, n

    n = size(A, 2)
    allocate(x(n))
    x(1) = b(1) / A(1,1)
    do i = 2, n
      x(i) = (b(i) - dot_product(A(i,1:i-1), x(1:i-1))) / A(i,i)
    end do
end function

function resol_lu(A, b) result(x)
    real, intent(in) :: A(:,:), b(:)
    real, allocatable :: x(:)
    real, allocatable :: L(:,:), U(:,:)

    call lu(A, L, U)
    x = ascend(U, drop(L, b))
end function

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! QR
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


end module
4 Jun 2020 3:16 #25567

FTN95 is a Fortran 95 compiler, with support for a few features from later versions of standard Fortran. Your program requires the 'allocate on assignment' feature, which is not (yet) supported.

4 Jun 2020 3:25 #25569

Quoted from mecej4 FTN95 is a Fortran 95 compiler, with support for a few features from later versions of standard Fortran. Your program requires the 'allocate on assignment' feature, which is not (yet) supported.

Thank you mecej4, for your reply.

Is there an alternative in FTN95 or must I assign a large amount of memory for the array?

4 Jun 2020 3:46 #25570

Replace functions whose result type is an allocatable array by subroutines. For example,

 Subroutine Ascend( A, B, X)

instead of

 Function Ascend(A, B) result (X)
4 Jun 2020 4:35 #25572

Quoted from mecej4 Replace functions whose result type is an allocatable array by subroutines. For example,

 Subroutine Ascend( A, B, X)

instead of

 Function Ascend(A, B) result (X)

Thank you mecej4.

I will try that. Thank you.

4 Jun 2020 4:50 #25573

In that case, do note that you also have to modify code containing references to those functions.

In some instances, you may need to declare a new result variable for use in calling the subroutine, add a call to the subroutine, and then use that result variable in the expression.

4 Jun 2020 5:29 #25574

Quoted from mecej4 In that case, do note that you also have to modify code containing references to those functions.

In some instances, you may need to declare a new result variable for use in calling the subroutine, add a call to the subroutine, and then use that result variable in the expression.

Noted! Thank you.

27 Jun 2020 4:04 #25838

It is interesting to note that the implied overhead of 'allocate on assignment' is quite high. Just suppose that you could get the compiler to do the following for all array types and ranks...

   module asgn
   contains
   subroutine DoEquals(y,x)
   integer,allocatable,intent(out)::y(:)
   integer,intent(in)::x(:)
   isx = size(x)
   if(.not.allocated(y))then
     allocate(y(isx))
   else if(size(y) /= isx)then
     deallocate(y)
     allocate(y(isx))
   endif
   y = x
   end subroutine DoEquals
   end module asgn

   program main
   use asgn
   integer, allocatable :: array(:)
   call DoEquals(array,(/1,2,3/))
   print*, array
   call DoEquals(array,(/1,2,3,4/))
   print*, array
   end
27 Jun 2020 5:13 #25840

I agree, Paul, and as a user I have the additional handicap of not knowing the performance implications of using newer features of the language, which often vary widely from compiler to compiler, so I am left with 'instrument, test both ways, and select'.

A compiler that is able to do in-depth dataflow analysis may be able to keep track of allocation status and current array size, and use that information to reduce the number of times it has to do 'if(allocated)..else ..endif'.

9 Jul 2020 7:38 #25945

'Allocate on assignment' has now been added for the next release of FTN95.

If you know of any other standard Fortran 20xx features that are missing from FTN95 and that you would use if they were provided then please let me know.

9 Jul 2020 8:32 #25946

Paul,

2008 DO CONCURRENT construct—for loop iterations with no interdependencies.

It strikes me that this is effectively what the multitasking parallel processing capabilities added at Version 8.30 provide (for 64 bit FTN) achieve. These do work but are extremely difficult to use since they require lots of changes to the code elsewhere – not just at the point where you identify a DO LOOP which would benefit from parallel processing (i.e. testing for master or slave is required elsewhere).

Perhaps a ‘longer term’ feature to be aimed for?

Ken

PS I have actually received code from others which contains the DO CONCURRENT structure. It would be good if FTN95 at least recognised the structure – even if it only processed the loop serially.

Please login to reply.