aton 0.0.1__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.
- aton/__init__.py +13 -0
- aton/_version.py +14 -0
- aton/interface/__init__.py +78 -0
- aton/interface/castep.py +93 -0
- aton/interface/phonopy.py +152 -0
- aton/interface/qe.py +1057 -0
- aton/interface/slurm.py +253 -0
- aton/phys/__init__.py +61 -0
- aton/phys/atoms.py +2441 -0
- aton/phys/functions.py +158 -0
- aton/phys/units.py +103 -0
- aton/qrotor/__init__.py +26 -0
- aton/qrotor/classes.py +296 -0
- aton/qrotor/constants.py +72 -0
- aton/qrotor/plot.py +319 -0
- aton/qrotor/potential.py +215 -0
- aton/qrotor/rotate.py +174 -0
- aton/qrotor/solve.py +115 -0
- aton/spx/__init__.py +53 -0
- aton/spx/classes.py +481 -0
- aton/spx/deuterium.py +273 -0
- aton/spx/fit.py +183 -0
- aton/spx/normalize.py +138 -0
- aton/spx/plot.py +144 -0
- aton/spx/samples.py +85 -0
- aton/st/__init__.py +20 -0
- aton/st/alias.py +99 -0
- aton/st/call.py +94 -0
- aton/st/file.py +279 -0
- aton/txt/__init__.py +41 -0
- aton/txt/edit.py +324 -0
- aton/txt/extract.py +162 -0
- aton/txt/find.py +456 -0
- aton-0.0.1.dist-info/LICENSE +661 -0
- aton-0.0.1.dist-info/METADATA +260 -0
- aton-0.0.1.dist-info/RECORD +46 -0
- aton-0.0.1.dist-info/WHEEL +5 -0
- aton-0.0.1.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
- tests/test_edit.py +112 -0
- tests/test_extract.py +32 -0
- tests/test_file.py +101 -0
- tests/test_find.py +51 -0
- tests/test_qe.py +244 -0
- tests/test_qrotor.py +32 -0
- tests/test_spx.py +80 -0
aton/__init__.py
ADDED
aton/_version.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""
|
|
2
|
+
# *Ab-initio* interfaces
|
|
3
|
+
|
|
4
|
+
This module contains interfaces for several *ab-initio* calculation softwares.
|
|
5
|
+
These interfaces can be easily expanded with the `aton.txt` module.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Index
|
|
9
|
+
|
|
10
|
+
| | |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| `aton.interface.qe` | Interface for [Quantum ESPRESSO](https://www.quantum-espresso.org/)'s [pw.x](https://www.quantum-espresso.org/Doc/INPUT_PW.html) module |
|
|
13
|
+
| `aton.interface.phonopy` | Interface for [Phonopy](https://phonopy.github.io/phonopy/) calculations |
|
|
14
|
+
| `aton.interface.castep` | Interface for [CASTEP](https://castep-docs.github.io/castep-docs/) calculations |
|
|
15
|
+
| `aton.interface.slurm` | Batch jobs via [Slurm](https://slurm.schedmd.com/) |
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# Examples
|
|
19
|
+
|
|
20
|
+
## Quantum ESPRESSO
|
|
21
|
+
|
|
22
|
+
To read the output from a Quantum ESPRESSO pw.x calculation,
|
|
23
|
+
```python
|
|
24
|
+
from aton.interface import qe
|
|
25
|
+
# Read to a dictionary
|
|
26
|
+
calculation = qe.read_out('relax.out')
|
|
27
|
+
calculation.keys() # See the available values
|
|
28
|
+
# Final energy from the calculation
|
|
29
|
+
energy = calculation['Energy']
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
To modify values from an input file,
|
|
33
|
+
```python
|
|
34
|
+
from aton.interface import qe
|
|
35
|
+
# Add a hydrogen atom to a specific position
|
|
36
|
+
qe.add_atom('H 0.10 0.20 0.30')
|
|
37
|
+
# Set the input ecutwfc value
|
|
38
|
+
qe.set_value('relax.in', 'ecutwfc', 60.0)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Check the full `aton.interface.qe` API reference for more details.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
## Phonopy
|
|
45
|
+
|
|
46
|
+
To perform a phonon calculation from a relaxed structure via Quantum ESPRESSO,
|
|
47
|
+
```python
|
|
48
|
+
from aton import interface
|
|
49
|
+
# Create the supercell inputs
|
|
50
|
+
interface.phonopy.make_supercells(dimension='2 2 2')
|
|
51
|
+
# Sbatch to a cluster
|
|
52
|
+
interface.slurm.sbatch('supercell-', 'template.slurm')
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Check the full `aton.interface.phonopy` API reference for more details.
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
## CASTEP
|
|
59
|
+
|
|
60
|
+
To read output values from a CASTEP calculation,
|
|
61
|
+
```python
|
|
62
|
+
from aton.interface import castep
|
|
63
|
+
# Read the output
|
|
64
|
+
output = castep.read_castep('calculation.castep')
|
|
65
|
+
# Get the final energy
|
|
66
|
+
energy = output['Energy']
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Check the full `aton.interface.castep` API reference for more details.
|
|
70
|
+
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
from . import qe
|
|
75
|
+
from . import phonopy
|
|
76
|
+
from . import castep
|
|
77
|
+
from . import slurm
|
|
78
|
+
|
aton/interface/castep.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""
|
|
2
|
+
# Description
|
|
3
|
+
|
|
4
|
+
Functions to work with [CASTEP](https://castep-docs.github.io/castep-docs/) calculation files.
|
|
5
|
+
|
|
6
|
+
# Index
|
|
7
|
+
|
|
8
|
+
| | |
|
|
9
|
+
| --- | --- |
|
|
10
|
+
| `read_castep()` | Output reading |
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
import aton.st.file as file
|
|
17
|
+
import aton.txt.find as find
|
|
18
|
+
import aton.txt.extract as extract
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def read_castep(filename) -> dict:
|
|
22
|
+
"""
|
|
23
|
+
Reads a CASTEP output file, specified in `filename`.
|
|
24
|
+
Returns a dictionary with the following keys:
|
|
25
|
+
`'Enthalpy'` (LBFGS: Final Enthalpy, in kJ/mol),
|
|
26
|
+
`'Energy'` (Total energy corrected for finite basis set, in eV),
|
|
27
|
+
`'Space group'`, `'Volume'` (Angstrom^3), `'Density'` (amu/Angstrom^3), `'Density_g'` (g/cm^3),
|
|
28
|
+
`'A'`, `'B'`, `'C'` (Angstroms), `'Alpha'`, `'Beta'`, `'Gamma'` (Degrees).\n
|
|
29
|
+
Note that these output keys start with a **C**apital letter.
|
|
30
|
+
"""
|
|
31
|
+
file_castep = file.get(filename)
|
|
32
|
+
# Initial definitions
|
|
33
|
+
enthalpy = None
|
|
34
|
+
energy = None
|
|
35
|
+
space_group = None
|
|
36
|
+
volume = None
|
|
37
|
+
density = None
|
|
38
|
+
density_g = None
|
|
39
|
+
a = None
|
|
40
|
+
b = None
|
|
41
|
+
c = None
|
|
42
|
+
alpha = None
|
|
43
|
+
beta = None
|
|
44
|
+
gamma = None
|
|
45
|
+
# Find the output values in the file
|
|
46
|
+
enthalpy_str = find.lines(file_castep, 'LBFGS: Final Enthalpy =', -1)
|
|
47
|
+
energy_str = find.lines(file_castep, 'Total energy corrected for finite basis set =', -1)
|
|
48
|
+
space_group_str = find.lines(file_castep, 'Space group of crystal =', -1)
|
|
49
|
+
volume_str = find.lines(file_castep, 'Current cell volume =', -1)
|
|
50
|
+
density_str = find.lines(file_castep, 'density =', -1, 1)
|
|
51
|
+
a_str = find.lines(file_castep, 'a =', -1)
|
|
52
|
+
b_str = find.lines(file_castep, 'b =', -1)
|
|
53
|
+
c_str = find.lines(file_castep, 'c =', -1)
|
|
54
|
+
|
|
55
|
+
if enthalpy_str:
|
|
56
|
+
enthalpy = extract.number(enthalpy_str[0], 'LBFGS: Final Enthalpy')
|
|
57
|
+
if energy_str:
|
|
58
|
+
energy = extract.number(energy_str[0], 'Total energy corrected for finite basis set')
|
|
59
|
+
if space_group_str:
|
|
60
|
+
# Avoid little stupid errors
|
|
61
|
+
space_group_str = space_group_str.replace(',','.')
|
|
62
|
+
space_group = extract.string(space_group_str[0], 'Space group of crystal')
|
|
63
|
+
if volume_str:
|
|
64
|
+
volume = extract.number(volume_str[0], 'Current cell volume')
|
|
65
|
+
if density_str:
|
|
66
|
+
density = extract.number(density_str[0], 'density')
|
|
67
|
+
density_g = extract.number(density_str[1], '')
|
|
68
|
+
if a:
|
|
69
|
+
a = extract.number(a_str, 'a')
|
|
70
|
+
alpha = extract.number(a_str, 'alpha')
|
|
71
|
+
if b:
|
|
72
|
+
b = extract.number(b_str, 'b')
|
|
73
|
+
beta = extract.number(b_str, 'beta')
|
|
74
|
+
if c:
|
|
75
|
+
c = extract.number(c_str, 'c')
|
|
76
|
+
gamma = extract.number(c_str, 'gamma')
|
|
77
|
+
# Return as a dict
|
|
78
|
+
dictionary = {
|
|
79
|
+
'Enthalpy' : enthalpy,
|
|
80
|
+
'Energy' : energy,
|
|
81
|
+
'Space group' : space_group,
|
|
82
|
+
'Volume' : volume,
|
|
83
|
+
'Density' : density,
|
|
84
|
+
'Density_g' : density_g,
|
|
85
|
+
'A' : a,
|
|
86
|
+
'B' : b,
|
|
87
|
+
'C' : c,
|
|
88
|
+
'Alpha' : alpha,
|
|
89
|
+
'Beta' : beta,
|
|
90
|
+
'Gamma' : gamma,
|
|
91
|
+
}
|
|
92
|
+
return dictionary
|
|
93
|
+
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""
|
|
2
|
+
# Description
|
|
3
|
+
|
|
4
|
+
Functions to work with [Phonopy](https://phonopy.github.io/phonopy/) calculations,
|
|
5
|
+
along with [Quantum ESPRESSO](https://www.quantum-espresso.org/).
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Index
|
|
9
|
+
|
|
10
|
+
| | |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| `make_supercells()` | Build supercell SCF inputs for phonon calculations |
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Examples
|
|
16
|
+
|
|
17
|
+
To create the supercells and run the phonon calculations
|
|
18
|
+
from a folder with `relax.in` and `relax.out` files,
|
|
19
|
+
using a `template.slurm` file,
|
|
20
|
+
```python
|
|
21
|
+
from aton import interface
|
|
22
|
+
interface.phonopy.make_supercells()
|
|
23
|
+
interface.slurm.sbatch('supercell-', 'scf.slurm')
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
import os
|
|
31
|
+
import re
|
|
32
|
+
from aton._version import __version__
|
|
33
|
+
import aton.st.file as file
|
|
34
|
+
import aton.st.call as call
|
|
35
|
+
import aton.txt.find as find
|
|
36
|
+
import aton.txt.edit as edit # text
|
|
37
|
+
import aton.txt.extract as extract
|
|
38
|
+
import aton.interface.qe as qe
|
|
39
|
+
import aton.interface.slurm as slurm
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def make_supercells(
|
|
43
|
+
dimension:str='2 2 2',
|
|
44
|
+
relax_in:str='relax.in',
|
|
45
|
+
relax_out:str='relax.out',
|
|
46
|
+
folder:str=None,
|
|
47
|
+
slurm_template:str=None,
|
|
48
|
+
) -> None:
|
|
49
|
+
"""
|
|
50
|
+
Creates the supercell inputs of a given `dimension` ('2 2 2' by default),
|
|
51
|
+
from the `relax_in` and `relax_out` files in the `folder`
|
|
52
|
+
('relax.in', 'relax.out' and CWD by default, respectively),
|
|
53
|
+
needed for the Phonopy calculations with Quantum ESPRESSO.
|
|
54
|
+
|
|
55
|
+
If `slurm_template` is present,
|
|
56
|
+
it checks it with `aton.interface.slurm.check_template()`.
|
|
57
|
+
"""
|
|
58
|
+
print(f'\nWelcome to thotpy.phonopy {__version__}\n'
|
|
59
|
+
'Creating all supercell inputs with Phonopy for Quantum ESPRESSO...\n')
|
|
60
|
+
qe.scf_from_relax(folder, relax_in, relax_out)
|
|
61
|
+
_supercells_from_scf(dimension, folder)
|
|
62
|
+
_copy_scf_header_to_supercells(folder)
|
|
63
|
+
print('\n------------------------------------------------------\n'
|
|
64
|
+
'PLEASE CHECH BELOW THE CONTENT OF THE supercell-001.in\n'
|
|
65
|
+
'------------------------------------------------------\n')
|
|
66
|
+
call.bash('head -n 100 supercell-001.in')
|
|
67
|
+
print('\n------------------------------------------------------\n'
|
|
68
|
+
'PLEASE CHECH THE CONTENT OF THE supercell-001.in\n'
|
|
69
|
+
'The first 100 lines of the input were printed above!\n'
|
|
70
|
+
'------------------------------------------------------\n\n'
|
|
71
|
+
'If it seems correct, run the calculations with thotpy.phonopy.sbatch()\n')
|
|
72
|
+
if slurm_template:
|
|
73
|
+
slurm.check_template(slurm_template, folder)
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _supercells_from_scf(
|
|
78
|
+
dimension:str='2 2 2',
|
|
79
|
+
folder:str=None,
|
|
80
|
+
scf:str='scf.in'
|
|
81
|
+
) -> None:
|
|
82
|
+
"""
|
|
83
|
+
Creates supercells of a given `dimension` (`2 2 2` by default) inside a `folder`,
|
|
84
|
+
from a Quantum ESPRESSO `scf` input (`scf.in` by default).
|
|
85
|
+
"""
|
|
86
|
+
print(f'\naton.interface.phonopy {__version__}\n')
|
|
87
|
+
folder = call.here(folder)
|
|
88
|
+
scf_in = file.get(folder, scf, True)
|
|
89
|
+
if scf_in is None:
|
|
90
|
+
raise ValueError('No SCF input found in path!')
|
|
91
|
+
call.bash(f'phonopy --qe -d --dim="{dimension}" -c {scf_in}')
|
|
92
|
+
return None
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _copy_scf_header_to_supercells(
|
|
96
|
+
folder:str=None,
|
|
97
|
+
scf:str='scf.in',
|
|
98
|
+
) -> None:
|
|
99
|
+
"""Paste the header from the `scf` file in `folder` to the supercells created by Phonopy."""
|
|
100
|
+
print(f'\naton.interface.phonopy {__version__}\n'
|
|
101
|
+
f'Adding headers to Phonopy supercells for Quantum ESPRESSO...\n')
|
|
102
|
+
folder = call.here(folder)
|
|
103
|
+
# Check if the header file, the scf.in, exists
|
|
104
|
+
scf_file = file.get(folder, scf, True)
|
|
105
|
+
if scf_file is None:
|
|
106
|
+
raise ValueError('No header file found in path!')
|
|
107
|
+
# Check if the supercells exist
|
|
108
|
+
supercells = file.get_list(folder, 'supercell-')
|
|
109
|
+
if supercells is None:
|
|
110
|
+
raise ValueError('No supercells found in path!')
|
|
111
|
+
# Check if the supercells contains '&CONTROL' and abort if so
|
|
112
|
+
supercell_sample = supercells[0]
|
|
113
|
+
is_control = find.lines(supercell_sample, r'(&CONTROL|&control)', 1, 0, False, True)
|
|
114
|
+
if is_control:
|
|
115
|
+
raise ValueError('Supercells already contain &CONTROL! Did you do this already?')
|
|
116
|
+
# Check if the keyword is in the scf file
|
|
117
|
+
is_header = find.lines(scf_file, r'ATOMIC_SPECIES', 1, 0, False, False)
|
|
118
|
+
if not is_header:
|
|
119
|
+
raise ValueError('No ATOMIC_SPECIES found in header!')
|
|
120
|
+
# Copy the scf to a temp file
|
|
121
|
+
temp_scf = '_scf_temp.in'
|
|
122
|
+
file.copy(scf_file, temp_scf)
|
|
123
|
+
# Remove the top content from the temp file
|
|
124
|
+
edit.delete_under(temp_scf, 'K_POINTS', -1, 2, False)
|
|
125
|
+
# Find the new number of atoms and replace the line
|
|
126
|
+
updated_values = find.lines(supercell_sample, 'ibrav', 1) # ! ibrav = 0, nat = 384, ntyp = 5
|
|
127
|
+
if not updated_values:
|
|
128
|
+
print("!!! Okay listen, this is weird. This code should never be running, "
|
|
129
|
+
"but for some reson we couldn't find the updated values in the supercells. "
|
|
130
|
+
"Please, introduce the NEW NUMBER OF ATOMS in the supercells manually (int):")
|
|
131
|
+
nat = int(input('nat = '))
|
|
132
|
+
else:
|
|
133
|
+
nat = extract.number(updated_values[0], 'nat')
|
|
134
|
+
qe.set_value(temp_scf, 'nat', nat)
|
|
135
|
+
# Remove the lattice parameters, since Phonopy already indicates units
|
|
136
|
+
qe.set_value(temp_scf, 'celldm(1)', '')
|
|
137
|
+
qe.set_value(temp_scf, 'A', '')
|
|
138
|
+
qe.set_value(temp_scf, 'B', '')
|
|
139
|
+
qe.set_value(temp_scf, 'C', '')
|
|
140
|
+
qe.set_value(temp_scf, 'cosAB', '')
|
|
141
|
+
qe.set_value(temp_scf, 'cosAC', '')
|
|
142
|
+
qe.set_value(temp_scf, 'cosBC', '')
|
|
143
|
+
# Add the header to the supercells
|
|
144
|
+
with open(temp_scf, 'r') as f:
|
|
145
|
+
header = f.read()
|
|
146
|
+
for supercell in supercells:
|
|
147
|
+
edit.insert_at(supercell, header, 0)
|
|
148
|
+
# Remove the temp file
|
|
149
|
+
os.remove('_scf_temp.in')
|
|
150
|
+
print('Done!')
|
|
151
|
+
return None
|
|
152
|
+
|