nomad-parser-plugins-workflow 1.0__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.
Files changed (58) hide show
  1. nomad_parser_plugins_workflow-1.0.dist-info/LICENSE +202 -0
  2. nomad_parser_plugins_workflow-1.0.dist-info/METADATA +319 -0
  3. nomad_parser_plugins_workflow-1.0.dist-info/RECORD +58 -0
  4. nomad_parser_plugins_workflow-1.0.dist-info/WHEEL +5 -0
  5. nomad_parser_plugins_workflow-1.0.dist-info/entry_points.txt +11 -0
  6. nomad_parser_plugins_workflow-1.0.dist-info/top_level.txt +1 -0
  7. workflowparsers/__init__.py +314 -0
  8. workflowparsers/aflow/__init__.py +19 -0
  9. workflowparsers/aflow/__main__.py +31 -0
  10. workflowparsers/aflow/metainfo/__init__.py +19 -0
  11. workflowparsers/aflow/metainfo/aflow.py +1240 -0
  12. workflowparsers/aflow/parser.py +741 -0
  13. workflowparsers/asr/__init__.py +19 -0
  14. workflowparsers/asr/__main__.py +31 -0
  15. workflowparsers/asr/metainfo/__init__.py +19 -0
  16. workflowparsers/asr/metainfo/asr.py +306 -0
  17. workflowparsers/asr/parser.py +266 -0
  18. workflowparsers/atomate/__init__.py +19 -0
  19. workflowparsers/atomate/__main__.py +31 -0
  20. workflowparsers/atomate/metainfo/__init__.py +19 -0
  21. workflowparsers/atomate/metainfo/atomate.py +395 -0
  22. workflowparsers/atomate/parser.py +357 -0
  23. workflowparsers/elastic/__init__.py +19 -0
  24. workflowparsers/elastic/__main__.py +31 -0
  25. workflowparsers/elastic/metainfo/__init__.py +19 -0
  26. workflowparsers/elastic/metainfo/elastic.py +364 -0
  27. workflowparsers/elastic/parser.py +798 -0
  28. workflowparsers/fhivibes/__init__.py +19 -0
  29. workflowparsers/fhivibes/__main__.py +31 -0
  30. workflowparsers/fhivibes/metainfo/__init__.py +19 -0
  31. workflowparsers/fhivibes/metainfo/fhi_vibes.py +898 -0
  32. workflowparsers/fhivibes/parser.py +566 -0
  33. workflowparsers/lobster/__init__.py +19 -0
  34. workflowparsers/lobster/__main__.py +31 -0
  35. workflowparsers/lobster/metainfo/__init__.py +19 -0
  36. workflowparsers/lobster/metainfo/lobster.py +446 -0
  37. workflowparsers/lobster/parser.py +618 -0
  38. workflowparsers/phonopy/__init__.py +19 -0
  39. workflowparsers/phonopy/__main__.py +31 -0
  40. workflowparsers/phonopy/calculator.py +260 -0
  41. workflowparsers/phonopy/metainfo/__init__.py +19 -0
  42. workflowparsers/phonopy/metainfo/phonopy.py +83 -0
  43. workflowparsers/phonopy/parser.py +583 -0
  44. workflowparsers/quantum_espresso_epw/__init__.py +19 -0
  45. workflowparsers/quantum_espresso_epw/__main__.py +31 -0
  46. workflowparsers/quantum_espresso_epw/metainfo/__init__.py +19 -0
  47. workflowparsers/quantum_espresso_epw/metainfo/quantum_espresso_epw.py +579 -0
  48. workflowparsers/quantum_espresso_epw/parser.py +583 -0
  49. workflowparsers/quantum_espresso_phonon/__init__.py +19 -0
  50. workflowparsers/quantum_espresso_phonon/__main__.py +31 -0
  51. workflowparsers/quantum_espresso_phonon/metainfo/__init__.py +19 -0
  52. workflowparsers/quantum_espresso_phonon/metainfo/quantum_espresso_phonon.py +389 -0
  53. workflowparsers/quantum_espresso_phonon/parser.py +483 -0
  54. workflowparsers/quantum_espresso_xspectra/__init__.py +19 -0
  55. workflowparsers/quantum_espresso_xspectra/__main__.py +31 -0
  56. workflowparsers/quantum_espresso_xspectra/metainfo/__init__.py +19 -0
  57. workflowparsers/quantum_espresso_xspectra/metainfo/quantum_espresso_xspectra.py +290 -0
  58. workflowparsers/quantum_espresso_xspectra/parser.py +586 -0
@@ -0,0 +1,260 @@
1
+ #
2
+ # Copyright The NOMAD Authors.
3
+ #
4
+ # This file is part of NOMAD.
5
+ # See https://nomad-lab.eu for further info.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ from itertools import combinations
20
+ import numpy as np
21
+ import re
22
+ from typing import Any, Optional
23
+ from fractions import Fraction
24
+
25
+ from ase import lattice as aselattice
26
+ from ase.cell import Cell
27
+ from ase.dft.kpoints import (
28
+ special_paths,
29
+ parse_path_string,
30
+ get_special_points,
31
+ sc_special_points,
32
+ )
33
+
34
+ from phonopy.phonon.band_structure import BandStructure
35
+ from phonopy.units import EvTokJmol, VaspToTHz
36
+
37
+
38
+ def generate_kpath_parameters(
39
+ points: dict[str, np.ndarray], paths: list[list[str]], npoints: int
40
+ ) -> list[dict[str, Any]]:
41
+ k_points: list[list[np.ndarray]] = []
42
+ for p in paths:
43
+ k_points.append([points[k] for k in p])
44
+ for index in range(len(p)):
45
+ if p[index] == 'G':
46
+ p[index] = 'Γ'
47
+ parameters: list[dict[str, Any]] = []
48
+ for h, seg in enumerate(k_points):
49
+ for i, path in enumerate(seg):
50
+ parameter: dict[str, Any] = {}
51
+ parameter['npoints'] = npoints
52
+ parameter['startname'] = paths[h][i]
53
+ if i == 0 and len(seg) > 2:
54
+ parameter['kstart'] = path
55
+ parameter['kend'] = seg[i + 1]
56
+ parameter['endname'] = paths[h][i + 1]
57
+ parameters.append(parameter)
58
+ elif i == (len(seg) - 2):
59
+ parameter['kstart'] = path
60
+ parameter['kend'] = seg[i + 1]
61
+ parameter['endname'] = paths[h][i + 1]
62
+ parameters.append(parameter)
63
+ break
64
+ else:
65
+ parameter['kstart'] = path
66
+ parameter['kend'] = seg[i + 1]
67
+ parameter['endname'] = paths[h][i + 1]
68
+ parameters.append(parameter)
69
+ return parameters
70
+
71
+
72
+ def read_kpath(filename: str) -> list[dict[str, Any]]:
73
+ with open(filename) as f:
74
+ string = f.read()
75
+
76
+ labels_extracted = re.search(r'BAND_LABELS\s*=\s*(.+)', string)
77
+ try:
78
+ labels = labels_extracted.group(1).strip().split()
79
+ except Exception:
80
+ return []
81
+
82
+ points_extracted = re.search(r'BAND\s*=\s*(.+)', string)
83
+ try:
84
+ points = points_extracted.group(1)
85
+ points = [float(Fraction(p)) for p in points.split()]
86
+ points = np.reshape(points, (len(labels), 3))
87
+ points = {labels[i]: points[i] for i in range(len(labels))}
88
+ except Exception:
89
+ return []
90
+
91
+ npoints_extracted = re.search(r'BAND_POINTS\s*\=\s*(\d+)', string)
92
+ npoints = 100 if npoints_extracted is None else int(npoints_extracted.group(1))
93
+
94
+ return generate_kpath_parameters(points, [labels], npoints)
95
+
96
+
97
+ def test_non_canonical_hexagonal(cell: Cell, symprec: float) -> Optional[int]:
98
+ """
99
+ Tests if the cell is a non-canonical hexagonal cell
100
+ and returns the index of the ~ 60 degree angle (error range controlled by `symprec`).
101
+ """
102
+ try:
103
+ target = 60
104
+ angles = cell.angles()
105
+ lattices = cell.lengths()
106
+ except AttributeError:
107
+ raise ValueError('Cell is not ase.cell.Cell')
108
+
109
+ # 2 tests:
110
+ ## 1. if there is only one angle close to 60 degrees
111
+ ## 2. if there is only one pair of lattice vectors with the same length
112
+ condition_angles = (angles > target - symprec) & (angles < target + symprec)
113
+ lattice_pairs = list(combinations(lattices, 2))
114
+ if (len(match_id := np.where(condition_angles)[0]) == 1) and (
115
+ sum([lat[1] - symprec <= lat[0] <= lat[1] + symprec for lat in lattice_pairs])
116
+ == 1
117
+ ):
118
+ return int(match_id[0])
119
+ return None
120
+
121
+
122
+ def generate_kpath_ase(cell: Cell, symprec: float, logger=None) -> list[dict[str, Any]]:
123
+ try:
124
+ if not isinstance(cell, Cell):
125
+ cell = Cell(cell)
126
+ if isinstance(
127
+ rot_axis_id := test_non_canonical_hexagonal(cell, 1e2 * symprec), int
128
+ ): # be more lenient with the angle
129
+ logger.warning(
130
+ 'Non-canonical hexagonal cell detected. Will correct the orientation.'
131
+ )
132
+ target_axis_id = list(set(range(3)) - {rot_axis_id})[0]
133
+ mirror_matrix = np.eye(3)
134
+ mirror_matrix[target_axis_id, target_axis_id] *= -1
135
+ cell = Cell(mirror_matrix @ cell)
136
+ lattice = aselattice.get_lattice_from_canonical_cell(cell, eps=symprec)
137
+ paths = parse_path_string(lattice.special_path)
138
+ points = lattice.get_special_points()
139
+ except Exception:
140
+ logger.warning('Cannot resolve lattice paths.')
141
+ paths = special_paths['orthorombic'] # TODO: remove reliance on `ase`
142
+ points = sc_special_points['orthorombic'] # TODO: remove reliance on `ase`
143
+ if points is None:
144
+ try:
145
+ points = get_special_points(cell)
146
+ except Exception:
147
+ return []
148
+
149
+ if isinstance(paths, str):
150
+ paths = [list(path) for path in paths.split(',')]
151
+ return generate_kpath_parameters(points, paths, 100)
152
+
153
+
154
+ class PhononProperties:
155
+ def __init__(self, phonopy_obj, logger, **kwargs):
156
+ self.logger = logger
157
+ self.phonopy_obj = phonopy_obj
158
+ self.t_max = kwargs.get('t_max', 1000)
159
+ self.t_min = kwargs.get('t_min', 0)
160
+ self.t_step = kwargs.get('t_step', 100)
161
+ self.band_conf = kwargs.get('band_conf')
162
+
163
+ self.n_atoms = len(phonopy_obj.unitcell)
164
+
165
+ k_mesh = kwargs.get('k_mesh', 30)
166
+ mesh_density = (2 * k_mesh**3) / self.n_atoms
167
+ mesh_number = np.round(mesh_density ** (1.0 / 3.0))
168
+ self.mesh = [mesh_number, mesh_number, mesh_number]
169
+
170
+ self.n_atoms_supercell = len(phonopy_obj.supercell)
171
+
172
+ def get_bandstructure(self):
173
+ phonopy_obj = self.phonopy_obj
174
+
175
+ frequency_unit_factor = VaspToTHz
176
+ is_eigenvectors = False
177
+
178
+ unit_cell = phonopy_obj.unitcell.get_cell()
179
+ sym_tol = phonopy_obj.symmetry.tolerance
180
+ if self.band_conf is not None:
181
+ parameters = read_kpath(self.band_conf)
182
+ else:
183
+ parameters = generate_kpath_ase(unit_cell, sym_tol, self.logger)
184
+ if not parameters:
185
+ return None, None, None
186
+
187
+ # Distances calculated in phonopy.band_structure.BandStructure object
188
+ # are based on absolute positions of q-points in reciprocal space
189
+ # as calculated by using the cell which is handed over during instantiation.
190
+ # Fooling that object by handing over a "unit cell" diag(1,1,1) instead clashes
191
+ # with calculation of non-analytical terms.
192
+ # Hence generate appropriate distances and special k-points list based on fractional
193
+ # coordinates in reciprocal space (to keep backwards compatibility with previous
194
+ # FHI-aims phonon implementation).
195
+ bands = []
196
+ bands_distances = []
197
+ distance = 0.0
198
+ bands_special_points = [distance]
199
+ bands_labels = []
200
+ label = parameters[0]['startname']
201
+ for b in parameters:
202
+ kstart = np.array(b['kstart'])
203
+ kend = np.array(b['kend'])
204
+ npoints = b['npoints']
205
+ dk = (kend - kstart) / (npoints - 1)
206
+ bands.append([(kstart + dk * n) for n in range(npoints)])
207
+ dk_length = np.linalg.norm(dk)
208
+
209
+ for n in range(npoints):
210
+ bands_distances.append(distance + dk_length * n)
211
+
212
+ distance += dk_length * (npoints - 1)
213
+ bands_special_points.append(distance)
214
+ label = [b['startname'], b['endname']]
215
+ bands_labels.append(label)
216
+
217
+ bs_obj = BandStructure(
218
+ bands,
219
+ phonopy_obj.dynamical_matrix,
220
+ with_eigenvectors=is_eigenvectors,
221
+ factor=frequency_unit_factor,
222
+ )
223
+
224
+ freqs = bs_obj.get_frequencies()
225
+
226
+ return np.array(freqs), np.array(bands), np.array(bands_labels)
227
+
228
+ def get_dos(self):
229
+ phonopy_obj = self.phonopy_obj
230
+ mesh = self.mesh
231
+
232
+ phonopy_obj.set_mesh(mesh, is_gamma_center=True)
233
+ q_points = phonopy_obj.get_mesh()[0]
234
+ phonopy_obj.set_qpoints_phonon(q_points, is_eigenvectors=False)
235
+
236
+ frequencies = phonopy_obj.get_qpoints_phonon()[0]
237
+ self.frequencies = np.array(frequencies)
238
+ min_freq = min(np.ravel(frequencies))
239
+ max_freq = max(np.ravel(frequencies)) + max(np.ravel(frequencies)) * 0.05
240
+
241
+ phonopy_obj.set_total_DOS(
242
+ freq_min=min_freq, freq_max=max_freq, tetrahedron_method=True
243
+ )
244
+ f, dos = phonopy_obj.get_total_DOS()
245
+
246
+ return f, dos
247
+
248
+ def get_thermodynamical_properties(self):
249
+ phonopy_obj = self.phonopy_obj
250
+
251
+ phonopy_obj.set_mesh(self.mesh, is_gamma_center=True)
252
+ phonopy_obj.set_thermal_properties(
253
+ t_step=self.t_step, t_max=self.t_max, t_min=self.t_min
254
+ )
255
+ T, fe, entropy, cv = phonopy_obj.get_thermal_properties()
256
+ kJmolToEv = 1.0 / EvTokJmol
257
+ fe = fe * kJmolToEv
258
+ JmolToEv = kJmolToEv / 1000
259
+ cv = JmolToEv * cv
260
+ return T, fe, entropy, cv
@@ -0,0 +1,19 @@
1
+ #
2
+ # Copyright The NOMAD Authors.
3
+ #
4
+ # This file is part of NOMAD.
5
+ # See https://nomad-lab.eu for further info.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ from . import phonopy
@@ -0,0 +1,83 @@
1
+ #
2
+ # Copyright The NOMAD Authors.
3
+ #
4
+ # This file is part of NOMAD.
5
+ # See https://nomad-lab.eu for further info.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ import numpy as np # pylint: disable=unused-import
20
+ import typing # pylint: disable=unused-import
21
+ from nomad.metainfo import ( # pylint: disable=unused-import
22
+ MSection,
23
+ MCategory,
24
+ Category,
25
+ Package,
26
+ Quantity,
27
+ Section,
28
+ SubSection,
29
+ SectionProxy,
30
+ Reference,
31
+ )
32
+ import runschema.run # pylint: disable=unused-import
33
+ import runschema.calculation # pylint: disable=unused-import
34
+ import runschema.method # pylint: disable=unused-import
35
+ import runschema.system # pylint: disable=unused-import
36
+
37
+
38
+ m_package = Package()
39
+
40
+
41
+ class x_phonopy_input(MCategory):
42
+ """
43
+ Information about properties that concern phonopy calculations.
44
+ """
45
+
46
+ m_def = Category()
47
+
48
+
49
+ class Method(runschema.method.Method):
50
+ m_def = Section(validate=False, extends_base_section=True)
51
+
52
+ x_phonopy_displacement = Quantity(
53
+ type=np.float64,
54
+ shape=[],
55
+ unit='meter',
56
+ description="""
57
+ Amplitude of the atom diplacement for the phonopy supercell
58
+ """,
59
+ categories=[x_phonopy_input],
60
+ )
61
+
62
+ x_phonopy_symprec = Quantity(
63
+ type=np.float64,
64
+ shape=[],
65
+ unit='meter',
66
+ description="""
67
+ Symmetry threshold for the space group identification of the crystal for which the
68
+ vibrational properties are to be calculated
69
+ """,
70
+ categories=[x_phonopy_input],
71
+ )
72
+
73
+
74
+ class System(runschema.system.System):
75
+ m_def = Section(validate=False, extends_base_section=True)
76
+
77
+ x_phonopy_original_system_ref = Quantity(
78
+ type=runschema.system.System,
79
+ shape=[],
80
+ description="""
81
+ Original cell from which the supercell for the DFT calculations was constructed
82
+ """,
83
+ )