Skip to content

Commit

Permalink
logic to estimate supercell button
Browse files Browse the repository at this point in the history
  • Loading branch information
AndresOrtegaGuerrero committed Nov 29, 2024
1 parent 16b999d commit b18fe6d
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 139 deletions.
77 changes: 76 additions & 1 deletion src/aiidalab_qe_vibroscopy/app/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,41 @@
from aiidalab_qe.common.mixins import HasInputStructure
from aiidalab_qe.common.panel import ConfigurationSettingsModel

from aiida_phonopy.data.preprocess import PreProcessData
from aiida.plugins import DataFactory

HubbardStructureData = DataFactory("quantumespresso.hubbard_structure")
from aiida_vibroscopy.calculations.spectra_utils import get_supercells_for_hubbard
from aiida_vibroscopy.workflows.phonons.base import get_supercell_hubbard_structure

# spinner for waiting time (supercell estimations)
spinner_html = """
<style>
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.spinner {
display: inline-block;
width: 15px;
height: 15px;
}
.spinner div {
width: 100%;
height: 100%;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
}
</style>
<div class="spinner">
<div></div>
</div>
"""


class VibroConfigurationSettingsModel(ConfigurationSettingsModel, HasInputStructure):
dependencies = [
Expand Down Expand Up @@ -36,6 +71,7 @@ class VibroConfigurationSettingsModel(ConfigurationSettingsModel, HasInputStruct
trait=tl.Int(),
default_value=[2, 2, 2],
)
supercell_number_estimator = tl.Unicode("?")

def get_model_state(self):
return {
Expand All @@ -56,6 +92,9 @@ def reset(self):
self.symmetry_symprec = 1e-5
self.supercell = [2, 2, 2]
self.supercell_x, self.supercell_y, self.supercell_z = self.supercell
self.supercell_number_estimator = self._get_default(
"supercell_number_estimator"
)

def _get_default(self, trait):
return self._defaults.get(trait, self.traits()[trait].default_value)
Expand Down Expand Up @@ -102,7 +141,6 @@ def suggest_supercell(self, _=None):
# Sync the updated values to the supercell list
self.supercell = [self.supercell_x, self.supercell_y, self.supercell_z]

# self._activate_estimate_supercells()
else:
return

Expand All @@ -121,3 +159,40 @@ def reset_symprec(self, _=None):
if self.input_structure.pbc != (True, False, False)
else 1e-3
)
self.supercell_number_estimator = self._get_default(
"supercell_number_estimator"
)

def _estimate_supercells(self, _=None):
if self.input_structure:
self.supercell_number_estimator = spinner_html

preprocess_data = PreProcessData(
structure=self.input_structure,
supercell_matrix=[
[self.supercell_x, 0, 0],
[0, self.supercell_y, 0],
[0, 0, self.supercell_z],
],
symprec=self.symmetry_symprec,
distinguish_kinds=False,
is_symmetry=True,
)

if isinstance(self.input_structure, HubbardStructureData):
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 = f"{len(supercells)}"

return
167 changes: 29 additions & 138 deletions src/aiidalab_qe_vibroscopy/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,15 +223,6 @@ def render(self):
# supercell reset reaction
self.supercell_reset_button.on_click(self._model.supercell_reset)

# Estimate supercell button
self.supercell_estimate_button = ipw.Button(
description="Estimate number of supercells ➡",
disabled=False,
layout=ipw.Layout(width="240px", display="none"),
button_style="info",
tooltip="Number of supercells for phonons calculations;\nwarning: for large systems, this may take some time.",
)

self.symmetry_symprec_reset_button = ipw.Button(
description="Reset symprec",
disabled=False,
Expand All @@ -241,16 +232,27 @@ def render(self):
# supercell reset reaction
self.symmetry_symprec_reset_button.on_click(self._model.reset_symprec)

# supercell reset reaction
# self.supercell_estimate_button.on_click(self._estimate_supercells)

# Estimate the number of supercells for frozen phonons.
self.supercell_number_estimator = ipw.HTML(
# description="Number of supercells:",
value="?",
style={"description_width": "initial"},
layout=ipw.Layout(display="none"),
)
ipw.link(
(self._model, "supercell_number_estimator"),
(self.supercell_number_estimator, "value"),
)

# Estimate supercell button
self.supercell_estimate_button = ipw.Button(
description="Estimate number of supercells ➡",
disabled=False,
layout=ipw.Layout(width="240px", display="none"),
button_style="info",
tooltip="Number of supercells for phonons calculations;\nwarning: for large systems, this may take some time.",
)

# supercell reset reaction
self.supercell_estimate_button.on_click(self._model._estimate_supercells)

## end supercell hint.

Expand Down Expand Up @@ -308,6 +310,7 @@ def render(self):
]

self.rendered = True
self._on_change_simulation_type({"new": 0})

def _on_input_structure_change(self, _):
self.refresh(specific="structure")
Expand All @@ -317,127 +320,15 @@ def _on_change_simulation_type(self, _):
self.supercell_widget.layout.display = (
"block" if self._model.simulation_type in [1, 3] else "none"
)

# we define a block for the estimation of the supercell if we ask for hint,
# so that we call the estimator only at the end of the supercell hint generator,
# and now each time after the x, y, z generation (i.e., 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:
# for direction, periodic in zip(
# [self._sc_x, self._sc_y, self._sc_z], self.input_structure.pbc
# ):
# direction.value = 2 if periodic else 1
# direction.disabled = False if periodic else True

# self.supercell_number_estimator.layout.display = (
# "block" if len(self.input_structure.sites) <= 30 else "none"
# )
# self.supercell_estimate_button.layout.display = (
# "block" if len(self.input_structure.sites) <= 30 else "none"
# )
# else:
# self.supercell_number_estimator.layout.display = "none"
# self.supercell_estimate_button.layout.display = "none"

# def _suggest_supercell(self, _=None):
# """
# minimal supercell size for phonons, imposing a minimum lattice parameter of 15 A.
# """
# if self.input_structure:
# s = self.input_structure.get_ase()
# 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 `_activate_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._activate_estimate_supercells()
# else:
# return

# def _activate_estimate_supercells(self, _=None):
# self.supercell_estimate_button.disabled = False
# self.supercell_number_estimator.value = "?"

# # @tl.observe("input_structure")
# @disable_print
# def _estimate_supercells(self, _=None):
# """_summary_

# Estimate the number of supercells to be computed for frozen phonon calculation.
# """
# if self.block:
# return

# symprec_value = self.symmetry_symprec.value

# self.symmetry_symprec.value = max(1e-5, min(symprec_value, 1))

# self.supercell_number_estimator.value = spinner_html

# from aiida_phonopy.data.preprocess import PreProcessData

# 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=self.symmetry_symprec.value,
# 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)}"
# self.supercell_estimate_button.disabled = True

# return

# def _reset_supercell(self, _=None):
# 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
# ):
# reset_supercell.append(2 if periodic else 1)
# (self._sc_x.value, self._sc_y.value, self._sc_z.value) = reset_supercell
# self.block = False
# self._activate_estimate_supercells()
# return

# def _reset_symprec(self, _=None):
# self.symmetry_symprec.value = 1e-5
# self._activate_estimate_supercells()
# return
self.supercell_number_estimator.layout.display = (
"block"
if self._model.simulation_type in [1, 3]
and len(self._model.input_structure.sites) <= 30
else "none"
)
self.supercell_estimate_button.layout.display = (
"block"
if self._model.simulation_type in [1, 3]
and len(self._model.input_structure.sites) <= 30
else "none"
)

0 comments on commit b18fe6d

Please sign in to comment.