Specifying Units for Variables

Specifying Units for Variables#

As we saw in Declaring Continuous Variables, we can specify units for inputs, outputs, and residuals. There is a units argument to add_input to specify input units, and there are units and res_units arguments on add_output to specify output and residual units, respectively. A complete listing of all available units is given here.

Note

Residual units, if not specified, default to the same units as the output variable. res_units is very rarely specified.

Specifying units has the following result:

  1. Unit conversions occur during data passing. For instance, let’s say we have a TimeComp component that outputs time1 in hours and a SpeedComp component takes time2 as an input but in seconds. If we connect TimeComp.time1 to SpeedComp.time2 with hours/seconds specified during the corresponding add_output/add_input calls, then OpenMDAO automatically converts from hours to seconds.

  2. The user always gets/sets the variable in the specified units. Declaring an input, output, or residual to have certain units means that any value ‘set’ into the variable is assumed to be in the given units and any time the user asks to ‘get’ the variable, the value is return in the given units. This is the case not only in <Component> methods such as compute, apply_nonlinear, and apply_linear, but everywhere, including the user’s run script.

  3. In add_input and add_output, all arguments are assumed to be given in the specified units. In the case of add_input, if units is specified, then val is assumed to be given in those units. In the case of add_output, if units is specified, then val, lower, upper, ref, and ref0 are all assumed to be given in those units. Also in add_output, if res_units is specified, then res_ref is assumed to be given in res_units.

Units syntax#

Units are specified as a string that adheres to the following syntax. The string is a composition of numbers and known units that are combined with multiplication (*), division (/), and exponentiation (**) operators. The known units can be prefixed by kilo (k), Mega (M), and so on. The list of units and valid prefixes can be found in the units library.

For example, each of the following is a valid unit string representing the same quantity:

  • N

  • 0.224809 * lbf

  • kg * m / s ** 2

  • kg * m * s ** -2

  • kkg * mm / s ** 2

Note

If units are not specified, or are specified as None then the variable is assumed to be unitless. If such a variable is connected to a variable with units, the connection will be allowed, but a warning will be issued.

Example#

This example illustrates how we can compute speed from distance and time given in km and h using a component that computes speed using m and s.

We first define the component.

import openmdao.api as om


class SpeedComp(om.ExplicitComponent):
    """Simple speed computation from distance and time with unit conversations."""

    def setup(self):
        self.add_input('distance', val=1.0, units='km')
        self.add_input('time', val=1.0, units='h')
        self.add_output('speed', val=1.0, units='km/h')

    def compute(self, inputs, outputs):
        outputs['speed'] = inputs['distance'] / inputs['time']

In the overall problem, the first component, c1, defines distance and time in m and s. OpenMDAO handles the unit conversions when passing these two variables into c2, our ‘SpeedComp’. There is a further unit conversion from c2 to c3 since speed must be converted now to m/s.

import openmdao.api as om
from openmdao.core.tests.test_units import SpeedComp

prob = om.Problem()
prob.model.add_subsystem('c1', SpeedComp())
prob.model.add_subsystem('c2', om.ExecComp('f=speed',speed={'units': 'm/s'}))

prob.model.set_input_defaults('c1.distance', val=1., units='m')
prob.model.set_input_defaults('c1.time', val=1., units='s')

prob.model.connect('c1.speed', 'c2.speed')

prob.setup()
prob.run_model()

print(prob.get_val('c1.distance'))  # units: km
[0.001]
print(prob.get_val('c1.time'))   # units: h
[0.00027778]
print(prob.get_val('c1.speed'))       # units: km/h
[3.6]
print(prob.get_val('c2.f'))           # units: m/s
[1.]