Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F91926345
units.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Fri, Nov 15, 19:19
Size
10 KB
Mime Type
text/x-python
Expires
Sun, Nov 17, 19:19 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
22348623
Attached To
rLAMMPS lammps
units.py
View Options
"""Contains fundamental constants in atomic units.
Copyright (C) 2013, Joshua More and Michele Ceriotti
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http.//www.gnu.org/licenses/>.
Classes:
Constants: Class whose members are fundamental constants.
Elements: Class which contains the mass of different elements
Units: Class which contains the methods needed to transform
between different systems of units.
"""
import
re
from
ipi.utils.messages
import
verbosity
,
info
__all__
=
[
'Constants'
,
'Elements'
,
'unit_to_internal'
,
'unit_to_user'
]
class
Constants
:
"""Class whose members are fundamental constants.
Attributes:
kb: Boltzmann constant.
hbar: Reduced Planck's constant.
amu: Atomic mass unit.
"""
kb
=
1.0
hbar
=
1.0
amu
=
1822.8885
class
Elements
(
dict
):
"""Class which contains the mass of different elements.
Attributes:
mass_list: A dictionary containing the masses of different elements.
Has the form {"label": Mass in a.m.u.}. Note that the generic "X"
label is assumed to be an electron.
"""
mass_list
=
{
"X"
:
1.0000
/
Constants
.
amu
,
"H"
:
1.00794
,
"D"
:
2.0141
,
"Z"
:
1.382943
,
#an interpolated H-D atom, based on y=1/sqrt(m) scaling
"H2"
:
2.0160
,
"He"
:
4.002602
,
"Li"
:
6.9410
,
"Be"
:
9.012182
,
"B"
:
10.811
,
"C"
:
12.0107
,
"N"
:
14.00674
,
"O"
:
15.9994
,
"F"
:
18.998403
,
"Ne"
:
20.1797
,
"Na"
:
22.989770
,
"Mg"
:
24.3050
,
"Al"
:
26.981538
,
"Si"
:
28.0855
,
"P"
:
30.973761
,
"S"
:
32.066
,
"Cl"
:
35.4527
,
"Ar"
:
39.9480
,
"K"
:
39.0983
,
"Ca"
:
40.078
,
"Sc"
:
44.955910
,
"Ti"
:
47.867
,
"V"
:
50.9415
,
"Cr"
:
51.9961
,
"Mn"
:
54.938049
,
"Fe"
:
55.845
,
"Co"
:
58.933200
,
"Ni"
:
58.6934
,
"Cu"
:
63.546
,
"Zn"
:
65.39
,
"Ga"
:
69.723
,
"Ge"
:
72.61
,
"As"
:
74.92160
,
"Se"
:
78.96
,
"Br"
:
79.904
,
"Kr"
:
83.80
,
"Rb"
:
85.4678
,
"Sr"
:
87.62
,
"Y"
:
88.90585
,
"Zr"
:
91.224
,
"Nb"
:
92.90638
,
"Mo"
:
95.94
,
"Tc"
:
98
,
"Ru"
:
101.07
,
"Rh"
:
102.90550
,
"Pd"
:
106.42
,
"Ag"
:
107.8682
,
"Cd"
:
112.411
,
"In"
:
114.818
,
"Sn"
:
118.710
,
"Sb"
:
121.760
,
"Te"
:
127.60
,
"I"
:
126.90447
,
"Xe"
:
131.29
,
"Cs"
:
132.90545
,
"Ba"
:
137.327
,
"La"
:
138.9055
,
"Ce"
:
140.166
,
"Pr"
:
140.90765
,
"Nd"
:
144.24
,
"Pm"
:
145
,
"Sm"
:
150.36
,
"Eu"
:
151.964
,
"Gd"
:
157.25
,
"Tb"
:
158.92534
,
"Dy"
:
162.50
,
"Ho"
:
164.93032
,
"Er"
:
167.26
,
"Tm"
:
168.93241
,
"Yb"
:
173.04
,
"Lu"
:
174.967
,
"Hf"
:
178.49
,
"Ta"
:
180.9479
,
"W"
:
183.84
,
"Re"
:
186.207
,
"Os"
:
190.23
,
"Ir"
:
192.217
,
"Pt"
:
195.078
,
"Au"
:
196.96655
,
"Hg"
:
200.59
,
"Tl"
:
204.3833
,
"Pb"
:
207.2
,
"Bi"
:
208.98038
,
"Po"
:
209
,
"At"
:
210
,
"Rn"
:
222
,
"Fr"
:
223
,
"Ra"
:
226
,
"Ac"
:
227
,
"Th"
:
232.0381
,
"Pa"
:
231.03588
,
"U"
:
238.0289
,
"Np"
:
237
,
"Pu"
:
244
,
"Am"
:
243
,
"Cm"
:
247
,
"Bk"
:
247
,
"Cf"
:
251
,
"Es"
:
252
,
"Fm"
:
257
,
"Md"
:
258
,
"No"
:
259
,
"Lr"
:
262
,
"Rf"
:
267
,
"Db"
:
268
,
"Sg"
:
269
,
"Bh"
:
270
,
"Hs"
:
269
,
"Mt"
:
278
,
"Ds"
:
281
,
"Rg"
:
280
,
"Cn"
:
285
,
"Uut"
:
286
,
"Fl"
:
289
,
"Uup"
:
288
,
"Lv"
:
293
,
"Uus"
:
294
,
"Uuo"
:
294
}
@classmethod
def
mass
(
cls
,
label
):
"""Function to access the mass_list attribute.
Note that this does not require an instance of the Elements class to be
created, as this is a class method. Therefore using Elements.mass(label)
will give the mass of the element with the atomic symbol given by label.
Args:
label: The atomic symbol of the atom whose mass is required.
Returns:
A float giving the mass of the atom with atomic symbol label.
"""
try
:
return
cls
.
mass_list
[
label
]
*
Constants
.
amu
except
KeyError
:
info
(
"Unknown element given, you must specify the mass"
,
verbosity
.
low
)
return
-
1.0
# these are the conversion FROM the unit stated to internal (atomic) units
UnitMap
=
{
"undefined"
:
{
""
:
1.00
},
"energy"
:
{
""
:
1.00
,
"atomic_unit"
:
1.00
,
"electronvolt"
:
0.036749326
,
"j/mol"
:
0.00000038087989
,
"cal/mol"
:
0.0000015946679
,
"kelvin"
:
3.1668152e-06
},
"temperature"
:
{
""
:
1.00
,
"atomic_unit"
:
1.00
,
"kelvin"
:
3.1668152e-06
},
"time"
:
{
""
:
1.00
,
"atomic_unit"
:
1.00
,
"second"
:
4.1341373e+16
},
"frequency"
:
{
# NB Internally, ANGULAR frequencies are used.
""
:
1.00
,
"atomic_unit"
:
1.00
,
"inversecm"
:
4.5563353e-06
,
"hertz*rad"
:
2.4188843e-17
,
"hertz"
:
1.5198298e-16
},
"ms-momentum"
:
{
# TODO fill up units here (mass-scaled momentum)
""
:
1.00
,
"atomic_unit"
:
1.00
},
"length"
:
{
""
:
1.00
,
"atomic_unit"
:
1.00
,
"angstrom"
:
1.8897261
,
"meter"
:
1.8897261e+10
},
"volume"
:
{
""
:
1.00
,
"atomic_unit"
:
1.00
,
"angstrom3"
:
6.748334231
,
},
"velocity"
:
{
""
:
1.00
,
"atomic_unit"
:
1.00
,
"m/s"
:
4.5710289e-7
},
"momentum"
:
{
""
:
1.00
,
"atomic_unit"
:
1.00
},
"mass"
:
{
""
:
1.00
,
"atomic_unit"
:
1.00
,
"dalton"
:
1.00
*
Constants
.
amu
,
"electronmass"
:
1.00
},
"pressure"
:
{
""
:
1.00
,
"atomic_unit"
:
1.00
,
"bar"
:
3.398827377e-9
,
"atmosphere"
:
3.44386184e-9
,
"pascal"
:
3.398827377e-14
},
"density"
:
{
""
:
1.00
,
"atomic_unit"
:
1.00
,
"g/cm3"
:
162.67263
},
"force"
:
{
""
:
1.00
,
"atomic_unit"
:
1.00
,
"newton"
:
12137805
}
}
# a list of magnitude prefixes
UnitPrefix
=
{
""
:
1.0
,
"yotta"
:
1e24
,
"zetta"
:
1e21
,
"exa"
:
1e18
,
"peta"
:
1e15
,
"tera"
:
1e12
,
"giga"
:
1e9
,
"mega"
:
1e6
,
"kilo"
:
1e3
,
"milli"
:
1e-3
,
"micro"
:
1e-6
,
"nano"
:
1e-9
,
"pico"
:
1e-12
,
"femto"
:
1e-15
,
"atto"
:
1e-18
,
"zepto"
:
1e-21
,
"yocto"
:
1e-24
}
# builds a RE to match prefix and split out the base unit
UnitPrefixRE
=
""
for
key
in
UnitPrefix
:
UnitPrefixRE
=
UnitPrefixRE
+
key
+
"|"
UnitPrefixRE
=
" *("
+
UnitPrefixRE
[
1
:]
+
")(.*) *"
UnitPrefixRE
=
re
.
compile
(
UnitPrefixRE
)
########################################################################
# Atomic units are used EVERYWHERE internally. In order to quickly #
# interface with any "outside" unit, we set up a simple conversion #
# library. #
########################################################################
def
unit_to_internal
(
family
,
unit
,
number
):
"""Converts a number of given dimensions and units into internal units.
Args:
family: The dimensionality of the number.
unit: The units 'number' is originally in.
number: The value of the parameter in the units 'unit'.
Returns:
The number in internal units.
Raises:
ValueError: Raised if the user specified units aren't given in the
UnitMap dictionary.
IndexError: Raised if the programmer specified dimensionality for the
parameter isn't in UnitMap. Shouldn't happen, for obvious reasons.
TypeError: Raised if the prefix is correct, but the base unit is not, in
the user specified unit string.
"""
if
not
(
family
==
"number"
or
family
in
UnitMap
):
raise
IndexError
(
family
+
" is an undefined units kind."
)
if
family
==
"number"
:
return
number
if
unit
==
""
:
prefix
=
""
base
=
""
else
:
m
=
UnitPrefixRE
.
match
(
unit
);
if
m
is
None
:
raise
ValueError
(
"Unit "
+
unit
+
" is not structured with a prefix+base syntax."
)
prefix
=
m
.
group
(
1
)
base
=
m
.
group
(
2
)
if
not
prefix
in
UnitPrefix
:
raise
TypeError
(
prefix
+
" is not a valid unit prefix."
)
if
not
base
in
UnitMap
[
family
]:
raise
TypeError
(
base
+
" is an undefined unit for kind "
+
family
+
"."
)
return
number
*
UnitMap
[
family
][
base
]
*
UnitPrefix
[
prefix
]
def
unit_to_user
(
family
,
unit
,
number
):
"""Converts a number of given dimensions from internal to user units.
Args:
family: The dimensionality of the number.
unit: The units 'number' should be changed to.
number: The value of the parameter in internal units.
Returns:
The number in the user specified units
"""
return
number
/
unit_to_internal
(
family
,
unit
,
1.0
)
Event Timeline
Log In to Comment