From 7f99a398fc42526f966dcd60bd013c3fc2d2eb89 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Fri, 3 Jul 2026 16:37:12 -0700 Subject: [PATCH 1/2] update: optimize O(n) -> O(1) --- .../crystal_site/crystal_site.py | 5 +++-- .../point_defect_site/builder.py | 21 ++++++++++--------- .../core/combinations/merge/builder.py | 9 ++++++++ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/py/mat3ra/made/tools/build_components/entities/auxiliary/zero_dimensional/crystal_site/crystal_site.py b/src/py/mat3ra/made/tools/build_components/entities/auxiliary/zero_dimensional/crystal_site/crystal_site.py index f132151cc..63d838f55 100644 --- a/src/py/mat3ra/made/tools/build_components/entities/auxiliary/zero_dimensional/crystal_site/crystal_site.py +++ b/src/py/mat3ra/made/tools/build_components/entities/auxiliary/zero_dimensional/crystal_site/crystal_site.py @@ -6,13 +6,14 @@ CrystalSiteSchema, ) from mat3ra.made.material import Material +from pydantic import Field class CrystalSite(CrystalSiteSchema, InMemoryEntityPydantic): - crystal: Optional[Material] = None + crystal: Optional[Material] = Field(None, exclude=True) # element: str coordinate: Optional[List[float]] = None - nearest_neighbor_vectors: List[np.ndarray] = [] + nearest_neighbor_vectors: List[np.ndarray] = Field([], exclude=True) # coordination_number: int = 0 # see https://www.cryst.ehu.es/cgi-bin/cryst/programs/nph-wp-list for an example diff --git a/src/py/mat3ra/made/tools/build_components/entities/auxiliary/zero_dimensional/point_defect_site/builder.py b/src/py/mat3ra/made/tools/build_components/entities/auxiliary/zero_dimensional/point_defect_site/builder.py index ef9079acf..3adae33a5 100644 --- a/src/py/mat3ra/made/tools/build_components/entities/auxiliary/zero_dimensional/point_defect_site/builder.py +++ b/src/py/mat3ra/made/tools/build_components/entities/auxiliary/zero_dimensional/point_defect_site/builder.py @@ -1,3 +1,6 @@ +from mat3ra.code.array_with_ids import ArrayWithIds +from mat3ra.made.basis import Basis, Coordinates + from ......build_components import MaterialWithBuildMetadata from ..... import BaseSingleBuilder from .configuration import PointDefectSiteConfiguration @@ -14,18 +17,16 @@ def _generate(self, configuration: PointDefectSiteConfiguration) -> MaterialWith if configuration.crystal is None: raise ValueError("Crystal configuration is required for PointDefectSiteBuilder") - new_material = MaterialWithBuildMetadata.create( - { - "name": configuration.crystal.name, - "lattice": configuration.crystal.lattice.to_dict(), - "basis": configuration.crystal.basis.to_dict(), - } + crystal = configuration.crystal + basis = Basis( + elements=ArrayWithIds(values=[], ids=[]), + coordinates=Coordinates(values=[], ids=[]), + units=crystal.basis.units, + cell=crystal.basis.cell, ) - elements = configuration.crystal.basis.elements.values - new_material.basis.remove_atoms_by_elements(elements) - new_material.basis.add_atom( + basis.add_atom( element=configuration.element.chemical_element, coordinate=configuration.coordinate, label=configuration.host_atom_label, ) - return new_material + return MaterialWithBuildMetadata(name=crystal.name, lattice=crystal.lattice, basis=basis) diff --git a/src/py/mat3ra/made/tools/build_components/operations/core/combinations/merge/builder.py b/src/py/mat3ra/made/tools/build_components/operations/core/combinations/merge/builder.py index 8760b49de..4edec9b27 100644 --- a/src/py/mat3ra/made/tools/build_components/operations/core/combinations/merge/builder.py +++ b/src/py/mat3ra/made/tools/build_components/operations/core/combinations/merge/builder.py @@ -79,6 +79,15 @@ def _generate(self, configuration: TypeConfiguration) -> MaterialWithBuildMetada if len(materials) == 1: return materials[0] + # Optimization: when there are many materials to merge, combine all non-first + # materials into one before merging with the base to avoid N sequential merges. + if len(materials) > 2: + base = materials[0] + combined = materials[1] + for m in materials[2:]: + combined.basis.add_atoms_from_another_basis(m.basis) + materials = [base, combined] + parameters = self.build_parameters or self._DefaultBuildParameters merge_method = getattr(configuration, "merge_method", None) return self._merge_by_method(materials, parameters, merge_method) From 30022749e9d7a3cbbcaaecf23428a33115fce6fe Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Fri, 3 Jul 2026 16:39:13 -0700 Subject: [PATCH 2/2] update: fix non-existant --- src/py/mat3ra/made/basis/__init__.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/py/mat3ra/made/basis/__init__.py b/src/py/mat3ra/made/basis/__init__.py index 5ab6f20db..7f1f94f16 100644 --- a/src/py/mat3ra/made/basis/__init__.py +++ b/src/py/mat3ra/made/basis/__init__.py @@ -175,9 +175,12 @@ def add_atoms_from_another_basis(self, other_basis: "Basis"): other_basis (Basis): The other basis to add atoms from. """ - self.elements.add_items(other_basis.elements.values) - self.coordinates.add_items(other_basis.coordinates.values) - self.labels.add_items(other_basis.labels.values) + for el in other_basis.elements.values: + self.elements.add_item(el) + for coord in other_basis.coordinates.values: + self.coordinates.add_item(coord) + for label in other_basis.labels.values: + self.labels.add_item(label) def remove_atom_by_id(self, id: int): self.elements.remove_item(id)