From 58a6d9c96240d24faafabd82fcaefc37af47b10e Mon Sep 17 00:00:00 2001 From: mikibonacci Date: Mon, 23 Sep 2024 16:26:00 +0000 Subject: [PATCH] Ensuring performance for the supercell estimation - update the number of supercell only when all the three vectors are updated (from hint) or reset - we provide also spinning loading icon when we compute the number of supercells. - missing: symprec integration. --- src/aiidalab_qe_vibroscopy/app/settings.py | 142 ++++++++++++++++----- 1 file changed, 113 insertions(+), 29 deletions(-) diff --git a/src/aiidalab_qe_vibroscopy/app/settings.py b/src/aiidalab_qe_vibroscopy/app/settings.py index b400fe7..be88215 100644 --- a/src/aiidalab_qe_vibroscopy/app/settings.py +++ b/src/aiidalab_qe_vibroscopy/app/settings.py @@ -14,14 +14,49 @@ from aiidalab_qe.common.panel import Panel from IPython.display import clear_output, display + import sys import os + +from aiida.plugins import CalculationFactory, DataFactory, WorkflowFactory + +HubbardStructureData = DataFactory("quantumespresso.hubbard_structure") + +# spinner for waiting time (supercell estimations) +spinner_html = """ + +
+
+
+""" + + def disable_print(func): def wrapper(*args, **kwargs): # Save the current standard output original_stdout = sys.stdout # Redirect standard output to os.devnull - sys.stdout = open(os.devnull, 'w') + sys.stdout = open(os.devnull, "w") try: # Call the function result = func(*args, **kwargs) @@ -30,6 +65,7 @@ def wrapper(*args, **kwargs): sys.stdout.close() sys.stdout = original_stdout return result + return wrapper @@ -149,7 +185,7 @@ def change_supercell(_=None): ) # supercell hint (15A lattice params) self.supercell_hint_button.on_click(self._suggest_supercell) - + # reset supercell self.supercell_reset_button = ipw.Button( description="Reset", @@ -159,13 +195,13 @@ def change_supercell(_=None): ) # supercell reset reaction self.supercell_reset_button.on_click(self._reset_supercell) - + # Estimate the number of supercells for frozen phonons. self.supercell_number_estimator = ipw.HTML( - description="Number of supercells to be computed:", - value = "0", - style={"description_width": "initial"}, - ) + description="Number of supercells to be computed:", + value="0", + style={"description_width": "initial"}, + ) ## end supercell hint. @@ -174,11 +210,11 @@ def change_supercell(_=None): self.hint_button_help, ipw.HBox( [ - self.supercell_selector, - self.supercell_hint_button, + self.supercell_selector, + self.supercell_hint_button, self.supercell_number_estimator, self.supercell_reset_button, - ], + ], ), ] ) @@ -213,6 +249,11 @@ def change_supercell(_=None): super().__init__(**kwargs) + # we define a block for the estimation of the supercell if we ask for hint, + # so that we call the estimator at the end (we don't lose time). + # see the methods below. + self.block = False + @tl.observe("input_structure") def _update_input_structure(self, change): if self.input_structure is not None: @@ -238,13 +279,18 @@ def _suggest_supercell(self, _=None): suggested_3D = 15 // np.array(s.cell.cellpar()[:3]) + 1 # if disabled, it means that it is a non-periodic direction. + # here we manually unobserve the `_estimate_supercells`, so it is faster + # and only compute when all the three directions are updated + self.block = True for direction, suggested, original in zip( [self._sc_x, self._sc_y, self._sc_z], suggested_3D, s.cell.cellpar()[:3] ): direction.value = suggested if not direction.disabled else 1 + self.block = False + self._estimate_supercells() else: return - + @tl.observe("input_structure") @disable_print def _estimate_supercells(self, _=None): @@ -252,28 +298,66 @@ def _estimate_supercells(self, _=None): Estimate the number of supercells to be computed for frozen phonon calculation. """ + if self.block: + return + + self.supercell_number_estimator.value = spinner_html + from aiida_phonopy.data.preprocess import PreProcessData - - supercells = PreProcessData( - structure=self.input_structure, - supercell_matrix=[ - [self._sc_x.value, 0, 0], - [0, self._sc_y.value, 0], - [0, 0, self._sc_z.value]], - symprec=1e-5, - distinguish_kinds=False, - is_symmetry=True, - ).get_supercells_with_displacements() - - self.supercell_number_estimator.value = f"{len(supercells)}" - - return + + if self.input_structure: + preprocess_data = PreProcessData( + structure=self.input_structure, + supercell_matrix=[ + [self._sc_x.value, 0, 0], + [0, self._sc_y.value, 0], + [0, 0, self._sc_z.value], + ], + symprec=1e-5, + distinguish_kinds=False, + is_symmetry=True, + ) + + supercells = preprocess_data.get_supercells_with_displacements() + + # for now, we comment the following part, as the HubbardSD is generated in the submission step. + """if isinstance(self.input_structure, HubbardStructureData): + from aiida_vibroscopy.calculations.spectra_utils import get_supercells_for_hubbard + from aiida_vibroscopy.workflows.phonons.base import get_supercell_hubbard_structure + supercell = get_supercell_hubbard_structure( + self.input_structure, + self.input_structure, + metadata={"store_provenance": False}, + ) + supercells = get_supercells_for_hubbard( + preprocess_data=preprocess_data, + ref_structure=supercell, + metadata={"store_provenance": False}, + ) + + else: + supercells = preprocess_data.get_supercells_with_displacements() + """ + self.supercell_number_estimator.value = f"{len(supercells)}" + + return def _reset_supercell(self, _=None): - for direction in [self._sc_x, self._sc_y, self._sc_z]: - direction.value = 2 + if self.input_structure is not None: + reset_supercell = [] + self.block = True + for direction, periodic in zip( + [self._sc_x, self._sc_y, self._sc_z], self.input_structure.pbc + ): + if periodic: + reset_supercell.append(2) + else: + reset_supercell.append(1) + (self._sc_x.value, self._sc_y.value, self._sc_z.value) = reset_supercell + self.block = False + self._estimate_supercells() return - + def get_panel_value(self): """Return a dictionary with the input parameters for the plugin.""" return {