aton 0.0.1rc5__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 +12 -0
- aton/_version.py +14 -0
- aton/interface/__init__.py +76 -0
- aton/interface/castep.py +93 -0
- aton/interface/phonopy.py +267 -0
- aton/interface/qe.py +1028 -0
- aton/phys/__init__.py +61 -0
- aton/phys/atoms.py +2437 -0
- aton/phys/functions.py +157 -0
- aton/phys/units.py +103 -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 +90 -0
- aton/st/call.py +94 -0
- aton/st/file.py +213 -0
- aton/text/__init__.py +41 -0
- aton/text/edit.py +321 -0
- aton/text/extract.py +162 -0
- aton/text/find.py +436 -0
- aton-0.0.1rc5.dist-info/LICENSE +661 -0
- aton-0.0.1rc5.dist-info/METADATA +234 -0
- aton-0.0.1rc5.dist-info/RECORD +37 -0
- aton-0.0.1rc5.dist-info/WHEEL +5 -0
- aton-0.0.1rc5.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 +112 -0
- tests/test_find.py +51 -0
- tests/test_qe.py +237 -0
- tests/test_spx.py +80 -0
aton/__init__.py
ADDED
aton/_version.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
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.text` 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
|
+
|
|
16
|
+
|
|
17
|
+
# Examples
|
|
18
|
+
|
|
19
|
+
## Quantum ESPRESSO
|
|
20
|
+
|
|
21
|
+
To read the output from a Quantum ESPRESSO pw.x calculation,
|
|
22
|
+
```python
|
|
23
|
+
from aton.interface import qe
|
|
24
|
+
# Read to a dictionary
|
|
25
|
+
calculation = qe.read_out('relax.out')
|
|
26
|
+
calculation.keys() # See the available values
|
|
27
|
+
# Final energy from the calculation
|
|
28
|
+
energy = calculation['Energy']
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
To modify values from an input file,
|
|
32
|
+
```python
|
|
33
|
+
from aton.interface import qe
|
|
34
|
+
# Add a hydrogen atom to a specific position
|
|
35
|
+
qe.add_atom('H 0.10 0.20 0.30')
|
|
36
|
+
# Set the input ecutwfc value
|
|
37
|
+
qe.set_value('relax.in', 'ecutwfc', 60.0)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Check the full `aton.interface.qe` API reference for more details.
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
## Phonopy
|
|
44
|
+
|
|
45
|
+
To perform a phonon calculation from a relaxed structure via Quantum ESPRESSO,
|
|
46
|
+
```python
|
|
47
|
+
from aton import interface
|
|
48
|
+
# Create the supercell inputs
|
|
49
|
+
interface.phonopy.make(dimension='2 2 2', folder='./calculation')
|
|
50
|
+
# Sbatch to a cluster
|
|
51
|
+
interface.phonopy.sbatch('./calculation')
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Check the full `aton.interface.phonopy` API reference for more details.
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
## CASTEP
|
|
58
|
+
|
|
59
|
+
To read output values from a CASTEP calculation,
|
|
60
|
+
```python
|
|
61
|
+
from aton.interface import castep
|
|
62
|
+
# Read the output
|
|
63
|
+
output = castep.read_castep('calculation.castep')
|
|
64
|
+
# Get the final energy
|
|
65
|
+
energy = output['Energy']
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Check the full `aton.interface.castep` API reference for more details.
|
|
69
|
+
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
from . import qe
|
|
74
|
+
from . import phonopy
|
|
75
|
+
from . import castep
|
|
76
|
+
|
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.text.find as find
|
|
18
|
+
import aton.text.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,267 @@
|
|
|
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
|
+
Create supercell inputs and sbatch phonon calculations
|
|
11
|
+
| | |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| `make()` | Build the supercell inputs |
|
|
14
|
+
| `sbatch()` | Sbatch'es the supercell calculations |
|
|
15
|
+
|
|
16
|
+
For more control
|
|
17
|
+
`supercells_from_scf()`
|
|
18
|
+
`scf_header_to_supercells()`
|
|
19
|
+
`check_slurm_template()`
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
import os
|
|
26
|
+
import re
|
|
27
|
+
from aton._version import __version__
|
|
28
|
+
import aton.st.file as file
|
|
29
|
+
import aton.st.call as call
|
|
30
|
+
import aton.text.find as find
|
|
31
|
+
import aton.text.edit as edit # text
|
|
32
|
+
import aton.text.extract as extract
|
|
33
|
+
import aton.interface.qe as qe
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def make(
|
|
37
|
+
dimension:str='2 2 2',
|
|
38
|
+
folder:str=None,
|
|
39
|
+
relax_in:str='relax.in',
|
|
40
|
+
relax_out:str='relax.out',
|
|
41
|
+
slurm_template:str='scf.slurm'
|
|
42
|
+
) -> None:
|
|
43
|
+
'''
|
|
44
|
+
Starting on a given `folder` (CWD if none) from the `relax_in` and `relax_out` (default ones),
|
|
45
|
+
creates the supercells of a `dimension` (`2 2 2` by default)
|
|
46
|
+
needed for the Phonopy calculations with Quantum ESPRESSO.
|
|
47
|
+
It runs sequentially `thotpy.qe.scf_from_relax()`, `supercells_from_scf()` and `scf_header_to_supercells()`.
|
|
48
|
+
Finally, it checks the `slurm_template` with `check_slurm_template()`.
|
|
49
|
+
'''
|
|
50
|
+
print(f'\nWelcome to thotpy.phonopy {__version__}\n'
|
|
51
|
+
'Creating all supercell inputs with Phonopy for Quantum ESPRESSO...\n')
|
|
52
|
+
qe.scf_from_relax(folder, relax_in, relax_out)
|
|
53
|
+
supercells_from_scf(dimension, folder)
|
|
54
|
+
scf_header_to_supercells(folder)
|
|
55
|
+
print('\n------------------------------------------------------\n'
|
|
56
|
+
'PLEASE CHECH BELOW THE CONTENT OF THE supercell-001.in\n'
|
|
57
|
+
'------------------------------------------------------\n')
|
|
58
|
+
call.bash('head -n 100 supercell-001.in')
|
|
59
|
+
print('\n------------------------------------------------------\n'
|
|
60
|
+
'PLEASE CHECH THE CONTENT OF THE supercell-001.in\n'
|
|
61
|
+
'The first 100 lines of the input were printed above!\n'
|
|
62
|
+
'------------------------------------------------------\n\n'
|
|
63
|
+
'If it seems correct, run the calculations with thotpy.phonopy.sbatch()\n')
|
|
64
|
+
check_slurm_template(folder, slurm_template)
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def sbatch(
|
|
69
|
+
folder=None,
|
|
70
|
+
slurm_template:str='scf.slurm',
|
|
71
|
+
testing:bool=False
|
|
72
|
+
) -> None:
|
|
73
|
+
'''
|
|
74
|
+
Launch all your supercell calculations to a cluster using a SLURM manager.
|
|
75
|
+
Runs from a `folder` (CWD if empty), using a `slurm_template` (`scf.slurm` by default).\n
|
|
76
|
+
If `testing=True` it skips the final sbatching, just printing the commands on the screen.\n
|
|
77
|
+
The slurm template must contain the keywords
|
|
78
|
+
`INPUT_FILE`, `OUTPUT_FILE`, and `JOB_NAME` in the following lines:
|
|
79
|
+
```
|
|
80
|
+
#SBATCH --job-name=JOB_NAME
|
|
81
|
+
mpirun pw.x -inp INPUT_FILE > OUTPUT_FILE
|
|
82
|
+
```
|
|
83
|
+
'''
|
|
84
|
+
print(f'\naton.interface.phonopy {__version__}\n'
|
|
85
|
+
'Sbatching all supercells...\n')
|
|
86
|
+
key_input = 'INPUT_FILE'
|
|
87
|
+
key_output = 'OUTPUT_FILE'
|
|
88
|
+
key_jobname = 'JOB_NAME'
|
|
89
|
+
id_pattern = re.compile(r'supercell-(\d\d\d).in')
|
|
90
|
+
slurm_folder = 'slurms'
|
|
91
|
+
folder = call.here(folder)
|
|
92
|
+
# Get supercells and abort if not found
|
|
93
|
+
supercells = file.get_list(folder, 'supercell-')
|
|
94
|
+
if len(supercells) == 0:
|
|
95
|
+
raise FileNotFoundError('Supercells were not found! Did you run thotpy.phonopy.make() ?')
|
|
96
|
+
call.bash(f"mkdir {slurm_folder}", folder, True, True)
|
|
97
|
+
# Get the template
|
|
98
|
+
slurm_file = check_slurm_template(folder, slurm_template)
|
|
99
|
+
if not slurm_file:
|
|
100
|
+
print(f'Aborting... Please correct {slurm_template}\n')
|
|
101
|
+
return None
|
|
102
|
+
for supercell in supercells:
|
|
103
|
+
# Get the file ID
|
|
104
|
+
match = re.search(id_pattern, supercell)
|
|
105
|
+
calc_id = match.group(1)
|
|
106
|
+
# Create slurm file for this supercell
|
|
107
|
+
slurm_id = 'scf-' + calc_id + '.slurm'
|
|
108
|
+
supercell = os.path.basename(supercell)
|
|
109
|
+
supercell_out = supercell.replace('.in', '.out')
|
|
110
|
+
fixing_dict = {
|
|
111
|
+
key_jobname: calc_id,
|
|
112
|
+
key_input: supercell,
|
|
113
|
+
key_output: supercell_out
|
|
114
|
+
}
|
|
115
|
+
edit.from_template(slurm_file, slurm_id, fixing_dict)
|
|
116
|
+
if testing:
|
|
117
|
+
call.bash(f"echo {slurm_id}", folder)
|
|
118
|
+
else:
|
|
119
|
+
call.bash(f"sbatch {slurm_id}", folder, True, False)
|
|
120
|
+
call.bash(f"mv {slurm_id} {slurm_folder}", folder, False, True) # Do not raise error if we can't move the file
|
|
121
|
+
print(f'\nDone! Temporary slurm files were moved to /{slurm_folder}/\n')
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def supercells_from_scf(
|
|
125
|
+
dimension:str='2 2 2',
|
|
126
|
+
folder:str=None,
|
|
127
|
+
scf:str='scf.in'
|
|
128
|
+
) -> None:
|
|
129
|
+
'''
|
|
130
|
+
Creates supercells of a given `dimension` (`2 2 2` by default) inside a `folder`,
|
|
131
|
+
from a Quantum ESPRESSO `scf` input (`scf.in` by default).
|
|
132
|
+
'''
|
|
133
|
+
print(f'\naton.interface.phonopy {__version__}\n')
|
|
134
|
+
folder = call.here(folder)
|
|
135
|
+
scf_in = file.get(folder, scf, True)
|
|
136
|
+
if scf_in is None:
|
|
137
|
+
raise ValueError('No SCF input found in path!')
|
|
138
|
+
call.bash(f'phonopy --qe -d --dim="{dimension}" -c {scf_in}')
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def scf_header_to_supercells(
|
|
143
|
+
folder:str=None,
|
|
144
|
+
scf:str='scf.in',
|
|
145
|
+
) -> None:
|
|
146
|
+
'''
|
|
147
|
+
Paste the header from the `scf` file in `folder` to the supercells created by Phonopy.
|
|
148
|
+
'''
|
|
149
|
+
print(f'\naton.interface.phonopy {__version__}\n'
|
|
150
|
+
f'Adding headers to Phonopy supercells for Quantum ESPRESSO...\n')
|
|
151
|
+
folder = call.here(folder)
|
|
152
|
+
# Check if the header file, the scf.in, exists
|
|
153
|
+
scf_file = file.get(folder, scf, True)
|
|
154
|
+
if scf_file is None:
|
|
155
|
+
raise ValueError('No header file found in path!')
|
|
156
|
+
# Check if the supercells exist
|
|
157
|
+
supercells = file.get_list(folder, 'supercell-')
|
|
158
|
+
if supercells is None:
|
|
159
|
+
raise ValueError('No supercells found in path!')
|
|
160
|
+
# Check if the supercells contains '&CONTROL' and abort if so
|
|
161
|
+
supercell_sample = supercells[0]
|
|
162
|
+
is_control = find.lines(supercell_sample, r'(&CONTROL|&control)', 1, 0, False, True)
|
|
163
|
+
if is_control:
|
|
164
|
+
raise ValueError('Supercells already contain &CONTROL! Did you do this already?')
|
|
165
|
+
# Check if the keyword is in the scf file
|
|
166
|
+
is_header = find.lines(scf_file, r'ATOMIC_SPECIES', 1, 0, False, False)
|
|
167
|
+
if not is_header:
|
|
168
|
+
raise ValueError('No ATOMIC_SPECIES found in header!')
|
|
169
|
+
# Copy the scf to a temp file
|
|
170
|
+
temp_scf = '_scf_temp.in'
|
|
171
|
+
file.copy(scf_file, temp_scf)
|
|
172
|
+
# Remove the top content from the temp file
|
|
173
|
+
edit.delete_under(temp_scf, 'K_POINTS', -1, 2, False)
|
|
174
|
+
# Find the new number of atoms and replace the line
|
|
175
|
+
updated_values = find.lines(supercell_sample, 'ibrav', 1) # ! ibrav = 0, nat = 384, ntyp = 5
|
|
176
|
+
if not updated_values:
|
|
177
|
+
print("!!! Okay listen, this is weird. This code should never be running, "
|
|
178
|
+
"but for some reson we couldn't find the updated values in the supercells. "
|
|
179
|
+
"Please, introduce the NEW NUMBER OF ATOMS in the supercells manually (int):")
|
|
180
|
+
nat = int(input('nat = '))
|
|
181
|
+
else:
|
|
182
|
+
nat = extract.number(updated_values[0], 'nat')
|
|
183
|
+
qe.set_value(temp_scf, 'nat', nat)
|
|
184
|
+
# Remove the lattice parameters, since Phonopy already indicates units
|
|
185
|
+
qe.set_value(temp_scf, 'celldm(1)', '')
|
|
186
|
+
qe.set_value(temp_scf, 'A', '')
|
|
187
|
+
qe.set_value(temp_scf, 'B', '')
|
|
188
|
+
qe.set_value(temp_scf, 'C', '')
|
|
189
|
+
qe.set_value(temp_scf, 'cosAB', '')
|
|
190
|
+
qe.set_value(temp_scf, 'cosAC', '')
|
|
191
|
+
qe.set_value(temp_scf, 'cosBC', '')
|
|
192
|
+
# Add the header to the supercells
|
|
193
|
+
with open(temp_scf, 'r') as f:
|
|
194
|
+
header = f.read()
|
|
195
|
+
for supercell in supercells:
|
|
196
|
+
edit.insert_at(supercell, header, 0)
|
|
197
|
+
# Remove the temp file
|
|
198
|
+
os.remove('_scf_temp.in')
|
|
199
|
+
print('Done!')
|
|
200
|
+
return None
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def check_slurm_template(
|
|
204
|
+
folder=None,
|
|
205
|
+
slurm_template:str='scf.slurm'
|
|
206
|
+
) -> str:
|
|
207
|
+
'''
|
|
208
|
+
Check a `slurm_template` inside `folder`.
|
|
209
|
+
The current working directory is used if `folder` is not provided.
|
|
210
|
+
If the file does not exist or is invalid, creates a `scf_EXAMPLE.slurm` file for reference.
|
|
211
|
+
'''
|
|
212
|
+
folder = call.here(folder)
|
|
213
|
+
slurm_example = 'scf_EXAMPLE.slurm'
|
|
214
|
+
new_slurm_file = os.path.join(folder, slurm_example)
|
|
215
|
+
# Default slurm template
|
|
216
|
+
content =f'''# Automatic slurm template created with aton.interface.phonopy {__version__}. https://github.com/pablogila/ThotPy
|
|
217
|
+
#!/bin/bash
|
|
218
|
+
#SBATCH --partition=general
|
|
219
|
+
#SBATCH --qos=regular
|
|
220
|
+
#SBATCH --job-name=JOB_NAME
|
|
221
|
+
#SBATCH --ntasks=32
|
|
222
|
+
#SBATCH --time=1-00:00:00
|
|
223
|
+
#SBATCH --mem=128G
|
|
224
|
+
# #SBATCH --mail-user=YOUR@EMAIL
|
|
225
|
+
# #SBATCH --mail-type=END
|
|
226
|
+
|
|
227
|
+
module purge
|
|
228
|
+
module load QuantumESPRESSO/7.3-foss-2023a
|
|
229
|
+
|
|
230
|
+
mpirun pw.x -inp INPUT_FILE > OUTPUT_FILE
|
|
231
|
+
'''
|
|
232
|
+
# If the slurm template does not exist, create one
|
|
233
|
+
slurm_file = file.get(folder, slurm_template, True)
|
|
234
|
+
if not slurm_file:
|
|
235
|
+
with open(new_slurm_file, 'w') as f:
|
|
236
|
+
f.write(content)
|
|
237
|
+
print(f'!!! WARNING: Slurm template missing, so an example was generated automatically:\n'
|
|
238
|
+
f'{slurm_example}\n'
|
|
239
|
+
f'PLEASE CHECK it, UPDATE it and RENAME it to {slurm_template}\n'
|
|
240
|
+
'before running thotpy.phonopy.sbatch()\n')
|
|
241
|
+
return None
|
|
242
|
+
# Check that the slurm file contains the INPUT_FILE, OUTPUT_FILE and JOB_NAME keywords
|
|
243
|
+
key_input = find.lines(slurm_file, 'INPUT_FILE')
|
|
244
|
+
key_output = find.lines(slurm_file, 'OUTPUT_FILE')
|
|
245
|
+
key_jobname = find.lines(slurm_file, 'JOB_NAME')
|
|
246
|
+
missing = []
|
|
247
|
+
if not key_input:
|
|
248
|
+
missing.append('INPUT_FILE')
|
|
249
|
+
if not key_output:
|
|
250
|
+
missing.append('OUTPUT_FILE')
|
|
251
|
+
if not key_jobname:
|
|
252
|
+
missing.append('JOB_NAME')
|
|
253
|
+
if len(missing) > 0:
|
|
254
|
+
with open(new_slurm_file, 'w') as f:
|
|
255
|
+
f.write(content)
|
|
256
|
+
print('!!! WARNING: Some keywords were missing from your slurm template,\n'
|
|
257
|
+
f'PLEASE CHECK the example at {slurm_example}\n'
|
|
258
|
+
'before running thotpy.phonopy.sbatch()\n'
|
|
259
|
+
f'The following keywords were missing from your {slurm_template}:')
|
|
260
|
+
for key in missing:
|
|
261
|
+
print(key)
|
|
262
|
+
print('')
|
|
263
|
+
return None
|
|
264
|
+
print(f"Your slurm template {slurm_template} SEEMS OKAY, "
|
|
265
|
+
"but don't forget to check it before running thotpy.phonopy.sbatch()\n")
|
|
266
|
+
return slurm_file # Ready to use!
|
|
267
|
+
|