Source code for atomate2.cp2k.sets.core
"""Module defining core CP2K input set generators."""
from __future__ import annotations
import logging
from dataclasses import dataclass
from typing import TYPE_CHECKING
from pymatgen.io.cp2k.utils import get_truncated_coulomb_cutoff
from atomate2.cp2k.sets.base import Cp2kInputGenerator
if TYPE_CHECKING:
from pymatgen.core import Structure
from pymatgen.io.cp2k.inputs import Cp2kInput
from pymatgen.io.cp2k.outputs import Cp2kOutput
logger = logging.getLogger(__name__)
[docs]
@dataclass
class StaticSetGenerator(Cp2kInputGenerator):
"""Class to generate CP2K static input sets."""
[docs]
def get_input_updates(self, *args, **kwargs) -> dict:
"""Get updates to the input for a static job."""
return {"run_type": "ENERGY_FORCE"}
[docs]
@dataclass
class RelaxSetGenerator(Cp2kInputGenerator):
"""
Class to generate CP2K relax sets.
I.e., sets for optimization of internal coordinates without cell parameter
optimization.
"""
[docs]
def get_input_updates(self, *args, **kwargs) -> dict:
"""Get updates to the input for a relax job."""
return {
"run_type": "GEO_OPT",
"activate_motion": {"optimizer": "BFGS", "trust_radius": 0.1},
}
[docs]
@dataclass
class CellOptSetGenerator(Cp2kInputGenerator):
"""
Class to generate CP2K cell optimization sets.
I.e., sets for optimization of both internal coordinates and the lattice vectors.
"""
[docs]
def get_input_updates(self, *args, **kwargs) -> dict:
"""Get updates to the input for a cell opt job."""
return {
"run_type": "CELL_OPT",
"activate_motion": {"optimizer": "BFGS", "trust_radius": 0.1},
}
[docs]
@dataclass
class HybridStaticSetGenerator(Cp2kInputGenerator):
"""Class for generating static hybrid input sets."""
[docs]
def get_input_updates(self, structure: Structure, *args, **kwargs) -> dict:
"""Get input updates for a hybrid calculation."""
updates: dict = {
"run_type": "ENERGY_FORCE",
"activate_hybrid": {
"hybrid_functional": "PBE0",
"screen_on_initial_p": False,
"screen_p_forces": False,
"eps_schwarz": 1e-7,
"eps_schwarz_forces": 1e-5,
},
}
if hasattr(structure, "lattice"):
updates["activate_hybrid"]["cutoff_radius"] = get_truncated_coulomb_cutoff(
structure
)
return updates
[docs]
@dataclass
class HybridRelaxSetGenerator(Cp2kInputGenerator):
"""Class for generating hybrid relaxation input sets."""
[docs]
def get_input_updates(self, structure: Structure, *args, **kwargs) -> dict:
"""Get input updates for a hybrid calculation."""
updates: dict = {
"run_type": "GEO_OPT",
"activate_motion": {"optimizer": "BFGS", "trust_radius": 0.1},
"activate_hybrid": {
"hybrid_functional": "PBE0",
"screen_on_initial_p": False,
"screen_p_forces": False,
"eps_schwarz": 1e-7,
"eps_schwarz_forces": 1e-5,
},
}
if hasattr(structure, "lattice"):
updates["activate_hybrid"]["cutoff_radius"] = get_truncated_coulomb_cutoff(
structure
)
return updates
[docs]
@dataclass
class HybridCellOptSetGenerator(Cp2kInputGenerator):
"""Class for generating hybrid cell optimization input sets."""
[docs]
def get_input_updates(self, structure: Structure, *args, **kwargs) -> dict:
"""Get input updates for a hybrid calculation."""
updates: dict = {
"run_type": "CELL_OPT",
"activate_motion": {"optimizer": "BFGS", "trust_radius": 0.1},
"activate_hybrid": {
"hybrid_functional": "PBE0",
"screen_on_initial_p": False,
"screen_p_forces": False,
"eps_schwarz": 1e-7,
"eps_schwarz_forces": 1e-5,
},
}
if hasattr(structure, "lattice"):
updates["activate_hybrid"]["cutoff_radius"] = get_truncated_coulomb_cutoff(
structure
)
return updates
[docs]
@dataclass
class NonSCFSetGenerator(Cp2kInputGenerator):
"""
Class to generate CP2K non-self-consistent field input sets.
**Note** cp2k doesn't have a true non scf option. All you can do is set
max_scf to 1, and use a pre-converged wavefunction. While this seems to
be the same, it means that the kpoint grid used to generate the restart file
needs to be present in the input set or the first scf step can slightly jump
away from the minimum that was found.
Parameters
----------
mode
Type of band structure mode. Options are "line", "uniform"
reciprocal_density
Density of k-mesh by reciprocal volume.
line_density
Line density for line mode band structure.
"""
mode: str = "line"
reciprocal_density: float = 100
line_density: float = 20
def __post_init__(self) -> None:
"""Ensure mode is set correctly."""
self.mode = self.mode.lower()
supported_modes = ("line", "uniform")
if self.mode not in supported_modes:
raise ValueError(f"Supported modes are: {', '.join(supported_modes)}")
[docs]
def get_kpoints_updates(
self,
structure: Structure,
prev_input: Cp2kInput = None,
) -> dict:
"""Get updates to the kpoints configuration for a non-self consistent VASP job.
Note, these updates will be ignored if the user has set user_kpoint_settings.
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 to the KPOINTS config.
"""
if self.mode == "line":
return {"line_density": self.line_density}
return {"reciprocal_density": self.reciprocal_density}
[docs]
def get_input_updates(
self,
structure: Structure,
prev_input: Cp2kInput = None,
cp2k_output: Cp2kOutput = None,
) -> dict:
"""Get input updates for a non scf calculation."""
return {
"max_scf": 1,
"print_bandstructure": True,
"kpoints_line_density": self.line_density if self.mode == "line" else 1,
"print_dos": True,
"print_pdos": False, # Not possible as of 2022.1
"print_mo_cubes": False,
"run_type": "ENERGY_FORCE",
}
[docs]
@dataclass
class MDSetGenerator(Cp2kInputGenerator):
"""Class to generate molecular dynamics input sets."""
[docs]
def get_input_updates(self, structure: Structure, *args, **kwargs) -> dict:
"""Get input updates for running a MD calculation."""
return {
"run_type": "MD",
"activate_motion": {
"ensemble": "NVT",
"temperature": 300,
"timestep": 2,
"nsteps": 1000,
"thermostat": "NOSE",
},
"print_bandstructure": False, # Disable printing
"print_dos": False,
"print_pdos": False,
"print_v_hartree": False,
"print_e_density": False,
"print_mo_cubes": False,
}