From d2d789f099d89256c740de0f48c1efaff2912bde Mon Sep 17 00:00:00 2001 From: David Waroquiers Date: Mon, 25 Sep 2023 12:55:41 +0200 Subject: [PATCH] Added vasp sets and jobs + ccsd workflow. --- src/pycc4s/workflows/flows/__init__.py | 1 + src/pycc4s/workflows/flows/core.py | 84 +++++++ src/pycc4s/workflows/jobs/core.py | 2 +- src/pycc4s/workflows/jobs/vasp.py | 1 + src/pycc4s/workflows/sets/vasp.py | 335 +++++++++++++++++++++++++ 5 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 src/pycc4s/workflows/flows/__init__.py create mode 100644 src/pycc4s/workflows/flows/core.py create mode 100644 src/pycc4s/workflows/jobs/vasp.py create mode 100644 src/pycc4s/workflows/sets/vasp.py diff --git a/src/pycc4s/workflows/flows/__init__.py b/src/pycc4s/workflows/flows/__init__.py new file mode 100644 index 0000000..de8d609 --- /dev/null +++ b/src/pycc4s/workflows/flows/__init__.py @@ -0,0 +1 @@ +"""Jobflow flows for pycc4s.""" diff --git a/src/pycc4s/workflows/flows/core.py b/src/pycc4s/workflows/flows/core.py new file mode 100644 index 0000000..bac4473 --- /dev/null +++ b/src/pycc4s/workflows/flows/core.py @@ -0,0 +1,84 @@ +"""Core module for cc4s flows.""" + + +from dataclasses import dataclass, field + +from atomate2.vasp.jobs.base import BaseVaspMaker +from atomate2.vasp.jobs.core import NonSCFMaker, StaticMaker +from jobflow import Flow, Maker + +from pycc4s.workflows.jobs.base import BaseCC4SMaker +from pycc4s.workflows.jobs.core import CoupledClusterCC4SMaker +from pycc4s.workflows.sets.vasp import ( + NonSCFHFNOsSetGenerator, + NonSCFHFSetGenerator, + NonSCFMP2CBSSetGenerator, + NonSCFMP2NOsSetGenerator, + StaticHFSetGenerator, + VaspDumpCc4sFilesGenerator, +) + + +@dataclass +class CoupledClusterMaker(Maker): + """Maker for coupled cluster flow.""" + + name: str = "Coupled Cluster" + dft_static_maker: BaseVaspMaker = field(default_factory=StaticMaker) + hf_static_maker: BaseVaspMaker = field( + default=StaticMaker(input_set_generator=StaticHFSetGenerator()) + ) + hf_nonscf_maker: BaseVaspMaker = field( + default=NonSCFMaker(input_set_generator=NonSCFHFSetGenerator()) + ) + mp2_cbs_maker: BaseVaspMaker = field( + default=NonSCFMaker(input_set_generator=NonSCFMP2CBSSetGenerator()) + ) + mp2_nos_maker: BaseVaspMaker = field( + default=NonSCFMaker(input_set_generator=NonSCFMP2NOsSetGenerator()) + ) + hf_nos_maker: BaseVaspMaker = field( + default=NonSCFMaker(input_set_generator=NonSCFHFNOsSetGenerator()) + ) + cc4s_generation_maker: BaseVaspMaker = field( + default=NonSCFMaker(input_set_generator=VaspDumpCc4sFilesGenerator()) + ) + coupled_cluster_cc4s_maker: BaseCC4SMaker = field(default=CoupledClusterCC4SMaker()) + + def make(self, structure): + """Return a coupled cluster flow.""" + dft_job = self.dft_static_maker.make(structure) + hf_job = self.hf_static_maker.make( + structure, prev_vasp_dir=dft_job.output.dir_name + ) + hf_diag_job = self.hf_nonscf_maker.make( + structure, prev_vasp_dir=hf_job.output.dir_name + ) + mp2_cbs_job = self.mp2_cbs_maker.make( + structure, prev_vasp_dir=hf_diag_job.output.dir_name + ) + mp2_nos_job = self.mp2_nos_maker.make( + structure, prev_vasp_dir=mp2_cbs_job.output.dir_name + ) + hf_nos_job = self.hf_nos_maker.make( + structure, prev_vasp_dir=mp2_nos_job.output.dir_name + ) + cc4s_gen_job = self.cc4s_generation_maker.make( + structure, prev_vasp_dir=hf_nos_job.output.dir_name + ) + cc4s_job = self.coupled_cluster_cc4s_maker.make( + structure, prev_dor=cc4s_gen_job.output.dir_name + ) + return Flow( + [ + dft_job, + hf_job, + hf_diag_job, + mp2_cbs_job, + mp2_nos_job, + hf_nos_job, + cc4s_gen_job, + cc4s_job, + ], + output=cc4s_job.output, + ) diff --git a/src/pycc4s/workflows/jobs/core.py b/src/pycc4s/workflows/jobs/core.py index 0575939..0bdaaa6 100644 --- a/src/pycc4s/workflows/jobs/core.py +++ b/src/pycc4s/workflows/jobs/core.py @@ -11,7 +11,7 @@ @dataclass -class CoupledClusterMaker(BaseCC4SMaker): +class CoupledClusterCC4SMaker(BaseCC4SMaker): """Maker for cc4s jobs.""" input_set_generator: CoupledClusterGenerator = CoupledClusterGenerator() diff --git a/src/pycc4s/workflows/jobs/vasp.py b/src/pycc4s/workflows/jobs/vasp.py new file mode 100644 index 0000000..b337777 --- /dev/null +++ b/src/pycc4s/workflows/jobs/vasp.py @@ -0,0 +1 @@ +"""Module for vasp jobs.""" diff --git a/src/pycc4s/workflows/sets/vasp.py b/src/pycc4s/workflows/sets/vasp.py new file mode 100644 index 0000000..dbac3c5 --- /dev/null +++ b/src/pycc4s/workflows/sets/vasp.py @@ -0,0 +1,335 @@ +"""Core input set generators for vasp. + +Note that this module will ultimately be moved to atomate2. +""" +from dataclasses import dataclass + +from atomate2.vasp.sets.base import VaspInputSetGenerator +from atomate2.vasp.sets.core import StaticSetGenerator +from pymatgen.core.structure import Structure +from pymatgen.io.vasp.outputs import Outcar, Vasprun + + +@dataclass +class StaticHFSetGenerator(StaticSetGenerator): + """Generator for static HF calculations.""" + + calc_type: str = "static_hf" + + def get_incar_updates( + self, + structure: Structure, + prev_incar: dict = None, + bandgap: float = 0, + vasprun: Vasprun = None, + outcar: Outcar = None, + ) -> dict: + """Get updates to the INCAR for a static VASP job. + + Parameters + ---------- + structure + A structure. + prev_incar + An incar from a previous calculation. + bandgap + The band gap. + vasprun + A vasprun from a previous calculation. + outcar + An outcar from a previous calculation. + + Returns + ------- + dict + A dictionary of updates to apply. + """ + updates = super().get_incar_updates( + structure, prev_incar, bandgap, vasprun, outcar + ) + updates["LHFCALC"] = True + updates["AEXX"] = 1.0 + updates["ALGO"] = "C" + return updates + + +@dataclass +class NonSCFHFSetGenerator(VaspInputSetGenerator): + """Class to generate VASP non-self-consistent field Hartree-Fock input sets.""" + + calc_type: str = "nonscf_hf" + + def get_incar_updates( + self, + structure: Structure, + prev_incar: dict = None, + bandgap: float = 0, + vasprun: Vasprun = None, + outcar: Outcar = None, + ) -> dict: + """Get updates to the INCAR for a static VASP job. + + Parameters + ---------- + structure + A structure. + prev_incar + An incar from a previous calculation. + bandgap + The band gap. + vasprun + A vasprun from a previous calculation. + outcar + An outcar from a previous calculation. + + Returns + ------- + dict + A dictionary of updates to apply. + """ + nb = max(outcar.data["nplwvs_at_kpoints"]) * 2 - 1 + updates = { + "LHFCALC": True, + "AEXX": 1.0, + "ISYM": -1, + "ALGO": "sub", + "NELM": 1, + "NBANDS": nb, + } + + # ENCUT = $enc + # SIGMA = 0.0001 + # EDIFF = 1E-6 + # LHFCALC =.TRUE. + # AEXX = 1.0 + # ISYM = -1 + # ALGO = sub; + # NELM = 1 + # NBANDS = $nb + return updates + + +@dataclass +class NonSCFMP2CBSSetGenerator(VaspInputSetGenerator): + """Class to generate VASP non-self-consistent field Hartree-Fock input sets.""" + + calc_type: str = "nonscf_hf" + + def get_incar_updates( + self, + structure: Structure, + prev_incar: dict = None, + bandgap: float = 0, + vasprun: Vasprun = None, + outcar: Outcar = None, + ) -> dict: + """Get updates to the INCAR for a static VASP job. + + Parameters + ---------- + structure + A structure. + prev_incar + An incar from a previous calculation. + bandgap + The band gap. + vasprun + A vasprun from a previous calculation. + outcar + An outcar from a previous calculation. + + Returns + ------- + dict + A dictionary of updates to apply. + """ + nb = max(outcar.data["nplwvs_at_kpoints"]) * 2 - 1 + updates = { + "LHFCALC": True, + "AEXX": 1.0, + "ISYM": -1, + "ALGO": "MP2", + "LSFACTOR": True, + "NBANDS": nb, + } + + # ENCUT = $enc + # SIGMA = 0.0001 + # LHFCALC =.TRUE. + # AEXX = 1.0 + # ISYM = -1 + # ALGO = MP2 + # NBANDS = $nb + # LSFACTOR =.TRUE. + return updates + + +@dataclass +class NonSCFMP2NOsSetGenerator(VaspInputSetGenerator): + """Class to generate VASP non-self-consistent field Hartree-Fock input sets.""" + + calc_type: str = "nonscf_hf" + + def get_incar_updates( + self, + structure: Structure, + prev_incar: dict = None, + bandgap: float = 0, + vasprun: Vasprun = None, + outcar: Outcar = None, + ) -> dict: + """Get updates to the INCAR for a static VASP job. + + Parameters + ---------- + structure + A structure. + prev_incar + An incar from a previous calculation. + bandgap + The band gap. + vasprun + A vasprun from a previous calculation. + outcar + An outcar from a previous calculation. + + Returns + ------- + dict + A dictionary of updates to apply. + """ + nb = max(outcar.data["nplwvs_at_kpoints"]) * 2 - 1 + updates = { + "LHFCALC": True, + "AEXX": 1.0, + "ISYM": -1, + "ALGO": "MP2NO", + "LAPPROX": True, + "NBANDS": nb, + } + + # ENCUT = $enc + # SIGMA = 0.0001 + # LHFCALC =.TRUE. + # AEXX = 1.0 + # ISYM = -1 + # ALGO = MP2NO; + # NBANDS = $nb + # LAPPROX =.TRUE. + return updates + + +@dataclass +class NonSCFHFNOsSetGenerator(VaspInputSetGenerator): + """Class to generate VASP non-self-consistent field Hartree-Fock input sets.""" + + calc_type: str = "nonscf_hf" + + def get_incar_updates( + self, + structure: Structure, + prev_incar: dict = None, + bandgap: float = 0, + vasprun: Vasprun = None, + outcar: Outcar = None, + ) -> dict: + """Get updates to the INCAR for a static VASP job. + + Parameters + ---------- + structure + A structure. + prev_incar + An incar from a previous calculation. + bandgap + The band gap. + vasprun + A vasprun from a previous calculation. + outcar + An outcar from a previous calculation. + + Returns + ------- + dict + A dictionary of updates to apply. + """ + nb = max(outcar.data["nplwvs_at_kpoints"]) * 2 - 1 + updates = { + "LHFCALC": True, + "AEXX": 1.0, + "ISYM": -1, + "ALGO": "MP2NO", + "LAPPROX": True, + "NBANDS": nb, + } + + # ENCUT = $enc + # SIGMA = 0.0001 + # EDIFF = 1E-6 + # LHFCALC =.TRUE. + # AEXX = 1.0 + # ISYM = -1 + # ALGO = sub; + # NELM = 1 + # NBANDS = $nbno + # NBANDSHIGH = $nbno + return updates + + +@dataclass +class VaspDumpCc4sFilesGenerator(VaspInputSetGenerator): + """Class to generate input set for dumping cc4s files.""" + + calc_type: str = "vasp_cc4s_dump" + nbfp: int = 6 + + def get_incar_updates( + self, + structure: Structure, + prev_incar: dict = None, + bandgap: float = 0, + vasprun: Vasprun = None, + outcar: Outcar = None, + ) -> dict: + """Get updates to the INCAR for a static VASP job. + + Parameters + ---------- + structure + A structure. + prev_incar + An incar from a previous calculation. + bandgap + The band gap. + vasprun + A vasprun from a previous calculation. + outcar + An outcar from a previous calculation. + + Returns + ------- + dict + A dictionary of updates to apply. + """ + outcar.nelect + nbno = 0 + updates = { + "LHFCALC": True, + "AEXX": 1.0, + "ISYM": -1, + "ALGO": "CC4S", + "NBANDS": nbno, + } + + # ENCUT = $enc + # SIGMA = 0.0001 + # EDIFF = 1E-5 + # LHFCALC =.TRUE. + # AEXX = 1.0 + # ISYM = -1 + # ALGO = CC4S + # NBANDS = $nbno + # NBANDSHIGH = $nbno + # ENCUTGW =$egw + # ENCUTGWSOFT =$egw + return updates