Parameter export

In the previous section, we showed how to parse DIP files into a list of parameters. In this section, we provide several tools that use such parameter lists and export them into different formats.

Templates

Template solver was already introduced in previous sections concerning general DIP syntax. Class TemplateSolver can be, however, used also separately as a template parser.

Let’s take an example of a template file below:

template.txt
Geometry: {{?box.geometry}}
Box size: [{{?box.size.x}}, {{?box.size.y}}, {{?box.size.z}}]

This file can be easily processed using TemplateSolver class

>>> from scinumtools.dip import DIP
>>> from scinumtools.dip.solvers import TemplateSolver
>>>
>>> with DIP() as dip:
>>>     dip.add_file('definitions.dip')
>>>     env = dip.parse()
>>> with TemplateSolver(env) as ts:
>>>     text = ts.template('template.txt','processed.txt')

and exported as following text file:

processed.txt
Geometry: 3
Box size: [1e-06, 3.0, 23.0]

Configuration files

Low level language like C/C++, Fortran, or Rust usually require some kind of configuration file with settings, or constants. Many codes can already read parameters using (YAML, TOML, and other) configurations files. DIP can easily export parsed parameters into these languages and create corresponding configuration files using ExportConfig class. The following example DIP code

config.dip
radiation bool = none
simulation
  name str = 'Configuration test'
  output bool = true
box
  width float32 = 12 cm
    !tags ["selection"]
  height float = 15 cm
density float128 = 23 g/cm3
num_cells int = 100
  !tags ["selection"]
num_groups uint64 = 23994957
vector bool[3] = [true,true,false]
matrix int[2,3] = [[1,2,3],[4,5,6]] cm

can be parsed with DIP and exported using ExportConfig*** classes

>>> from scinumtools.dip import DIP
>>>
>>> with DIP() as dip:
>>>    dip.add_file("config.dip")
>>>    env = dip.parse()

One can also restrict which parameters will be exported using query and tag selectors:

>>> with ExportConfigC(env) as exp:
>>>     exp.select(query="box.*", tags=["selection"])
>>>     exp.parse()

Examples of the corresponding exports are available in pytests.

Since DIP parameter names are not suitable for all languages mentioned above, in some cases parameter names are automatically converted to upper case and hierarchy separators . are substituted by underscores. This feature can be switched off using the following export option: ExportConfigC(env, rename=False).

Note

Not all features of DIP can be mapped to other languages. So far exports are implemented only for simple data types and arrays. If you are missing some advanced export feature, you are welcome to write a GitHub Issue or implement it yourself.

C configuration

DIP parameters can be exported into a C header file in the following way:

>>> from scinumtools.dip.config import ExportConfigC
>>> with ExportConfigC(env) as exp:
>>>     exp.parse(
>>>        guard='CONFIG_H',
>>>        define=['radiation','simulation.name']
>>>     )
>>>     exp.save("config_c.h")

The header guard name can be modified. Parameters are parsed by default as constants const, but it is also possible to parse them as preprocessor definitions #define. If boolean DIP parameters are parsed, the corresponding C dependency <stdbool.h> is included.

config_c.h
#ifndef CONFIG_H
#define CONFIG_H

#include <stdbool.h>

#define RADIATION 
#define SIMULATION_NAME "Configuration test"
const bool SIMULATION_OUTPUT = true;
const float BOX_WIDTH = 12.0;
const double BOX_HEIGHT = 15.0;
const long double DENSITY = 23.0;
const int NUM_CELLS = 100;
const unsigned long long int NUM_GROUPS = 23994957;
const bool VECTOR[3] = {true, true, false};
const int MATRIX[2][3] = {{1, 2, 3}, {4, 5, 6}};

#endif /* CONFIG_H */

Note

Null values of DIP parameters parsed as preprocessor flags are omitted.

C++ configuration

In C++ configuration files, the DIP parameters are parsed by default as constant expressions constexpr. Nevertheless, it is possible to parse them explicitly as constants const, or preprocessor definitions #define. Examples are shown below.

>>> from scinumtools.dip.config import ExportConfigCPP
>>> with ExportConfigCPP(env) as exp:
>>>     exp.parse(
>>>        guard='CONFIG_H',
>>>        define=['radiation','simulation.name'],
>>>        const=['box.width','box.height']
>>>     )
>>>     exp.save("config_cpp.h")
config_cpp.h
#ifndef CONFIG_H
#define CONFIG_H

#define RADIATION 
#define SIMULATION_NAME "Configuration test"
constexpr bool SIMULATION_OUTPUT = true;
const float BOX_WIDTH = 12.0;
const double BOX_HEIGHT = 15.0;
constexpr long double DENSITY = 23.0;
constexpr int NUM_CELLS = 100;
constexpr unsigned long long int NUM_GROUPS = 23994957;
constexpr bool VECTOR[3] = {true, true, false};
constexpr int MATRIX[2][3] = {{1, 2, 3}, {4, 5, 6}};

#endif /* CONFIG_H */

Note

In case of C++ there is no dependency <stdbool.h> included.

Fortran configuration

In case of Fortran configuration, DIP variables are export in a separate module ConfigurationModule. The name of the module can be modified.

>>> from scinumtools.dip.config import ExportConfigFortran
>>> with ExportConfigFortran(env) as exp:
>>>     exp.parse(module="ConfigurationModule")
>>>     exp.save("config_fortran.f90")
config_fortran.f90
module ConfigurationModule
  implicit none

  logical, parameter :: RADIATION = .false.;
  character(len=20), parameter :: SIMULATION_NAME = "Configuration test";
  logical, parameter :: SIMULATION_OUTPUT = .true.;
  real, parameter :: BOX_WIDTH = 12.0;
  real(kind=8), parameter :: BOX_HEIGHT = 15.0;
  real(kind=16), parameter :: DENSITY = 23.0;
  integer, parameter :: NUM_CELLS = 100;
  integer(kind=8), parameter :: NUM_GROUPS = 23994957;
  logical, dimension (3) :: VECTOR = [.true., .true., .false.];
  integer, dimension (2,3), parameter :: MATRIX = reshape([1, 2, 3, 4, 5, 6],[2,3])

end module ConfigurationModule

Rust configuration

Export of DIP parameters into a Rust configuration goes as follows. Since Rust currently does not support 128 bit floats, all such parameters are exported as 64 bit variables.

>>> from scinumtools.dip.config import ExportConfigRust
>>> with ExportConfigFortran(env) as exp:
>>>     exp.parse()
>>>     exp.save("config_rust.rs")
config_rust.rs
pub const RADIATION: bool = false;
pub const SIMULATION_NAME: &str = "Configuration test";
pub const SIMULATION_OUTPUT: bool = true;
pub const BOX_WIDTH: f32 = 12.0;
pub const BOX_HEIGHT: f64 = 15.0;
pub const DENSITY: f64 = 23.0;
pub const NUM_CELLS: i32 = 100;
pub const NUM_GROUPS: u64 = 23994957;
pub const VECTOR: [bool; 3] = [true, true, false];
pub const MATRIX: [[i32; 3]; 2] = [[1, 2, 3], [4, 5, 6]];

Bash configuration

Since Bash does not natively support multidimensional arrays, such data has to be exported using associative arrays, where keys are coordinates of corresponding values. Parameters with none values are exported as empty variables. An example of a Bash configuration export is given below.

>>> from scinumtools.dip.config import ExportConfigBash
>>> with ExportConfigBash(env) as exp:
>>>     exp.parse(export=True)
>>>     exp.save("config_bash.sh")
config_bash.sh
export RADIATION=
export SIMULATION_NAME="Configuration test"
export SIMULATION_OUTPUT=0
export BOX_WIDTH=12.0
export BOX_HEIGHT=15.0
export DENSITY=23.0
export NUM_CELLS=100
export NUM_GROUPS=23994957
export VECTOR=("0" "0" "-1")
declare -A MATRIX
MATRIX[0,0]=1
MATRIX[0,1]=2
MATRIX[0,2]=3
MATRIX[1,0]=4
MATRIX[1,1]=5
MATRIX[1,2]=6
export MATRIX

YAML configuration

Export into YAML uses yaml Python module. In addition to all standard yaml options, it is also possible to show/hide parameter units. An example of an export is given below.

>>> from scinumtools.dip.config import ExportConfigYAML
>>> with ExportConfigYAML(env) as exp:
>>>     exp.parse(units=True, default_flow_style=True)
>>>     exp.save("config_yaml.yaml")
config_yaml.yaml
box.height:
  unit: cm
  value: 15.0
box.width:
  unit: cm
  value: 12.0
density:
  unit: g/cm3
  value: 23.0
matrix:
  unit: cm
  value:
  - - 1
    - 2
    - 3
  - - 4
    - 5
    - 6
num_cells: 100
num_groups: 23994957
radiation: null
simulation.name: Configuration test
simulation.output: true
vector:
- true
- true
- false

TOML configuration

Export into TOML uses toml Python module. In addition to all standard toml options, it is also possible to show/hide parameter units. An example of an export is given below.

>>> from scinumtools.dip.config import ExportConfigTOML
>>> with ExportConfigTOML(env) as exp:
>>>     exp.parse(units=True)
>>>     exp.save("config_toml.toml")
config_toml.toml
"simulation.name" = "Configuration test"
"simulation.output" = true
num_cells = 100
num_groups = 23994957
vector = [ true, true, false,]

["box.width"]
value = 12.0
unit = "cm"

["box.height"]
value = 15.0
unit = "cm"

[density]
value = 23.0
unit = "g/cm3"

[matrix]
value = [ [ 1, 2, 3,], [ 4, 5, 6,],]
unit = "cm"

JSON configuration

Export into JSON uses json Python module. In addition to all standard json options, it is also possible to show/hide parameter units. An example of an export is given below.

>>> from scinumtools.dip.config import ExportConfigJSON
>>> with ExportConfigJSON(env) as exp:
>>>     exp.parse(units=True, indent=2)
>>>     exp.save("config_json.json")
config_json.json
{
  "radiation": null,
  "simulation.name": "Configuration test",
  "simulation.output": true,
  "box.width": {
    "value": 12.0,
    "unit": "cm"
  },
  "box.height": {
    "value": 15.0,
    "unit": "cm"
  },
  "density": {
    "value": 23.0,
    "unit": "g/cm3"
  },
  "num_cells": 100,
  "num_groups": 23994957,
  "vector": [
    true,
    true,
    false
  ],
  "matrix": {
    "value": [
      [
        1,
        2,
        3
      ],
      [
        4,
        5,
        6
      ]
    ],
    "unit": "cm"
  }
}