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

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 

151 codata_version: str 

152 The CODATA version to be used. Implemented are 

153 

154 * '1986' 

155 * '1998' 

156 * '2002' 

157 * '2006' 

158 * '2010' 

159 * '2014' 

160 * '2018' 

161 * '2022' 

162 

163 Returns 

164 ------- 

165 

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. 

169 

170 Raises 

171 ------ 

172 

173 NotImplementedError 

174 If the required CODATA version is not known. 

175 """ 

176 

177 try: 

178 u = Units(CODATA[codata_version]) 

179 except KeyError: 

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

181 .format(codata_version)) 

182 

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 

186 

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 

191 

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

201 

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

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

204 

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

206 

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

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

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

210 

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 

216 

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 

226 

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

228 

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 

237 

238 return u 

239 

240 

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 

249 

250# Now update the module scope: 

251globals().update(create_units(__codata_version__))