Config Values

All of the values in a Pavilion configuration are parsed and resolved. They can contain expressions and iterations, which let Pavilion dynamically alter the each test configuration.

Environment Variables

To head off some confusion we’ve ran into with new Pavilion users - Variables in Pavilion are NOT environment variables. Pavilion variable references/expressions are resolved before any scripts are written, while environment variables would be resolved during the execution of those scripts.

For more information on environment variables in Pavilion, see Environment Variables.

Mathematical Expressions

Expressions are contained within double curly braces. They can contain variable references, function calls, and math operations. Expressions often behave similarly to Python3, but they are not Python3 code.

expr_test:
    variables:
        # Note that this is a string. Math operations will convert it
        # to a number automatically.
        min_threads: "5"

    run:
        env:
            # Whitespace within expression blocks is ignored.
            # Expression blocks always result in a string value.
            OMP_NUM_THREADS: '{{ min( [min_threads, sched.min_ppu] ) }}'
        cmds:
            # In the simple case, expressions are often just a variable
            # reference.
            - "{{sched.test_cmds}} ./my_cmd"

Types of Expressions

This documentation covers expressions within the context of Pavilion value strings. They may also be used, with the exact same syntax (but using result keys as variables), in the ‘result_evaluate’ section. See Result Evaluations.

Supported Math

Pavilion expressions support most common math operations, and they behave identically to Python3 (with one noted exception). This includes:

  • Addition, subtractions, multiplication and division. a + b - c * d / e.

  • Floor division // and modulus % operations. 4.0 // 3

  • Power operations, though Pavilion uses ^ to denote these. a ^ 3

  • Logical operations a and b or not False.

  • Parenthetical expressions a * (b + 1)

List Operations

When using math operations with list values, the operation is applied recursively to each element. Operations between two lists require that the lists be equal length, and apply the operation between each corresponding pair of items.

list_expr_test:
    variables:
        nums: [1, 2, 3, 4]
        mult: [4, 4, 2, 1.5]

        # This would add 3 to each value in the num list, then take average.
        # The result would thus be (4 + 5 + 6 + 7)/4 == 5.5
        avg_adj_nums: '{{avg(nums + 3)}}'

        # This would produce (1*4 + 2*4 + 3*2 + 4*1.5)/4 == 6.0
        mult_avg: '{{avg(nums*mult)}}'

Types and End Results

Math operations handle ints, floats, and booleans (True and False). Variable values are always strings, but are auto-converted as if they were literal ints, floats or booleans when used in math or logic operations.

Strings, lists (of these types) and dictionaries/mappings are allowed as well. While they can’t be used in math operations, they are often useful in as function arguments.

The final result of an expression cannot be a list or dict - this will result in an error.

Result Formatting

Expressions can be formatted using printf-like format codes. These are put at the end of the expression after a colon:

format_test:
    variables:
        # The chunk size will be the square root of sys_nodes, to three
        # decimal places.
        chunk_size: "{{ sched.sys_nodes^(0.5) :0.3f}}"
        # The id will be the current time zero-padded to 10 digits.
        id: "{{pav.timestamp:010d}}"

Formatting behaves exactly like Python format specs, because that’s exactly what they are.

Functions

Functions can be used within expressions as well.

  • Functions are all Expression Function Plugins.

  • Available functions can be listed with pav show functions.

  • Functions auto-convert argument types as appropriate.

Iterations

Iterations give you the ability to insert that string once for every value of a contained variable. They’re bracketed by [~ and ~].

substr_test:
    variables:
      dirs: ['/usr', '/root', '/opt']

    run:
      cmds: 'ls [~{{dirs}}/ ~]'

This would result in a command of ls /usr/ /root/ /opt/. Note that the trailing / and space are repeated as well.

super_magic_fs:
    variables:
      projects: [origami, fusion]

    run:
      cmds: 'srun ./super_magic [~-w /opt/proj/{{projects}} ~] -a'

This would get us a command of: srun ./super_magic -w /opt/proj/origami -w /opt/proj/fusion  -a

Iteration Separators

In the above examples, the trailing space from the iteration resulted in an extra space at the end. That’s fine in most circumstances, but what if we need to separate the strings with something that can’t be repeated at the end?

To do that, simply insert your separator between the tilde ~ and closing square bracket ]. The separator can be of any length, and any closing square brackets need to be escaped (\]).

substr_test2:
    variables:
      groups: [testers, supertesters]

    run:
      cmds: 'grep --quiet "[~{{groups}}~|]" /etc/group'

The command would be: grep --quiet "testers|supertesters" /etc/group

Multiple Variables

Iterations can contain multiple variables, in which case the iteration will be repeated for every combination of the variable values.

super_magic_fs:
    variables:
      projects: [origami, fusion]
      test_users: [bob, jane]

    run:
      cmds: 'srun ./super_magic [~-w {{projects}}/{{test_users}} ~]'

This would result in the command:

srun ./super_magic -w origami/bob -w fusion/bob -w origami/jane -w fusion/jane

Direct Variable Access

In all the iterations we’ve used so far, the variables were in the form: 'var.projects' or just 'projects'. If we want to access a specific value from a multi-valued variable, we can still do that. You can’t, however, access a specific value from a variable that is being iterated over.

..code-block

super_magic_fs:
variables:

projects: [origami, fusion] test_users: [bob, jane]

cmds:

# This is ok - ‘srun ./super_magic [~-w {{projects}}/{{test_users.0}} ~]’ # srun ./super_magic -w origami/bob -w fusion/bob

# This is NOT ok, and will cause an error. - ‘echo “[~{{test_users}} {{test_users.1}} ~]”