Unit EquivalenciesΒΆ


Some physical quantities are directly related to other unitful quantities by a constant, but otherwise do not have the same units. To facilitate conversions between these quantities, yt implements a system of unit equivalencies (inspired by the AstroPy implementation). The possible unit equivalencies are:

  • "thermal": conversions between temperature and energy ($E = k_BT$)
  • "spectral": conversions between wavelength, frequency, and energy for photons ($E = h\nu = hc/\lambda, c = \lambda\nu$)
  • "mass_energy": conversions between mass and energy ($E = mc^2$)
  • "lorentz": conversions between velocity and Lorentz factor ($\gamma = 1/\sqrt{1-(v/c)^2}$)
  • "schwarzschild": conversions between mass and Schwarzschild radius ($R_S = 2GM/c^2$)
  • "compton": conversions between mass and Compton wavelength ($\lambda = h/mc$)

The following unit equivalencies only apply under conditions applicable for an ideal gas with a constant mean molecular weight $\mu$ and ratio of specific heats $\gamma$:

  • "number_density": conversions between density and number density ($n = \rho/\mu{m_p}$)
  • "sound_speed": conversions between temperature and sound speed for an ideal gas ($c_s^2 = \gamma{k_BT}/\mu{m_p}$)

A YTArray or YTQuantity can be converted to an equivalent using in_units (previously described in Fields and Unit Conversion), where the unit and the equivalence name are provided as additional arguments:

In [1]:
import yt
from yt import YTQuantity
import numpy as np

ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')

dd = ds.all_data()

print (dd["temperature"].in_units("erg", equivalence="thermal"))
print (dd["temperature"].in_units("eV", equivalence="thermal"))

# Rest energy of the proton
from yt.units import mp
E_p = mp.in_units("GeV", equivalence="mass_energy")
print (E_p)
/usr/lib64/python3.6/site-packages/h5py/__init__.py:34: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
[1.28901457e-12 1.29145390e-12 1.29077059e-12 ... 1.63255074e-12
 1.59991889e-12 1.40453699e-12] erg
[0.80453965 0.80606216 0.80563567 ... 1.01895807 0.99859087 0.87664308] eV
0.9388966459173169 GeV

Most equivalencies can go in both directions, without any information required other than the unit you want to convert to (this is not the case for the electromagnetic equivalencies, which we'll discuss later):

In [2]:
from yt.units import clight
v = 0.1*clight
g = v.in_units("dimensionless", equivalence="lorentz")
print (g)
print (g.in_units("c", equivalence="lorentz"))
1.005037815259212 dimensionless
0.10000000000000003 c

The previously described to_value method, which works like in_units except that it returns a bare NumPy array or floating-point number, also accepts equivalencies:

In [3]:
print (dd["temperature"].to_value("erg", equivalence="thermal"))
print (mp.to_value("GeV", equivalence="mass_energy"))
[1.28901457e-12 1.29145390e-12 1.29077059e-12 ... 1.63255074e-12
 1.59991889e-12 1.40453699e-12]

Special Equivalencies

Some equivalencies can take supplemental information. The "number_density" equivalence can take a custom mean molecular weight (default is $\mu = 0.6$):

In [4]:
print (dd["density"].max())
print (dd["density"].in_units("cm**-3", equivalence="number_density").max())
print (dd["density"].in_units("cm**-3", equivalence="number_density", mu=0.75).max())
7.73426503924e-24 g/cm**3
7.701601513028228 cm**(-3)
6.161281210422581 cm**(-3)

The "sound_speed" equivalence optionally takes the ratio of specific heats $\gamma$ and the mean molecular weight $\mu$ (defaults are $\gamma$ = 5/3, $\mu = 0.6$):

In [5]:
print (dd["temperature"].in_units("km/s", equivalence="sound_speed").mean())
print (dd["temperature"].in_units("km/s", equivalence="sound_speed", gamma=4./3., mu=0.5).mean())
16.073631400834987 km/s
15.74887809824916 km/s

These options must be used with caution, and only if you know the underlying data adheres to these assumptions!

Electromagnetic Equivalencies

Special, one-way equivalencies exist for converting between electromagnetic units in the cgs and SI unit systems. These exist since in the cgs system, electromagnetic units are comprised of the base units of seconds, grams and centimeters, whereas in the SI system Ampere is a base unit. For example, the dimensions of charge are completely different in the two systems:

In [6]:
Q1 = YTQuantity(1.0,"C")
Q2 = YTQuantity(1.0,"esu")
print ("Q1 dims =", Q1.units.dimensions)
print ("Q2 dims =", Q2.units.dimensions)
print ("Q1 base units =", Q1.in_mks())
print ("Q2 base units =", Q2.in_cgs())
Q1 dims = (current_mks)*(time)
Q2 dims = (length)**(3/2)*sqrt((mass))/(time)
Q1 base units = 1.0 A*s
Q2 base units = 1.0 cm**(3/2)*sqrt(g)/s

To convert from a cgs unit to an SI unit, use the "SI" equivalency:

In [7]:
from yt.units import qp # the elementary charge in esu
qp_SI = qp.in_units("C", equivalence="SI") # convert to Coulombs
print (qp)
print (qp_SI)
4.8032056e-10 esu
1.6021769300146971e-19 C

To convert from an SI unit to a cgs unit, use the "CGS" equivalency:

In [8]:
B = YTQuantity(1.0,"T") # magnetic field in Tesla
print (B, B.in_units("gauss", equivalence="CGS")) # convert to Gauss
1.0 T 10000.0 gauss

Equivalencies exist between the SI and cgs dimensions of charge, current, magnetic field, electric potential, and resistance. As a neat example, we can convert current in Amperes and resistance in Ohms to their cgs equivalents, and then use them to calculate the "Joule heating" of a conductor with resistance $R$ and current $I$:

In [9]:
I = YTQuantity(1.0,"A")
I_cgs = I.in_units("statA", equivalence="CGS")
R = YTQuantity(1.0,"ohm")
R_cgs = R.in_units("statohm", equivalence="CGS")
P = I**2*R
P_cgs = I_cgs**2*R_cgs

The dimensions of current and resistance in the two systems are completely different, but the formula gives us the power dissipated dimensions of energy per time, so the dimensions and the result should be the same, which we can check:

In [10]:
print (P_cgs.units.dimensions == P.units.dimensions)
print (P.in_units("W"), P_cgs.in_units("W"))
1.0 W 1.0 W

Determining Valid Equivalencies

If a certain equivalence does not exist for a particular unit, then an error will be thrown:

In [11]:
from yt.utilities.exceptions import YTInvalidUnitEquivalence

    x = v.in_units("angstrom", equivalence="spectral")
except YTInvalidUnitEquivalence as e:
    print (e)
The unit equivalence 'spectral' does not exist for the units 'cm/s' and 'angstrom'.

You can check if a YTArray has a given equivalence with has_equivalent:

In [12]:
print (mp.has_equivalent("compton"))
print (mp.has_equivalent("thermal"))

To list the equivalencies available for a given YTArray or YTQuantity, use the list_equivalencies method:

In [13]:
thermal: temperature <-> energy
mass_energy: mass <-> energy
spectral: length <-> rate <-> energy
sound_speed (ideal gas): velocity <-> temperature <-> energy

(6)_Unit_Equivalencies.ipynb; 6)_Unit_Equivalencies_evaluated.ipynb; 6)_Unit_Equivalencies.py)