Parameters and ParameterFrames

Parameter and ParameterFrame are the means by which the physical configuration of a bluemira analysis are setup.

Parameters

A Parameter object wraps a value and holds metadata relating to that value. To create a Parameter, as a minimum, the name, the value and a unit need to be provided but other information can be added:

name

The shorthand name of the Parameter used for access when used as part of a ParameterFrame.

value

The value of the Parameter.

unit

The unit associated with the value.

source

The origin of a Parameter, for instance the module it was set from.

description

A description of the Parameter. This is a good place for references and other useful information.

long_name

A longer more descriptive name for instance ‘A’ could be the Parameter name but ‘Aspect Ratio’ is more helpful for a user.

>>> from bluemira.base.parameter_frame import Parameter
>>> r_0 = Parameter(
...     name="R_0",
...     value=5000,
...     unit="cm",
...     source="Input",
...     description="Tokamak major radius",
...     long_name="Major Radius",
... )
>>> print(r_0)
<Parameter(R_0=5000 cm)>

Only the value of the Parameter can be directly updated after initialisation. However if you want to change the source the set_value() method can be used.

>>> r_0.value = 6000
>>> print(r_0, r_0.source or None)
<Parameter(R_0=6000 cm)> None
>>> r_0.set_value(20, "New Input")
>>> print(r_0, r_0.source or None)
<Parameter(R_0=20 cm)> New Input

If you want to access the value of the Parameter in a different unit, the value_as() method can be used.

>>> r_0.value_as('m')
0.2

Any update to a Parameter value is stored and can be accessed with the history() method which can be useful to understand why a Parameter value changed.

>>> r_0.history()
[ParameterValue(value=5000, source='Input'),
 ParameterValue(value=6000, source=''),
 ParameterValue(value=20, source='New Input')]

ParameterFrames

A ParameterFrame allows Parameters to be grouped together to describe the overall parameterisation of a particular analysis or class within bluemira. For this reason you will interact with Parameters via a ParameterFrame in most cases.

A ParameterFrame is written as a dataclass:

from dataclasses import dataclass
from bluemira.base.parameter_frame import Parameter, ParameterFrame

@dataclass
class MyParameterFrame(ParameterFrame):
    R_0: Parameter[float]
    A: Parameter[float]

The type of each Parameter must be specified and adhered to in the initialisation of the ParameterFrame. A ParameterFrame can be initialised from a dictionary, a json file or another ParameterFrame (must be a superset of the ParameterFrame being initialised).

param_dict = {
    "R_0": {
        "value": 9,
        "unit": "m",
        "source": "Input",
    },
    "A": {
        "value": 3.1,
        "unit": "dimensionless",
        "source": "Input",
    },
}
params = MyParameterFrame.from_dict(param_dict)
param_2 = MyParameterFrame.from_frame(params)

Units

ParameterFrames always enforce the same set of standard units Unit conventions. Parameters within a ParameterFrame whose units are convertible to one of bluemira’s standard units, have their values and converted to the corresponding standard unit. This keeps the units used within bluemira consistent across classes and modules.

For this reason, if your inputs use a non-standard unit, the value you put into a Parameter will be different to the one you get out.

>>> param_dict = {
...     "R_0": {
...         "value": 9,
...         "unit": "cm",
...         "source": "Input",
...     },
...     "A": {
...         "value": 3.1,
...         "unit": "dimensionless",
...         "source": "Input",
...     },
... }
>>> print(MyParameterFrame.from_dict(param_dict))
╒════════╤═════════╤═══════════════╤══════════╤═══════════════╤═════════════╕
│ name   │   value │ unit          │ source   │ description   │ long_name   │
╞════════╪═════════╪═══════════════╪══════════╪═══════════════╪═════════════╡
│ A      │     3.1 │ dimensionless │ Input    │ N/A           │ N/A         │
├────────┼─────────┼───────────────┼──────────┼───────────────┼─────────────┤
│ R_0    │    0.09 │ m             │ Input    │ N/A           │ N/A         │
╘════════╧═════════╧═══════════════╧══════════╧═══════════════╧═════════════╛

Use Parameter.value_as() to return parameter values in a non-standard unit. Input values with units listed in Unit conventions are not modified.