From 7b3c57fb4aca0a49addc0ccc25b8841f87c0e018 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 27 Aug 2024 11:19:02 -0500 Subject: [PATCH 1/7] Squashed profile commits that mat_optimize had --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0bbb6347..821d4633 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -160,6 +160,7 @@ jobs: - run: python benchmark/benchmark_big_model.py name: Benchmark against big model + changelog-test: runs-on: ubuntu-latest if: github.ref != 'refs/heads/main' From f1a211814702c3c8f6ab2d58dcdfc1d0072a4f4a Mon Sep 17 00:00:00 2001 From: Micah Gale Date: Tue, 27 Aug 2024 20:14:46 -0500 Subject: [PATCH 2/7] Made mechanism for data inputs to flag self for deletion. --- montepy/data_inputs/data_input.py | 2 ++ montepy/mcnp_problem.py | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/montepy/data_inputs/data_input.py b/montepy/data_inputs/data_input.py index 80b0fd59..f6cf97f9 100644 --- a/montepy/data_inputs/data_input.py +++ b/montepy/data_inputs/data_input.py @@ -179,6 +179,8 @@ def update_pointers(self, data_inputs): :param data_inputs: a list of the data inputs in the problem :type data_inputs: list + :returns: True iff this input should be removed from ``problem.data_inputs`` + :rtype: bool, None """ pass diff --git a/montepy/mcnp_problem.py b/montepy/mcnp_problem.py index cbdd05ed..2f1ae98b 100644 --- a/montepy/mcnp_problem.py +++ b/montepy/mcnp_problem.py @@ -332,9 +332,11 @@ def handle_error(e): ParticleTypeNotInCell, ) as e: handle_error(e) - for input in self._data_inputs: + to_delete = [] + for data_index, data_input in enumerate(self._data_inputs): try: - input.update_pointers(self._data_inputs) + if data_input.update_pointers(self._data_inputs): + to_delete.append(data_index) except ( BrokenObjectLinkError, MalformedInputError, @@ -343,6 +345,8 @@ def handle_error(e): ) as e: handle_error(e) continue + for delete_index in to_delete[::-1]: + del self._data_inputs[delete_index] def remove_duplicate_surfaces(self, tolerance): """Finds duplicate surfaces in the problem, and remove them. From 7ffa07345ab74a4a41659583fa499f14a5ab51f3 Mon Sep 17 00:00:00 2001 From: Micah Gale Date: Tue, 27 Aug 2024 20:15:36 -0500 Subject: [PATCH 3/7] Moved material linking to thermal_scattering with hashing. --- montepy/data_inputs/material.py | 13 +--------- montepy/data_inputs/thermal_scattering.py | 31 +++++++++++++++++++---- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/montepy/data_inputs/material.py b/montepy/data_inputs/material.py index a6fe2c04..0c754e95 100644 --- a/montepy/data_inputs/material.py +++ b/montepy/data_inputs/material.py @@ -177,18 +177,7 @@ def update_pointers(self, data_inputs): :param data_inputs: a list of the data inputs in the problem :type data_inputs: list """ - for input in list(data_inputs): - if isinstance(input, thermal_scattering.ThermalScatteringLaw): - if input.old_number == self.number: - if not self._thermal_scattering: - self._thermal_scattering = input - input._parent_material = self - data_inputs.remove(input) - else: - raise MalformedInputError( - self, - f"Multiple MT inputs were specified for this material: {self.number}.", - ) + pass @staticmethod def _class_prefix(): diff --git a/montepy/data_inputs/thermal_scattering.py b/montepy/data_inputs/thermal_scattering.py index 4f5bd5d6..c52b083a 100644 --- a/montepy/data_inputs/thermal_scattering.py +++ b/montepy/data_inputs/thermal_scattering.py @@ -122,19 +122,40 @@ def update_pointers(self, data_inputs): :param data_inputs: a list of the data inputs in the problem :type data_inputs: list + :returns: True iff this input should be removed from ``problem.data_inputs`` + :rtype: bool """ + # use caching first + if self._problem: + try: + mat = self._problem.materials[self.old_number] + except KeyError: + raise MalformedInputError( + self._input, "MT input is detached from a parent material" + ) + # brute force it found = False - for input in data_inputs: - if isinstance(input, montepy.data_inputs.material.Material): - if input.number == self.old_number: + for data_input in data_inputs: + if isinstance(data_input, montepy.data_inputs.material.Material): + if data_input.number == self.old_number: + mat = data_input found = True - self._parent_material = input - + break + # actually update things if not found: raise MalformedInputError( self._input, "MT input is detached from a parent material" ) + if mat.thermal_scattering: + raise MalformedInputError( + self, + f"Multiple MT inputs were specified for this material: {self.old_number}.", + ) + mat.thermal_scattering = self + self._parent_material = mat + return True + def __str__(self): return f"THERMAL SCATTER: {self.thermal_scattering_laws}" From ee67149dd4ef1814cf5209530f4abe3c9ba17f88 Mon Sep 17 00:00:00 2001 From: Micah Gale Date: Tue, 27 Aug 2024 20:16:24 -0500 Subject: [PATCH 4/7] Changed how thermal scattering linking occurs in test. --- tests/test_material.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_material.py b/tests/test_material.py index 86d15bad..603b92c7 100644 --- a/tests/test_material.py +++ b/tests/test_material.py @@ -340,7 +340,8 @@ def test_thermal_scattering_format_mcnp(self): in_str = "M20 1001.80c 0.5 8016.80c 0.5" input_card = Input([in_str], BlockType.DATA) material = Material(input_card) - material.update_pointers([card]) + material.thermal_scattering = card + card._parent_material = material material.thermal_scattering.thermal_scattering_laws = ["grph.20t"] self.assertEqual(card.format_for_mcnp_input((6, 2, 0)), ["Mt20 grph.20t "]) From 3f248a93385f7fcc537ec31045336142040386d3 Mon Sep 17 00:00:00 2001 From: Micah Gale Date: Tue, 27 Aug 2024 20:20:55 -0500 Subject: [PATCH 5/7] Seriously lowered the benchmark threshold --- benchmark/benchmark_big_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/benchmark_big_model.py b/benchmark/benchmark_big_model.py index 89d1d4ad..26af2a9b 100644 --- a/benchmark/benchmark_big_model.py +++ b/benchmark/benchmark_big_model.py @@ -3,7 +3,7 @@ import time import tracemalloc -FAIL_THRESHOLD = 500 +FAIL_THRESHOLD = 30 tracemalloc.start() start = time.time() From ff6144757c49a5257d2e7022d9d3a7db1692c586 Mon Sep 17 00:00:00 2001 From: Micah Gale Date: Tue, 27 Aug 2024 20:24:39 -0500 Subject: [PATCH 6/7] Added #510 to changelog. --- doc/source/changelog.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index 0cda72cb..530c536c 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -1,6 +1,13 @@ MontePy Changelog ================= +#Next Version# +-------------- + +**Performance Improvement** + +* Fixed method of linking ``Material`` to ``ThermalScattering`` objects, avoiding a very expensive O(N:sup:`2`) (:issue:`510`). + 0.4.0 -------------- From 05a9bcee64cd93db4a30891aac3611b7c9394911 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Wed, 28 Aug 2024 07:28:36 -0500 Subject: [PATCH 7/7] Switched order of filters to make sense. --- prof/dump_results.py | 4 ++-- prof/profile_big_model.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/prof/dump_results.py b/prof/dump_results.py index fa9f9a53..75beede4 100644 --- a/prof/dump_results.py +++ b/prof/dump_results.py @@ -2,5 +2,5 @@ from pstats import SortKey stats = pstats.Stats("prof/combined.prof") -stats.sort_stats(SortKey.CUMULATIVE, SortKey.TIME).print_stats(300, "montepy") -stats.sort_stats(SortKey.CUMULATIVE, SortKey.TIME).print_stats(100, "sly") +stats.sort_stats(SortKey.CUMULATIVE, SortKey.TIME).print_stats("montepy", 50) +stats.sort_stats(SortKey.CUMULATIVE, SortKey.TIME).print_stats("sly", 20) diff --git a/prof/profile_big_model.py b/prof/profile_big_model.py index b9701f39..8998d069 100644 --- a/prof/profile_big_model.py +++ b/prof/profile_big_model.py @@ -10,6 +10,6 @@ stats = pstats.Stats("prof/big.prof") stats.sort_stats(pstats.SortKey.CUMULATIVE, pstats.SortKey.TIME).print_stats( - 100, "montepy" + "montepy", 70 ) -stats.sort_stats(pstats.SortKey.CUMULATIVE, pstats.SortKey.TIME).print_stats(100, "sly") +stats.sort_stats(pstats.SortKey.CUMULATIVE, pstats.SortKey.TIME).print_stats("sly", 20)