3

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?

4
  • Well, you see it is a yes, so you can just put a 1 there... Otherwise you can try some cpp macros. Tell your cluster admins that a recent version of Intel is available for free. Commented Jun 14, 2021 at 10:14
  • Some machines support multiple versions of compilers via the use of environment modules - do you know if this is available on your system? If so a later compiler version might be available already via a suitable "module load" command Commented Jun 14, 2021 at 10:35
  • Unfortunately, the cluster machine, which I can access, is rather old one and there is no module with recent version of compiler. Obviously, the best option is to update the compiler. But, the cluster machine is not well managed. Commented Jun 15, 2021 at 0:57
  • Note that compilers can often be also installed by you in your home directory. On clusters you might then hit a wall when getting the right drivers for the local Infiniband or for the scheduling system when compiling an MPI library, but that is a different issue. Commented Jun 15, 2021 at 6:07

1 Answer 1

2

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.

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

2 Comments

Thanks for the explanation and suggestion. Unfortunately, the parameter 'L' is heavily used in the code and it will be difficult to change all of them as you suggested.
Using the expression as a specification expression is far from ideal (even for just one array). I would struggle to write Fortran 95 programs now.

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.