Looper
Looper

Reputation: 364

Conditional parameter declaration in Fortran

I'm shopping for ideas on how to implement a "conditional" parameter declaration. The problem is, in essence, that I have a project in which parameters are declared in a separate module, and the main program and all the other modules in the project load the parameter module. The problem is that I would like to be able to run the same project with two different sets of parameter values without having to modify the program and related files much (it would take too much time at this point).

The current program I have, with only one set of parameters, is the following. First the main program:

program main

    use myparams
    implicit none

    ! Execute program, call modules, etc...
    print *, 'Value for x =', x

end program main

Then a module with the parameters:

module myparams

    implicit none
    integer,parameter :: set = 1
    real,parameter    :: x = 2.0
    
end module myparams

Essentially, I would like to have x = 3.0 whenever compiling a case in which set = 2, for example. I, of course, know that I cannot use a conditional in the variable declaration block, so I'm looking for alternatives. Maybe at compilation? In a Makefile?

I have two separate projects (different folders, so duplicated source files), one in which x = 2.0 and another one in which x = 3.0, but any changes in other parts of the program require going back and forth and updating the same code in both projects... so not ideal.

Upvotes: 2

Views: 408

Answers (3)

Federico Perini
Federico Perini

Reputation: 1416

The approach depends on what's the impact of using parameters vs. standard module variables.

  1. Are these variables set as parameters because their values could critically affect the code's runtime performance? If so, the best choice would be to use a preprocessor. For example, with gcc/gfortran you can use the C preprocessor (-cpp) and pass a defined variable via the build system (-Dvariable):
gfortran -cpp -DOPTIONAL my_sources.f90

where you can instrument the source file as

#ifdef OPTIONAL
   real, parameter :: x = 3.0
#else
   real, parameter :: x = 2.0
#endif
  1. Is it not strictly necessary that those module variables are parameters? then, you can use whatever user input you like to set them, or to define a flag which then set them: a command-line interface, an external file, a user prompt.

Upvotes: 0

Ian Bush
Ian Bush

Reputation: 7433

You have an array of things to choose from, so why not use an array?

ijb@LAPTOP-GUG8KQ9I:~/work/stack$ cat param_set.f90
Module all_params_module

  Implicit None

  Real, Parameter, Public, Dimension( * ) :: all_x = [ 3.0, 4.0, 6.0 ]

  Private
  
End Module all_params_module

Module myparams

  Use all_params_module, Only : all_x
  
  Implicit None

  Integer, Parameter, Private :: set = 1
  
  Real, Parameter, Public :: x = all_x( set )

  Private

End Module myparams

Program testit

  Use myparams, Only : x

  Write( *, * ) 'x = ', x

End Program testit
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ gfortran -std=f2018 -Wall -Wextra -fcheck=all -g -O param_set.f90 -o param_set
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ ./param_set 
 x =    3.00000000    
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ 

Upvotes: 1

francescalus
francescalus

Reputation: 32366

A constant expression's evaluation can depend conditionally on the value of another constant, using elemental intrinsic functions.

A popular choice for expression value selection is the MERGE function, but other evaluations are possible:

  implicit none

  integer, parameter :: set = 2
  real, parameter :: x = MERGE(3., 2., set==2)
  real, parameter :: y = x - COUNT([set==2])

  print '(F2.0)', x, y

end program

Upvotes: 4

Related Questions