A series of Python3 script to lower the barrier of computing and simulating molecular and material systems.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

231 lines
7.8 KiB

"""ase.units
Physical constants and units derived from CODATA for converting
to and from ase internal units.
"""
from math import pi, sqrt
# the version we actually use
__codata_version__ = '2014'
# Instead of a plain dict, if the units are in the __dict__ of a
# dict subclass, they can be accessed as attributes in a similar way
# to a module.
class Units(dict):
"""Dictionary for units that supports .attribute access."""
def __init__(self, *args, **kwargs):
super(Units, self).__init__(*args, **kwargs)
self.__dict__ = self
# this is the hard-coded CODATA values
# all other units are dynamically derived from these values upon import of the
# module
CODATA = {
# the "original" CODATA version ase used ever since
# Constants from Konrad Hinsen's PhysicalQuantities module (1986 CODATA)
# Add the constant pi used to define the mu0 and hbar here for reference
# as well
'1986': {'_c': 299792458., # speed of light, m/s
'_mu0': 4.e-7 * pi, # permeability of vacuum
'_Grav': 6.67259e-11, # gravitational constant
'_hplanck': 6.6260755e-34, # Planck constant, J s
'_e': 1.60217733e-19, # elementary charge
'_me': 9.1093897e-31, # electron mass
'_mp': 1.6726231e-27, # proton mass
'_Nav': 6.0221367e23, # Avogadro number
'_k': 1.380658e-23, # Boltzmann constant, J/K
'_amu': 1.6605402e-27}, # atomic mass unit, kg
# CODATA 1998 taken from
# https://doi.org/10.1103/RevModPhys.72.351
'1998': {'_c': 299792458.,
'_mu0': 4.0e-7 * pi,
'_Grav': 6.673e-11,
'_hplanck': 6.62606876e-34,
'_e': 1.602176462e-19,
'_me': 9.10938188e-31,
'_mp': 1.67262158e-27,
'_Nav': 6.02214199e23,
'_k': 1.3806503e-23,
'_amu': 1.66053873e-27},
# CODATA 2002 taken from
# https://doi.org/10.1103/RevModPhys.77.1
'2002': {'_c': 299792458.,
'_mu0': 4.0e-7 * pi,
'_Grav': 6.6742e-11,
'_hplanck': 6.6260693e-34,
'_e': 1.60217653e-19,
'_me': 9.1093826e-31,
'_mp': 1.67262171e-27,
'_Nav': 6.0221415e23,
'_k': 1.3806505e-23,
'_amu': 1.66053886e-27},
# CODATA 2006 taken from
# https://doi.org/10.1103/RevModPhys.80.633
'2006': {'_c': 299792458.,
'_mu0': 4.0e-7 * pi,
'_Grav': 6.67428e-11,
'_hplanck': 6.62606896e-34,
'_e': 1.602176487e-19,
'_me': 9.10938215e-31,
'_mp': 1.672621637e-27,
'_Nav': 6.02214179e23,
'_k': 1.3806504e-23,
'_amu': 1.660538782e-27},
# CODATA 2010 taken from
# https://doi.org/10.1103/RevModPhys.84.1527
'2010': {'_c': 299792458.,
'_mu0': 4.0e-7 * pi,
'_Grav': 6.67384e-11,
'_hplanck': 6.62606957e-34,
'_e': 1.602176565e-19,
'_me': 9.10938291e-31,
'_mp': 1.672621777e-27,
'_Nav': 6.02214129e23,
'_k': 1.3806488e-23,
'_amu': 1.660538921e-27},
# CODATA 2014 taken from
# http://arxiv.org/pdf/1507.07956.pdf
'2014': {'_c': 299792458.,
'_mu0': 4.0e-7 * pi,
'_Grav': 6.67408e-11,
'_hplanck': 6.626070040e-34,
'_e': 1.6021766208e-19,
'_me': 9.10938356e-31,
'_mp': 1.672621898e-27,
'_Nav': 6.022140857e23,
'_k': 1.38064852e-23,
'_amu': 1.660539040e-27},
# CODATA 2018 taken from
# https://physics.nist.gov/cuu/Constants/index.html
'2018': {'_c': 299792458., # Exact
'_mu0': 4.0e-7 * pi, # Exact
'_Grav': 6.67430e-11, # +/- 0.000_15e-11
'_hplanck': 6.62607015e-34, # Exact
'_e': 1.602176634e-19, # Exact
'_me': 9.1093837015e-31, # +/- 0.000_000_0028e-31
'_mp': 1.67262192369e-27, # +/- 0.000_000_000_51e-27
'_Nav': 6.02214076e23, # Exact
'_k': 1.380649e-23, # Exact
'_amu': 1.66053906660e-27}, # +/- 0.000_000_000_50e-27
}
def create_units(codata_version):
"""
Function that creates a dictionary containing all units previously hard
coded in ase.units depending on a certain CODATA version. Note that
returned dict has attribute access it can be used in place of the module
or to update your local or global namespace.
Parameters:
codata_version: str
The CODATA version to be used. Implemented are
* '1986'
* '1998'
* '2002'
* '2006'
* '2010'
* '2014'
Returns:
units: dict
Dictionary that contains all formerly hard coded variables from
ase.units as key-value pairs. The dict supports attribute access.
Raises:
NotImplementedError
If the required CODATA version is not known.
"""
try:
u = Units(CODATA[codata_version])
except KeyError:
raise NotImplementedError('CODATA version "{0}" not implemented'
.format(codata_version))
# derived from the CODATA values
u['_eps0'] = (1 / u['_mu0'] / u['_c']**2) # permittivity of vacuum
u['_hbar'] = u['_hplanck'] / (2 * pi) # Planck constant / 2pi, J s
u['Ang'] = u['Angstrom'] = 1.0
u['nm'] = 10.0
u['Bohr'] = (4e10 * pi * u['_eps0'] * u['_hbar']**2 /
u['_me'] / u['_e']**2) # Bohr radius
u['eV'] = 1.0
u['Hartree'] = (u['_me'] * u['_e']**3 / 16 / pi**2 /
u['_eps0']**2 / u['_hbar']**2)
u['kJ'] = 1000.0 / u['_e']
u['kcal'] = 4.184 * u['kJ']
u['mol'] = u['_Nav']
u['Rydberg'] = 0.5 * u['Hartree']
u['Ry'] = u['Rydberg']
u['Ha'] = u['Hartree']
u['second'] = 1e10 * sqrt(u['_e'] / u['_amu'])
u['fs'] = 1e-15 * u['second']
u['kB'] = u['_k'] / u['_e'] # Boltzmann constant, eV/K
u['Pascal'] = (1 / u['_e']) / 1e30 # J/m^3
u['GPa'] = 1e9 * u['Pascal']
u['bar'] = 1e5 * u['Pascal']
u['Debye'] = 1.0 / 1e11 / u['_e'] / u['_c']
u['alpha'] = (u['_e']**2 / (4 * pi * u['_eps0']) /
u['_hbar'] / u['_c']) # fine structure constant
u['invcm'] = (100 * u['_c'] * u['_hplanck'] /
u['_e']) # cm^-1 energy unit
# Derived atomic units that have no assigned name:
# atomic unit of time, s:
u['_aut'] = u['_hbar'] / (u['alpha']**2 * u['_me'] * u['_c']**2)
# atomic unit of velocity, m/s:
u['_auv'] = u['_e']**2 / u['_hbar'] / (4 * pi * u['_eps0'])
# atomic unit of force, N:
u['_auf'] = u['alpha']**3 * u['_me']**2 * u['_c']**3 / u['_hbar']
# atomic unit of pressure, Pa:
u['_aup'] = u['alpha']**5 * u['_me']**4 * u['_c']**5 / u['_hbar']**3
u['AUT'] = u['second'] * u['_aut']
# SI units
u['m'] = 1e10 * u['Ang'] # metre
u['kg'] = 1. / u['_amu'] # kilogram
u['s'] = u['second'] # second
u['A'] = 1.0 / u['_e'] / u['s'] # ampere
# derived
u['J'] = u['kJ'] / 1000 # Joule = kg * m**2 / s**2
u['C'] = 1.0 / u['_e'] # Coulomb = A * s
return u
# Define all the expected symbols with dummy values so that introspection
# will know that they exist when the module is imported, even though their
# values are immediately overwritten.
# pylint: disable=invalid-name
(_Grav, _Nav, _amu, _auf, _aup, _aut, _auv, _c, _e, _eps0,
_hbar, _hplanck, _k, _me, _mp, _mu0, alpha, eV, fs, invcm,
kB, kJ, kcal, kg, m, mol, nm, s, second, A, AUT, Ang, Angstrom,
Bohr, C, Debye, GPa, Ha, Hartree, J, Pascal, bar, Ry, Rydberg) = [0.0] * 44
# Now update the module scope:
globals().update(create_units(__codata_version__))