Skip to content
Snippets Groups Projects
To learn more about this project, read the wiki.

Exercise Runtime Parameters (DuMuX course)


## Problem set-up

Here we will expand on what we've covered in the mainfile exercise, and the problem set up will remain the same.

Preparing the exercise

  • Navigate to the directory dumux-course/exercises/exercise-runtimeparams/



Task 1: Understanding Input Parameters


For this task we will edit the following files:
  • The shared problem file: injection2pproblem.hh
  • And the shared input file: exercise_runtimeparams.input

Parameters can either be directly defined within your program, or specified via the input file. Within every main file, (*.cc), the following function is called, which will read in the imput file parameters

// parse command line arguments and input file
Parameters::init(argc, argv);

This input file should either be named the same as the executable file, with a trailing *.input, as is standard in our CMake system, or be explicitly written as the first shell argument after the executable file is called.

./exercise_runtimeparams
    (Calls a file (exercise_runtimeparams.input) as the default input file.)
./exercise_runtimeparams exercise1.input
    (Calls the input file provided (exercise1.input) as the input file.)

In the input file exercise_runtimeparams.input you can find the following section

[SpatialParams]
PermeabilityAquitard = 1e-15 # m^2
EntryPressureAquitard = 4.5e4 # Pa
PermeabilityAquifer = 1e-12 # m^2
EntryPressureAquifer = 1e4 # Pa

When a parameter is defined directly within your program, you'll need to recompile your program everytime you change the value. When a parameter is passed via the imput file, this is not the case. If we decided to vary the entry pressure in our geologic units a few times via the parameters listed above, there would be no need to recompile between simulation runs.

  • Task 1: Change the aquitard's entry pressure in the input file to a lower value and compare the results with the previous solution. You don't need to recompile the executable.



Task 2: Setting a variable to collect a runtime parameter


Let's free one of the variables in this exercise. Within the class injection2p2cproblem.hh, in the first line of the neumann boundary condition definition function neumannAtPos(...), the injection rate is defined as 1e-4 kg/(s m^2).

// inject nitrogen. negative values mean injection
// units kg/(s*m^2)
values[Indices::conti0EqIdx + FluidSystem::N2Idx]= -1e-4/FluidSystem::molarMass(FluidSystem::N2Idx);
values[Indices::conti0EqIdx + FluidSystem::H2OIdx] = 0.0;

This parameter may need to change, and if we choose to always change this within the class, we will need to recompile every time.

Instead of hard defining this parameter within the funciton, we can set a variable to read into our parameter tree via the input file and use this in our function instead. To do this, there are two functions defined in dumux/dumux/common/parameters.hh, getParam() and getParamFromGroup(). They use the following format:

variable_ = getParam<TYPE>("GROUPNAME.PARAMNAME");

or

variable_ = getParamFromGroup<TYPE>("GROUPNAME", "PARAMNAME");

<TYPE>,<GROUPNAME>,<PARAMNAME> should be appropriatly defined for your variable:

  • <TYPE> is the type of the parameter to read
  • <GROUPNAME> is the group in the input file
  • <PARAMNAME> is the name of the parameter in the input file

An example of this is already performed in the problem constructor. The Injection Duration (injectionDuration_) is defined via the imput file, and can then be used later in the problem.

// depth of the aquifer, units: m
aquiferDepth_ = getParam<Scalar>("Problem.AquiferDepth");
// the duration of the injection, units: second
injectionDuration_ = getParamFromGroup<Scalar>("Problem","InjectionDuration");

The injection duration parameter is located in the [Problem] group, is named InjectionDuration, and has the type Scalar.

This variable should then be defined as Scalar at the bottom of this problem class in the private section.

Scalar injectionDuration_;

In the input file, within the group [Problem], a value is set to the Parameter name called in the class.

[Problem]
InjectionDuration = 2.628e6 # in seconds, i.e. one month
  • Task 2: The goal is to replace the value -1e-4 in

values[Indices::conti0EqIdx + FluidSystem::N2Idx]= -1e-4/FluidSystem::molarMass(FluidSystem::N2Idx);

with a runtime variable. (2a) Develop a new variable called totalAreaSpecificInflow_, (2b) record a value to this variable from a path in the input file, and (2c) incorporate this variable into the injection boundary condition.

When your problem file and the input file are edited, compile and run the exercise.

make exercise_runtimeparams && ./exercise_runtimeparams exercise_runtimeparams.input



Task 3: Default Values for Runtime Parameters


In the case that no path to a required runtime parameter is provided in the input file, the program will no longer run. You can try this if you like by removing the TotalAreaSpecificInflow from the input file. The resulting error message should look like this:

loggingparametertree.hh:316:
Key Problem.TotalAreaSpecificInflow not found in the parameter tree ---> Abort!

To avoid this, we can place a default value in the variable defintion. Whenever the parameter is specified in the input file, this default value in your class will be overwritten, but in the case that no value is provided in the input file, this default value will be used. In order to do this, follow the following template.

variable_ = getParam<TYPE>("GROUPNAME.PARAMNAME", DEFAULTVALUE);
variable_ = getParamFromGroup<TYPE>("GROUPNAME","PARAMNAME", DEFAULTVALUE);
  • Task 3: Set up the totalAreaSpecificInflow_ variable to record a default value of -1e-4, and run this with and without a provided value of -1e-3 in the input file.



Task 4: Other Runtime Parameter Functions


Setting default values for variables defined with runtime parameters can also lead to problems. If one runtime parameter from the input file is set to multiple different variables, each with a different Default value, changing the variable in one location can lead to unexpected changes elsewhere. On top of this, in DuMux, there are a few base variables that are set with default values for all DuMux simulations. These can be found in the header file dumux/common/parameters.hh in the function globalDefaultParameters.

One way to check this is to use either the hasParam() or the hasParamInGroup() function. These functions returning bools will check to see if a parameter is read in via the input file. These functions are also both defined in the dumux/dumux/common/parameters.hh class, and follow a similar format to that of getParam() and getParamFromGroup()

An example of this would look like this:

if (hasParam("GROUPNAME.PARAMNAME"))
   std::cout << "Parameter value is read from the input file." << std::endl;
else
   std::cout << "Using the default parameter value." << std::endl;

or,

if (hasParamInGroup("GROUPNAME","PARAMNAME"))
   std::cout << "Parameter value is read from the input file." << std::endl;
else
   std::cout << "Using the default parameter value." << std::endl;

Using these functions we can better check which parameter values are being included in our program.

  • Task 4: Using one of the bool hasParam functions, place output in the problem file to alert the user to where the parameter value comes from.