Coverage for ase / units.py: 100.00%
48 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-30 08:22 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-30 08:22 +0000
1# fmt: off
3"""ase.units
5Physical constants and units derived from CODATA for converting
6to and from ase internal units.
9"""
12from math import pi, sqrt
14# the version we actually use
15__codata_version__ = '2014'
18# Instead of a plain dict, if the units are in the __dict__ of a
19# dict subclass, they can be accessed as attributes in a similar way
20# to a module.
21class Units(dict):
22 """Dictionary for units that supports .attribute access."""
24 def __init__(self, *args, **kwargs):
25 super().__init__(*args, **kwargs)
26 self.__dict__ = self
29# this is the hard-coded CODATA values
30# all other units are dynamically derived from these values upon import of the
31# module
32CODATA = {
33 # the "original" CODATA version ase used ever since
34 # Constants from Konrad Hinsen's PhysicalQuantities module (1986 CODATA)
35 # Add the constant pi used to define the mu0 and hbar here for reference
36 # as well
37 '1986': {'_c': 299792458., # speed of light, m/s
38 '_mu0': 4.e-7 * pi, # permeability of vacuum
39 '_Grav': 6.67259e-11, # gravitational constant
40 '_hplanck': 6.6260755e-34, # Planck constant, J s
41 '_e': 1.60217733e-19, # elementary charge
42 '_me': 9.1093897e-31, # electron mass
43 '_mp': 1.6726231e-27, # proton mass
44 '_Nav': 6.0221367e23, # Avogadro number
45 '_k': 1.380658e-23, # Boltzmann constant, J/K
46 '_amu': 1.6605402e-27}, # atomic mass unit, kg
48 # CODATA 1998 taken from
49 # https://doi.org/10.1103/RevModPhys.72.351
50 '1998': {'_c': 299792458.,
51 '_mu0': 4.0e-7 * pi,
52 '_Grav': 6.673e-11,
53 '_hplanck': 6.62606876e-34,
54 '_e': 1.602176462e-19,
55 '_me': 9.10938188e-31,
56 '_mp': 1.67262158e-27,
57 '_Nav': 6.02214199e23,
58 '_k': 1.3806503e-23,
59 '_amu': 1.66053873e-27},
61 # CODATA 2002 taken from
62 # https://doi.org/10.1103/RevModPhys.77.1
63 '2002': {'_c': 299792458.,
64 '_mu0': 4.0e-7 * pi,
65 '_Grav': 6.6742e-11,
66 '_hplanck': 6.6260693e-34,
67 '_e': 1.60217653e-19,
68 '_me': 9.1093826e-31,
69 '_mp': 1.67262171e-27,
70 '_Nav': 6.0221415e23,
71 '_k': 1.3806505e-23,
72 '_amu': 1.66053886e-27},
74 # CODATA 2006 taken from
75 # https://doi.org/10.1103/RevModPhys.80.633
76 '2006': {'_c': 299792458.,
77 '_mu0': 4.0e-7 * pi,
78 '_Grav': 6.67428e-11,
79 '_hplanck': 6.62606896e-34,
80 '_e': 1.602176487e-19,
81 '_me': 9.10938215e-31,
82 '_mp': 1.672621637e-27,
83 '_Nav': 6.02214179e23,
84 '_k': 1.3806504e-23,
85 '_amu': 1.660538782e-27},
87 # CODATA 2010 taken from
88 # https://doi.org/10.1103/RevModPhys.84.1527
89 '2010': {'_c': 299792458.,
90 '_mu0': 4.0e-7 * pi,
91 '_Grav': 6.67384e-11,
92 '_hplanck': 6.62606957e-34,
93 '_e': 1.602176565e-19,
94 '_me': 9.10938291e-31,
95 '_mp': 1.672621777e-27,
96 '_Nav': 6.02214129e23,
97 '_k': 1.3806488e-23,
98 '_amu': 1.660538921e-27},
100 # CODATA 2014 taken from
101 # http://arxiv.org/pdf/1507.07956.pdf
102 '2014': {'_c': 299_792_458., # Exact
103 '_mu0': 4.0e-7 * pi, # Exact
104 '_Grav': 6.674_08e-11, # +/- 0.000_31e-11
105 '_hplanck': 6.626_070_040e-34, # +/- 0.000_000_081e-34
106 '_e': 1.602_176_6208e-19, # +/- 0.000_000_0098e-19
107 '_me': 9.109_383_56e-31, # +/- 0.000_000_11e-31
108 '_mp': 1.672_621_898e-27, # +/- 0.000_000_021e-27
109 '_Nav': 6.022_140_857e23, # +/- 0.000_000_074e23
110 '_k': 1.380_648_52e-23, # +/- 0.000_000_79e-23
111 '_amu': 1.660_539_040e-27}, # +/- 0.000_000_020e-27
113 # CODATA 2018 taken from
114 # https://physics.nist.gov/cuu/pdf/all_2018.pdf
115 '2018': {'_c': 299_792_458., # Exact
116 '_mu0': 1.256_637_062_12e-6, # +/- 0.000_000_000_19e−6
117 '_Grav': 6.674_30e-11, # +/- 0.000_15e-11
118 '_hplanck': 6.626_070_15e-34, # Exact
119 '_e': 1.602_176_634e-19, # Exact
120 '_me': 9.109_383_7015e-31, # +/- 0.000_000_0028e-31
121 '_mp': 1.672_621_923_69e-27, # +/- 0.000_000_000_51e-27
122 '_Nav': 6.022_140_76e23, # Exact
123 '_k': 1.380_649e-23, # Exact
124 '_amu': 1.660_539_066_60e-27}, # +/- 0.000_000_000_50e-27
126 # CODATA 2022 (current) taken from
127 # https://physics.nist.gov/cuu/Constants/index.html
128 '2022': {'_c': 299_792_458., # Exact
129 '_mu0': 1.256_637_061_27e-6, # +/- 0.000_000_000_20e−6
130 '_Grav': 6.674_30e-11, # +/- 0.000_15e-11
131 '_hplanck': 6.626_070_15e-34, # Exact
132 '_e': 1.602_176_634e-19, # Exact
133 '_me': 9.109_383_7139e-31, # +/- 0.000_000_0028e−31
134 '_mp': 1.672_621_925_95e-27, # +/- 0.000_000_000_52e−27
135 '_Nav': 6.022_140_76e23, # Exact
136 '_k': 1.380_649e-23, # Exact
137 '_amu': 1.660_539_068_92e-27}, # +/- 0.000_000_000_52e−27
138}
141def create_units(codata_version):
142 """
143 Function that creates a dictionary containing all units previously hard
144 coded in ase.units depending on a certain CODATA version. Note that
145 returned dict has attribute access it can be used in place of the module
146 or to update your local or global namespace.
148 Parameters
149 ----------
151 codata_version: str
152 The CODATA version to be used. Implemented are
154 * '1986'
155 * '1998'
156 * '2002'
157 * '2006'
158 * '2010'
159 * '2014'
160 * '2018'
161 * '2022'
163 Returns
164 -------
166 units: dict
167 Dictionary that contains all formerly hard coded variables from
168 ase.units as key-value pairs. The dict supports attribute access.
170 Raises
171 ------
173 NotImplementedError
174 If the required CODATA version is not known.
175 """
177 try:
178 u = Units(CODATA[codata_version])
179 except KeyError:
180 raise NotImplementedError('CODATA version "{}" not implemented'
181 .format(codata_version))
183 # derived from the CODATA values
184 u['_eps0'] = (1 / u['_mu0'] / u['_c']**2) # permittivity of vacuum
185 u['_hbar'] = u['_hplanck'] / (2 * pi) # Planck constant / 2pi, J s
187 u['Ang'] = u['Angstrom'] = 1.0
188 u['nm'] = 10.0
189 u['Bohr'] = (4e10 * pi * u['_eps0'] * u['_hbar']**2 /
190 u['_me'] / u['_e']**2) # Bohr radius
192 u['eV'] = 1.0
193 u['Hartree'] = (u['_me'] * u['_e']**3 / 16 / pi**2 /
194 u['_eps0']**2 / u['_hbar']**2)
195 u['kJ'] = 1000.0 / u['_e']
196 u['kcal'] = 4.184 * u['kJ']
197 u['mol'] = u['_Nav']
198 u['Rydberg'] = 0.5 * u['Hartree']
199 u['Ry'] = u['Rydberg']
200 u['Ha'] = u['Hartree']
202 u['second'] = 1e10 * sqrt(u['_e'] / u['_amu'])
203 u['fs'] = 1e-15 * u['second']
205 u['kB'] = u['_k'] / u['_e'] # Boltzmann constant, eV/K
207 u['Pascal'] = (1 / u['_e']) / 1e30 # J/m^3
208 u['GPa'] = 1e9 * u['Pascal']
209 u['bar'] = 1e5 * u['Pascal']
211 u['Debye'] = 1.0 / 1e11 / u['_e'] / u['_c']
212 u['alpha'] = (u['_e']**2 / (4 * pi * u['_eps0']) /
213 u['_hbar'] / u['_c']) # fine structure constant
214 u['invcm'] = (100 * u['_c'] * u['_hplanck'] /
215 u['_e']) # cm^-1 energy unit
217 # Derived atomic units that have no assigned name:
218 # atomic unit of time, s:
219 u['_aut'] = u['_hbar'] / (u['alpha']**2 * u['_me'] * u['_c']**2)
220 # atomic unit of velocity, m/s:
221 u['_auv'] = u['_e']**2 / u['_hbar'] / (4 * pi * u['_eps0'])
222 # atomic unit of force, N:
223 u['_auf'] = u['alpha']**3 * u['_me']**2 * u['_c']**3 / u['_hbar']
224 # atomic unit of pressure, Pa:
225 u['_aup'] = u['alpha']**5 * u['_me']**4 * u['_c']**5 / u['_hbar']**3
227 u['AUT'] = u['second'] * u['_aut']
229 # SI units
230 u['m'] = 1e10 * u['Ang'] # metre
231 u['kg'] = 1. / u['_amu'] # kilogram
232 u['s'] = u['second'] # second
233 u['A'] = 1.0 / u['_e'] / u['s'] # ampere
234 # derived
235 u['J'] = u['kJ'] / 1000 # Joule = kg * m**2 / s**2
236 u['C'] = 1.0 / u['_e'] # Coulomb = A * s
238 return u
241# Define all the expected symbols with dummy values so that introspection
242# will know that they exist when the module is imported, even though their
243# values are immediately overwritten.
244# pylint: disable=invalid-name
245(_Grav, _Nav, _amu, _auf, _aup, _aut, _auv, _c, _e, _eps0,
246 _hbar, _hplanck, _k, _me, _mp, _mu0, alpha, eV, fs, invcm,
247 kB, kJ, kcal, kg, m, mol, nm, s, second, A, AUT, Ang, Angstrom,
248 Bohr, C, Debye, GPa, Ha, Hartree, J, Pascal, bar, Ry, Rydberg) = [0.0] * 44
250# Now update the module scope:
251globals().update(create_units(__codata_version__))