Units Handling in Pyomo
Pyomo Units Container Module
This module provides support for including units within Pyomo expressions. This module can be used to define units on a model, and to check the consistency of units within the underlying constraints and expressions in the model. The module also supports conversion of units within expressions using the convert method to support construction of constraints that contain embedded unit conversions.
To use this package within your Pyomo model, you first need an instance of a PyomoUnitsContainer. You can use the module level instance already defined as ‘units’. This object ‘contains’ the units - that is, you can access units on this module using common notation.
>>> from pyomo.environ import units as u >>> print(3.0*u.kg) 3.0*kg
Units can be assigned to Var, Param, and ExternalFunction components, and can be used directly in expressions (e.g., defining constraints). You can also verify that the units are consistent on a model, or on individual components like the objective function, constraint, or expression using assert_units_consistent (from pyomo.util.check_units). There are other methods there that may be helpful for verifying correct units on a model.
>>> from pyomo.environ import ConcreteModel, Var, Objective >>> from pyomo.environ import units as u >>> from pyomo.util.check_units import assert_units_consistent, assert_units_equivalent, check_units_equivalent >>> model = ConcreteModel() >>> model.acc = Var(initialize=5.0, units=u.m/u.s**2) >>> model.obj = Objective(expr=(model.acc - 9.81*u.m/u.s**2)**2) >>> assert_units_consistent(model.obj) # raise exc if units invalid on obj >>> assert_units_consistent(model) # raise exc if units invalid anywhere on the model >>> assert_units_equivalent(model.obj.expr, u.m**2/u.s**4) # raise exc if units not equivalent >>> print(u.get_units(model.obj.expr)) # print the units on the objective m**2/s**4 >>> print(check_units_equivalent(model.acc, u.m/u.s**2)) True
The implementation is currently based on the pint package and supports all the units that are supported by pint. The list of units that are supported by pint can be found at the following url: https://github.com/hgrecco/pint/blob/master/pint/default_en.txt.
If you need a unit that is not in the standard set of defined units,
you can create your own units by adding to the unit definitions within
pint. See PyomoUnitsContainer.load_definitions_from_file()
or
PyomoUnitsContainer.load_definitions_from_strings()
for more
information.
Note
In this implementation of units, “offset” units for temperature are not supported within expressions (i.e. the non-absolute temperature units including degrees C and degrees F). This is because there are many non-obvious combinations that are not allowable. This concern becomes clear if you first convert the non-absolute temperature units to absolute and then perform the operation. For example, if you write 30 degC + 30 degC == 60 degC, but convert each entry to Kelvin, the expression is not true (i.e., 303.15 K + 303.15 K is not equal to 333.15 K). Therefore, there are several operations that are not allowable with non-absolute units, including addition, multiplication, and division.
This module does support conversion of offset units to absolute units numerically, using convert_value_K_to_C, convert_value_C_to_K, convert_value_R_to_F, convert_value_F_to_R. These are useful for converting input data to absolute units, and for converting data to convenient units for reporting.
Please see the pint documentation here for more discussion. While pint implements “delta” units (e.g., delta_degC) to support correct unit conversions, it can be difficult to identify and guarantee valid operations in a general algebraic modeling environment. While future work may support units with relative scale, the current implementation requires use of absolute temperature units (i.e. K and R) within expressions and a direct conversion of numeric values using specific functions for converting input data and reporting.
- class pyomo.core.base.units_container.PyomoUnitsContainer(pint_registry=NOTSET)[source]
Bases:
object
Class that is used to create and contain units in Pyomo.
This is the class that is used to create, contain, and interact with units in Pyomo. The module (
pyomo.core.base.units_container
) also contains a module level units containerunits
that is an instance of a PyomoUnitsContainer. This module instance should typically be used instead of creating your own instance of aPyomoUnitsContainer
. For an overview of the usage of this class, see the module documentation (pyomo.core.base.units_container
)This class is based on the “pint” module. Documentation for available units can be found at the following url: https://github.com/hgrecco/pint/blob/master/pint/default_en.txt
Note
Pre-defined units can be accessed through attributes on the PyomoUnitsContainer class; however, these attributes are created dynamically through the __getattr__ method, and are not present on the class until they are requested.
- convert(src, to_units=None)[source]
This method returns an expression that contains the explicit conversion from one unit to another.
- Parameters:
src (Pyomo expression) – The source value that will be converted. This could be a Pyomo Var, Pyomo Param, or a more complex expression.
to_units (Pyomo units expression) – The desired target units for the new expression
- Returns:
ret
- Return type:
Pyomo expression
- convert_temp_C_to_K(value_in_C)[source]
Convert a value in degrees Celsius to Kelvin Note that this method converts a numerical value only. If you need temperature conversions in expressions, please work in absolute temperatures only.
- convert_temp_F_to_R(value_in_F)[source]
Convert a value in degrees Fahrenheit to Rankine. Note that this method converts a numerical value only. If you need temperature conversions in expressions, please work in absolute temperatures only.
- convert_temp_K_to_C(value_in_K)[source]
Convert a value in Kelvin to degrees Celsius. Note that this method converts a numerical value only. If you need temperature conversions in expressions, please work in absolute temperatures only.
- convert_temp_R_to_F(value_in_R)[source]
Convert a value in Rankine to degrees Fahrenheit. Note that this method converts a numerical value only. If you need temperature conversions in expressions, please work in absolute temperatures only.
- convert_value(num_value, from_units=None, to_units=None)[source]
This method performs explicit conversion of a numerical value from one unit to another, and returns the new value.
The argument “num_value” must be a native numeric type (e.g. float). Note that this method returns a numerical value only, and not an expression with units.
- Parameters:
num_value (float or other native numeric type) – The value that will be converted
from_units (Pyomo units expression) – The units to convert from
to_units (Pyomo units expression) – The units to convert to
- Returns:
float
- Return type:
The converted value
- get_units(expr)[source]
Return the Pyomo units corresponding to this expression (also performs validation and will raise an exception if units are not consistent).
- Parameters:
expr (Pyomo expression) – The expression containing the desired units
- Returns:
Returns the units corresponding to the expression
- Return type:
Pyomo unit (expression)
- Raises:
- load_definitions_from_file(definition_file)[source]
Load new units definitions from a file
This method loads additional units definitions from a user specified definition file. An example of a definitions file can be found at: https://github.com/hgrecco/pint/blob/master/pint/default_en.txt
If we have a file called
my_additional_units.txt
with the following lines:USD = [currency]
Then we can add this to the container with:
>>> u.load_definitions_from_file('my_additional_units.txt') >>> print(u.USD) USD
- load_definitions_from_strings(definition_string_list)[source]
Load new units definitions from a string
This method loads additional units definitions from a list of strings (one for each line). An example of the definitions strings can be found at: https://github.com/hgrecco/pint/blob/master/pint/default_en.txt
For example, to add the currency dimension and US dollars as a unit, use
>>> u.load_definitions_from_strings(['USD = [currency]']) >>> print(u.USD) USD