emmet-builders 0.78.3__py3-none-any.whl → 0.86.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.
- emmet/builders/abinit/phonon.py +47 -47
- emmet/builders/abinit/sound_velocity.py +15 -11
- emmet/builders/feff/xas.py +1 -2
- emmet/builders/materials/absorption_spectrum.py +25 -14
- emmet/builders/materials/alloys.py +10 -11
- emmet/builders/materials/chemenv.py +2 -3
- emmet/builders/materials/corrected_entries.py +21 -15
- emmet/builders/materials/dielectric.py +19 -11
- emmet/builders/materials/elasticity.py +44 -33
- emmet/builders/materials/electrodes.py +35 -28
- emmet/builders/materials/electronic_structure.py +17 -17
- emmet/builders/materials/magnetism.py +11 -4
- emmet/builders/materials/optimade.py +7 -3
- emmet/builders/materials/piezoelectric.py +24 -21
- emmet/builders/materials/provenance.py +16 -13
- emmet/builders/materials/robocrys.py +2 -3
- emmet/builders/materials/substrates.py +9 -8
- emmet/builders/materials/summary.py +3 -3
- emmet/builders/materials/thermo.py +17 -11
- emmet/builders/matscholar/missing_compositions.py +12 -8
- emmet/builders/mobility/migration_graph.py +5 -5
- emmet/builders/settings.py +21 -17
- emmet/builders/utils.py +101 -12
- emmet/builders/vasp/materials.py +40 -51
- emmet/builders/vasp/mp_potcar_stats.json.gz +0 -0
- emmet/builders/vasp/task_validator.py +25 -36
- emmet_builders-0.86.0.dist-info/METADATA +37 -0
- emmet_builders-0.86.0.dist-info/RECORD +41 -0
- {emmet_builders-0.78.3.dist-info → emmet_builders-0.86.0.dist-info}/WHEEL +1 -1
- emmet/builders/materials/ml.py +0 -87
- emmet/builders/molecules/atomic.py +0 -589
- emmet/builders/molecules/bonds.py +0 -324
- emmet/builders/molecules/metal_binding.py +0 -526
- emmet/builders/molecules/orbitals.py +0 -288
- emmet/builders/molecules/redox.py +0 -496
- emmet/builders/molecules/summary.py +0 -383
- emmet/builders/molecules/thermo.py +0 -500
- emmet/builders/molecules/vibration.py +0 -278
- emmet/builders/qchem/__init__.py +0 -0
- emmet/builders/qchem/molecules.py +0 -734
- emmet_builders-0.78.3.dist-info/METADATA +0 -47
- emmet_builders-0.78.3.dist-info/RECORD +0 -51
- /emmet/builders/{molecules/__init__.py → py.typed} +0 -0
- {emmet_builders-0.78.3.dist-info → emmet_builders-0.86.0.dist-info}/top_level.txt +0 -0
|
@@ -17,8 +17,9 @@ The build proceeds in the below steps:
|
|
|
17
17
|
7. Fit the elastic tensor.
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
20
22
|
from datetime import datetime
|
|
21
|
-
from typing import Any, Dict, Generator, List, Optional, Tuple, Union
|
|
22
23
|
|
|
23
24
|
import numpy as np
|
|
24
25
|
from maggma.core import Builder, Store
|
|
@@ -29,10 +30,18 @@ from pymatgen.core import Structure
|
|
|
29
30
|
from pymatgen.core.tensors import TensorMapping
|
|
30
31
|
|
|
31
32
|
from emmet.core.elasticity import ElasticityDoc
|
|
32
|
-
from emmet.core.mpid import
|
|
33
|
+
from emmet.core.mpid import AlphaID
|
|
33
34
|
from emmet.core.utils import jsanitize
|
|
34
35
|
from emmet.core.vasp.calc_types import CalcType
|
|
35
36
|
|
|
37
|
+
from typing import TYPE_CHECKING
|
|
38
|
+
|
|
39
|
+
if TYPE_CHECKING:
|
|
40
|
+
from collections.abc import Generator
|
|
41
|
+
from typing import Any
|
|
42
|
+
|
|
43
|
+
from emmet.core.types.typing import IdentifierType
|
|
44
|
+
|
|
36
45
|
|
|
37
46
|
class ElasticityBuilder(Builder):
|
|
38
47
|
def __init__(
|
|
@@ -40,7 +49,7 @@ class ElasticityBuilder(Builder):
|
|
|
40
49
|
tasks: Store,
|
|
41
50
|
materials: Store,
|
|
42
51
|
elasticity: Store,
|
|
43
|
-
query:
|
|
52
|
+
query: dict | None = None,
|
|
44
53
|
fitting_method: str = "finite_difference",
|
|
45
54
|
**kwargs,
|
|
46
55
|
):
|
|
@@ -78,7 +87,7 @@ class ElasticityBuilder(Builder):
|
|
|
78
87
|
|
|
79
88
|
def get_items(
|
|
80
89
|
self,
|
|
81
|
-
) -> Generator[
|
|
90
|
+
) -> Generator[tuple[str, dict[str, str], list[dict]], None, None]:
|
|
82
91
|
"""
|
|
83
92
|
Gets all items to process into elasticity docs.
|
|
84
93
|
|
|
@@ -129,8 +138,8 @@ class ElasticityBuilder(Builder):
|
|
|
129
138
|
yield material_id, calc_types, tasks
|
|
130
139
|
|
|
131
140
|
def process_item(
|
|
132
|
-
self, item:
|
|
133
|
-
) ->
|
|
141
|
+
self, item: tuple[IdentifierType, dict[str, str], list[dict]]
|
|
142
|
+
) -> dict | None:
|
|
134
143
|
"""
|
|
135
144
|
Process all tasks belong to the same material into an elasticity doc.
|
|
136
145
|
|
|
@@ -191,7 +200,7 @@ class ElasticityBuilder(Builder):
|
|
|
191
200
|
|
|
192
201
|
# convert to elasticity doc
|
|
193
202
|
deforms = []
|
|
194
|
-
stresses = []
|
|
203
|
+
stresses: list[Stress] = [] # TODO: mypy misfires on `Stress`
|
|
195
204
|
deform_task_ids = []
|
|
196
205
|
deform_dir_names = []
|
|
197
206
|
for doc in final_deform:
|
|
@@ -200,7 +209,7 @@ class ElasticityBuilder(Builder):
|
|
|
200
209
|
)
|
|
201
210
|
# 0.1 to convert to GPa from kBar, and the minus sign to flip the stress
|
|
202
211
|
# direction from compressive as positive (in vasp) to tensile as positive
|
|
203
|
-
stresses.append(-0.1 * Stress(doc["output"]["stress"]))
|
|
212
|
+
stresses.append(-0.1 * Stress(doc["output"]["stress"])) # type: ignore[arg-type]
|
|
204
213
|
deform_task_ids.append(doc["task_id"])
|
|
205
214
|
deform_dir_names.append(doc["dir_name"])
|
|
206
215
|
|
|
@@ -208,10 +217,10 @@ class ElasticityBuilder(Builder):
|
|
|
208
217
|
structure=Structure.from_dict(final_opt["output"]["structure"]),
|
|
209
218
|
material_id=material_id,
|
|
210
219
|
deformations=deforms,
|
|
211
|
-
stresses=stresses,
|
|
220
|
+
stresses=stresses, # type: ignore[arg-type]
|
|
212
221
|
deformation_task_ids=deform_task_ids,
|
|
213
222
|
deformation_dir_names=deform_dir_names,
|
|
214
|
-
equilibrium_stress=-0.1 * Stress(final_opt["output"]["stress"]),
|
|
223
|
+
equilibrium_stress=-0.1 * Stress(final_opt["output"]["stress"]), # type: ignore[arg-type]
|
|
215
224
|
optimization_task_id=final_opt["task_id"],
|
|
216
225
|
optimization_dir_name=final_opt["dir_name"],
|
|
217
226
|
fitting_method="finite_difference",
|
|
@@ -220,7 +229,7 @@ class ElasticityBuilder(Builder):
|
|
|
220
229
|
|
|
221
230
|
return elasticity_doc
|
|
222
231
|
|
|
223
|
-
def update_targets(self, items:
|
|
232
|
+
def update_targets(self, items: list[dict]):
|
|
224
233
|
"""
|
|
225
234
|
Insert the new elasticity docs into the elasticity collection.
|
|
226
235
|
|
|
@@ -233,24 +242,26 @@ class ElasticityBuilder(Builder):
|
|
|
233
242
|
|
|
234
243
|
|
|
235
244
|
def filter_opt_tasks(
|
|
236
|
-
tasks:
|
|
237
|
-
calc_types:
|
|
238
|
-
target_calc_type: str = CalcType.GGA_Structure_Optimization,
|
|
239
|
-
) ->
|
|
245
|
+
tasks: list[dict],
|
|
246
|
+
calc_types: dict[str, str],
|
|
247
|
+
target_calc_type: str | CalcType = CalcType.GGA_Structure_Optimization,
|
|
248
|
+
) -> list[dict]:
|
|
240
249
|
"""
|
|
241
250
|
Filter optimization tasks, by
|
|
242
251
|
- calculation type
|
|
243
252
|
"""
|
|
244
|
-
opt_tasks = [
|
|
253
|
+
opt_tasks = [
|
|
254
|
+
t for t in tasks if calc_types[str(AlphaID(t["task_id"]))] == target_calc_type
|
|
255
|
+
]
|
|
245
256
|
|
|
246
257
|
return opt_tasks
|
|
247
258
|
|
|
248
259
|
|
|
249
260
|
def filter_deform_tasks(
|
|
250
|
-
tasks:
|
|
251
|
-
calc_types:
|
|
252
|
-
target_calc_type: str = CalcType.GGA_Deformation,
|
|
253
|
-
) ->
|
|
261
|
+
tasks: list[dict],
|
|
262
|
+
calc_types: dict[str, str],
|
|
263
|
+
target_calc_type: str | CalcType = CalcType.GGA_Deformation,
|
|
264
|
+
) -> list[dict]:
|
|
254
265
|
"""
|
|
255
266
|
Filter deformation tasks, by
|
|
256
267
|
- calculation type
|
|
@@ -271,8 +282,8 @@ def filter_deform_tasks(
|
|
|
271
282
|
|
|
272
283
|
|
|
273
284
|
def filter_by_incar_settings(
|
|
274
|
-
tasks:
|
|
275
|
-
) ->
|
|
285
|
+
tasks: list[dict], incar_settings: dict[str, Any] | None = None
|
|
286
|
+
) -> list[dict]:
|
|
276
287
|
"""
|
|
277
288
|
Filter tasks by incar parameters.
|
|
278
289
|
"""
|
|
@@ -315,7 +326,7 @@ def filter_by_incar_settings(
|
|
|
315
326
|
return selected
|
|
316
327
|
|
|
317
328
|
|
|
318
|
-
def filter_opt_tasks_by_time(tasks:
|
|
329
|
+
def filter_opt_tasks_by_time(tasks: list[dict], logger) -> dict:
|
|
319
330
|
"""
|
|
320
331
|
Filter a set of tasks to select the latest completed one.
|
|
321
332
|
|
|
@@ -330,8 +341,8 @@ def filter_opt_tasks_by_time(tasks: List[Dict], logger) -> Dict:
|
|
|
330
341
|
|
|
331
342
|
|
|
332
343
|
def filter_deform_tasks_by_time(
|
|
333
|
-
tasks:
|
|
334
|
-
) ->
|
|
344
|
+
tasks: list[dict], deform_comp_tol: float = 1e-5, logger=None
|
|
345
|
+
) -> list[dict]:
|
|
335
346
|
"""
|
|
336
347
|
For deformation tasks with the same deformation, select the latest completed one.
|
|
337
348
|
|
|
@@ -364,7 +375,7 @@ def filter_deform_tasks_by_time(
|
|
|
364
375
|
return selected
|
|
365
376
|
|
|
366
377
|
|
|
367
|
-
def _filter_tasks_by_time(tasks:
|
|
378
|
+
def _filter_tasks_by_time(tasks: list[dict], mode: str, logger) -> dict:
|
|
368
379
|
"""
|
|
369
380
|
Helper function to filter a set of tasks to select the latest completed one.
|
|
370
381
|
"""
|
|
@@ -388,11 +399,11 @@ def _filter_tasks_by_time(tasks: List[Dict], mode: str, logger) -> Dict:
|
|
|
388
399
|
|
|
389
400
|
|
|
390
401
|
def select_final_opt_deform_tasks(
|
|
391
|
-
opt_tasks:
|
|
392
|
-
deform_tasks:
|
|
402
|
+
opt_tasks: list[tuple[np.ndarray, dict]],
|
|
403
|
+
deform_tasks: list[tuple[np.ndarray, list[dict]]],
|
|
393
404
|
logger,
|
|
394
405
|
lattice_comp_tol: float = 1e-5,
|
|
395
|
-
) ->
|
|
406
|
+
) -> tuple[dict | None, list[dict] | None]:
|
|
396
407
|
"""
|
|
397
408
|
Select the final opt task and deform tasks for fitting.
|
|
398
409
|
|
|
@@ -445,8 +456,8 @@ def select_final_opt_deform_tasks(
|
|
|
445
456
|
|
|
446
457
|
|
|
447
458
|
def group_by_parent_lattice(
|
|
448
|
-
tasks:
|
|
449
|
-
) ->
|
|
459
|
+
tasks: list[dict], mode: str, lattice_comp_tol: float = 1e-5
|
|
460
|
+
) -> list[tuple[np.ndarray, list[dict]]]:
|
|
450
461
|
"""
|
|
451
462
|
Groups a set of task docs by parent lattice equivalence.
|
|
452
463
|
|
|
@@ -459,11 +470,11 @@ def group_by_parent_lattice(
|
|
|
459
470
|
lattice_comp_tol: tolerance for comparing lattice equivalence.
|
|
460
471
|
|
|
461
472
|
Returns:
|
|
462
|
-
[(lattice,
|
|
473
|
+
[(lattice, list[tasks])]: each tuple gives the common parent lattice of a
|
|
463
474
|
list of the structures before deformation (if any), and the list tasks
|
|
464
475
|
from which the structures are taken.
|
|
465
476
|
"""
|
|
466
|
-
docs_by_lattice:
|
|
477
|
+
docs_by_lattice: list[tuple[np.ndarray, list[dict]]] = []
|
|
467
478
|
|
|
468
479
|
for doc in tasks:
|
|
469
480
|
sim_lattice = get(doc, "output.structure.lattice.matrix")
|
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
import operator
|
|
2
|
+
from collections import defaultdict
|
|
2
3
|
from datetime import datetime
|
|
3
4
|
from functools import lru_cache
|
|
4
5
|
from itertools import chain
|
|
5
6
|
from math import ceil
|
|
6
|
-
from typing import Any, Iterator, Dict, List, Optional
|
|
7
|
-
from collections import defaultdict
|
|
8
7
|
|
|
9
8
|
from maggma.builders import Builder
|
|
10
9
|
from maggma.stores import MongoStore
|
|
11
10
|
from maggma.utils import grouper
|
|
12
|
-
from pymatgen.
|
|
11
|
+
from pymatgen.analysis.phase_diagram import Composition, PhaseDiagram
|
|
13
12
|
from pymatgen.entries.compatibility import MaterialsProject2020Compatibility
|
|
14
|
-
from pymatgen.
|
|
13
|
+
from pymatgen.entries.computed_entries import ComputedEntry, ComputedStructureEntry
|
|
15
14
|
|
|
16
|
-
from emmet.
|
|
15
|
+
from emmet.builders.settings import EmmetBuildSettings
|
|
16
|
+
from emmet.core.electrode import ConversionElectrodeDoc, InsertionElectrodeDoc
|
|
17
17
|
from emmet.core.structure_group import StructureGroupDoc, _get_id_lexi
|
|
18
18
|
from emmet.core.utils import jsanitize
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
from typing import TYPE_CHECKING
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from typing import Any
|
|
24
|
+
from collections.abc import Iterator
|
|
20
25
|
|
|
21
26
|
|
|
22
27
|
def s_hash(el):
|
|
@@ -85,7 +90,7 @@ class StructureGroupBuilder(Builder):
|
|
|
85
90
|
materials: MongoStore,
|
|
86
91
|
sgroups: MongoStore,
|
|
87
92
|
working_ion: str,
|
|
88
|
-
query:
|
|
93
|
+
query: dict | None = None,
|
|
89
94
|
ltol: float = default_build_settings.LTOL,
|
|
90
95
|
stol: float = default_build_settings.STOL,
|
|
91
96
|
angle_tol: float = default_build_settings.ANGLE_TOL,
|
|
@@ -115,15 +120,15 @@ class StructureGroupBuilder(Builder):
|
|
|
115
120
|
self.check_newer = check_newer
|
|
116
121
|
self.chunk_size = chunk_size
|
|
117
122
|
|
|
118
|
-
self.query[
|
|
119
|
-
|
|
120
|
-
|
|
123
|
+
self.query["deprecated"] = (
|
|
124
|
+
False # Ensure only non-deprecated materials are chosen
|
|
125
|
+
)
|
|
121
126
|
|
|
122
127
|
super().__init__(
|
|
123
128
|
sources=[materials], targets=[sgroups], chunk_size=chunk_size, **kwargs
|
|
124
129
|
)
|
|
125
130
|
|
|
126
|
-
def prechunk(self, number_splits: int) -> Iterator[
|
|
131
|
+
def prechunk(self, number_splits: int) -> Iterator[dict]: # pragma: no cover
|
|
127
132
|
"""
|
|
128
133
|
Prechunk method to perform chunking by the key field
|
|
129
134
|
"""
|
|
@@ -268,7 +273,7 @@ class StructureGroupBuilder(Builder):
|
|
|
268
273
|
else:
|
|
269
274
|
yield {"chemsys": chemsys, "materials": all_mats_in_chemsys}
|
|
270
275
|
|
|
271
|
-
def update_targets(self, items:
|
|
276
|
+
def update_targets(self, items: list):
|
|
272
277
|
items = list(filter(None, chain.from_iterable(items)))
|
|
273
278
|
if len(items) > 0:
|
|
274
279
|
self.logger.info("Updating {} sgroups documents".format(len(items)))
|
|
@@ -319,7 +324,7 @@ class InsertionElectrodeBuilder(Builder):
|
|
|
319
324
|
grouped_materials: MongoStore,
|
|
320
325
|
thermo: MongoStore,
|
|
321
326
|
insertion_electrode: MongoStore,
|
|
322
|
-
query:
|
|
327
|
+
query: dict | None = None,
|
|
323
328
|
strip_structures: bool = False,
|
|
324
329
|
**kwargs,
|
|
325
330
|
):
|
|
@@ -335,7 +340,7 @@ class InsertionElectrodeBuilder(Builder):
|
|
|
335
340
|
**kwargs,
|
|
336
341
|
)
|
|
337
342
|
|
|
338
|
-
def prechunk(self, number_splits: int) -> Iterator[
|
|
343
|
+
def prechunk(self, number_splits: int) -> Iterator[dict]:
|
|
339
344
|
"""
|
|
340
345
|
Prechunk method to perform chunking by the key field
|
|
341
346
|
"""
|
|
@@ -418,7 +423,7 @@ class InsertionElectrodeBuilder(Builder):
|
|
|
418
423
|
else:
|
|
419
424
|
yield None
|
|
420
425
|
|
|
421
|
-
def process_item(self, item) ->
|
|
426
|
+
def process_item(self, item) -> dict:
|
|
422
427
|
"""
|
|
423
428
|
- Add volume information to each entry to create the insertion electrode document
|
|
424
429
|
- Add the host structure
|
|
@@ -460,14 +465,14 @@ class InsertionElectrodeBuilder(Builder):
|
|
|
460
465
|
# {"failed_reason": "unable to create InsertionElectrode document"}
|
|
461
466
|
return jsanitize(ie.model_dump())
|
|
462
467
|
|
|
463
|
-
def update_targets(self, items:
|
|
468
|
+
def update_targets(self, items: list):
|
|
464
469
|
items = list(filter(None, items))
|
|
465
470
|
if len(items) > 0:
|
|
466
471
|
self.logger.info("Updating {} battery documents".format(len(items)))
|
|
467
472
|
for struct_group_dict in items:
|
|
468
|
-
struct_group_dict[
|
|
469
|
-
|
|
470
|
-
|
|
473
|
+
struct_group_dict[self.grouped_materials.last_updated_field] = (
|
|
474
|
+
datetime.utcnow()
|
|
475
|
+
)
|
|
471
476
|
self.insertion_electrode.update(docs=items, key=["battery_id"])
|
|
472
477
|
else:
|
|
473
478
|
self.logger.info("No items to update")
|
|
@@ -480,7 +485,7 @@ class ConversionElectrodeBuilder(Builder):
|
|
|
480
485
|
conversion_electrode_store: MongoStore,
|
|
481
486
|
working_ion: str,
|
|
482
487
|
thermo_type: str,
|
|
483
|
-
query:
|
|
488
|
+
query: dict | None = None,
|
|
484
489
|
**kwargs,
|
|
485
490
|
):
|
|
486
491
|
self.phase_diagram_store = phase_diagram_store
|
|
@@ -499,7 +504,7 @@ class ConversionElectrodeBuilder(Builder):
|
|
|
499
504
|
**kwargs,
|
|
500
505
|
)
|
|
501
506
|
|
|
502
|
-
def prechunk(self, number_splits: int) -> Iterator[
|
|
507
|
+
def prechunk(self, number_splits: int) -> Iterator[dict]:
|
|
503
508
|
"""
|
|
504
509
|
Prechunk method to perform chunking by the key field
|
|
505
510
|
"""
|
|
@@ -532,7 +537,7 @@ class ConversionElectrodeBuilder(Builder):
|
|
|
532
537
|
for phase_diagram_doc in self.phase_diagram_store.query(criteria=q):
|
|
533
538
|
yield phase_diagram_doc
|
|
534
539
|
|
|
535
|
-
def process_item(self, item) ->
|
|
540
|
+
def process_item(self, item) -> dict:
|
|
536
541
|
"""
|
|
537
542
|
- For each phase diagram doc, find all possible conversion electrodes and create conversion electrode docs
|
|
538
543
|
"""
|
|
@@ -564,14 +569,16 @@ class ConversionElectrodeBuilder(Builder):
|
|
|
564
569
|
# Get lowest material_id with matching composition
|
|
565
570
|
material_ids = [
|
|
566
571
|
(
|
|
567
|
-
lambda x:
|
|
568
|
-
|
|
569
|
-
|
|
572
|
+
lambda x: (
|
|
573
|
+
x.data["material_id"] # type: ignore[attr-defined]
|
|
574
|
+
if x.composition.reduced_formula == v[1].reduced_formula
|
|
575
|
+
else None
|
|
576
|
+
)
|
|
570
577
|
)(e)
|
|
571
578
|
for e in pd.entries
|
|
572
579
|
]
|
|
573
580
|
material_ids = list(filter(None, material_ids))
|
|
574
|
-
lowest_id = min(material_ids, key=_get_id_lexi)
|
|
581
|
+
lowest_id = min(material_ids, key=_get_id_lexi) # type: ignore[arg-type]
|
|
575
582
|
conversion_electrode_doc = (
|
|
576
583
|
ConversionElectrodeDoc.from_composition_and_pd(
|
|
577
584
|
comp=v[1],
|
|
@@ -597,7 +604,7 @@ class ConversionElectrodeBuilder(Builder):
|
|
|
597
604
|
relevant_entry_data = []
|
|
598
605
|
for e in pd.entries:
|
|
599
606
|
if e.composition == Composition(c):
|
|
600
|
-
relevant_entry_data.append((e.energy_per_atom, e.entry_id))
|
|
607
|
+
relevant_entry_data.append((e.energy_per_atom, e.entry_id)) # type: ignore[attr-defined]
|
|
601
608
|
relevant_entry_data.sort(key=lambda x: x[0])
|
|
602
609
|
entry_id_mapping[c] = relevant_entry_data[0][1]
|
|
603
610
|
|
|
@@ -609,7 +616,7 @@ class ConversionElectrodeBuilder(Builder):
|
|
|
609
616
|
|
|
610
617
|
return new_docs # type: ignore
|
|
611
618
|
|
|
612
|
-
def update_targets(self, items:
|
|
619
|
+
def update_targets(self, items: list):
|
|
613
620
|
combined_items = []
|
|
614
621
|
for _items in items:
|
|
615
622
|
_items = list(filter(None, _items))
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
from collections import defaultdict
|
|
2
|
-
from math import ceil
|
|
3
1
|
import itertools
|
|
4
2
|
import re
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from math import ceil
|
|
5
|
+
|
|
5
6
|
import boto3
|
|
6
7
|
import numpy as np
|
|
7
8
|
from botocore.handlers import disable_signing
|
|
8
9
|
from maggma.builders import Builder
|
|
9
10
|
from maggma.utils import grouper
|
|
10
11
|
from pymatgen.analysis.magnetism.analyzer import CollinearMagneticStructureAnalyzer
|
|
12
|
+
from pymatgen.analysis.structure_matcher import StructureMatcher
|
|
11
13
|
from pymatgen.core import Structure
|
|
12
|
-
from pymatgen.electronic_structure.core import Spin
|
|
13
14
|
from pymatgen.electronic_structure.bandstructure import BandStructureSymmLine
|
|
15
|
+
from pymatgen.electronic_structure.core import Spin
|
|
14
16
|
from pymatgen.electronic_structure.dos import CompleteDos
|
|
15
|
-
from pymatgen.symmetry.bandstructure import HighSymmKpath
|
|
16
|
-
from pymatgen.analysis.structure_matcher import StructureMatcher
|
|
17
|
-
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
|
|
18
17
|
from pymatgen.io.vasp.sets import MPStaticSet
|
|
18
|
+
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
|
|
19
|
+
from pymatgen.symmetry.bandstructure import HighSymmKpath
|
|
19
20
|
|
|
20
|
-
from emmet.
|
|
21
|
+
from emmet.builders.utils import query_open_data
|
|
21
22
|
from emmet.core.electronic_structure import ElectronicStructureDoc
|
|
23
|
+
from emmet.core.settings import EmmetSettings
|
|
22
24
|
from emmet.core.utils import jsanitize
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
SETTINGS = EmmetSettings()
|
|
26
|
+
SETTINGS = EmmetSettings() # type: ignore[call-arg]
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class ElectronicStructureBuilder(Builder):
|
|
@@ -297,7 +297,7 @@ class ElectronicStructureBuilder(Builder):
|
|
|
297
297
|
Inserts electronic structure documents into the electronic_structure collection
|
|
298
298
|
|
|
299
299
|
Args:
|
|
300
|
-
items ([
|
|
300
|
+
items ([dict]): A list of ElectronicStructureDoc dictionaries to update
|
|
301
301
|
"""
|
|
302
302
|
|
|
303
303
|
items = list(filter(None, items))
|
|
@@ -577,9 +577,9 @@ class ElectronicStructureBuilder(Builder):
|
|
|
577
577
|
|
|
578
578
|
other_calcs.append(
|
|
579
579
|
{
|
|
580
|
-
"is_static":
|
|
581
|
-
|
|
582
|
-
|
|
580
|
+
"is_static": (
|
|
581
|
+
True if "Static" in mat["task_types"][task_id] else False
|
|
582
|
+
),
|
|
583
583
|
"task_id": task_id,
|
|
584
584
|
"is_hubbard": int(is_hubbard),
|
|
585
585
|
"nkpoints": int(nkpoints),
|
|
@@ -640,9 +640,9 @@ class ElectronicStructureBuilder(Builder):
|
|
|
640
640
|
bs_obj["data"] if bs_obj is not None else None
|
|
641
641
|
)
|
|
642
642
|
|
|
643
|
-
materials_doc["bandstructure"][bs_type][
|
|
644
|
-
"output_structure"
|
|
645
|
-
|
|
643
|
+
materials_doc["bandstructure"][bs_type]["output_structure"] = (
|
|
644
|
+
sorted_bs_data[0]["output_structure"]
|
|
645
|
+
)
|
|
646
646
|
|
|
647
647
|
materials_doc["origins"].append(
|
|
648
648
|
{
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from math import ceil
|
|
2
|
-
from typing import Dict, Iterator, Optional
|
|
3
4
|
|
|
4
5
|
from maggma.builders import Builder
|
|
5
6
|
from maggma.stores import Store
|
|
@@ -7,8 +8,14 @@ from maggma.utils import grouper
|
|
|
7
8
|
from pymatgen.core.structure import Structure
|
|
8
9
|
|
|
9
10
|
from emmet.core.magnetism import MagnetismDoc
|
|
11
|
+
from emmet.core.mpid import AlphaID
|
|
10
12
|
from emmet.core.utils import jsanitize
|
|
11
13
|
|
|
14
|
+
from typing import TYPE_CHECKING
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from collections.abc import Iterator
|
|
18
|
+
|
|
12
19
|
__author__ = "Shyam Dwaraknath <shyamd@lbl.gov>, Matthew Horton <mkhorton@lbl.gov>"
|
|
13
20
|
|
|
14
21
|
|
|
@@ -18,7 +25,7 @@ class MagneticBuilder(Builder):
|
|
|
18
25
|
materials: Store,
|
|
19
26
|
magnetism: Store,
|
|
20
27
|
tasks: Store,
|
|
21
|
-
query:
|
|
28
|
+
query: dict | None = None,
|
|
22
29
|
**kwargs,
|
|
23
30
|
):
|
|
24
31
|
"""
|
|
@@ -42,7 +49,7 @@ class MagneticBuilder(Builder):
|
|
|
42
49
|
|
|
43
50
|
super().__init__(sources=[materials, tasks], targets=[magnetism], **kwargs)
|
|
44
51
|
|
|
45
|
-
def prechunk(self, number_splits: int) -> Iterator[
|
|
52
|
+
def prechunk(self, number_splits: int) -> Iterator[dict]: # pragma: no cover
|
|
46
53
|
"""
|
|
47
54
|
Prechunk method to perform chunking by the key field
|
|
48
55
|
"""
|
|
@@ -131,7 +138,7 @@ class MagneticBuilder(Builder):
|
|
|
131
138
|
|
|
132
139
|
for origin in mat_doc["origins"]:
|
|
133
140
|
if origin["name"] == "structure":
|
|
134
|
-
task_id = origin["task_id"]
|
|
141
|
+
task_id = str(AlphaID(origin["task_id"]))
|
|
135
142
|
|
|
136
143
|
task_query = self.tasks.query_one(
|
|
137
144
|
properties=["last_updated", "calcs_reversed"],
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from math import ceil
|
|
2
|
-
from typing import Dict, Iterator, Optional
|
|
3
2
|
|
|
4
3
|
from maggma.builders import Builder
|
|
5
4
|
from maggma.core import Store
|
|
@@ -9,6 +8,11 @@ from pymatgen.core.structure import Structure
|
|
|
9
8
|
from emmet.core.optimade import OptimadeMaterialsDoc
|
|
10
9
|
from emmet.core.utils import jsanitize
|
|
11
10
|
|
|
11
|
+
from typing import TYPE_CHECKING
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from collections.abc import Iterator
|
|
15
|
+
|
|
12
16
|
|
|
13
17
|
class OptimadeMaterialsBuilder(Builder):
|
|
14
18
|
def __init__(
|
|
@@ -16,7 +20,7 @@ class OptimadeMaterialsBuilder(Builder):
|
|
|
16
20
|
materials: Store,
|
|
17
21
|
thermo: Store,
|
|
18
22
|
optimade: Store,
|
|
19
|
-
query:
|
|
23
|
+
query: dict | None = None,
|
|
20
24
|
**kwargs,
|
|
21
25
|
):
|
|
22
26
|
"""
|
|
@@ -42,7 +46,7 @@ class OptimadeMaterialsBuilder(Builder):
|
|
|
42
46
|
|
|
43
47
|
super().__init__(sources=[materials, thermo], targets=optimade, **kwargs)
|
|
44
48
|
|
|
45
|
-
def prechunk(self, number_splits: int) -> Iterator[
|
|
49
|
+
def prechunk(self, number_splits: int) -> Iterator[dict]: # pragma: no cover
|
|
46
50
|
"""
|
|
47
51
|
Prechunk method to perform chunking by the key field
|
|
48
52
|
"""
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from math import ceil
|
|
2
|
-
from typing import Dict, Optional
|
|
3
2
|
|
|
4
3
|
import numpy as np
|
|
5
4
|
from maggma.builders import Builder
|
|
@@ -8,6 +7,7 @@ from maggma.utils import grouper
|
|
|
8
7
|
from pymatgen.core.structure import Structure
|
|
9
8
|
|
|
10
9
|
from emmet.core.polar import PiezoelectricDoc
|
|
10
|
+
from emmet.core.mpid import AlphaID
|
|
11
11
|
from emmet.core.utils import jsanitize
|
|
12
12
|
|
|
13
13
|
|
|
@@ -17,7 +17,7 @@ class PiezoelectricBuilder(Builder):
|
|
|
17
17
|
materials: Store,
|
|
18
18
|
tasks: Store,
|
|
19
19
|
piezoelectric: Store,
|
|
20
|
-
query:
|
|
20
|
+
query: dict | None = None,
|
|
21
21
|
**kwargs,
|
|
22
22
|
):
|
|
23
23
|
self.materials = materials
|
|
@@ -190,20 +190,19 @@ class PiezoelectricBuilder(Builder):
|
|
|
190
190
|
"last_updated",
|
|
191
191
|
"input.is_hubbard",
|
|
192
192
|
"orig_inputs.kpoints",
|
|
193
|
-
"orig_inputs.
|
|
193
|
+
"orig_inputs.structure",
|
|
194
194
|
"input.parameters",
|
|
195
195
|
"input.structure",
|
|
196
|
-
"
|
|
197
|
-
"output.piezo_ionic_tensor",
|
|
196
|
+
"calcs_reversed",
|
|
198
197
|
"output.bandgap",
|
|
199
198
|
],
|
|
200
|
-
criteria={self.tasks.key: str(task_id)},
|
|
199
|
+
criteria={self.tasks.key: str(AlphaID(task_id))},
|
|
201
200
|
)
|
|
202
201
|
if task_query["output"]["bandgap"] > 0:
|
|
203
202
|
try:
|
|
204
|
-
structure = task_query["orig_inputs"]["poscar"]["structure"]
|
|
205
|
-
except KeyError:
|
|
206
203
|
structure = task_query["input"]["structure"]
|
|
204
|
+
except KeyError:
|
|
205
|
+
structure = task_query["orig_inputs"]["structure"]
|
|
207
206
|
|
|
208
207
|
is_hubbard = task_query["input"]["is_hubbard"]
|
|
209
208
|
|
|
@@ -223,19 +222,23 @@ class PiezoelectricBuilder(Builder):
|
|
|
223
222
|
lu_dt = mat_doc["last_updated"]
|
|
224
223
|
task_updated = task_query["last_updated"]
|
|
225
224
|
|
|
226
|
-
|
|
227
|
-
{
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
225
|
+
if (cr := task_query.get("calcs_reversed", [])) and (
|
|
226
|
+
outcar := cr[0].get("output", {}).get("outcar", {})
|
|
227
|
+
):
|
|
228
|
+
|
|
229
|
+
final_docs.append(
|
|
230
|
+
{
|
|
231
|
+
"task_id": task_id,
|
|
232
|
+
"is_hubbard": int(is_hubbard),
|
|
233
|
+
"nkpoints": int(nkpoints),
|
|
234
|
+
"piezo_static": outcar.get("piezo_tensor"),
|
|
235
|
+
"piezo_ionic": outcar.get("piezo_ionic_tensor"),
|
|
236
|
+
"structure": structure,
|
|
237
|
+
"updated_on": lu_dt,
|
|
238
|
+
"task_updated": task_updated,
|
|
239
|
+
self.materials.key: mat_doc[self.materials.key],
|
|
240
|
+
}
|
|
241
|
+
)
|
|
239
242
|
|
|
240
243
|
if len(final_docs) > 0:
|
|
241
244
|
sorted_final_docs = sorted(
|