This tutorial demonstrates the usage of simulation parameters using the JSON format.
Copy the demo code
parameters
is one of many installed demos in BioDynaMo. It can be copied out
with biodynamo demo
.
biodynamo demo parameters
Inspect the code
Go into the parameters
directory and open the files src/parameters.h
and src/parameters.cc
in your
favorite editor and inspect the code.
We can note the following things from its content:
1. Add simulation specific parameters
We add the simulation specific parameters foo
and bar
.
Therefore, we create a new struct called SimParam
, which inherits
from ParamGroup
.
To reduce the amount of boilerplate code, BioDynaMo provides the macro
BDM_PARAM_GROUP_HEADER
.
// Parameters specific for this simulation
struct SimParam : public ParamGroup {
BDM_PARAM_GROUP_HEADER(SimParam, 1);
real_t foo = 3.14;
int bar = -42;
};
2. Initialize ParamGroupUid
Every ParamGroup must have a unique identifier.
Definition of SimParam::kUid
must be done in a source file (src/parameters.cc
).
const ParamGroupUid SimParam::kUid = ParamGroupUidGenerator::Get()->NewUid();
3. Register new parameters
Before we create a simulation, we have to tell BioDynaMo about the new parameters.
Param::RegisterParamGroup(new SimParam());
4. Create simulation
We create a new simulation and pass the command line arguments to it.
Simulation simulation(argc, argv);
5. Print parameters
We obtain pointers to the core and our simulation specific parameters and print out a few values.
// get a pointer to the param object
auto* param = simulation.GetParam();
// get a pointer to an instance of SimParam
auto* sparam = param->Get<SimParam>();
std::cout << "Value of simulation time step " << param->simulation_time_step << std::endl;
std::cout << "Value of foo " << sparam->foo << std::endl;
std::cout << "Value of bar " << sparam->bar << std::endl;
NB: If you don't have a pointer to bdm::Simulation
inside e.g. a behavior, you can
obtain it by calling Simulation::GetActive()
.
Build the simulation
In this tutorial, we use cmake
and make
directly instead of biodynamo build
or biodynamo run
.
mkdir build
cd build
cmake ..
make -j4
These commands create a binary called parameters
Run the simulation
Execute ./parameters
in your build directory.
You should see the following output.
Value of simulation time step 0.01
Value of foo 3.14
Value of bar -42
Simulation completed successfully!
These three parameters are set to their default values.
Explore available parameters
BioDynaMo comes with a command line option to print all available simulation parameters.
Execute ./parameters --output-default-json
.
You should see output similar to this:
Below you can find a JSON string with all available parameters and their default values.
Have a look at https://biodynamo.org/bioapi/ for more details about each parameter.
{
"bdm::Param": {
"_typename": "bdm::Param",
"backup_file": "",
"backup_interval": 1800,
"bound_space": 0,
"cache_neighbors": false,
"calculate_gradients": true,
"compute_target": "cpu",
"debug_numa": false,
"detect_static_agents": false,
"diffusion_method": "euler",
"export_visualization": false,
"diffusion_boundary_condition": "open",
"max_bound": 100,
"mem_mgr_aligned_pages_shift": 8,
"mem_mgr_growth_rate": 1.1,
"mem_mgr_max_mem_per_thread_factor": 1,
"min_bound": 0,
"minimize_memory_while_rebalancing": true,
"numerical_ode_solver": 1,
"opencl_debug": false,
"output_dir": "output",
"preferred_gpu": 0,
"restore_file": "",
"root_visualization": false,
"scheduling_batch_size": 1000,
"show_simulation_step": 0,
"simulation_max_displacement": 3,
"simulation_time_step": 0.01,
"statistics": false,
"thread_safety_mechanism": 1,
"use_bdm_mem_mgr": true,
"visualization_engine": "paraview",
"visualization_export_generate_pvsm": true,
"visualize_diffusion": [],
"visualize_agents": {
"_typename": "map<string,set<string> >"
}
},
"bdm::SimParam": {
"_typename": "bdm::SimParam",
"bar": -42,
"foo": 3.14
}
}
NB: You can ignore keys with name _typename
Create a JSON config file
Now let's create a JSON config file. The output from the previous step can serve as a good starting point.
Create a new file bdm.json
in the project root directory with the following content.
{
"bdm::Param": {
"simulation_time_step": 1.0
},
"bdm::SimParam": {
"bar": 84
}
}
Execute ./parameters
in your build directory.
You should see the following output.
Value of simulation time step 1
Value of foo 3.14
Value of bar 84
Simulation completed successfully!
BioDynaMo automatically picked up the configuration file and parsed its content.
BioDynaMo looks for a file with the name bdm.json
in the current working directory and
it's parent directory. If it finds one it automatically uses it.
Use specific JSON config file
Rename the file bdm.json
from the previous step to config.json
.
If you execute ./parameters
again, you get the same output as running without config file.
BioDynaMo has different methods to choose a specific configuration file. This allows us to have multiple configuration files in the same project.
Execute ./parameters --config ../config.json
from within the build directory.
You should see the following output.
Value of simulation time step 1
Value of foo 3.14
Value of bar 84
Simulation completed successfully!
There is another way to tell BioDynaMo to use a specific configuration file. You can pass a config file parameter as an argument to the bdm::Simulation
constructor.
Therefore, in file src/parameters.h
replace Simulation simulation(argc, argv)
with Simulation simulation(argc, argv, {"../config.json"})
.
Since we changed the code, we have to recompile it before we can execute it.
make -j4
./parameters
Although we didn't specify any command line argument, BioDynaMo still picks up our config.json
configuration file.
Value of simulation time step 1
Value of foo 3.14
Value of bar 84
Simulation completed successfully!
Use inline config command line parameter
In addition to a configuration file, BioDynaMo offers the functionality to specify the JSON string on the command line using the
inline-config
option.
Execute the following command to change the foo
parameter on the command line.
./parameters --inline-config '{ "bdm::SimParam": { "foo": 6.28 } }'
You should see the following output.
Value of simulation time step 1
Value of foo 6.28
Value of bar 84
Simulation completed successfully!
We can see that parameter foo
was correctly updated to 6.28
. The other parameters are set to the values in config.json
.
If the same value is set in the configuration file and the inline-config
parameter, the inline-config
value takes precedence.
Output used simulation parameters
BioDynaMo offers the functionality to output simulation metadata at the end of the simulation. This contains a list of all parameters with their values.
To turn it on update the file config.json
:
{
"bdm::Param": {
"statistics": true,
"simulation_time_step": 1.0
},
"bdm::SimParam": {
"bar": 84
}
}
Once more, execute ./parameters --inline-config '{ "bdm::SimParam": { "foo": 6.28 } }'
.
You should see output similar to this:
Value of simulation time step 1
Value of foo 6.28
Value of bar 84
Simulation completed successfully!
***********************************************
***********************************************
Simulation Metadata:
***********************************************
General
Command : ./parameters --inline-config { "bdm::SimParam": { "foo": 6.28 } }
Simulation name : parameters
Number of iterations executed : 0
Number of agents : 0
Output directory : output/parameters
size : 4.0K
***********************************************
No statistics were gathered!
***********************************************
Thread Info
max_threads : 4
num_numa nodes : 1
thread to numa mapping : 0 0 0 0
thread id in numa node : 0 1 2 3
num threads per numa : 4
***********************************************
Agents per numa node
numa node 0 -> size: 0
***********************************************
Parameters
{
"bdm::Param": {
"_typename": "bdm::Param",
"backup_file": "",
"backup_interval": 1800,
"bound_space": 0,
"cache_neighbors": false,
"calculate_gradients": true,
"compute_target": "cpu",
"debug_numa": false,
"detect_static_agents": false,
"diffusion_method": "euler",
"export_visualization": false,
"diffusion_boundary_condition": "open",
"max_bound": 100,
"mem_mgr_aligned_pages_shift": 8,
"mem_mgr_growth_rate": 1.1,
"mem_mgr_max_mem_per_thread_factor": 1,
"min_bound": 0,
"minimize_memory_while_rebalancing": true,
"numerical_ode_solver": 1,
"opencl_debug": false,
"output_dir": "output",
"preferred_gpu": 0,
"restore_file": "",
"root_visualization": false,
"scheduling_batch_size": 1000,
"show_simulation_step": 0,
"simulation_max_displacement": 3,
"simulation_time_step": 1,
"statistics": true,
"thread_safety_mechanism": 1,
"use_bdm_mem_mgr": true,
"visualization_engine": "paraview",
"visualization_export_generate_pvsm": true,
"visualize_diffusion": [],
"visualize_agents": {
"_typename": "map<string,set<string> >"
}
},
"bdm::SimParam": {
"_typename": "bdm::SimParam",
"bar": 84,
"foo": 6.28
}
}
***********************************************
***********************************************
The values in the parameter list are the final values that were used in the simulation. This includes applying a config file, command line arguments, or hardcoded parameters in the source code.