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

1# fmt: off 

2 

3"""ase.units 

4 

5Physical constants and units derived from CODATA for converting 

6to and from ase internal units. 

7 

8 

9""" 

10 

11 

12from math import pi, sqrt 

13 

14# the version we actually use 

15__codata_version__ = '2014' 

16 

17 

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.""" 

23 

24 def __init__(self, *args, **kwargs): 

25 super().__init__(*args, **kwargs) 

26 self.__dict__ = self 

27 

28 

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 

47 

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}, 

60 

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}, 

73 

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}, 

86 

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}, 

99 

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 

112 

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 

125 

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} 

139 

140 

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. 

147 

148 Parameters: 

149 

150 codata_version: str 

151 The CODATA version to be used. Implemented are 

152 

153 * '1986' 

154 * '1998' 

155 * '2002' 

156 * '2006' 

157 * '2010' 

158 * '2014' 

159 * '2018' 

160 * '2022' 

161 

162 Returns: 

163 

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. 

167 

168 Raises: 

169 

170 NotImplementedError 

171 If the required CODATA version is not known. 

172 """ 

173 

174 try: 

175 u = Units(CODATA[codata_version]) 

176 except KeyError: 

177 raise NotImplementedError('CODATA version "{}" not implemented' 

178 .format(codata_version)) 

179 

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 

183 

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 

188 

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'] 

198 

199 u['second'] = 1e10 * sqrt(u['_e'] / u['_amu']) 

200 u['fs'] = 1e-15 * u['second'] 

201 

202 u['kB'] = u['_k'] / u['_e'] # Boltzmann constant, eV/K 

203 

204 u['Pascal'] = (1 / u['_e']) / 1e30 # J/m^3 

205 u['GPa'] = 1e9 * u['Pascal'] 

206 u['bar'] = 1e5 * u['Pascal'] 

207 

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 

213 

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 

223 

224 u['AUT'] = u['second'] * u['_aut'] 

225 

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 

234 

235 return u 

236 

237 

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 

246 

247# Now update the module scope: 

248globals().update(create_units(__codata_version__))