Skip to content

Commit

Permalink
Preprocess Structure Reduction Before Bulk Match (#4137)
Browse files Browse the repository at this point in the history
The `AflowPrototypeMatcher` matches a structure against predefined AFLOW
prototype structures using `StructureMatcher`. `StructureMatcher` requires
preprocessing via lattice reduction and primitive-cell conversion. This commit
optimizes performance by preprocessing AFLOW prototype structures during the
initialization of `AflowPrototypeMatcher`. This change eliminates redundant
processing when `AflowPrototypeMatcher.get_prototypes` is called multiple times.

Co-authored-by: Shyue Ping Ong <[email protected]>
  • Loading branch information
lan496 and shyuep authored Nov 12, 2024
1 parent dc9a97d commit 5066870
Showing 1 changed file with 21 additions and 7 deletions.
28 changes: 21 additions & 7 deletions src/pymatgen/analysis/prototypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from pymatgen.util.due import Doi, due

if TYPE_CHECKING:
from pymatgen.core import Structure
from pymatgen.core.structure import Structure

MODULE_DIR = os.path.dirname(os.path.abspath(__file__))
AFLOW_PROTOTYPE_LIBRARY = loadfn(f"{MODULE_DIR}/aflow_prototypes.json")
Expand Down Expand Up @@ -62,12 +62,24 @@ def __init__(self, initial_ltol=0.2, initial_stol=0.3, initial_angle_tol=5):
self.initial_stol = initial_stol
self.initial_angle_tol = initial_angle_tol

# Preprocess AFLOW prototypes
self._aflow_prototype_library = []
for dct in AFLOW_PROTOTYPE_LIBRARY:
structure: Structure = dct["snl"].structure
reduced_structure = self._preprocess_structure(structure)
self._aflow_prototype_library.append((reduced_structure, dct))

@staticmethod
def _match_prototype(structure_matcher, structure):
def _preprocess_structure(structure: Structure) -> Structure:
return structure.get_reduced_structure(reduction_algo="niggli").get_primitive_structure()

def _match_prototype(self, structure_matcher: StructureMatcher, reduced_structure: Structure):
tags = []
for dct in AFLOW_PROTOTYPE_LIBRARY:
struct = dct["snl"].structure
match = structure_matcher.fit_anonymous(struct, structure)
for aflow_reduced_structure, dct in self._aflow_prototype_library:
# Since both structures are already reduced, we can skip the structure reduction step
match = structure_matcher.fit_anonymous(
aflow_reduced_structure, reduced_structure, skip_structure_reduction=True
)
if match:
tags.append(dct)
return tags
Expand All @@ -77,13 +89,15 @@ def _match_single_prototype(self, structure: Structure):
ltol=self.initial_ltol,
stol=self.initial_stol,
angle_tol=self.initial_angle_tol,
primitive_cell=True,
)
tags = self._match_prototype(sm, structure)
reduced_structure = self._preprocess_structure(structure)
tags = self._match_prototype(sm, reduced_structure)
while len(tags) > 1:
sm.ltol *= 0.8
sm.stol *= 0.8
sm.angle_tol *= 0.8
tags = self._match_prototype(sm, structure)
tags = self._match_prototype(sm, reduced_structure)
if sm.ltol < 0.01:
break
return tags
Expand Down

0 comments on commit 5066870

Please sign in to comment.