From f7030f56dff0ab74919b434a442e39a6c069e60a Mon Sep 17 00:00:00 2001 From: t-reents Date: Tue, 13 Feb 2024 10:35:57 +0100 Subject: [PATCH 1/2] `SelfConsistentHubbardWorkChain`: Relabeling of `HubbardStructure`. The `current_hubbard_structure` is not relabeled in `SelfConsistentHubbardWorkChain` if `skip_relax_iterations != 0`. This can cause problems in the subsequent `PwRelaxWorkChains` if new types are introduced. Therefore, the relabeling step is moved to a separate method that is called in any case. --- .../workflows/hubbard.py | 44 ++++++---- tests/workflows/test_hubbard.py | 82 +++++++++++++++++++ 2 files changed, 112 insertions(+), 14 deletions(-) diff --git a/src/aiida_quantumespresso_hp/workflows/hubbard.py b/src/aiida_quantumespresso_hp/workflows/hubbard.py index 7673964..c381bc0 100644 --- a/src/aiida_quantumespresso_hp/workflows/hubbard.py +++ b/src/aiida_quantumespresso_hp/workflows/hubbard.py @@ -421,6 +421,28 @@ def get_pseudos(self) -> dict: return results + def relabel_onsite_hubbard(self, workchain): + """Relabel the Hubbard structure if new types have been detected.""" + from aiida_quantumespresso.utils.hubbard import is_intersite_hubbard + + relabeling_message = '' + + if not is_intersite_hubbard(workchain.outputs.hubbard_structure.hubbard): + for site in workchain.outputs.hubbard.dict.sites: + if not site['type'] == site['new_type']: + result = structure_relabel_kinds( + self.ctx.current_hubbard_structure, workchain.outputs.hubbard, self.ctx.current_magnetic_moments + ) + self.ctx.current_hubbard_structure = result['hubbard_structure'] + if self.ctx.current_magnetic_moments is not None: + self.ctx.current_magnetic_moments = result['starting_magnetization'] + relabeling_message = 'new types have been detected: relabeling the structure.' + break + + if relabeling_message and self.inputs.meta_convergence: + relabeling_message = relabeling_message[:-1] + ' and starting new iteration.' + return relabeling_message + def run_relax(self): """Run the PwRelaxWorkChain to run a relax PwCalculation.""" inputs = self.get_inputs(PwRelaxWorkChain, 'relax') @@ -578,14 +600,17 @@ def inspect_hp(self): if not self.should_check_convergence(): self.ctx.current_hubbard_structure = workchain.outputs.hubbard_structure + relabeling_message = self.relabel_onsite_hubbard(workchain) + if not self.inputs.meta_convergence: self.report('meta convergence is switched off, so not checking convergence of Hubbard parameters.') self.ctx.is_converged = True + if relabeling_message: + self.report(relabeling_message) + def check_convergence(self): """Check the convergence of the Hubbard parameters.""" - from aiida_quantumespresso.utils.hubbard import is_intersite_hubbard - workchain = self.ctx.workchains_hp[-1] # We store in memory the parameters before relabelling to make the comparison easier. @@ -601,18 +626,9 @@ def check_convergence(self): # We check if new types were created, in which case we relabel the `HubbardStructureData` self.ctx.current_hubbard_structure = workchain.outputs.hubbard_structure - - if not is_intersite_hubbard(workchain.outputs.hubbard_structure.hubbard): - for site in workchain.outputs.hubbard.dict.sites: - if not site['type'] == site['new_type']: - self.report('new types have been detected: relabeling the structure and starting new iteration.') - result = structure_relabel_kinds( - self.ctx.current_hubbard_structure, workchain.outputs.hubbard, self.ctx.current_magnetic_moments - ) - self.ctx.current_hubbard_structure = result['hubbard_structure'] - if self.ctx.current_magnetic_moments is not None: - self.ctx.current_magnetic_moments = result['starting_magnetization'] - break + relabeling_message = self.relabel_onsite_hubbard(workchain) + if relabeling_message: + self.report(relabeling_message) if not len(ref_params) == len(new_params): self.report('The new and old Hubbard parameters have different lenghts. Assuming to be at the first cycle.') diff --git a/tests/workflows/test_hubbard.py b/tests/workflows/test_hubbard.py index 2a06584..f86988e 100644 --- a/tests/workflows/test_hubbard.py +++ b/tests/workflows/test_hubbard.py @@ -227,6 +227,41 @@ def test_skip_relax_iterations(generate_workchain_hubbard, generate_inputs_hubba assert process.should_check_convergence() +@pytest.mark.usefixtures('aiida_profile') +def test_skip_relax_iterations_relabeling( + generate_workchain_hubbard, generate_inputs_hubbard, generate_hp_workchain_node, generate_hubbard_structure +): + """Test `SelfConsistentHubbardWorkChain` when skipping the first relax iterations and relabeling is needed.""" + from aiida.orm import Bool, Int + + inputs = generate_inputs_hubbard() + inputs['skip_relax_iterations'] = Int(1) + inputs['meta_convergence'] = Bool(True) + process = generate_workchain_hubbard(inputs=inputs) + process.setup() + + current_hubbard_structure = generate_hubbard_structure(u_value=1, only_u=True) + process.current_hubbard_structure = current_hubbard_structure + # 1 + process.update_iteration() + assert process.ctx.skip_relax_iterations == 1 + assert process.ctx.iteration == 1 + assert not process.should_run_relax() + assert not process.should_check_convergence() + process.ctx.workchains_hp = [generate_hp_workchain_node(relabel=True, u_value=1, only_u=True)] + process.inspect_hp() + assert process.ctx.current_hubbard_structure.get_kind_names( + ) != process.ctx.workchains_hp[-1].outputs.hubbard_structure.get_kind_names() + # 2 + process.update_iteration() + assert process.should_run_relax() + assert process.should_check_convergence() + # 3 + process.update_iteration() + assert process.should_run_relax() + assert process.should_check_convergence() + + @pytest.mark.usefixtures('aiida_profile') def test_relax_frequency(generate_workchain_hubbard, generate_inputs_hubbard): """Test `SelfConsistentHubbardWorkChain` when `relax_frequency` is different from 1.""" @@ -441,3 +476,50 @@ def test_inspect_hp(generate_workchain_hubbard, generate_inputs_hubbard, generat process.ctx.workchains_hp = [generate_hp_workchain_node(exit_status=300)] result = process.inspect_hp() assert result == WorkChain.exit_codes.ERROR_SUB_PROCESS_FAILED_HP.format(iteration=process.ctx.iteration) + + +@pytest.mark.usefixtures('aiida_profile') +def test_relabel_onsite_hubbard( + generate_workchain_hubbard, generate_inputs_hubbard, generate_hp_workchain_node, generate_hubbard_structure +): + """Test `SelfConsistentHubbardWorkChain.relabel_onsite_hubbard`.""" + from aiida.orm import Bool + inputs = generate_inputs_hubbard() + + # Scenario 1: `meta_convergence` is False and intersite parameters are present + process = generate_workchain_hubbard(inputs=inputs) + process.setup() + + current_hubbard_structure = generate_hubbard_structure(u_value=1, only_u=True) + process.ctx.current_hubbard_structure = current_hubbard_structure + # Contains intersite parameters --> no relabeling + workchain_hp = generate_hp_workchain_node(relabel=True, u_value=100, only_u=False) + relabeling_message = process.relabel_onsite_hubbard(workchain_hp) + assert relabeling_message == '' + + # Scenario 2: `meta_convergence` is False and only onsite parameters are present + process = generate_workchain_hubbard(inputs=inputs) + process.setup() + + current_hubbard_structure = generate_hubbard_structure(u_value=1, only_u=True) + process.ctx.current_hubbard_structure = current_hubbard_structure + # Contains only onsite parameters --> relabeling + # `meta_convergence` is False, so relableing message should not contain + # new iteration + workchain_hp = generate_hp_workchain_node(relabel=True, u_value=100, only_u=True) + relabeling_message = process.relabel_onsite_hubbard(workchain_hp) + assert relabeling_message == 'new types have been detected: relabeling the structure.' + + # Scenario 3: `meta_convergence` is True and only onsite parameters are present + inputs['meta_convergence'] = Bool(True) + process = generate_workchain_hubbard(inputs=inputs) + process.setup() + + current_hubbard_structure = generate_hubbard_structure(u_value=1, only_u=True) + process.ctx.current_hubbard_structure = current_hubbard_structure + # Contains only onsite parameters --> relabeling + # `meta_convergence` is True, so relableing message should contain + # new iteration + workchain_hp = generate_hp_workchain_node(relabel=True, u_value=100, only_u=True) + relabeling_message = process.relabel_onsite_hubbard(workchain_hp) + assert relabeling_message == 'new types have been detected: relabeling the structure and starting new iteration.' From 1bcc18328829329539efb05d3e477d92bbe0413a Mon Sep 17 00:00:00 2001 From: Timo Reents <77727843+t-reents@users.noreply.github.com> Date: Tue, 13 Feb 2024 11:52:02 +0100 Subject: [PATCH 2/2] Simplify reporting messages. Co-authored-by: Lorenzo <79980269+bastonero@users.noreply.github.com> --- .../workflows/hubbard.py | 21 ++------- tests/workflows/test_hubbard.py | 47 ------------------- 2 files changed, 5 insertions(+), 63 deletions(-) diff --git a/src/aiida_quantumespresso_hp/workflows/hubbard.py b/src/aiida_quantumespresso_hp/workflows/hubbard.py index c381bc0..d517163 100644 --- a/src/aiida_quantumespresso_hp/workflows/hubbard.py +++ b/src/aiida_quantumespresso_hp/workflows/hubbard.py @@ -421,12 +421,10 @@ def get_pseudos(self) -> dict: return results - def relabel_onsite_hubbard(self, workchain): + def relabel_hubbard_structure(self, workchain) -> None: """Relabel the Hubbard structure if new types have been detected.""" from aiida_quantumespresso.utils.hubbard import is_intersite_hubbard - relabeling_message = '' - if not is_intersite_hubbard(workchain.outputs.hubbard_structure.hubbard): for site in workchain.outputs.hubbard.dict.sites: if not site['type'] == site['new_type']: @@ -436,12 +434,8 @@ def relabel_onsite_hubbard(self, workchain): self.ctx.current_hubbard_structure = result['hubbard_structure'] if self.ctx.current_magnetic_moments is not None: self.ctx.current_magnetic_moments = result['starting_magnetization'] - relabeling_message = 'new types have been detected: relabeling the structure.' - break - - if relabeling_message and self.inputs.meta_convergence: - relabeling_message = relabeling_message[:-1] + ' and starting new iteration.' - return relabeling_message + self.report('new types have been detected: relabeling the structure.') + return def run_relax(self): """Run the PwRelaxWorkChain to run a relax PwCalculation.""" @@ -600,15 +594,12 @@ def inspect_hp(self): if not self.should_check_convergence(): self.ctx.current_hubbard_structure = workchain.outputs.hubbard_structure - relabeling_message = self.relabel_onsite_hubbard(workchain) + self.relabel_hubbard_structure(workchain) if not self.inputs.meta_convergence: self.report('meta convergence is switched off, so not checking convergence of Hubbard parameters.') self.ctx.is_converged = True - if relabeling_message: - self.report(relabeling_message) - def check_convergence(self): """Check the convergence of the Hubbard parameters.""" workchain = self.ctx.workchains_hp[-1] @@ -626,9 +617,7 @@ def check_convergence(self): # We check if new types were created, in which case we relabel the `HubbardStructureData` self.ctx.current_hubbard_structure = workchain.outputs.hubbard_structure - relabeling_message = self.relabel_onsite_hubbard(workchain) - if relabeling_message: - self.report(relabeling_message) + self.relabel_hubbard_structure(workchain) if not len(ref_params) == len(new_params): self.report('The new and old Hubbard parameters have different lenghts. Assuming to be at the first cycle.') diff --git a/tests/workflows/test_hubbard.py b/tests/workflows/test_hubbard.py index f86988e..c24802c 100644 --- a/tests/workflows/test_hubbard.py +++ b/tests/workflows/test_hubbard.py @@ -476,50 +476,3 @@ def test_inspect_hp(generate_workchain_hubbard, generate_inputs_hubbard, generat process.ctx.workchains_hp = [generate_hp_workchain_node(exit_status=300)] result = process.inspect_hp() assert result == WorkChain.exit_codes.ERROR_SUB_PROCESS_FAILED_HP.format(iteration=process.ctx.iteration) - - -@pytest.mark.usefixtures('aiida_profile') -def test_relabel_onsite_hubbard( - generate_workchain_hubbard, generate_inputs_hubbard, generate_hp_workchain_node, generate_hubbard_structure -): - """Test `SelfConsistentHubbardWorkChain.relabel_onsite_hubbard`.""" - from aiida.orm import Bool - inputs = generate_inputs_hubbard() - - # Scenario 1: `meta_convergence` is False and intersite parameters are present - process = generate_workchain_hubbard(inputs=inputs) - process.setup() - - current_hubbard_structure = generate_hubbard_structure(u_value=1, only_u=True) - process.ctx.current_hubbard_structure = current_hubbard_structure - # Contains intersite parameters --> no relabeling - workchain_hp = generate_hp_workchain_node(relabel=True, u_value=100, only_u=False) - relabeling_message = process.relabel_onsite_hubbard(workchain_hp) - assert relabeling_message == '' - - # Scenario 2: `meta_convergence` is False and only onsite parameters are present - process = generate_workchain_hubbard(inputs=inputs) - process.setup() - - current_hubbard_structure = generate_hubbard_structure(u_value=1, only_u=True) - process.ctx.current_hubbard_structure = current_hubbard_structure - # Contains only onsite parameters --> relabeling - # `meta_convergence` is False, so relableing message should not contain - # new iteration - workchain_hp = generate_hp_workchain_node(relabel=True, u_value=100, only_u=True) - relabeling_message = process.relabel_onsite_hubbard(workchain_hp) - assert relabeling_message == 'new types have been detected: relabeling the structure.' - - # Scenario 3: `meta_convergence` is True and only onsite parameters are present - inputs['meta_convergence'] = Bool(True) - process = generate_workchain_hubbard(inputs=inputs) - process.setup() - - current_hubbard_structure = generate_hubbard_structure(u_value=1, only_u=True) - process.ctx.current_hubbard_structure = current_hubbard_structure - # Contains only onsite parameters --> relabeling - # `meta_convergence` is True, so relableing message should contain - # new iteration - workchain_hp = generate_hp_workchain_node(relabel=True, u_value=100, only_u=True) - relabeling_message = process.relabel_onsite_hubbard(workchain_hp) - assert relabeling_message == 'new types have been detected: relabeling the structure and starting new iteration.'