Download this example

Download this example as a Jupyter Notebook or as a Python script.


PyAnsys Geometry 101: Units#

To handle units inside the source code, PyAnsys Geometry uses Pint, a third-party open source software that other PyAnsys libraries also use.

The following code examples show how to operate with units inside the PyAnsys Geometry codebase and create objects with different units.

Import units handler#

The following line of code imports the units handler: pint.util.UnitRegistry. For more information on the UnitRegistry class in the pint API, see Most important classes in the Pint documentation.

[1]:
from ansys.geometry.core.misc import UNITS

Create and work with Quantity objects#

With the UnitRegistry object called UNITS, you can create Quantity objects. A Quantity object is simply a container class with two core elements:

  • A number

  • A unit

Quantity objects have convenience methods, including those for transforming to different units and comparing magnitudes, values, and units. For more information on the Quantity class in the pint API, see Most important classes in the Pint documentation. You can also step through this Pint tutorial.

[2]:
from pint import Quantity

a = Quantity(10, UNITS.mm)

print(f"Object a is a pint.Quantity: {a}")

print("Request its magnitude in different ways (accessor methods):")
print(f"Magnitude: {a.m}.")
print(f"Also magnitude: {a.magnitude}.")

print("Request its units in different ways (accessor methods):")
print(f"Units: {a.u}.")
print(f"Also units: {a.units}.")

# Quantities can be compared between different units
# You can also build Quantity objects as follows:
a2 = 10 * UNITS.mm
print(f"Compare quantities built differently: {a == a2}")

# Quantities can be compared between different units
a2_diff_units = 1 * UNITS.cm
print(f"Compare quantities with different units: {a == a2_diff_units}")
Object a is a pint.Quantity: 10 millimeter
Request its magnitude in different ways (accessor methods):
Magnitude: 10.
Also magnitude: 10.
Request its units in different ways (accessor methods):
Units: millimeter.
Also units: millimeter.
Compare quantities built differently: True
Compare quantities with different units: True

PyAnsys Geometry objects work by returning Quantity objects whenever the property requested has a physical meaning.

Return Quantity objects for Point3D objects.

[3]:
from ansys.geometry.core.math import Point3D

point_a = Point3D([1,2,4])
print("========================= Point3D([1,2,4]) ========================")
print(f"Point3D is a numpy.ndarray in SI units: {point_a}.")
print(f"However, request each of the coordinates individually...\n")
print(f"X Coordinate: {point_a.x}")
print(f"Y Coordinate: {point_a.y}")
print(f"Z Coordinate: {point_a.z}\n")

# Now, store the information with different units...
point_a_km = Point3D([1,2,4], unit=UNITS.km)
print("================= Point3D([1,2,4], unit=UNITS.km) =================")
print(f"Point3D is a numpy.ndarray in SI units: {point_a_km}.")
print(f"However, request each of the coordinates individually...\n")
print(f"X Coordinate: {point_a_km.x}")
print(f"Y Coordinate: {point_a_km.y}")
print(f"Z Coordinate: {point_a_km.z}\n")

# These points, although they are in different units, can be added together.
res = point_a + point_a_km

print("=================== res = point_a + point_a_km ====================")
print(f"numpy.ndarray: {res}")
print(f"X Coordinate: {res.x}")
print(f"Y Coordinate: {res.y}")
print(f"Z Coordinate: {res.z}")
========================= Point3D([1,2,4]) ========================
Point3D is a numpy.ndarray in SI units: [1. 2. 4.].
However, request each of the coordinates individually...

X Coordinate: 1 meter
Y Coordinate: 2 meter
Z Coordinate: 4 meter

================= Point3D([1,2,4], unit=UNITS.km) =================
Point3D is a numpy.ndarray in SI units: [1000. 2000. 4000.].
However, request each of the coordinates individually...

X Coordinate: 1 kilometer
Y Coordinate: 2 kilometer
Z Coordinate: 4 kilometer

=================== res = point_a + point_a_km ====================
numpy.ndarray: [1001. 2002. 4004.]
X Coordinate: 1001.0 meter
Y Coordinate: 2002.0 meter
Z Coordinate: 4004.0 meter

Use default units#

PyAnsys Geometry implements the concept of default units.

[4]:
from ansys.geometry.core.misc import DEFAULT_UNITS

print("=== Default unit length ===")
print(DEFAULT_UNITS.LENGTH)

print("=== Default unit angle ===")
print(DEFAULT_UNITS.ANGLE)
=== Default unit length ===
meter
=== Default unit angle ===
radian

It is important to differentiate between client-side default units and server-side default units. You are able to control both of them.

Print the default server unit length.

[5]:
print("=== Default server unit length ===")
print(DEFAULT_UNITS.SERVER_LENGTH)
=== Default server unit length ===
meter

Use default units.

[6]:
from ansys.geometry.core.math import Point2D
from ansys.geometry.core.misc import DEFAULT_UNITS

DEFAULT_UNITS.LENGTH = UNITS.mm

point_2d_default_units = Point2D([3, 4])
print("This is a Point2D with default units")
print(f"X Coordinate: {point_2d_default_units.x}")
print(f"Y Coordinate: {point_2d_default_units.y}")
print(f"numpy.ndarray value: {point_2d_default_units}")

# Revert back to original default units
DEFAULT_UNITS.LENGTH = UNITS.m
This is a Point2D with default units
X Coordinate: 3 millimeter
Y Coordinate: 4 millimeter
numpy.ndarray value: [0.003 0.004]

PyAnsys Geometry has certain auxiliary classes implemented that provide proper unit checking when assigning values. Although they are basically intended for internal use of the library, you can define them for use.

[7]:
from ansys.geometry.core.misc import Angle, Distance

Start with Distance. The main difference between a Quantity object (that is, from pint import Quantity) and a Distance is that there is an active check on the units passed (in case they are not the default ones). Here are some examples.

[8]:
radius = Distance(4)
print(f"The radius is {radius.value}.")

# Reassign the value of the distance
radius.value = 7 * UNITS.cm
print(f"After reassignment, the radius is {radius.value}.")


# Change the units if desired
radius.unit = UNITS.cm
print(f"After changing its units, the radius is {radius.value}.")
The radius is 4 meter.
After reassignment, the radius is 0.07 meter.
After changing its units, the radius is 7.000000000000001 centimeter.

The next two code examples show how unreasonable operations raise errors.

[9]:
try:
    radius.value = 3 * UNITS.degrees
except TypeError as err:
    print(f"Error raised: {err}")
Error raised: The pint.Unit provided as an input should be a [length] quantity.
[10]:
try:
    radius.unit = UNITS.fahrenheit
except TypeError as err:
    print(f"Error raised: {err}")
Error raised: The pint.Unit provided as an input should be a [length] quantity.

The same behavior applies to the Angle object. Here are some examples.

[11]:
import numpy as np

rotation_angle = Angle(np.pi / 2)
print(f"The rotation angle is {rotation_angle.value}.")

# Try reassigning the value of the distance
rotation_angle.value = 7 * UNITS.degrees
print(f"After reassignment, the rotation angle is {rotation_angle.value}.")

# You could also change its units if desired
rotation_angle.unit = UNITS.degrees
print(f"After changing its units, the rotation angle is {rotation_angle.value}.")
The rotation angle is 1.5707963267948966 radian.
After reassignment, the rotation angle is 0.12217304763960307 radian.
After changing its units, the rotation angle is 7.0 degree.

Download this example

Download this example as a Jupyter Notebook or as a Python script.