Coverage for /builds/ase/ase/ase/units.py: 100.00%
48 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +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:
150 codata_version: str
151 The CODATA version to be used. Implemented are
153 * '1986'
154 * '1998'
155 * '2002'
156 * '2006'
157 * '2010'
158 * '2014'
159 * '2018'
160 * '2022'
162 Returns:
164 units: dict
165 Dictionary that contains all formerly hard coded variables from
166 ase.units as key-value pairs. The dict supports attribute access.
168 Raises:
170 NotImplementedError
171 If the required CODATA version is not known.
172 """
174 try:
175 u = Units(CODATA[codata_version])
176 except KeyError:
177 raise NotImplementedError('CODATA version "{}" not implemented'
178 .format(codata_version))
180 # derived from the CODATA values
181 u['_eps0'] = (1 / u['_mu0'] / u['_c']**2) # permittivity of vacuum
182 u['_hbar'] = u['_hplanck'] / (2 * pi) # Planck constant / 2pi, J s
184 u['Ang'] = u['Angstrom'] = 1.0
185 u['nm'] = 10.0
186 u['Bohr'] = (4e10 * pi * u['_eps0'] * u['_hbar']**2 /
187 u['_me'] / u['_e']**2) # Bohr radius
189 u['eV'] = 1.0
190 u['Hartree'] = (u['_me'] * u['_e']**3 / 16 / pi**2 /
191 u['_eps0']**2 / u['_hbar']**2)
192 u['kJ'] = 1000.0 / u['_e']
193 u['kcal'] = 4.184 * u['kJ']
194 u['mol'] = u['_Nav']
195 u['Rydberg'] = 0.5 * u['Hartree']
196 u['Ry'] = u['Rydberg']
197 u['Ha'] = u['Hartree']
199 u['second'] = 1e10 * sqrt(u['_e'] / u['_amu'])
200 u['fs'] = 1e-15 * u['second']
202 u['kB'] = u['_k'] / u['_e'] # Boltzmann constant, eV/K
204 u['Pascal'] = (1 / u['_e']) / 1e30 # J/m^3
205 u['GPa'] = 1e9 * u['Pascal']
206 u['bar'] = 1e5 * u['Pascal']
208 u['Debye'] = 1.0 / 1e11 / u['_e'] / u['_c']
209 u['alpha'] = (u['_e']**2 / (4 * pi * u['_eps0']) /
210 u['_hbar'] / u['_c']) # fine structure constant
211 u['invcm'] = (100 * u['_c'] * u['_hplanck'] /
212 u['_e']) # cm^-1 energy unit
214 # Derived atomic units that have no assigned name:
215 # atomic unit of time, s:
216 u['_aut'] = u['_hbar'] / (u['alpha']**2 * u['_me'] * u['_c']**2)
217 # atomic unit of velocity, m/s:
218 u['_auv'] = u['_e']**2 / u['_hbar'] / (4 * pi * u['_eps0'])
219 # atomic unit of force, N:
220 u['_auf'] = u['alpha']**3 * u['_me']**2 * u['_c']**3 / u['_hbar']
221 # atomic unit of pressure, Pa:
222 u['_aup'] = u['alpha']**5 * u['_me']**4 * u['_c']**5 / u['_hbar']**3
224 u['AUT'] = u['second'] * u['_aut']
226 # SI units
227 u['m'] = 1e10 * u['Ang'] # metre
228 u['kg'] = 1. / u['_amu'] # kilogram
229 u['s'] = u['second'] # second
230 u['A'] = 1.0 / u['_e'] / u['s'] # ampere
231 # derived
232 u['J'] = u['kJ'] / 1000 # Joule = kg * m**2 / s**2
233 u['C'] = 1.0 / u['_e'] # Coulomb = A * s
235 return u
238# Define all the expected symbols with dummy values so that introspection
239# will know that they exist when the module is imported, even though their
240# values are immediately overwritten.
241# pylint: disable=invalid-name
242(_Grav, _Nav, _amu, _auf, _aup, _aut, _auv, _c, _e, _eps0,
243 _hbar, _hplanck, _k, _me, _mp, _mu0, alpha, eV, fs, invcm,
244 kB, kJ, kcal, kg, m, mol, nm, s, second, A, AUT, Ang, Angstrom,
245 Bohr, C, Debye, GPa, Ha, Hartree, J, Pascal, bar, Ry, Rydberg) = [0.0] * 44
247# Now update the module scope:
248globals().update(create_units(__codata_version__))