Units
In Euphonic, units are handled by Pint. Pint
wraps Numpy arrays as a Quantity
object, so you can easily see which units
values are in.
Euphonic’s ureg
Units in euphonic are accessed through euphonic.ureg
, which is a
Pint.UnitRegistry
object that contains all required units. For example, to
create temperature as a Quantity
with units in Kelvin rather than a plain
float:
from euphonic import ureg
temperature = 5.0*ureg('K')
This can also be done with Numpy arrays, to create an array with units. For example, to create an array of energy bins in meV:
from euphonic import ureg
import numpy as np
arr = np.arange(0, 100, 1)
energy_bins = arr*ureg('meV')
Quantities as Function Arguments
Many Euphonic functions require Quantity
wrapped values as arguments.
Simply import the unit registry and create a Quantity
, then pass it to
a function:
from euphonic import QpointPhononModes, ureg
phonons = QpointPhononModes.from_castep('quartz.phonon')
fm = ureg('fm')
scattering_lengths = {'Si': 4.1491*fm, 'O': 5.803*fm}
sf = phonons.calculate_structure_factor(scattering_lengths)
Object Attributes
Any dimensioned attributes (attributes with units) on a Euphonic object,
for example cell_vectors
or frequencies
, are actually properties.
They are stored internally in atomic units, and only wrapped as a
Quantity
in user-friendly units once they are accessed.
Changing attribute units
When a Euphonic object is created, its dimensioned attributes will be
in default units (e.g. meV for frequencies, angstrom for cell vectors).
Each Quantity
attribute has an associated string attribute that can
be used to change the units. See the following example to change the units
of frequency in QpointPhononModes
:
>>> from euphonic import QpointPhononModes
>>> phonons = QpointPhononModes.from_castep('quartz.phonon')
>>> phonons.frequencies[5]
<Quantity([ 7.597 14.964 15.853 17. 21.604 27.9
33.892 36.467 37.509 41.034 46.834 50.083
52.757 53.321 58.286 62.749 80.168 88.254
98.021 100.962 101.436 132.376 134.143 134.503
142.526 145.486 149.365], 'millielectron_volt')>
>>> phonons.frequencies_unit = '1/cm'
>>> phonons.frequencies[5]
<Quantity([ 61.271 120.695 127.866 137.113 174.25
225.028 273.359 294.127 302.533 330.961
377.744 403.949 425.516 430.063 470.105
506.108 646.598 711.815 790.593 814.312
818.136 1067.682 1081.933 1084.837 1149.553
1173.42 1204.709], '1 / centimeter')>
The pattern is the same for any Quantity
attribute e.g.
ForceConstants.force_constants
has ForceConstants.force_constants_unit
,
Crystal.cell_vectors
has Crystal.cell_vectors_unit
Changing attribute values
Each dimensioned property also has a setter which allows it to be set. For
example, to set new Crystal.cell_vectors
:
>>> import numpy as np
>>> from euphonic import ForceConstants, ureg
>>> fc = ForceConstants.from_castep('quartz.castep_bin')
>>> fc.crystal.cell_vectors
<Quantity([[ 2.426 -4.202 0. ]
[ 2.426 4.202 0. ]
[ 0. 0. 5.35 ]], 'angstrom')>
>>> fc.crystal.cell_vectors = np.ones((3, 3))*ureg('angstrom')
>>> fc.crystal.cell_vectors
<Quantity([[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]], 'angstrom')>
However as dimensioned attributes are properties, individual elements can’t be
set by indexing, for example the following to set a single element of
Crystal.atom_mass
does not work:
>>> import numpy as np
>>> from euphonic import ForceConstants, ureg
>>> fc = ForceConstants.from_castep('quartz.castep_bin')
>>> fc.crystal.atom_mass
<Quantity([15.999 15.999 15.999 15.999 15.999 15.999 28.085
28.085 28.085], 'unified_atomic_mass_unit')>
>>> fc.crystal.atom_mass[0] = 17.999*ureg('amu')
>>> fc.crystal.atom_mass
<Quantity([15.999 15.999 15.999 15.999 15.999 15.999 28.085
28.085 28.085], 'unified_atomic_mass_unit')>
Nothing has changed! Instead, get the entire array, change any desired entries and then set the whole attribute as follows:
>>> from euphonic import ForceConstants, ureg
>>> fc = ForceConstants.from_castep('quartz.castep_bin')
>>> atom_mass = fc.crystal.atom_mass
>>> atom_mass[0] = 17.999*ureg('amu')
>>> fc.crystal.atom_mass = atom_mass
>>> fc.crystal.atom_mass
<Quantity([17.999 15.999 15.999 15.999 15.999 15.999 28.085
28.085 28.085], 'unified_atomic_mass_unit')>