qrotor 4.1.1__py3-none-any.whl → 4.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of qrotor might be problematic. Click here for more details.
- qrotor/_version.py +1 -1
- qrotor/constants.py +4 -4
- qrotor/plot.py +17 -1
- qrotor/potential.py +4 -1
- qrotor/system.py +1 -1
- {qrotor-4.1.1.dist-info → qrotor-4.1.2.dist-info}/METADATA +1 -1
- qrotor-4.1.2.dist-info/RECORD +20 -0
- {qrotor-4.1.1.dist-info → qrotor-4.1.2.dist-info}/top_level.txt +1 -0
- tests/__init__.py +0 -0
- tests/test_constants.py +13 -0
- tests/test_potential.py +37 -0
- tests/test_rotate.py +53 -0
- tests/test_solve.py +28 -0
- tests/test_system.py +24 -0
- qrotor-4.1.1.dist-info/RECORD +0 -14
- {qrotor-4.1.1.dist-info → qrotor-4.1.2.dist-info}/WHEEL +0 -0
- {qrotor-4.1.1.dist-info → qrotor-4.1.2.dist-info}/licenses/LICENSE +0 -0
qrotor/_version.py
CHANGED
qrotor/constants.py
CHANGED
|
@@ -51,13 +51,13 @@ I_ND3 = 3 * (periodictable.D.mass * _amu * r_NH**2)
|
|
|
51
51
|
# Rotational energy
|
|
52
52
|
_hbar = const.physical_constants['reduced Planck constant'][0]
|
|
53
53
|
B_CH3 = ((_hbar**2) / (2 * I_CH3)) * (1000 / const.eV)
|
|
54
|
-
"""
|
|
54
|
+
"""Kinetic rotational energy of CH3, in meV·s/kg·m^2."""
|
|
55
55
|
B_CD3 = ((_hbar**2) / (2 * I_CD3)) * (1000 / const.eV)
|
|
56
|
-
"""
|
|
56
|
+
"""Kinetic rotational energy of CD3, in meV·s/kg·m^2."""
|
|
57
57
|
B_NH3 = ((_hbar**2) / (2 * I_NH3)) * (1000 / const.eV)
|
|
58
|
-
"""
|
|
58
|
+
"""Kinetic rotational energy of NH3, in meV·s/kg·m^2."""
|
|
59
59
|
B_ND3 = ((_hbar**2) / (2 * I_ND3)) * (1000 / const.eV)
|
|
60
|
-
"""
|
|
60
|
+
"""Kinetic rotational energy of ND3, in meV·s/kg·m^2."""
|
|
61
61
|
|
|
62
62
|
# Potential constants from titov2023 [C1, C2, C3, C4, C5]
|
|
63
63
|
constants_titov2023 = [
|
qrotor/plot.py
CHANGED
|
@@ -34,6 +34,8 @@ def potential(
|
|
|
34
34
|
marker='',
|
|
35
35
|
linestyle='-',
|
|
36
36
|
cm:bool=False,
|
|
37
|
+
normalize:bool=False,
|
|
38
|
+
ylim:tuple=None,
|
|
37
39
|
) -> None:
|
|
38
40
|
"""Plot the potential values of `data` (System object, or list of systems).
|
|
39
41
|
|
|
@@ -42,8 +44,13 @@ def potential(
|
|
|
42
44
|
|
|
43
45
|
`marker` and `linestyle` can be a Matplotlib string or list of strings.
|
|
44
46
|
Optionally, the Viridis colormap can be used with `cm = True`.
|
|
47
|
+
|
|
48
|
+
Set `normalize = True` to normalize by their respective `qrotor.system.System.potential_max`.
|
|
49
|
+
This can be useful if you have performed subtractions or similar operations.
|
|
50
|
+
In this case, you might also want to play with `ylim` to adjust the y-axis limits.
|
|
45
51
|
"""
|
|
46
|
-
|
|
52
|
+
data_copy = deepcopy(data)
|
|
53
|
+
system = systems.as_list(data_copy)
|
|
47
54
|
title_str = title if title else (system[0].comment if (system[0].comment and (len(system) == 1 or not system[-1].comment)) else 'Rotational potential energy')
|
|
48
55
|
# Marker as a list
|
|
49
56
|
if isinstance(marker, list):
|
|
@@ -62,6 +69,15 @@ def potential(
|
|
|
62
69
|
plt.title(title_str)
|
|
63
70
|
plt.xlabel('Angle / rad')
|
|
64
71
|
plt.ylabel('Potential energy / meV')
|
|
72
|
+
|
|
73
|
+
if normalize:
|
|
74
|
+
plt.ylabel('Energy / V$_{3}$')
|
|
75
|
+
for s in system:
|
|
76
|
+
s.potential_values = s.potential_values / s.potential_max
|
|
77
|
+
|
|
78
|
+
if ylim:
|
|
79
|
+
plt.ylim(ylim)
|
|
80
|
+
|
|
65
81
|
plt.xticks([-2*np.pi, -3*np.pi/2, -np.pi, -np.pi/2, 0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi], [r'$-2\pi$', r'$-\frac{3\pi}{2}$', r'$-\pi$', r'$-\frac{\pi}{2}$', '0', r'$\frac{\pi}{2}$', r'$\pi$', r'$\frac{3\pi}{2}$', r'$2\pi$'])
|
|
66
82
|
|
|
67
83
|
if cm: # Plot using a colormap
|
qrotor/potential.py
CHANGED
|
@@ -372,7 +372,10 @@ def interpolate(system:System) -> System:
|
|
|
372
372
|
grid = system.grid
|
|
373
373
|
gridsize = system.gridsize
|
|
374
374
|
new_grid = np.linspace(0, 2*np.pi, gridsize)
|
|
375
|
-
|
|
375
|
+
# Impose periodic boundary conditions
|
|
376
|
+
grid_periodic = np.append(grid, grid[0] + 2*np.pi)
|
|
377
|
+
V_periodic = np.append(V, V[0])
|
|
378
|
+
cubic_spline = CubicSpline(grid_periodic, V_periodic, bc_type='periodic')
|
|
376
379
|
new_V = cubic_spline(new_grid)
|
|
377
380
|
system.grid = new_grid
|
|
378
381
|
system.potential_values = new_V
|
qrotor/system.py
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
qrotor/__init__.py,sha256=rG2dH4QjsVUOMBhFnv5gXs3QnrUg7fywd5pIDmMBXcQ,246
|
|
2
|
+
qrotor/_version.py,sha256=gtnQ4qGBlYQr4K9VzdiULHRclyxik47zCja1dRudtyk,198
|
|
3
|
+
qrotor/constants.py,sha256=Q59CU5QrvOyCz-2TFP31GDKJYi7G7LUxbs10ZTMiKIE,3408
|
|
4
|
+
qrotor/plot.py,sha256=s0XYMxQ7BxN_MngU-UAvX5mGk5R8c_Hznw2xFX9-8nI,14028
|
|
5
|
+
qrotor/potential.py,sha256=2HjSDVJWSvwplyH5pq0MMPoQsLIBJbbTwkr350u949I,18491
|
|
6
|
+
qrotor/rotate.py,sha256=Wje9Q9SFhDvizz58MzNGBwsmgV-3wN9z2SnUNTIXzeg,8107
|
|
7
|
+
qrotor/solve.py,sha256=YkOR1SJlpk41PCNEhslv6X3wV1TWMNztT78qX3Pngf0,10722
|
|
8
|
+
qrotor/system.py,sha256=ahYurNUmVOV7B6aZSe7rhcruagj5rW9UClqG-H1vVvY,11454
|
|
9
|
+
qrotor/systems.py,sha256=Hcx0QvMWpaPMfC6HWpkZPPWDyHk9rxWKdAxWNnD2NMg,8184
|
|
10
|
+
qrotor-4.1.2.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
|
11
|
+
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
tests/test_constants.py,sha256=YHKkPyZlzjchxxzON_VSNsQdKnpkknsFVoIA6TcUk70,399
|
|
13
|
+
tests/test_potential.py,sha256=_Vq9t9Xm59kNbyYwXlRnvKcxwL7vntD2j14W2aUtF6I,1302
|
|
14
|
+
tests/test_rotate.py,sha256=2On2d1E82hdisFC5DXpaqqYNnteX7ZP3PAnGa_oGm2M,1896
|
|
15
|
+
tests/test_solve.py,sha256=tEjLUZC7oe6LCQD5b2xf2aaK9lu-zI4lzuPXOGR2GAs,861
|
|
16
|
+
tests/test_system.py,sha256=36d-8AdoJdzq0O9_O3s8wwBPGa-M7A86YiHqhhAsCZ8,742
|
|
17
|
+
qrotor-4.1.2.dist-info/METADATA,sha256=5oHcJpRWIUcYiIzE5ilaFOWfH0xVy_7klIULdL2WhH0,8719
|
|
18
|
+
qrotor-4.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
19
|
+
qrotor-4.1.2.dist-info/top_level.txt,sha256=mLnYs07-amqX4TqbDV2_XvgdpHfgrYmzmYb7dwoh6EQ,13
|
|
20
|
+
qrotor-4.1.2.dist-info/RECORD,,
|
tests/__init__.py
ADDED
|
File without changes
|
tests/test_constants.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import qrotor as qr
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_constants():
|
|
5
|
+
assert round(qr.B_CH3, 5) == 0.64518
|
|
6
|
+
assert round(qr.B_CD3, 5) == 0.32289
|
|
7
|
+
assert round(qr.B_NH3, 5) == 0.73569
|
|
8
|
+
assert round(qr.B_ND3, 5) == 0.36819
|
|
9
|
+
assert round(qr.Ry_to_eV, 5) == 13.60569
|
|
10
|
+
assert round(qr.Ry_to_meV, 5) == 13605.69312
|
|
11
|
+
assert round(qr.eV_to_Ry, 5) == 0.07350
|
|
12
|
+
assert round(qr.meV_to_Ry, 10) == .0000734986
|
|
13
|
+
|
tests/test_potential.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import qrotor as qr
|
|
2
|
+
import aton
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
folder = 'tests/samples/'
|
|
6
|
+
structure = folder + 'CH3NH3.in'
|
|
7
|
+
structure_120 = folder + 'CH3NH3_120.in'
|
|
8
|
+
structure_60 = folder + 'CH3NH3_60.in'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_save_and_load():
|
|
12
|
+
system = qr.System()
|
|
13
|
+
system.gridsize = 36
|
|
14
|
+
system.potential_name = 'sin'
|
|
15
|
+
system.B = 1
|
|
16
|
+
system.solve_potential()
|
|
17
|
+
potential_file = folder + '_temp_potential.csv'
|
|
18
|
+
# Remove the file if it exists
|
|
19
|
+
try:
|
|
20
|
+
aton.file.remove(potential_file)
|
|
21
|
+
except:
|
|
22
|
+
pass
|
|
23
|
+
qr.potential.save(system, comment='hi', filepath=potential_file)
|
|
24
|
+
system_new = qr.potential.load(potential_file)
|
|
25
|
+
assert system_new.gridsize == system.gridsize
|
|
26
|
+
assert round(system_new.potential_values[0], 5) == round(system.potential_values[0], 5)
|
|
27
|
+
assert round(system_new.potential_values[5], 5) == round(system.potential_values[5], 5)
|
|
28
|
+
assert round(system_new.potential_values[13], 5) == round(system.potential_values[13], 5)
|
|
29
|
+
assert system_new.comment == 'hi'
|
|
30
|
+
aton.file.remove(potential_file)
|
|
31
|
+
# If we don't provide a comment, it should be the name of the folder
|
|
32
|
+
system.comment = None
|
|
33
|
+
qr.potential.save(system, filepath=potential_file)
|
|
34
|
+
system_new = qr.potential.load(potential_file)
|
|
35
|
+
assert system_new.comment == 'samples'
|
|
36
|
+
aton.file.remove(potential_file)
|
|
37
|
+
|
tests/test_rotate.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import qrotor as qr
|
|
2
|
+
import aton.api as api
|
|
3
|
+
import aton.txt.extract as extract
|
|
4
|
+
import aton.file as file
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
folder = 'tests/samples/'
|
|
8
|
+
structure = folder + 'CH3NH3.in'
|
|
9
|
+
structure_120 = folder + 'CH3NH3_120.in'
|
|
10
|
+
structure_60 = folder + 'CH3NH3_60.in'
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_rotate():
|
|
14
|
+
CH3 = [
|
|
15
|
+
'0.100 0.183 0.316',
|
|
16
|
+
'0.151 0.532 0.842',
|
|
17
|
+
'0.118 0.816 0.277',
|
|
18
|
+
]
|
|
19
|
+
# 120 degrees (it should remain the same)
|
|
20
|
+
qr.rotate.structure_qe(filepath=structure, positions=CH3, angle=120, precision=2)
|
|
21
|
+
for coord in CH3:
|
|
22
|
+
rotated_coord = api.qe.get_atom(filepath=structure_120, position=coord, precision=2)
|
|
23
|
+
rotated_coord = extract.coords(rotated_coord)
|
|
24
|
+
coord = extract.coords(coord)
|
|
25
|
+
rotated_coord_rounded = []
|
|
26
|
+
coord_rounded = []
|
|
27
|
+
for i in rotated_coord:
|
|
28
|
+
rotated_coord_rounded.append(round(i, 2))
|
|
29
|
+
for i in coord:
|
|
30
|
+
coord_rounded.append(round(i, 2))
|
|
31
|
+
assert coord_rounded == rotated_coord_rounded
|
|
32
|
+
file.remove(structure_120)
|
|
33
|
+
|
|
34
|
+
# 60 degrees (it should change quite a lot)
|
|
35
|
+
ideal = [
|
|
36
|
+
'0.146468644022416 0.837865866372631 0.641449758215011',
|
|
37
|
+
'0.095062781582172 0.488975944606740 0.115053787468686',
|
|
38
|
+
'0.128156574395412 0.205890189020629 0.680672454316303',
|
|
39
|
+
]
|
|
40
|
+
qr.rotate.structure_qe(filepath=structure, positions=CH3, angle=60, precision=2)
|
|
41
|
+
for coord in ideal:
|
|
42
|
+
rotated_coord = api.qe.get_atom(filepath=structure_60, position=coord, precision=3)
|
|
43
|
+
rotated_coord = extract.coords(rotated_coord)
|
|
44
|
+
coord = extract.coords(coord)
|
|
45
|
+
rotated_coord_rounded = []
|
|
46
|
+
coord_rounded = []
|
|
47
|
+
for i in rotated_coord:
|
|
48
|
+
rotated_coord_rounded.append(round(i, 2))
|
|
49
|
+
for i in coord:
|
|
50
|
+
coord_rounded.append(round(i, 2))
|
|
51
|
+
assert coord_rounded == rotated_coord_rounded
|
|
52
|
+
file.remove(structure_60)
|
|
53
|
+
|
tests/test_solve.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import qrotor as qr
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_solve_zero():
|
|
5
|
+
system = qr.System()
|
|
6
|
+
system.gridsize = 50000
|
|
7
|
+
system.potential_name = 'zero'
|
|
8
|
+
system.B = 1
|
|
9
|
+
system.solve()
|
|
10
|
+
assert round(system.eigenvalues[0], 2) == 0.0
|
|
11
|
+
assert round(system.eigenvalues[1], 2) == 1.0
|
|
12
|
+
assert round(system.eigenvalues[2], 2) == 1.0
|
|
13
|
+
assert round(system.eigenvalues[3], 2) == 4.0
|
|
14
|
+
assert round(system.eigenvalues[4], 2) == 4.0
|
|
15
|
+
assert round(system.eigenvalues[5], 2) == 9.0
|
|
16
|
+
assert round(system.eigenvalues[6], 2) == 9.0
|
|
17
|
+
assert round(system.eigenvalues[7], 2) == 16.0
|
|
18
|
+
assert round(system.eigenvalues[8], 2) == 16.0
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_solve_potential():
|
|
22
|
+
system = qr.System()
|
|
23
|
+
system.gridsize = 500
|
|
24
|
+
system.potential_name = 'sin'
|
|
25
|
+
system.potential_constants = [0, 1, 3, 0]
|
|
26
|
+
system.solve_potential()
|
|
27
|
+
assert round(system.potential_max, 2) == 1.0
|
|
28
|
+
|
tests/test_system.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import qrotor as qr
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_phase():
|
|
6
|
+
sys = qr.System()
|
|
7
|
+
sys.B = 1.0
|
|
8
|
+
sys.potential_name = 'cos'
|
|
9
|
+
sys.gridsize = 10000
|
|
10
|
+
sys.solve()
|
|
11
|
+
# plus pi/2, which will be -3pi/2
|
|
12
|
+
sys.change_phase(0.5)
|
|
13
|
+
assert round(sys.grid[0], 2) == round(-np.pi * 3/2, 2)
|
|
14
|
+
# The first potential value should be 0,
|
|
15
|
+
# but remember that the potential offset is corrected
|
|
16
|
+
# so it should be half potential_max, so 1.0/2
|
|
17
|
+
assert round(sys.potential_values[0], 2) == 0.5
|
|
18
|
+
# minus pi, which will become -pi/2
|
|
19
|
+
sys.change_phase(-1)
|
|
20
|
+
assert round(sys.grid[0], 2) == round(-np.pi/2, 2)
|
|
21
|
+
assert round(sys.potential_values[0], 2) == 0.5
|
|
22
|
+
# Were eigenvalues calculated?
|
|
23
|
+
assert len(sys.eigenvalues) > 0
|
|
24
|
+
|
qrotor-4.1.1.dist-info/RECORD
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
qrotor/__init__.py,sha256=rG2dH4QjsVUOMBhFnv5gXs3QnrUg7fywd5pIDmMBXcQ,246
|
|
2
|
-
qrotor/_version.py,sha256=2MgvxBLj7nl20vruBp0VlxrcVaLnJcKclBipVBi68xM,198
|
|
3
|
-
qrotor/constants.py,sha256=XjKlaHnquVtrpt0vtNS1UoXeI9EWf-wzz2QAByJp_Ck,3376
|
|
4
|
-
qrotor/plot.py,sha256=th6eDoTB01KaVjfH2uiKMjU4VJMfdv0yK97PwCJydKI,13479
|
|
5
|
-
qrotor/potential.py,sha256=9NyekNIMbjiRtJ8G6CtCMHX5v-g7kKC8un2x3blq-2w,18320
|
|
6
|
-
qrotor/rotate.py,sha256=Wje9Q9SFhDvizz58MzNGBwsmgV-3wN9z2SnUNTIXzeg,8107
|
|
7
|
-
qrotor/solve.py,sha256=YkOR1SJlpk41PCNEhslv6X3wV1TWMNztT78qX3Pngf0,10722
|
|
8
|
-
qrotor/system.py,sha256=v6BFA9Pm1HbYdfm-XrPP7iWlbcvjxX7ynGBMOxDR7yc,11447
|
|
9
|
-
qrotor/systems.py,sha256=Hcx0QvMWpaPMfC6HWpkZPPWDyHk9rxWKdAxWNnD2NMg,8184
|
|
10
|
-
qrotor-4.1.1.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
|
11
|
-
qrotor-4.1.1.dist-info/METADATA,sha256=k0oAqJRLC6Rr8au36Lj_cmJYiFJVYtqfbTkEn94KOXM,8719
|
|
12
|
-
qrotor-4.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
13
|
-
qrotor-4.1.1.dist-info/top_level.txt,sha256=SFRMgcJiR1GiEtZ4aLo-x5TdfSCo7Igxezp2qyI0u5A,7
|
|
14
|
-
qrotor-4.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|