Using units
All physical quantities within MDMC should possess units.
Everything related to units in MDMC is defined in MDMC.common.units
.
This includes:
the system of units (in the
SYSTEM
dictionary)A
Unit
class, which derives fromstr
to add additional arithmetic methods (__mul__
,__div__
, and__pow__
) so that strings representing units (e.g.'Ang'
,'s'
) can be combined by these operations:Unit('Ang') * Unit('s') == Unit('Ang s')
UnitFloat
andUnitNDArray
classes, which derive fromfloat
andnumpy.ndArray
to add additional aUnit
object to the representation, by means of aunit
attribute.
So all physical quantities must be a UnitFloat
or a
UnitNDArray
, and have the correct
Unit
object as an attribute. This can be achieved by
having the unit as a property, rather than an attribute, and using one of the
following decorators (in MDMC.common.decorators
):
unit_decorator
: This should typically be the decorator that is used as it sets the property to be either aUnitFloat
orUnitNDArray
. It should be added to the property setter:
@property
def velocity(self):
return self._velocity
@velocity.setter
@unit_decorator(unit=units.LENGTH / units.TIME)
def velocity(self, velocity):
self._velocity = velocity
unit_decorator_getter
: This only be used either where the property has no setter method or where the getter method performs a calculation before setting the value (which may result in theUnitFloat
/UnitNDArray
being cast to afloat
/ndArray
). It should only be used in these cases as it is more expensive thanunit_decorator
, as it initialises aUnitFloat
/UnitNDArray
object every time the getter is called. It should be added to the property getter:
@property
@unit_decorator_getter(unit=units.LENGTH)
def dims(self):
return self._dims
In both of the above examples the unit passed to the decorator is a constant
from the SYSTEM
of units defined in the MDMC.common.units
;
however it would be equally valid to define a unit in this argument:
from MDMC.common.units import Unit
@property
@unit_decorator_getter(unit=Unit('nm'))
def dims(self):
return self._dims
It is then obviously important that all functions and methods that use these properties have the correct factors to ensure the unit conversions are correct.