Reputation: 364
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
Reputation: 1416
The approach depends on what's the impact of using parameter
s vs. standard module variables.
parameter
s 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
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
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
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