dict

Description

The native file format used by dictIO shares, by intention, some commonalities with the OpenFOAM file format, but is kept simpler and more tolerant to different flavours of string formatting.

Structure

The basic structure of a dict file consists of

  • header (block comment) [optional]

  • include directive(s) [optional]

  • key’d elements (each written as key value pair)

As header and include directives are optional, in its simplest form a dict file can contain just a single key’d element:

var1     3.14159;

#include Directive(s)

One of the most powerful features of dict files is their ability to be cascaded through the use of #include directives. An #include directive declares a (child) dict file to be merged into the (parent) dict when reading.

This allows to separate i.e. a case agnostic configuration file from its case specific parameterization: While the core configuration dict is kept unchanged, case specific parameterization is accomplished by varying only the parameter dict.

An #include directive consists of the #include statement followed by the path to the dict to be included:

#include 'a_paramDict_in_same_folder'
#include 'subfolder/a_paramDict_in_subfolder'  // Posix style with forward slashes is recommended (will work also on Windows)
#include '../a_paramDict_in_parent_folder'
#include 'subfolder\a_paramDict_in_subfolder'  // also ok, but not recommended
#include '..\a_paramDict_in_parent_folder'

Element Types

The following element types are supported in dict files read and written by dictIO. The table also indicates to which Python data type they are casted when a dict file is read.

element type

example

(Python type)

boolean

true, false, on, off

bool

number

1, 1.0

int, float

none

None, none, NULL, null

None

string

aString, ‘a string’, “a string”

str

dict

{key1 value1; key2 value2;}

dict

list

(1.0 2.0 3.0)

list

reference

$var1

(type of var1)

expression

“$var1 + 4”

(type of var1)

Examples

Below examples demonstrate the different element types supported by dictIO in dict files.

booleans

    bool1           true;           // True
    bool2           false;          // False
    bool3           True;           // True
    bool4           False;          // False
    bool5           on;             // True
    bool6           off;            // False
    bool7           ON;             // True
    bool8           OFF;            // False

numbers

int1            0;              // int
int2            120;            // int
float1          3.5;            // float
float2          1.00000000e+00; // float

nones

none1           None;           // None
none2           none;           // None
none3           NULL;           // None
none4           null;           // None

strings

string1         '';
string2         'string';
string3         'string with spaces';
string4         singleWordsWithoutSpacesCanAlsoBeDeclaredWithoutQuotes;
string5         'string with single quotes';
string6         "string with double quotes";

dicts

emptyDict
{

}

dictWithNumbers
{
    var1        1;
    var2        2.0;
    var3        3.14;
}

dictWithStrings
{
    string1     'string1';
    string2     'string2 has spaces';
    string3     'string3';
    string4     'string4 is ok but note that string5 is empty';
    string5     '';
}

lists

emptyList
(

);

listWithNumbers
(
    1      2.0     3.14
);

matrix                              // a matrix is represented by a list of lists
(
    (11    12    13)
    (21    22    23)
    (31    32    33)
);


listWithStrings
(
    'string1'    'string2 has spaces'    'string3'     'string4 is ok but note that string5 is empty'     ''
);

References and Expressions

Any key’d element in a dict file can also be treated as a variable that can be pointed to using references. A reference is denoted by a $ character followed by the key of the element being referenced, also known as $keyword syntax.

References, in turn, can be used inside expressions. Expressions are double-quoted strings containing a mathematical expression where at least one operand is a reference.

Below code listing demonstrates the use of references and expressions:

varA            1.0;
varB            2.0;
list            (1.0   2.0   3.0);
matrix
(
    (11    12    13)
    (21    22    23)
    (31    32    33)
);

reference1      $varA;              // simple reference to a variable. References are prefixed with $.
reference2      $list[0];           // indexed reference to an item in a list.
reference3      $matrix[0];         // indexed reference to a specific row in a matrix (=returns a list).
reference4      $matrix[0][1];      // indexed reference to a specific value in a matrix.
expression1     "$varA";            // expression. However, result of this expression is same as using a simple reference without double quotes.
expression2     "$varA + 4";        // expression with one reference and one constant.
expression3     "$varA + $varB";    // expression with two references.
expression4     "$list[0] + 3.14";  // expression with an indexed reference.

Nesting

Both dicts and lists can be nested. In fact, dicts and lists in a dict file can be arbitrarily nested.

While lexically possible, readability of nested data structures quickly suffers. In dict files intended to be read and edited by humans, such as configuration files, nesting should hence be used carefully and reasonably limited (an example that commonly causes misinterpretation is where a dict is nested inside a list, see section The dict-in-a-list Pitfall further below).

From a pure lexical / technical point of view, though, complex nesting of dicts and lists is possible. So, in cases where dict files are written and read purely by machines, this can provide additional capabilities.

nesting
{
    emptyNestedDict
    {

    }
    emptyNestedList
    (

    );
    nestedDictWithNestedList
    {
        list1
        (
            1.00000000e+00  2.20972831e-17  3.15717747e-18
        );
        list2
        (
            2.20972831e-17  1.00000000e+00 -7.07290050e-18
        );
        list3
        (
            3.15717747e-18 -7.07290050e-18  1.00000000e+00
        );
    }
    nestedListWithNestedList
    (
        (
            1.00000000e+00  2.20972831e-17  3.15717747e-18
        )
        (
            2.20972831e-17  1.00000000e+00 -7.07290050e-18
        )
        (
            3.15717747e-18 -7.07290050e-18  1.00000000e+00
        )
    );
    nestedListWithNestedDict
    (
        (
            11       12       13
        )
        {
            value21     21;
            value22     22;
            value23     23;
        }
        (
            31      32      33
        )
    );
}

The dict-in-a-list Pitfall

A very prominent example where nesting of dicts and lists deteriorates human readibility and causes misinterpretation is where a dict is nested inside a list. Read below example to see why:

keyToADict                  // This is a key. You can access its value (the subsequent dict {}) as a key'd element              -> myDict['keyToADict']
{                           // This is the key'd element associated with key 'keyToADict'. It is of type dict.
    keyToAList              // This is a key. You can access its value (the subsequent list ()) as a key'd element              -> myDict['keyToADict']['keyToAList']
    (                       // This is the key'd element associated with key 'keyToAList'. It is of type list.
        notAKey             // This is NOT a key. It is a list element of type string. You can access it by its index           -> myDict['keyToADict']['keyToAList'][0]
        {                   // This is NOT a key'd element. It is a list element of type dict. You can access it by its index   -> myDict['keyToADict']['keyToAList'][1]
            key1 value1;    // This is a key'd element inside the surrounding dict                                              -> myDict['keyToADict']['keyToAList'][1]['key1']
            key2 value2;    // This is a key'd element inside the surrounding dict                                              -> myDict['keyToADict']['keyToAList'][1]['key2']
        }
        notAKey             // another list element                                                                             -> myDict['keyToADict']['keyToAList'][2]
        notAKey             // yet another list element                                                                         -> myDict['keyToADict']['keyToAList'][3]
        notAKey             // yet .. well, you got the point ..                                                                -> myDict['keyToADict']['keyToAList'][4]
        notAKey             // NOT A KEY !!                                                                                     -> myDict['keyToADict']['keyToAList'][5]
        {                   // another list element of type dict                                                                -> myDict['keyToADict']['keyToAList'][6]
            key1 value1;    // This is a key'd element inside the surrounding dict                                              -> myDict['keyToADict']['keyToAList'][6]['key1']
            key2 value2;    // This is a key'd element inside the surrounding dict                                              -> myDict['keyToADict']['keyToAList'][6]['key2']
        }
    );
}