From ea11d0aaaccd81c7d7527b41d4310de5b400e750 Mon Sep 17 00:00:00 2001 From: Carlo Antonio Pignedoli Date: Mon, 11 Sep 2023 12:45:01 +0000 Subject: [PATCH 1/9] first draft --- .../cp2k/pdos_two_structures_workchain.py | 185 ++++++++++++++++++ pyproject.toml | 1 + 2 files changed, 186 insertions(+) create mode 100644 aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py diff --git a/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py b/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py new file mode 100644 index 00000000..fb09c6c3 --- /dev/null +++ b/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py @@ -0,0 +1,185 @@ +import copy + +import numpy as np +from aiida import engine, orm, plugins + +from ...utils import common_utils, split_structure +from . import cp2k_utils + +Cp2kDiagWorkChain = plugins.WorkflowFactory("nanotech_empa.cp2k.diag") +OverlapCalculation = plugins.CalculationFactory("nanotech_empa.overlap") + + +class Cp2kPdosTwoStructuresWorkChain(engine.WorkChain): + @classmethod + def define(cls, spec): + super().define(spec) + + # Codes. + spec.input("cp2k_code", valid_type=orm.Code) + spec.input("overlap_code", valid_type=orm.Code) + + # Structures. + spec.input( + "structure", + valid_type=orm.StructureData, + help="Coordinates of the whole system.", + ) + spec.input( + "fraction_structure", + valid_type=orm.StructureData, + help="Coordinates of the fraction system.", + ) + + spec.input("pdos_lists", valid_type=orm.List) + + # Numerical parameters. + spec.input( + "protocol", + valid_type=orm.Str, + default=lambda: orm.Str("standard"), + required=False, + help="Protocol supported by the Cp2kDiagWorkChain workchain.", + ) + spec.input("dft_params", valid_type=orm.Dict) + spec.input("overlap_params", valid_type=orm.Dict) + + # High-level things. + spec.input("parent_calc_folder", valid_type=orm.RemoteData, required=False) + spec.input_namespace( + "options", + valid_type=int, + non_db=True, + help="Define options for the cacluations: walltime, memory, CPUs, etc.", + ) + + spec.outline( + cls.setup, + cls.run_diags, + cls.run_overlap, + cls.finalize, + ) + + spec.outputs.dynamic = True + + spec.exit_code( + 390, + "ERROR_TERMINATION", + message="One or more steps of the work chain failed.", + ) + + def setup(self): + self.report("Setting up workchain") + structure_generator = split_structure.split_structure( + structure=self.inputs.structure, + fixed_atoms=[], + magnetization_per_site=self.inputs.dft_params["magnetization_per_site"] + if "magnetization_per_site" in self.inputs.dft_params + else None, + fragments={"molecule": self.inputs.molecule_indices}, + ) + + self.ctx.n_slab_atoms = len(self.inputs.structure.sites) + emax = float(self.inputs.overlap_params.get_dict()["--emax1"]) + nlumo = int(self.inputs.overlap_params.get_dict()["--nlumo2"]) + + dft_parameters = self.inputs.dft_params.get_dict() + # charges = dft_parameters.pop("charges") + # multiplicities = dft_parameters.pop("multiplicities", {}) + + # Set up DFT parameters of the whole system. + # slab_info = next(structure_generator) + self.ctx.structure = self.inputs.structure + self.ctx.dft_parameters = copy.deepcopy(dft_parameters) + # self.ctx.dft_parameters["charge"] = charges["all"] + # if "all" in multiplicities: + # self.ctx.dft_parameters["multiplicity"] = multiplicities["all"] + self.ctx.dft_parameters["added_mos"] = np.max( + [100, int(1.2 * self.ctx.n_slab_atoms * emax / 5.0)] + ) + + # Use the same cutoff for molecule and slab. + self.ctx.dft_parameters["cutoff"] = cp2k_utils.get_cutoff(self.ctx.structure) + + # Set up molecular DFT parameters. + # molecule_info = next(structure_generator) + self.ctx.molecule_structure = self.inputs.fraction_structure + self.ctx.mol_dft_parameters = copy.deepcopy(self.ctx.dft_parameters) + # self.ctx.mol_dft_parameters["charge"] = charges["molecule"] + # if "molecule" in multiplicities: + # self.ctx.mol_dft_parameters["multiplicity"] = multiplicities["molecule"] + self.ctx.mol_dft_parameters["added_mos"] = nlumo + 2 + self.ctx.mol_dft_parameters[ + "elpa_switch" + ] = False # Elpa can cause problems with small systems + # self.ctx.mol_dft_parameters["magnetization_per_site"] = molecule_info[ + # "magnetization_per_site" + # ] + + def run_diags(self): + # Slab part. + self.report("Running Diag Workchain for slab") + builder = Cp2kDiagWorkChain.get_builder() + builder.cp2k_code = self.inputs.cp2k_code + builder.structure = self.ctx.structure + builder.protocol = self.inputs.protocol + builder.dft_params = orm.Dict(self.ctx.dft_parameters) + builder.settings = orm.Dict({"additional_retrieve_list": ["*.pdos"]}) + builder.options = orm.Dict(self.inputs.options["slab"]) + + # Restart WFN. + if "parent_calc_folder" in self.inputs: + builder.parent_calc_folder = self.inputs.parent_calc_folder + + # PDOS. + if self.inputs.pdos_lists is not None: + builder.pdos_lists = orm.List([pdos[0] for pdos in self.inputs.pdos_lists]) + + self.to_context(slab_diag_scf=self.submit(builder)) + + # Molecule part. + self.report("Running Diag Workchain for molecule") + builder = Cp2kDiagWorkChain.get_builder() + builder.cp2k_code = self.inputs.cp2k_code + builder.structure = self.ctx.molecule_structure + builder.protocol = self.inputs.protocol + builder.dft_params = orm.Dict(self.ctx.mol_dft_parameters) + builder.options = orm.Dict(self.inputs.options["molecule"]) + self.to_context(mol_diag_scf=self.submit(builder)) + + def run_overlap(self): + for calculation in [self.ctx.slab_diag_scf, self.ctx.mol_diag_scf]: + if not common_utils.check_if_calc_ok(self, calculation): + return self.exit_codes.ERROR_TERMINATION + self.report("Running overlap") + builder = OverlapCalculation.get_builder() + builder.code = self.inputs.overlap_code + builder.parameters = self.inputs.overlap_params + builder.parent_slab_folder = self.ctx.slab_diag_scf.outputs.remote_folder + builder.parent_mol_folder = self.ctx.mol_diag_scf.outputs.remote_folder + + n_machines = 4 if self.ctx.n_slab_atoms < 2000 else 8 + + builder.metadata = { + "label": "overlap", + "options": { + "resources": {"num_machines": n_machines}, + "max_wallclock_seconds": 86400, + }, + } + + builder.settings = orm.Dict({"additional_retrieve_list": ["overlap.npz"]}) + future = self.submit(builder) + return engine.ToContext(overlap=future) + + def finalize(self): + if "overlap.npz" not in [ + obj.name for obj in self.ctx.overlap.outputs.retrieved.list_objects() + ]: + self.report("Overlap calculation did not finish correctly") + return self.exit_codes.ERROR_TERMINATION + self.out("slab_retrieved", self.ctx.slab_diag_scf.outputs.retrieved) + + # Add the workchain uuid to the input structure extras. + common_utils.add_extras(self.inputs.structure, "surfaces", self.node.uuid) + self.report("Work chain is finished") diff --git a/pyproject.toml b/pyproject.toml index 9c0fe2a5..86e1b0e0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,6 +76,7 @@ dev = [ "nanotech_empa.cp2k.molecule_gw" = "aiida_nanotech_empa.workflows.cp2k:Cp2kMoleculeGwWorkChain" "nanotech_empa.cp2k.mol_opt_gw" = "aiida_nanotech_empa.workflows.cp2k:Cp2kMoleculeOptGwWorkChain" "nanotech_empa.cp2k.pdos" = "aiida_nanotech_empa.workflows.cp2k:Cp2kPdosWorkChain" +"nanotech_empa.cp2k.pdos_two_structures" = "aiida_nanotech_empa.workflows.cp2k:Cp2kPdosTwoStructuresWorkChain" "nanotech_empa.cp2k.orbitals" = "aiida_nanotech_empa.workflows.cp2k:Cp2kOrbitalsWorkChain" "nanotech_empa.cp2k.stm" = "aiida_nanotech_empa.workflows.cp2k:Cp2kStmWorkChain" "nanotech_empa.cp2k.afm" = "aiida_nanotech_empa.workflows.cp2k:Cp2kAfmWorkChain" From e054e944781d436fa53d8389dc772b24fc067097 Mon Sep 17 00:00:00 2001 From: Carlo Antonio Pignedoli Date: Tue, 12 Sep 2023 07:46:28 +0000 Subject: [PATCH 2/9] bug fix --- aiida_nanotech_empa/workflows/cp2k/__init__.py | 2 ++ pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/aiida_nanotech_empa/workflows/cp2k/__init__.py b/aiida_nanotech_empa/workflows/cp2k/__init__.py index 8bf1ffcb..9e20e4cb 100644 --- a/aiida_nanotech_empa/workflows/cp2k/__init__.py +++ b/aiida_nanotech_empa/workflows/cp2k/__init__.py @@ -12,6 +12,7 @@ from .phonons_workchain import Cp2kPhononsWorkChain from .replica_workchain import Cp2kReplicaWorkChain from .stm_workchain import Cp2kStmWorkChain +from .pdos_two_structures_workchain import Cp2kPdosTwoStructuresWorkChain __all__ = ( "Cp2kGeoOptWorkChain", @@ -28,4 +29,5 @@ "Cp2kReplicaWorkChain", "Cp2kNebWorkChain", "Cp2kPhononsWorkChain", + "Cp2kPdosTwoStructuresWorkChain", ) diff --git a/pyproject.toml b/pyproject.toml index 86e1b0e0..91836c51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,7 +76,6 @@ dev = [ "nanotech_empa.cp2k.molecule_gw" = "aiida_nanotech_empa.workflows.cp2k:Cp2kMoleculeGwWorkChain" "nanotech_empa.cp2k.mol_opt_gw" = "aiida_nanotech_empa.workflows.cp2k:Cp2kMoleculeOptGwWorkChain" "nanotech_empa.cp2k.pdos" = "aiida_nanotech_empa.workflows.cp2k:Cp2kPdosWorkChain" -"nanotech_empa.cp2k.pdos_two_structures" = "aiida_nanotech_empa.workflows.cp2k:Cp2kPdosTwoStructuresWorkChain" "nanotech_empa.cp2k.orbitals" = "aiida_nanotech_empa.workflows.cp2k:Cp2kOrbitalsWorkChain" "nanotech_empa.cp2k.stm" = "aiida_nanotech_empa.workflows.cp2k:Cp2kStmWorkChain" "nanotech_empa.cp2k.afm" = "aiida_nanotech_empa.workflows.cp2k:Cp2kAfmWorkChain" @@ -85,6 +84,7 @@ dev = [ "nanotech_empa.cp2k.replica" = "aiida_nanotech_empa.workflows.cp2k:Cp2kReplicaWorkChain" "nanotech_empa.cp2k.neb" = "aiida_nanotech_empa.workflows.cp2k:Cp2kNebWorkChain" "nanotech_empa.cp2k.phonons" = "aiida_nanotech_empa.workflows.cp2k:Cp2kPhononsWorkChain" +"nanotech_empa.cp2k.pdos_two_structures" = "aiida_nanotech_empa.workflows.cp2k:Cp2kPdosTwoStructuresWorkChain" [project.entry-points."aiida.schedulers"] From 95ada55387dbcb087d51c3893aaa7516257a730e Mon Sep 17 00:00:00 2001 From: Carlo Antonio Pignedoli Date: Tue, 12 Sep 2023 09:43:58 +0000 Subject: [PATCH 3/9] bug fix --- .../cp2k/pdos_two_structures_workchain.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py b/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py index fb09c6c3..3d74868c 100644 --- a/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py +++ b/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py @@ -70,14 +70,14 @@ def define(cls, spec): def setup(self): self.report("Setting up workchain") - structure_generator = split_structure.split_structure( - structure=self.inputs.structure, - fixed_atoms=[], - magnetization_per_site=self.inputs.dft_params["magnetization_per_site"] - if "magnetization_per_site" in self.inputs.dft_params - else None, - fragments={"molecule": self.inputs.molecule_indices}, - ) + # structure_generator = split_structure.split_structure( + # structure=self.inputs.structure, + # fixed_atoms=[], + # magnetization_per_site=self.inputs.dft_params["magnetization_per_site"] + # if "magnetization_per_site" in self.inputs.dft_params + # else None, + # fragments={"molecule": self.inputs.molecule_indices}, + # ) self.ctx.n_slab_atoms = len(self.inputs.structure.sites) emax = float(self.inputs.overlap_params.get_dict()["--emax1"]) From 0c4843791bb2ad2bf5abfa5ed73e012565439b77 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 08:41:48 +0000 Subject: [PATCH 4/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- aiida_nanotech_empa/workflows/cp2k/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiida_nanotech_empa/workflows/cp2k/__init__.py b/aiida_nanotech_empa/workflows/cp2k/__init__.py index 9e20e4cb..0d717718 100644 --- a/aiida_nanotech_empa/workflows/cp2k/__init__.py +++ b/aiida_nanotech_empa/workflows/cp2k/__init__.py @@ -8,11 +8,11 @@ from .molecule_opt_gw_workchain import Cp2kMoleculeOptGwWorkChain from .neb_workchain import Cp2kNebWorkChain from .orbitals_workchain import Cp2kOrbitalsWorkChain +from .pdos_two_structures_workchain import Cp2kPdosTwoStructuresWorkChain from .pdos_workchain import Cp2kPdosWorkChain from .phonons_workchain import Cp2kPhononsWorkChain from .replica_workchain import Cp2kReplicaWorkChain from .stm_workchain import Cp2kStmWorkChain -from .pdos_two_structures_workchain import Cp2kPdosTwoStructuresWorkChain __all__ = ( "Cp2kGeoOptWorkChain", From 74ab8d52c85c46b173d9228ec11cd089b250c862 Mon Sep 17 00:00:00 2001 From: Carlo Antonio Pignedoli Date: Thu, 21 Sep 2023 09:10:56 +0000 Subject: [PATCH 5/9] toward general fragments --- aiida_nanotech_empa/plugins/overlap.py | 4 +- .../cp2k/pdos_two_structures_workchain.py | 74 +++++++++---------- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/aiida_nanotech_empa/plugins/overlap.py b/aiida_nanotech_empa/plugins/overlap.py index 658b5e9d..90ff9d4f 100644 --- a/aiida_nanotech_empa/plugins/overlap.py +++ b/aiida_nanotech_empa/plugins/overlap.py @@ -10,7 +10,9 @@ def define(cls, spec): "parent_slab_folder", valid_type=orm.RemoteData, help="slab scf folder" ) spec.input( - "parent_mol_folder", valid_type=orm.RemoteData, help="molecule scf folder" + "parent_fragment_folder", + valid_type=orm.RemoteData, + help="molecule scf folder", ) spec.input("settings", valid_type=orm.Dict, help="special settings") diff --git a/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py b/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py index 3d74868c..63b305cf 100644 --- a/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py +++ b/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py @@ -26,7 +26,7 @@ def define(cls, spec): help="Coordinates of the whole system.", ) spec.input( - "fraction_structure", + "fragment_structure", valid_type=orm.StructureData, help="Coordinates of the fraction system.", ) @@ -70,51 +70,49 @@ def define(cls, spec): def setup(self): self.report("Setting up workchain") - # structure_generator = split_structure.split_structure( - # structure=self.inputs.structure, - # fixed_atoms=[], - # magnetization_per_site=self.inputs.dft_params["magnetization_per_site"] - # if "magnetization_per_site" in self.inputs.dft_params - # else None, - # fragments={"molecule": self.inputs.molecule_indices}, - # ) self.ctx.n_slab_atoms = len(self.inputs.structure.sites) emax = float(self.inputs.overlap_params.get_dict()["--emax1"]) nlumo = int(self.inputs.overlap_params.get_dict()["--nlumo2"]) dft_parameters = self.inputs.dft_params.get_dict() - # charges = dft_parameters.pop("charges") - # multiplicities = dft_parameters.pop("multiplicities", {}) - + charges = dft_parameters.pop("charges") + multiplicities = dft_parameters.pop("multiplicities", {}) + magnetization_per_site = dft_parameters.pop("magnetization_per_site", {}) # Set up DFT parameters of the whole system. - # slab_info = next(structure_generator) self.ctx.structure = self.inputs.structure self.ctx.dft_parameters = copy.deepcopy(dft_parameters) - # self.ctx.dft_parameters["charge"] = charges["all"] - # if "all" in multiplicities: - # self.ctx.dft_parameters["multiplicity"] = multiplicities["all"] + self.ctx.dft_parameters["charge"] = charges["all"] + if "all" in multiplicities: + self.ctx.dft_parameters["multiplicity"] = multiplicities["all"] + if "all" in magnetization_per_site: + self.ctx.dft_parameters["magnetization_per_site"] = magnetization_per_site[ + "all" + ] self.ctx.dft_parameters["added_mos"] = np.max( [100, int(1.2 * self.ctx.n_slab_atoms * emax / 5.0)] ) - # Use the same cutoff for molecule and slab. + # Use the same cutoff for fragment and slab. self.ctx.dft_parameters["cutoff"] = cp2k_utils.get_cutoff(self.ctx.structure) - # Set up molecular DFT parameters. - # molecule_info = next(structure_generator) - self.ctx.molecule_structure = self.inputs.fraction_structure - self.ctx.mol_dft_parameters = copy.deepcopy(self.ctx.dft_parameters) - # self.ctx.mol_dft_parameters["charge"] = charges["molecule"] - # if "molecule" in multiplicities: - # self.ctx.mol_dft_parameters["multiplicity"] = multiplicities["molecule"] - self.ctx.mol_dft_parameters["added_mos"] = nlumo + 2 - self.ctx.mol_dft_parameters[ + # Set up fragment DFT parameters. + self.ctx.fragment_structure = self.inputs.fraction_structure + self.ctx.fragment_dft_parameters = copy.deepcopy(self.ctx.dft_parameters) + self.ctx.fragment_dft_parameters["charge"] = charges["fragment"] + if "fragment" in multiplicities: + self.ctx.fragment_dft_parameters["multiplicity"] = multiplicities[ + "fragment" + ] + if "fragment" in magnetization_per_site: + self.ctx.fragment_dft_parameters[ + "magnetization_per_site" + ] = magnetization_per_site["fragment"] + self.ctx.fragment_dft_parameters["added_mos"] = nlumo + 2 + self.ctx.fragment_dft_parameters["cutoff"] = self.ctx.dft_parameters["cutoff"] + self.ctx.fragment_dft_parameters[ "elpa_switch" ] = False # Elpa can cause problems with small systems - # self.ctx.mol_dft_parameters["magnetization_per_site"] = molecule_info[ - # "magnetization_per_site" - # ] def run_diags(self): # Slab part. @@ -137,18 +135,18 @@ def run_diags(self): self.to_context(slab_diag_scf=self.submit(builder)) - # Molecule part. - self.report("Running Diag Workchain for molecule") + # Fragment part. + self.report("Running Diag Workchain for fragment") builder = Cp2kDiagWorkChain.get_builder() builder.cp2k_code = self.inputs.cp2k_code - builder.structure = self.ctx.molecule_structure + builder.structure = self.ctx.fragment_structure builder.protocol = self.inputs.protocol - builder.dft_params = orm.Dict(self.ctx.mol_dft_parameters) - builder.options = orm.Dict(self.inputs.options["molecule"]) - self.to_context(mol_diag_scf=self.submit(builder)) + builder.dft_params = orm.Dict(self.ctx.fragment_dft_parameters) + builder.options = orm.Dict(self.inputs.options["fragment"]) + self.to_context(fragment_diag_scf=self.submit(builder)) def run_overlap(self): - for calculation in [self.ctx.slab_diag_scf, self.ctx.mol_diag_scf]: + for calculation in [self.ctx.slab_diag_scf, self.ctx.fragment_diag_scf]: if not common_utils.check_if_calc_ok(self, calculation): return self.exit_codes.ERROR_TERMINATION self.report("Running overlap") @@ -156,7 +154,9 @@ def run_overlap(self): builder.code = self.inputs.overlap_code builder.parameters = self.inputs.overlap_params builder.parent_slab_folder = self.ctx.slab_diag_scf.outputs.remote_folder - builder.parent_mol_folder = self.ctx.mol_diag_scf.outputs.remote_folder + builder.parent_fragment_folder = ( + self.ctx.fragment_diag_scf.outputs.remote_folder + ) n_machines = 4 if self.ctx.n_slab_atoms < 2000 else 8 From 7a87841e85dee46e98afe90bf56a8868a23740f8 Mon Sep 17 00:00:00 2001 From: Carlo Antonio Pignedoli Date: Thu, 21 Sep 2023 12:21:26 +0000 Subject: [PATCH 6/9] merging pdos --- .../workflows/cp2k/__init__.py | 1 - .../cp2k/pdos_two_structures_workchain.py | 185 ------------------ .../workflows/cp2k/pdos_workchain.py | 72 +++---- pyproject.toml | 1 - 4 files changed, 38 insertions(+), 221 deletions(-) delete mode 100644 aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py diff --git a/aiida_nanotech_empa/workflows/cp2k/__init__.py b/aiida_nanotech_empa/workflows/cp2k/__init__.py index 0d717718..7818f1a6 100644 --- a/aiida_nanotech_empa/workflows/cp2k/__init__.py +++ b/aiida_nanotech_empa/workflows/cp2k/__init__.py @@ -29,5 +29,4 @@ "Cp2kReplicaWorkChain", "Cp2kNebWorkChain", "Cp2kPhononsWorkChain", - "Cp2kPdosTwoStructuresWorkChain", ) diff --git a/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py b/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py deleted file mode 100644 index 63b305cf..00000000 --- a/aiida_nanotech_empa/workflows/cp2k/pdos_two_structures_workchain.py +++ /dev/null @@ -1,185 +0,0 @@ -import copy - -import numpy as np -from aiida import engine, orm, plugins - -from ...utils import common_utils, split_structure -from . import cp2k_utils - -Cp2kDiagWorkChain = plugins.WorkflowFactory("nanotech_empa.cp2k.diag") -OverlapCalculation = plugins.CalculationFactory("nanotech_empa.overlap") - - -class Cp2kPdosTwoStructuresWorkChain(engine.WorkChain): - @classmethod - def define(cls, spec): - super().define(spec) - - # Codes. - spec.input("cp2k_code", valid_type=orm.Code) - spec.input("overlap_code", valid_type=orm.Code) - - # Structures. - spec.input( - "structure", - valid_type=orm.StructureData, - help="Coordinates of the whole system.", - ) - spec.input( - "fragment_structure", - valid_type=orm.StructureData, - help="Coordinates of the fraction system.", - ) - - spec.input("pdos_lists", valid_type=orm.List) - - # Numerical parameters. - spec.input( - "protocol", - valid_type=orm.Str, - default=lambda: orm.Str("standard"), - required=False, - help="Protocol supported by the Cp2kDiagWorkChain workchain.", - ) - spec.input("dft_params", valid_type=orm.Dict) - spec.input("overlap_params", valid_type=orm.Dict) - - # High-level things. - spec.input("parent_calc_folder", valid_type=orm.RemoteData, required=False) - spec.input_namespace( - "options", - valid_type=int, - non_db=True, - help="Define options for the cacluations: walltime, memory, CPUs, etc.", - ) - - spec.outline( - cls.setup, - cls.run_diags, - cls.run_overlap, - cls.finalize, - ) - - spec.outputs.dynamic = True - - spec.exit_code( - 390, - "ERROR_TERMINATION", - message="One or more steps of the work chain failed.", - ) - - def setup(self): - self.report("Setting up workchain") - - self.ctx.n_slab_atoms = len(self.inputs.structure.sites) - emax = float(self.inputs.overlap_params.get_dict()["--emax1"]) - nlumo = int(self.inputs.overlap_params.get_dict()["--nlumo2"]) - - dft_parameters = self.inputs.dft_params.get_dict() - charges = dft_parameters.pop("charges") - multiplicities = dft_parameters.pop("multiplicities", {}) - magnetization_per_site = dft_parameters.pop("magnetization_per_site", {}) - # Set up DFT parameters of the whole system. - self.ctx.structure = self.inputs.structure - self.ctx.dft_parameters = copy.deepcopy(dft_parameters) - self.ctx.dft_parameters["charge"] = charges["all"] - if "all" in multiplicities: - self.ctx.dft_parameters["multiplicity"] = multiplicities["all"] - if "all" in magnetization_per_site: - self.ctx.dft_parameters["magnetization_per_site"] = magnetization_per_site[ - "all" - ] - self.ctx.dft_parameters["added_mos"] = np.max( - [100, int(1.2 * self.ctx.n_slab_atoms * emax / 5.0)] - ) - - # Use the same cutoff for fragment and slab. - self.ctx.dft_parameters["cutoff"] = cp2k_utils.get_cutoff(self.ctx.structure) - - # Set up fragment DFT parameters. - self.ctx.fragment_structure = self.inputs.fraction_structure - self.ctx.fragment_dft_parameters = copy.deepcopy(self.ctx.dft_parameters) - self.ctx.fragment_dft_parameters["charge"] = charges["fragment"] - if "fragment" in multiplicities: - self.ctx.fragment_dft_parameters["multiplicity"] = multiplicities[ - "fragment" - ] - if "fragment" in magnetization_per_site: - self.ctx.fragment_dft_parameters[ - "magnetization_per_site" - ] = magnetization_per_site["fragment"] - self.ctx.fragment_dft_parameters["added_mos"] = nlumo + 2 - self.ctx.fragment_dft_parameters["cutoff"] = self.ctx.dft_parameters["cutoff"] - self.ctx.fragment_dft_parameters[ - "elpa_switch" - ] = False # Elpa can cause problems with small systems - - def run_diags(self): - # Slab part. - self.report("Running Diag Workchain for slab") - builder = Cp2kDiagWorkChain.get_builder() - builder.cp2k_code = self.inputs.cp2k_code - builder.structure = self.ctx.structure - builder.protocol = self.inputs.protocol - builder.dft_params = orm.Dict(self.ctx.dft_parameters) - builder.settings = orm.Dict({"additional_retrieve_list": ["*.pdos"]}) - builder.options = orm.Dict(self.inputs.options["slab"]) - - # Restart WFN. - if "parent_calc_folder" in self.inputs: - builder.parent_calc_folder = self.inputs.parent_calc_folder - - # PDOS. - if self.inputs.pdos_lists is not None: - builder.pdos_lists = orm.List([pdos[0] for pdos in self.inputs.pdos_lists]) - - self.to_context(slab_diag_scf=self.submit(builder)) - - # Fragment part. - self.report("Running Diag Workchain for fragment") - builder = Cp2kDiagWorkChain.get_builder() - builder.cp2k_code = self.inputs.cp2k_code - builder.structure = self.ctx.fragment_structure - builder.protocol = self.inputs.protocol - builder.dft_params = orm.Dict(self.ctx.fragment_dft_parameters) - builder.options = orm.Dict(self.inputs.options["fragment"]) - self.to_context(fragment_diag_scf=self.submit(builder)) - - def run_overlap(self): - for calculation in [self.ctx.slab_diag_scf, self.ctx.fragment_diag_scf]: - if not common_utils.check_if_calc_ok(self, calculation): - return self.exit_codes.ERROR_TERMINATION - self.report("Running overlap") - builder = OverlapCalculation.get_builder() - builder.code = self.inputs.overlap_code - builder.parameters = self.inputs.overlap_params - builder.parent_slab_folder = self.ctx.slab_diag_scf.outputs.remote_folder - builder.parent_fragment_folder = ( - self.ctx.fragment_diag_scf.outputs.remote_folder - ) - - n_machines = 4 if self.ctx.n_slab_atoms < 2000 else 8 - - builder.metadata = { - "label": "overlap", - "options": { - "resources": {"num_machines": n_machines}, - "max_wallclock_seconds": 86400, - }, - } - - builder.settings = orm.Dict({"additional_retrieve_list": ["overlap.npz"]}) - future = self.submit(builder) - return engine.ToContext(overlap=future) - - def finalize(self): - if "overlap.npz" not in [ - obj.name for obj in self.ctx.overlap.outputs.retrieved.list_objects() - ]: - self.report("Overlap calculation did not finish correctly") - return self.exit_codes.ERROR_TERMINATION - self.out("slab_retrieved", self.ctx.slab_diag_scf.outputs.retrieved) - - # Add the workchain uuid to the input structure extras. - common_utils.add_extras(self.inputs.structure, "surfaces", self.node.uuid) - self.report("Work chain is finished") diff --git a/aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py b/aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py index c45f9d53..08fd854b 100644 --- a/aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py +++ b/aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py @@ -3,7 +3,7 @@ import numpy as np from aiida import engine, orm, plugins -from ...utils import common_utils, split_structure +from ...utils import common_utils from . import cp2k_utils Cp2kDiagWorkChain = plugins.WorkflowFactory("nanotech_empa.cp2k.diag") @@ -25,7 +25,11 @@ def define(cls, spec): valid_type=orm.StructureData, help="Coordinates of the whole system.", ) - spec.input("molecule_indices", valid_type=orm.List) + spec.input( + "fragment_structure", + valid_type=orm.StructureData, + help="Coordinates of the fraction system.", + ) spec.input("pdos_lists", valid_type=orm.List) @@ -66,14 +70,6 @@ def define(cls, spec): def setup(self): self.report("Setting up workchain") - structure_generator = split_structure.split_structure( - structure=self.inputs.structure, - fixed_atoms=[], - magnetization_per_site=self.inputs.dft_params["magnetization_per_site"] - if "magnetization_per_site" in self.inputs.dft_params - else None, - fragments={"molecule": self.inputs.molecule_indices}, - ) self.ctx.n_slab_atoms = len(self.inputs.structure.sites) emax = float(self.inputs.overlap_params.get_dict()["--emax1"]) @@ -82,35 +78,41 @@ def setup(self): dft_parameters = self.inputs.dft_params.get_dict() charges = dft_parameters.pop("charges") multiplicities = dft_parameters.pop("multiplicities", {}) - + magnetization_per_site = dft_parameters.pop("magnetization_per_site", {}) # Set up DFT parameters of the whole system. - slab_info = next(structure_generator) - self.ctx.structure = slab_info["structure"] + self.ctx.structure = self.inputs.structure self.ctx.dft_parameters = copy.deepcopy(dft_parameters) self.ctx.dft_parameters["charge"] = charges["all"] if "all" in multiplicities: self.ctx.dft_parameters["multiplicity"] = multiplicities["all"] + if "all" in magnetization_per_site: + self.ctx.dft_parameters["magnetization_per_site"] = magnetization_per_site[ + "all" + ] self.ctx.dft_parameters["added_mos"] = np.max( [100, int(1.2 * self.ctx.n_slab_atoms * emax / 5.0)] ) - # Use the same cutoff for molecule and slab. + # Use the same cutoff for fragment and slab. self.ctx.dft_parameters["cutoff"] = cp2k_utils.get_cutoff(self.ctx.structure) - # Set up molecular DFT parameters. - molecule_info = next(structure_generator) - self.ctx.molecule_structure = molecule_info["structure"] - self.ctx.mol_dft_parameters = copy.deepcopy(self.ctx.dft_parameters) - self.ctx.mol_dft_parameters["charge"] = charges["molecule"] - if "molecule" in multiplicities: - self.ctx.mol_dft_parameters["multiplicity"] = multiplicities["molecule"] - self.ctx.mol_dft_parameters["added_mos"] = nlumo + 2 - self.ctx.mol_dft_parameters[ + # Set up fragment DFT parameters. + self.ctx.fragment_structure = self.inputs.fraction_structure + self.ctx.fragment_dft_parameters = copy.deepcopy(self.ctx.dft_parameters) + self.ctx.fragment_dft_parameters["charge"] = charges["fragment"] + if "fragment" in multiplicities: + self.ctx.fragment_dft_parameters["multiplicity"] = multiplicities[ + "fragment" + ] + if "fragment" in magnetization_per_site: + self.ctx.fragment_dft_parameters[ + "magnetization_per_site" + ] = magnetization_per_site["fragment"] + self.ctx.fragment_dft_parameters["added_mos"] = nlumo + 2 + self.ctx.fragment_dft_parameters["cutoff"] = self.ctx.dft_parameters["cutoff"] + self.ctx.fragment_dft_parameters[ "elpa_switch" ] = False # Elpa can cause problems with small systems - self.ctx.mol_dft_parameters["magnetization_per_site"] = molecule_info[ - "magnetization_per_site" - ] def run_diags(self): # Slab part. @@ -133,18 +135,18 @@ def run_diags(self): self.to_context(slab_diag_scf=self.submit(builder)) - # Molecule part. - self.report("Running Diag Workchain for molecule") + # Fragment part. + self.report("Running Diag Workchain for fragment") builder = Cp2kDiagWorkChain.get_builder() builder.cp2k_code = self.inputs.cp2k_code - builder.structure = self.ctx.molecule_structure + builder.structure = self.ctx.fragment_structure builder.protocol = self.inputs.protocol - builder.dft_params = orm.Dict(self.ctx.mol_dft_parameters) - builder.options = orm.Dict(self.inputs.options["molecule"]) - self.to_context(mol_diag_scf=self.submit(builder)) + builder.dft_params = orm.Dict(self.ctx.fragment_dft_parameters) + builder.options = orm.Dict(self.inputs.options["fragment"]) + self.to_context(fragment_diag_scf=self.submit(builder)) def run_overlap(self): - for calculation in [self.ctx.slab_diag_scf, self.ctx.mol_diag_scf]: + for calculation in [self.ctx.slab_diag_scf, self.ctx.fragment_diag_scf]: if not common_utils.check_if_calc_ok(self, calculation): return self.exit_codes.ERROR_TERMINATION self.report("Running overlap") @@ -152,7 +154,9 @@ def run_overlap(self): builder.code = self.inputs.overlap_code builder.parameters = self.inputs.overlap_params builder.parent_slab_folder = self.ctx.slab_diag_scf.outputs.remote_folder - builder.parent_mol_folder = self.ctx.mol_diag_scf.outputs.remote_folder + builder.parent_fragment_folder = ( + self.ctx.fragment_diag_scf.outputs.remote_folder + ) n_machines = 4 if self.ctx.n_slab_atoms < 2000 else 8 diff --git a/pyproject.toml b/pyproject.toml index 91836c51..9c0fe2a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,7 +84,6 @@ dev = [ "nanotech_empa.cp2k.replica" = "aiida_nanotech_empa.workflows.cp2k:Cp2kReplicaWorkChain" "nanotech_empa.cp2k.neb" = "aiida_nanotech_empa.workflows.cp2k:Cp2kNebWorkChain" "nanotech_empa.cp2k.phonons" = "aiida_nanotech_empa.workflows.cp2k:Cp2kPhononsWorkChain" -"nanotech_empa.cp2k.pdos_two_structures" = "aiida_nanotech_empa.workflows.cp2k:Cp2kPdosTwoStructuresWorkChain" [project.entry-points."aiida.schedulers"] From d4485f37e7dfe23298b9b1a4bee9011d7174979e Mon Sep 17 00:00:00 2001 From: Carlo Antonio Pignedoli Date: Thu, 21 Sep 2023 14:22:02 +0000 Subject: [PATCH 7/9] added description --- aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py b/aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py index 08fd854b..d93511c9 100644 --- a/aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py +++ b/aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py @@ -20,11 +20,13 @@ def define(cls, spec): spec.input("overlap_code", valid_type=orm.Code) # Structures. + # Whole system spec.input( "structure", valid_type=orm.StructureData, help="Coordinates of the whole system.", ) + # Portion of the system, could also be not derived from the whole system spec.input( "fragment_structure", valid_type=orm.StructureData, From 6107bc8a4e02a0a1b60cae2bb81d448e0afb7545 Mon Sep 17 00:00:00 2001 From: Carlo Antonio Pignedoli Date: Fri, 22 Sep 2023 09:13:49 +0000 Subject: [PATCH 8/9] adapted the example for pdos --- aiida_nanotech_empa/plugins/overlap.py | 22 ++++--- .../workflows/cp2k/__init__.py | 1 - .../workflows/cp2k/pdos_workchain.py | 32 +++++---- examples/workflows/c2h2_for_pdos.xyz | 6 ++ examples/workflows/example_cp2k_geo_opt.py | 3 +- examples/workflows/example_cp2k_pdos.py | 65 ++++++++++--------- 6 files changed, 71 insertions(+), 58 deletions(-) create mode 100644 examples/workflows/c2h2_for_pdos.xyz diff --git a/aiida_nanotech_empa/plugins/overlap.py b/aiida_nanotech_empa/plugins/overlap.py index 90ff9d4f..a2c45510 100644 --- a/aiida_nanotech_empa/plugins/overlap.py +++ b/aiida_nanotech_empa/plugins/overlap.py @@ -7,12 +7,14 @@ def define(cls, spec): super().define(spec) spec.input("parameters", valid_type=orm.Dict, help="Overlap input parameters") spec.input( - "parent_slab_folder", valid_type=orm.RemoteData, help="slab scf folder" + "parent_all_folder", + valid_type=orm.RemoteData, + help="whole system scf folder", ) spec.input( "parent_fragment_folder", valid_type=orm.RemoteData, - help="molecule scf folder", + help="fragment scf folder", ) spec.input("settings", valid_type=orm.Dict, help="special settings") @@ -58,10 +60,10 @@ def prepare_for_submission(self, folder): calcinfo.retrieve_list = settings.pop("additional_retrieve_list", []) # Symlinks. - if "parent_slab_folder" in self.inputs: - comp_uuid = self.inputs.parent_slab_folder.computer.uuid - remote_path = self.inputs.parent_slab_folder.get_remote_path() - copy_info = (comp_uuid, remote_path, "parent_slab_folder/") + if "parent_all_folder" in self.inputs: + comp_uuid = self.inputs.parent_all_folder.computer.uuid + remote_path = self.inputs.parent_all_folder.get_remote_path() + copy_info = (comp_uuid, remote_path, "parent_all_folder/") if ( self.inputs.code.computer.uuid == comp_uuid ): # if running on the same computer - make a symlink @@ -70,10 +72,10 @@ def prepare_for_submission(self, folder): else: calcinfo.remote_copy_list.append(copy_info) - if "parent_mol_folder" in self.inputs: - comp_uuid = self.inputs.parent_mol_folder.computer.uuid - remote_path = self.inputs.parent_mol_folder.get_remote_path() - copy_info = (comp_uuid, remote_path, "parent_mol_folder/") + if "parent_fragment_folder" in self.inputs: + comp_uuid = self.inputs.parent_fragment_folder.computer.uuid + remote_path = self.inputs.parent_fragment_folder.get_remote_path() + copy_info = (comp_uuid, remote_path, "parent_fragment_folder/") if ( self.inputs.code.computer.uuid == comp_uuid ): # if running on the same computer - make a symlink diff --git a/aiida_nanotech_empa/workflows/cp2k/__init__.py b/aiida_nanotech_empa/workflows/cp2k/__init__.py index 7818f1a6..8bf1ffcb 100644 --- a/aiida_nanotech_empa/workflows/cp2k/__init__.py +++ b/aiida_nanotech_empa/workflows/cp2k/__init__.py @@ -8,7 +8,6 @@ from .molecule_opt_gw_workchain import Cp2kMoleculeOptGwWorkChain from .neb_workchain import Cp2kNebWorkChain from .orbitals_workchain import Cp2kOrbitalsWorkChain -from .pdos_two_structures_workchain import Cp2kPdosTwoStructuresWorkChain from .pdos_workchain import Cp2kPdosWorkChain from .phonons_workchain import Cp2kPhononsWorkChain from .replica_workchain import Cp2kReplicaWorkChain diff --git a/aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py b/aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py index d93511c9..ac40763d 100644 --- a/aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py +++ b/aiida_nanotech_empa/workflows/cp2k/pdos_workchain.py @@ -30,7 +30,7 @@ def define(cls, spec): spec.input( "fragment_structure", valid_type=orm.StructureData, - help="Coordinates of the fraction system.", + help="Coordinates of the fragment system.", ) spec.input("pdos_lists", valid_type=orm.List) @@ -73,7 +73,7 @@ def define(cls, spec): def setup(self): self.report("Setting up workchain") - self.ctx.n_slab_atoms = len(self.inputs.structure.sites) + self.ctx.n_all_atoms = len(self.inputs.structure.sites) emax = float(self.inputs.overlap_params.get_dict()["--emax1"]) nlumo = int(self.inputs.overlap_params.get_dict()["--nlumo2"]) @@ -92,14 +92,14 @@ def setup(self): "all" ] self.ctx.dft_parameters["added_mos"] = np.max( - [100, int(1.2 * self.ctx.n_slab_atoms * emax / 5.0)] + [100, int(1.2 * self.ctx.n_all_atoms * emax / 5.0)] ) - # Use the same cutoff for fragment and slab. + # Use the same cutoff for fragment and whole system. self.ctx.dft_parameters["cutoff"] = cp2k_utils.get_cutoff(self.ctx.structure) # Set up fragment DFT parameters. - self.ctx.fragment_structure = self.inputs.fraction_structure + self.ctx.fragment_structure = self.inputs.fragment_structure self.ctx.fragment_dft_parameters = copy.deepcopy(self.ctx.dft_parameters) self.ctx.fragment_dft_parameters["charge"] = charges["fragment"] if "fragment" in multiplicities: @@ -117,15 +117,15 @@ def setup(self): ] = False # Elpa can cause problems with small systems def run_diags(self): - # Slab part. - self.report("Running Diag Workchain for slab") + # Whole system part. + self.report("Running Diag Workchain for whole system") builder = Cp2kDiagWorkChain.get_builder() builder.cp2k_code = self.inputs.cp2k_code builder.structure = self.ctx.structure builder.protocol = self.inputs.protocol builder.dft_params = orm.Dict(self.ctx.dft_parameters) builder.settings = orm.Dict({"additional_retrieve_list": ["*.pdos"]}) - builder.options = orm.Dict(self.inputs.options["slab"]) + builder.options = orm.Dict(self.inputs.options["all"]) # Restart WFN. if "parent_calc_folder" in self.inputs: @@ -135,7 +135,7 @@ def run_diags(self): if self.inputs.pdos_lists is not None: builder.pdos_lists = orm.List([pdos[0] for pdos in self.inputs.pdos_lists]) - self.to_context(slab_diag_scf=self.submit(builder)) + self.to_context(all_diag_scf=self.submit(builder)) # Fragment part. self.report("Running Diag Workchain for fragment") @@ -148,19 +148,25 @@ def run_diags(self): self.to_context(fragment_diag_scf=self.submit(builder)) def run_overlap(self): - for calculation in [self.ctx.slab_diag_scf, self.ctx.fragment_diag_scf]: + for calculation in [self.ctx.all_diag_scf, self.ctx.fragment_diag_scf]: if not common_utils.check_if_calc_ok(self, calculation): return self.exit_codes.ERROR_TERMINATION self.report("Running overlap") builder = OverlapCalculation.get_builder() builder.code = self.inputs.overlap_code builder.parameters = self.inputs.overlap_params - builder.parent_slab_folder = self.ctx.slab_diag_scf.outputs.remote_folder + builder.parent_all_folder = self.ctx.all_diag_scf.outputs.remote_folder builder.parent_fragment_folder = ( self.ctx.fragment_diag_scf.outputs.remote_folder ) - n_machines = 4 if self.ctx.n_slab_atoms < 2000 else 8 + # set n_machines to 1 4 8 if n_all_atoms < 100 2000 or else + if self.ctx.n_all_atoms < 100: + n_machines = 1 + elif self.ctx.n_all_atoms < 2000: + n_machines = 4 + else: + n_machines = 8 builder.metadata = { "label": "overlap", @@ -180,7 +186,7 @@ def finalize(self): ]: self.report("Overlap calculation did not finish correctly") return self.exit_codes.ERROR_TERMINATION - self.out("slab_retrieved", self.ctx.slab_diag_scf.outputs.retrieved) + self.out("slab_retrieved", self.ctx.all_diag_scf.outputs.retrieved) # Add the workchain uuid to the input structure extras. common_utils.add_extras(self.inputs.structure, "surfaces", self.node.uuid) diff --git a/examples/workflows/c2h2_for_pdos.xyz b/examples/workflows/c2h2_for_pdos.xyz new file mode 100644 index 00000000..21b932d6 --- /dev/null +++ b/examples/workflows/c2h2_for_pdos.xyz @@ -0,0 +1,6 @@ +4 +Lattice="8.84399664 0.0 0.0 0.0 10.21216768 0.0 0.0 0.0 20.0" Properties=species:S:1:pos:R:3:masses:R:1 pbc="T T T" +H 2.89445002 3.11134486 9.51675909 1.00800000 +C 3.40914678 4.04942122 9.51675909 12.01100000 +C 4.06762878 5.24274647 9.51675909 12.01100000 +H 4.58232554 6.18082283 9.51675909 1.00800000 diff --git a/examples/workflows/example_cp2k_geo_opt.py b/examples/workflows/example_cp2k_geo_opt.py index 911f7a37..35df8644 100644 --- a/examples/workflows/example_cp2k_geo_opt.py +++ b/examples/workflows/example_cp2k_geo_opt.py @@ -18,8 +18,7 @@ def _example_cp2k_geo_opt(cp2k_code, sys_type, uks, n_nodes, n_cores_per_node): filters={"label": {"in": GEOS}}, ) structures = {} - for node_tuple in qb.iterall(): - node = node_tuple[0] + for node in qb.all(flat=True): structures[node.label] = node for required in GEOS: if required in structures: diff --git a/examples/workflows/example_cp2k_pdos.py b/examples/workflows/example_cp2k_pdos.py index 3f93f6ef..6c0ff60f 100644 --- a/examples/workflows/example_cp2k_pdos.py +++ b/examples/workflows/example_cp2k_pdos.py @@ -7,7 +7,7 @@ Cp2kPdosWorkChain = plugins.WorkflowFactory("nanotech_empa.cp2k.pdos") DATA_DIR = pathlib.Path(__file__).parent.absolute() -GEO_FILE = "c2h2_on_au111.xyz" +GEOS = ["c2h2_on_au111.xyz", "c2h2_for_pdos.xyz"] def _example_cp2k_pdos( @@ -15,29 +15,28 @@ def _example_cp2k_pdos( ): # Check test geometry is already in database. qb = orm.QueryBuilder() - qb.append(orm.Node, filters={"label": {"in": [GEO_FILE]}}) - structure = None - for node_tuple in qb.iterall(): - node = node_tuple[0] - structure = node - if structure is not None: - print(f"Found existing structure: {structure.pk}") - else: - structure = orm.StructureData(ase=ase.io.read(DATA_DIR / GEO_FILE)) - structure.label = GEO_FILE - structure.store() - print(f"Created new structure: {structure.pk}") + qb.append(orm.Node, filters={"label": {"in": GEOS}}) + structures = {} + for node in qb.all(flat=True): + structures[node.label] = node + for required in GEOS: + if required in structures: + print("found existing structure: ", required, structures[required].pk) + else: + structure = orm.StructureData(ase=ase.io.read(DATA_DIR / required)) + structure.label = required + structure.store() + structures[required] = structure + print("created new structure: ", required, structure.pk) builder = Cp2kPdosWorkChain.get_builder() builder.metadata.label = "CP2K_PDOS" - builder.metadata.description = "test description" + builder.metadata.description = "automatic test PDOS" builder.cp2k_code = cp2k_code - ase_geom_slab = ase.io.read(DATA_DIR / GEO_FILE) - ase_geom_mol = ase_geom_slab[0:4] - builder.slabsys_structure = orm.StructureData(ase=ase_geom_slab) - builder.mol_structure = orm.StructureData(ase=ase_geom_mol) - builder.pdos_lists = orm.List([("1..4", "molecule"), ("1", "cat")]) + builder.structure = structures["c2h2_on_au111.xyz"] + builder.fragment_structure = structures["c2h2_for_pdos.xyz"] + builder.pdos_lists = orm.List([("1..4", "C2H2"), ("1", "C_at")]) builder.protocol = orm.Str("debug") if uks: dft_params = { @@ -46,7 +45,8 @@ def _example_cp2k_pdos( "elpa_switch": False, "periodic": "XYZ", "uks": uks, - "multiplicity": 1, + "multiplicities": {"all": 1, "fragment": 1}, + "charges": {"all": 0, "fragment": 0}, "smear_t": 150, "spin_up_guess": [0], "spin_dw_guess": [1], @@ -58,12 +58,13 @@ def _example_cp2k_pdos( "elpa_switch": False, "periodic": "XYZ", "uks": uks, + "charges": {"all": 0, "fragment": 0}, "smear_t": 150, } builder.dft_params = orm.Dict(dft_params) builder.options = { - "slab": { + "all": { "max_wallclock_seconds": 600, "resources": { "num_machines": n_nodes, @@ -71,7 +72,7 @@ def _example_cp2k_pdos( "num_cores_per_mpiproc": 1, }, }, - "molecule": { + "fragment": { "max_wallclock_seconds": 600, "resources": { "num_machines": n_nodes, @@ -84,16 +85,16 @@ def _example_cp2k_pdos( builder.overlap_code = overlap_code builder.overlap_params = orm.Dict( { - "--cp2k_input_file1": "parent_slab_folder/aiida.inp", - "--basis_set_file1": "parent_slab_folder/BASIS_MOLOPT", - "--xyz_file1": "parent_slab_folder/aiida.coords.xyz", - "--wfn_file1": "parent_slab_folder/aiida-RESTART.wfn", + "--cp2k_input_file1": "parent_all_folder/aiida.inp", + "--basis_set_file1": "parent_all_folder/BASIS_MOLOPT", + "--xyz_file1": "parent_all_folder/aiida.coords.xyz", + "--wfn_file1": "parent_all_folder/aiida-RESTART.wfn", "--emin1": "-2", "--emax1": "2", - "--cp2k_input_file2": "parent_mol_folder/aiida.inp", - "--basis_set_file2": "parent_mol_folder/BASIS_MOLOPT", - "--xyz_file2": "parent_mol_folder/aiida.coords.xyz", - "--wfn_file2": "parent_mol_folder/aiida-RESTART.wfn", + "--cp2k_input_file2": "parent_fragment_folder/aiida.inp", + "--basis_set_file2": "parent_fragment_folder/BASIS_MOLOPT", + "--xyz_file2": "parent_fragment_folder/aiida.coords.xyz", + "--wfn_file2": "parent_fragment_folder/aiida-RESTART.wfn", "--nhomo2": "2", "--nlumo2": "2", "--output_file": "./overlap.npz", @@ -129,8 +130,8 @@ def run_all(cp2k_code, overlap_code, n_nodes, n_cores_per_node): sc_diag=False, force_multiplicity=True, uks=False, - n_nodes=n_nodes, - n_cores_per_node=n_cores_per_node, + n_nodes=1, + n_cores_per_node=1, ) From d39add7cbec3ecf9a82f2a8665278c30b23d69c8 Mon Sep 17 00:00:00 2001 From: Carlo Antonio Pignedoli Date: Fri, 22 Sep 2023 10:56:47 +0000 Subject: [PATCH 9/9] bugs magnetization --- .../workflows/cp2k/diag_workchain.py | 5 ++++- examples/workflows/example_cp2k_pdos.py | 14 +++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/aiida_nanotech_empa/workflows/cp2k/diag_workchain.py b/aiida_nanotech_empa/workflows/cp2k/diag_workchain.py index dcf319c8..d1060640 100644 --- a/aiida_nanotech_empa/workflows/cp2k/diag_workchain.py +++ b/aiida_nanotech_empa/workflows/cp2k/diag_workchain.py @@ -88,7 +88,10 @@ def setup(self): # Get initial magnetization. magnetization_per_site = [0 for i in range(len(self.inputs.structure.sites))] if "uks" in self.ctx.dft_params and self.ctx.dft_params["uks"]: - magnetization_per_site = self.ctx.dft_params["magnetization_per_site"] + try: + magnetization_per_site = self.ctx.dft_params["magnetization_per_site"] + except KeyError: + pass structure_with_tags, kinds_dict = cp2k_utils.determine_kinds( structure, magnetization_per_site diff --git a/examples/workflows/example_cp2k_pdos.py b/examples/workflows/example_cp2k_pdos.py index 6c0ff60f..cc47ddf0 100644 --- a/examples/workflows/example_cp2k_pdos.py +++ b/examples/workflows/example_cp2k_pdos.py @@ -32,13 +32,13 @@ def _example_cp2k_pdos( builder = Cp2kPdosWorkChain.get_builder() builder.metadata.label = "CP2K_PDOS" - builder.metadata.description = "automatic test PDOS" builder.cp2k_code = cp2k_code builder.structure = structures["c2h2_on_au111.xyz"] builder.fragment_structure = structures["c2h2_for_pdos.xyz"] builder.pdos_lists = orm.List([("1..4", "C2H2"), ("1", "C_at")]) builder.protocol = orm.Str("debug") if uks: + builder.metadata.description = "automatic test PDOS UKS" dft_params = { "sc_diag": sc_diag, "force_multiplicity": force_multiplicity, @@ -46,12 +46,14 @@ def _example_cp2k_pdos( "periodic": "XYZ", "uks": uks, "multiplicities": {"all": 1, "fragment": 1}, + "magnetization_per_site": {"fragment": [0, 1, -1, 0]}, "charges": {"all": 0, "fragment": 0}, "smear_t": 150, "spin_up_guess": [0], "spin_dw_guess": [1], } else: + builder.metadata.description = "automatic test PDOS RKS" dft_params = { "sc_diag": sc_diag, "force_multiplicity": force_multiplicity, @@ -133,6 +135,16 @@ def run_all(cp2k_code, overlap_code, n_nodes, n_cores_per_node): n_nodes=1, n_cores_per_node=1, ) + print("#### sc_diag UKS magnetization guess only on fragment") + _example_cp2k_pdos( + orm.load_code(cp2k_code), + orm.load_code(overlap_code), + sc_diag=True, + force_multiplicity=True, + uks=True, + n_nodes=1, + n_cores_per_node=1, + ) if __name__ == "__main__":