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 ADDED
@@ -0,0 +1,13 @@
1
+ """
2
+ .. include:: ../_README_temp.md
3
+ """
4
+
5
+
6
+ from ._version import __version__ as version
7
+ from . import st
8
+ from . import phys
9
+ from . import txt
10
+ from . import interface
11
+ from . import spx
12
+ from . import qrotor
13
+
aton/_version.py ADDED
@@ -0,0 +1,14 @@
1
+ """
2
+ # Description
3
+
4
+ Package version is defined here. Follows semantic versioning, as in:
5
+
6
+ `vMAJOR.MINOR.PATCH.`
7
+
8
+ More about semantic versioning:
9
+ https://semver.org/
10
+
11
+ """
12
+
13
+ __version__ = 'v0.0.1'
14
+
@@ -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
+
@@ -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
+