4

I am trying to the assign value to a variable at the time of declaration and use that variable to declare the dimensions of some arrays as follows,

  type (typ_A), intent (in) :: str_A          
     
  integer, parameter :: 
x val_4 = (str_A%val_1 + str_A%val_2),
x val_5 = str_A%val_3

  integer :: array_1(str_A%val_1, str_A%val_2), array_2(val_4, val_5)

In this code, the array_1 is declared properly with the expected sizes but the array_2 is not declared. Also, I am getting errors like "This symbol must be a defined parameter, an enumerator, or an argument of an inquiry function that evaluates to a compile-time constant."

Note - I can straight away use the expression of val_4 to declare array_2, but sometimes, the expression (str_A%val_1 + str_A%val_2 + ....) is very large and have to use it to define multiple arrays. Hence, for better readability and less number of lines, I want to put it in a variable (val_4 in this case)

2 Answers 2

5

A Fortran parameter must be computable at compile time, as the error message hints, and str_A%val_1 etc are not known at compile time. You can't use a variable directly for this, but you can create a nested argument:

subroutine x (str_A)
  type(whatever),intent(in)::str_A
  call x_2 (str_A, str_A%val_1 + str_A%val_2)
contains
  subroutine x_2 (str_A, mydim)
  type(whatever),intent(in)::str_A
  integer::mydim
  integer:: ary1(mydim), ary2(mydim), ary3(mydim)
  ...
  end subroutine x_2
end subroutine x

or if you can put at least the type and a helper function in a containing module you can do:

module t
  type whatever ...
contains
  pure function mydim(str_A)
    integer::mydim
    type(whatever),intent(in)::str_A
    mydim = str_A%val_1 + str_A%val_2
  end function mydim
  subroutine y (str_A)
    type(whatever),intent(in)::str_A
    integer:: ary1(mydim(str_A)), ary2(mydim(str_A)), ary3(mydim(str_A))
  ...
  end subroutine y
end module t

Added since you may not have considered/realized it:

Alternatively you could simply use ALLOCATABLE arrays instead; those can be allocated (not declared) with bounds computed by any runtime expression, including a local variable.

Sign up to request clarification or add additional context in comments.

Comments

1

The answer of @dave_thompson_085 already answers the root for your problem.

A Fortran parameter must be computable at compile time

There are four possibilities to achieve the behaviour you want:

  1. If you use the block statement you create a local, nested scope where you can declare new variables. You can then declare arrays that use runtime variables outside of the block for their shapes.
integer :: n
n = compute_at_runtime()
block
    integer :: M(n)
    ! do something with M
end block
! M does not exist anymore
  1. As @dave_thompson_085 also put it in his answer, you can use contained procedures with a local nested scope, to declare array with runtime variables that exist outside of the procedure.

  2. Or you use allocatable for dynamic memory and automatic destruction/deallocation.

  3. Or you use pointer for dynamic memory, but then you have to manually cleanup.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.