Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Elasticity doc and builder #326

Merged
merged 67 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
ac9aaff
Init elastic doc
mjwen Sep 24, 2021
7459d03
Add typing and description all fields
mjwen Sep 24, 2021
e153604
Add builder for elasticity
mjwen Dec 2, 2021
b68b107
Fix task_id from str to int; a working Builder!!!
mjwen Dec 2, 2021
d4814a1
Commented out unnecessary functions
mjwen Dec 2, 2021
0843c14
Use elastic doc in building
mjwen Dec 3, 2021
a8d9b3b
Reorganize elastic doc to make derived property a separate field
mjwen Dec 3, 2021
299e3c1
Add structure to elastic doc
mjwen Dec 29, 2021
2d49377
Group by lattice and filter incar params
mjwen Dec 30, 2021
e63983f
Add more fields to elasticity doc
mjwen Dec 30, 2021
aca93c2
Update ElasticityDoc to standardize fields
mjwen Dec 31, 2021
6c54c5d
Rename docs
mjwen Dec 31, 2021
f98bd9a
Add filters to elastic builder
mjwen Dec 31, 2021
0d25b25
Finished version of elastic builder
mjwen Dec 31, 2021
3c6d7b8
Use emmet jsanitize instead of that from monty
mjwen Dec 31, 2021
3643c9c
Fix typos
mjwen Dec 31, 2021
43f4415
Add state and warnings
mjwen Jan 3, 2022
f7ae350
Add origins
mjwen Jan 3, 2022
45263d5
Add connect() in process_item to make `mrun` work
mjwen Jan 4, 2022
5d726e0
Move query from tasks of the same material to get_items()
mjwen Jan 4, 2022
f4e3172
Move task label below
mjwen Mar 29, 2022
ccbb358
Merge branch 'main' into elastic
mjwen Mar 29, 2022
6171480
Update a few docstrings
mjwen Mar 29, 2022
5185eb0
Make `fitting_method` an argument of builder
mjwen Mar 29, 2022
969aafe
Fix mypy warnings
mjwen Mar 29, 2022
177dbb4
Split derived properties into multiple subcategories
mjwen May 4, 2022
f15fd93
Move Status to common.py to share it
mjwen May 4, 2022
0233d9f
Fix vector and matrix 3d to be tuples
mjwen May 5, 2022
171621a
Move all fitting code from elastic builder to doc
mjwen May 5, 2022
96cece1
Update builder to use new doc
mjwen May 5, 2022
cf5428a
Fix not invertable compliance tensor
mjwen May 5, 2022
de8c77c
Fix error message
mjwen May 5, 2022
0fb9563
Add filter by calc type and filter by incar settings
mjwen May 9, 2022
3a4af7f
Finish builder
mjwen May 10, 2022
41be77c
Fix calc_types
mjwen May 10, 2022
4e2ea3a
Delete old unused functions
mjwen May 10, 2022
2828764
Gather warnings/critical together
mjwen May 10, 2022
9f4df76
Put fit tensor and compliance tensor in different try block
mjwen May 11, 2022
4423944
Add optimized structure to elastic doc
mjwen May 11, 2022
3240b1a
Fix: add tol=0.002 for deform independence, and is_upper_triangular c…
mjwen May 12, 2022
ba16c37
Fix tolerance to 0.002 for deformation comparison
mjwen May 12, 2022
56b1966
Fix units for Young's modulus
mjwen May 12, 2022
f029735
Fix group by lattice docs x
mjwen May 12, 2022
003e2d4
Add total number of strain stress states to fitting data
mjwen May 12, 2022
4448cef
Early return if task type does not match
mjwen May 12, 2022
15a6379
Major: change to get derived data using strain from deform, to get aw…
mjwen May 13, 2022
d0c584b
Update warning message
mjwen May 13, 2022
0e5943f
Better error message
mjwen May 13, 2022
706e413
For failed status ones, set deprecated to True
mjwen May 17, 2022
68670f6
Add more docstring
mjwen May 24, 2022
101a233
Add elasticiy core test files
mjwen May 24, 2022
3119b63
Add tests for elasticity doc
mjwen May 24, 2022
29cb21f
Fix materials builder to use input.structure for deformation task
mjwen May 26, 2022
c97f0b9
Add elastic builder test
mjwen May 26, 2022
c37a0e4
Cleanup docstring of elastic doc
mjwen May 27, 2022
ee9c7e8
Set material id to the id of the optimization task used for fitting t…
mjwen May 27, 2022
e198532
Fix using undeformed structure in material builder
mjwen May 27, 2022
9915c44
String format
mjwen May 31, 2022
9d8b3f3
Merge branch 'main' of github.com:materialsproject/emmet into materia…
mjwen May 31, 2022
a999fcd
Merge branch 'materialsproject-main' into elastic
mjwen May 31, 2022
7bd2cb6
Add material_id index to elasticity collection
Jun 1, 2022
6b60794
Reverse the deformations to get undeformed structure in MaterialBuilder
mjwen Jun 2, 2022
a38a80e
Fix ValueEnum import error
mjwen Jun 2, 2022
00acf5f
Fix material_id
mjwen Jun 2, 2022
bbdf714
Adjust warning messages, specifically remove unnecessary checking for…
mjwen Jun 2, 2022
fe3adb1
Fix typing for mypy
mjwen Jun 6, 2022
a5f6b36
Fix mypy errors
mjwen Jun 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
474 changes: 474 additions & 0 deletions emmet-builders/emmet/builders/materials/elasticity.py

Large diffs are not rendered by default.

112 changes: 81 additions & 31 deletions emmet-builders/emmet/builders/vasp/materials.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
from datetime import datetime
from itertools import chain
from math import ceil
from typing import Dict, Iterable, Iterator, List, Optional
from typing import Dict, Iterable, Iterator, List, Optional, Union

from maggma.builders import Builder
from maggma.stores import Store
from maggma.utils import grouper
from pymatgen.analysis.elasticity.strain import Deformation
from pymatgen.core.structure import Structure
from pymatgen.transformations.standard_transformations import (
DeformStructureTransformation,
)

from emmet.builders.settings import EmmetBuildSettings
from emmet.core.utils import group_structures, jsanitize
from emmet.core.vasp.calc_types import TaskType
from emmet.core.vasp.material import MaterialsDoc
from emmet.core.vasp.task_valid import TaskDocument

Expand All @@ -19,9 +25,9 @@

class MaterialsBuilder(Builder):
"""
The Materials Builder matches VASP task documents by structure similarity into materials
document. The purpose of this builder is group calculations and determine the best structure.
All other properties are derived from other builders.
The Materials Builder matches VASP task documents by structure similarity into
materials document. The purpose of this builder is group calculations and determine
the best structure. All other properties are derived from other builders.

The process is as follows:

Expand Down Expand Up @@ -117,17 +123,17 @@ def prechunk(self, number_splits: int) -> Iterable[Dict]: # pragma: no cover
def get_items(self) -> Iterator[List[Dict]]:
"""
Gets all items to process into materials documents.
This does no datetime checking; relying on on whether
task_ids are included in the Materials Colection
This does no datetime checking; relying on whether
task_ids are included in the Materials Collection

Returns:
generator or list relevant tasks and materials to process into materials documents
generator or list relevant tasks and materials to process into materials
documents
"""

task_types = [t.value for t in self.settings.VASP_ALLOWED_VASP_TYPES]
self.logger.info("Materials builder started")
self.logger.info(
f"Allowed task types: {[task_type.value for task_type in self.settings.VASP_ALLOWED_VASP_TYPES]}"
)
self.logger.info(f"Allowed task types: {task_types}")

self.logger.info("Setting indexes")
self.ensure_indexes()
Expand Down Expand Up @@ -187,13 +193,15 @@ def get_items(self) -> Iterator[List[Dict]]:
"calcs_reversed.input.parameters",
"calcs_reversed.input.incar",
"orig_inputs",
"input.structure",
# needed for entry from task_doc
"output.energy",
"input.is_hubbard",
"input.hubbards",
"input.potcar_spec",
# needed for transform deformation structure back for grouping
"transmuter",
# misc info for materials doc
"input.structure",
"tags",
]

Expand All @@ -213,18 +221,23 @@ def process_item(self, items: List[Dict]) -> List[Dict]:
Process the tasks into a list of materials

Args:
tasks [dict] : a list of task docs
tasks [dict]: a list of task docs

Returns:
([dict],list) : a list of new materials docs and a list of task_ids that were processsed
([dict],list): a list of new materials docs and a list of task_ids that
were processsed
"""

tasks = [TaskDocument(**task) for task in items]
formula = tasks[0].formula_pretty
task_ids = [task.task_id for task in tasks]
self.logger.debug(f"Processing {formula} : {task_ids}")

grouped_tasks = self.filter_and_group_tasks(tasks)
# not all tasks contains transmuter
transmuters = [task.get("transmuter", None) for task in items]

self.logger.debug(f"Processing {formula}: {task_ids}")

grouped_tasks = self.filter_and_group_tasks(tasks, transmuters)
materials = []
for group in grouped_tasks:
try:
Expand Down Expand Up @@ -254,8 +267,8 @@ def update_targets(self, items: List[List[Dict]]):
Inserts the new task_types into the task_types collection

Args:
items ([([dict],[int])]): A list of tuples of materials to update and the corresponding
processed task_ids
items ([([dict],[int])]): A list of tuples of materials to update and the
corresponding processed task_ids
"""

docs = list(chain.from_iterable(items)) # type: ignore
Expand All @@ -268,33 +281,38 @@ def update_targets(self, items: List[List[Dict]]):
if len(items) > 0:
self.logger.info(f"Updating {len(docs)} materials")
self.materials.remove_docs({self.materials.key: {"$in": material_ids}})
self.materials.update(
docs=docs,
key=["material_id"],
)
self.materials.update(docs=docs, key=["material_id"])
else:
self.logger.info("No items to update")

def filter_and_group_tasks(
self, tasks: List[TaskDocument]
self, tasks: List[TaskDocument], transmuters: List[Union[Dict, None]]
) -> Iterator[List[TaskDocument]]:
"""
Groups tasks by structure matching
"""

filtered_tasks = [
task
for task in tasks
filtered_tasks = []
filtered_transmuters = []
for task, transmuter in zip(tasks, transmuters):
if any(
allowed_type is task.task_type
allowed_type == task.task_type
for allowed_type in self.settings.VASP_ALLOWED_VASP_TYPES
)
]
):
filtered_tasks.append(task)
filtered_transmuters.append(transmuter)

structures = []

for idx, task in enumerate(filtered_tasks):
s = task.output.structure
for idx, (task, transmuter) in enumerate(
zip(filtered_tasks, filtered_transmuters)
):
if task.task_type == TaskType.Deformation:
if transmuter is None:
raise RuntimeError("Cannot find transmuter for deformation task")
else:
s = undeform_structure(task.input.structure, transmuter)
else:
s = task.output.structure
s.index: int = idx # type: ignore
structures.append(s)

Expand All @@ -308,3 +326,35 @@ def filter_and_group_tasks(
for group in grouped_structures:
grouped_tasks = [filtered_tasks[struc.index] for struc in group] # type: ignore
yield grouped_tasks


def undeform_structure(structure: Structure, transmuter: Dict) -> Structure:
"""
Get the undeformed structure by applying the transformations in a reverse order.

Args:
structure: deformed structure
transmuter: transformation that deforms the structure

Returns:
undeformed structure
"""

for trans, params in reversed(
list(zip(transmuter["transformations"], transmuter["transformation_params"]))
):

# The transmuter only stores the transformation class and parameter, without
# module info and such. Therefore, there is no general way to reconstruct it,
# and has to do if else check.
if trans == "DeformStructureTransformation":
deform = Deformation(params["deformation"])
dst = DeformStructureTransformation(deform.inv)
structure = dst.apply_transformation(structure)
else:
raise RuntimeError(
"Expect transformation to be `DeformStructureTransformation`; "
f"got {trans}"
)

return structure
10 changes: 10 additions & 0 deletions emmet-core/emmet/core/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from emmet.core.utils import ValueEnum


class Status(ValueEnum):
"""
State of a calculation/analysis.
"""

SUCCESS = "successful"
FAILED = "failed"
Loading