Unit handling and unit conversions in qha-cij

For the convenience of calculation, the physical quantities in qha-cij are all stored in Rydberg atomic units. But to make things easier for user, we use units that is reported by scientists. Natually, there is a lot of unit handling involved. This tutorial will demostrate how unit conversions are done in qha-cij, so that if there is a need for you to address units issues on your own, you will not be lost.

The units module

The units module is provided in cij.util. Based on the pint package, the units is a instance of Pint UnitRegistry that will maintain a list of units. The atomic units are by default loaded and available after Pint 0.10.0 we will stick to that. A single UnitRegistry instance is supposed to be shared among the entire program.

[1]:
from cij.util import units

print("The type of `units` is actually a instance of", repr(type(units)))
The type of `units` is actually a instance of <class 'pint.registry.UnitRegistry'>

Declaring quantity

The physical variables are declared using Quantity to include the phyisical units

[2]:
print(units.Quantity(1, units.m))
print(units.Quantity(1, units.rydberg))
1 meter
1 rydberg

Conversion between units with to()

Units are converted by create a Quantity with unit, and convert the unit with to(), and the the value number is obtained using the .magnitude property.

Here we convert three terms:

  • Length: 1 Å = 0.529177 bohr

  • Volume: 1 Å\(^3\) = 0.148184 bohr\(^3\)

  • Pressure: 1 Ryd / bohr\(^3\) = 14710 GPa

[3]:
print("- Length:\t", units.Quantity(1, units.bohr).to(units.angstrom).magnitude)
print("- Volume:\t", units.Quantity(1, units.bohr ** 3).to(units.angstrom ** 3).magnitude)
print("- Pressure:\t", units.Quantity(1, units.rydberg / units.bohr ** 3).to(units.GPa).magnitude)
- Length:        0.5291772109039774
- Volume:        0.14818471147298387
- Pressure:      14710.50784817977

Helper functions to make it even better

To make unit conversion even easier, I have create a function called convert_unit. It takes three parameters, the original unit to convert from, the target unit to convert to, and the value.

[4]:
from cij.util import convert_unit

print("Convert unit by calling convert_unit directly:")

print("- Length:\t",   convert_unit(units.bohr, units.angstrom, 1))
print("- Volume:\t",   convert_unit(units.bohr ** 3, units.angstrom ** 3, 1))
print("- Pressure:\t", convert_unit(units.rydberg / units.bohr ** 3, units.GPa, 1))
Convert unit by calling convert_unit directly:
- Length:        0.5291772109039774
- Volume:        0.14818471147298387
- Pressure:      14710.50784817977

Omit the value field you will get a function for method conversion required.

[5]:
print("Convert unit by creating a unit conversion function first:")

_to_gpa = convert_unit(units.rydberg / units.bohr ** 3, units.GPa)

print("- Pressure:\t", convert_unit(units.rydberg / units.bohr ** 3, units.GPa, 1))
Convert unit by creating a unit conversion function first:
- Pressure:      14710.50784817977