Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

compatibility of Parameter initialization in Fortran

I have a large Fortran code which uses the Merge function in named constant (parameter) declaration. But, there is a problem in compilation.

To explain the problem, a simple code is

CHARACTER*3,PARAMETER :: Mode = 'yes'  ! 'yes' or 'no'
INTEGER,PARAMETER :: L = merge(1,2, trim(Mode) .eq.'yes') 
INTEGER,DIMENSION(L) :: some_array 

(One changes Mode depending on the purpose. Actual code is more complex, of course.)

The points are (1) parameter 'L' is initialized depending on 'Mode' (2) parameter 'L' is used to define other arrays.

This initialization of 'L' is okay for recent compiler.

However, the cluster machine has older version (around year 2013) of Fortran compiler, which does not accept this way of initialization of 'L'.

How can I achieve the same effects in old Fortran standard?

like image 263
user2775514 Avatar asked Nov 23 '25 11:11

user2775514


1 Answers

The statements given are valid under Fortran 2003 and later, but not in Fortran 90/95.

You really want to be using a compiler which supports Fortran 2003 (and indeed much later versions) and the comments suggests ways to look for this. There is no guarantee that this is the only Fortran 2003+ parts of the code you want to compile. However, there's a history lesson available here which tells us about a workaround.

First, the obvious workaround is

integer, parameter :: L=1   ! Change to 2 if mode is 'no'

but that's not nice. (As also commented, you may make this nicer by using non-Fortran preprocessing macros.)

As has been noted elsewhere, Fortran 2003 significantly expanded on what is allowed to be used to set the value of a named constant. In both Fortran 95 and Fortran 2003 the expression for setting the value is an initialization expression. However, in Fortran 95 merge (which is an elemental function) may not be used, because in that standard elemental functions can appear in initialization expressions only if all arguments are character or integer: the mask argument is logical. Fortran 2003 removed this restriction.

You will not sensibly be able to rewrite the initialization expression under the Fortran 95 rules.

Which leads to a second workaround.

You want to use the named constant L in the array specification of some_array. However, the array specification here need only be a (constant) specification expression, not necessarily a constant like L. A Fortran 95 specification expression is looser than an initialization expression:

character(len=3), parameter :: Mode = 'yes'  ! 'yes' or 'no'
integer, dimension(merge(1,2, trim(Mode).eq.'yes')) :: some_array

This isn't as nice as a named constant.

like image 60
francescalus Avatar answered Nov 27 '25 07:11

francescalus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!