Source code for dftbplus_step.choose_parameters
# -*- coding: utf-8 -*-
"""Setup DFTB+"""
import logging
from pathlib import Path
import dftbplus_step
import seamm
import seamm.data
from seamm_util import units_class
import seamm_util.printing as printing
from seamm_util.printing import FormattedText as __
from .base import DftbBase
logger = logging.getLogger(__name__)
job = printing.getPrinter()
printer = printing.getPrinter("DFTB+")
[docs]
class ChooseParameters(DftbBase):
def __init__(
self, flowchart=None, title="Choose Parameters", extension=None, logger=logger
):
"""Initialize the node"""
logger.debug("Creating ChooseParameters {}".format(self))
super().__init__(flowchart=flowchart, title=title, extension=extension)
self.parameters = dftbplus_step.ChooseParametersParameters()
self.description = ["Choose Slater-Koster parameters for DFTB+"]
@property
def is_runable(self):
"""Indicate whether this not runs or just adds input."""
return False
@property
def header(self):
"""A printable header for this section of output"""
return "Step {}: {}".format(".".join(str(e) for e in self._id), self.title)
@property
def version(self):
"""The semantic version of this module."""
return dftbplus_step.__version__
@property
def git_revision(self):
"""The git version of this module."""
return dftbplus_step.__git_revision__
[docs]
def description_text(self, P=None):
"""Prepare information about what this node will do"""
if not P:
P = self.parameters.values_to_dict()
dataset = P["dataset"]
subset = P["subset"]
text = f"Using the '{dataset}' set of Slater-Koster parameters"
if subset != "none":
text += f" with the specialized set '{subset}' added."
else:
text += "."
return self.header + "\n" + __(text, indent=4 * " ").__str__()
[docs]
def get_input(self):
"""Get the input for the Slater-Koster parameters for DFTB+"""
# Get the metadata for the Slater-Koster parameters
metadata = self.parent._metadata
slako_dir = Path(self.exe_config["slako-dir"]).expanduser()
# Create the directory
directory = Path(self.directory)
directory.mkdir(parents=True, exist_ok=True)
P = self.parameters.current_values_to_dict(
context=seamm.flowchart_variables._data
)
# Have to fix formatting for printing...
PP = dict(P)
for key in PP:
if isinstance(PP[key], units_class):
PP[key] = "{:~P}".format(PP[key])
self.description = []
self.description.append(__(self.description_text(PP), **PP, indent=4 * " "))
# The parameter data
parameter_set = P["dataset"]
if " - " not in parameter_set:
# From a variable ... find it!
for model in metadata.keys():
tmp = f"{model} - {parameter_set}"
if tmp in metadata[model]["datasets"]:
parameter_set = tmp
break
model, parameter_set_name = parameter_set.split(" - ", 1)
datasets = metadata[model]["datasets"]
dataset = datasets[parameter_set]
system_db = self.get_variable("_system_db")
configuration = system_db.system.configuration
parameters = {}
elements = set(configuration.atoms.symbols)
elements = sorted([*elements])
if model == "DFTB":
potentials = metadata[model]["potentials"]
pairs = dataset["potential pairs"]
self.model = parameter_set.replace(" - ", "/")
if P["subset"] == "none" or P["subset"] == "":
subset = None
else:
subset = P["subset"]
if " - " not in subset:
# From a variable
subset = f"{model} - {subset}"
self.model += "+" + subset.split(" - ")[1]
subset = datasets[subset]
subpairs = subset["potential pairs"]
# Broadcast to the parent so that other substeps can use
self.parent._dataset = dataset
self.parent._subset = subset
for el1 in elements:
for el2 in elements:
key = f"{el1}-{el2}"
# Not sure if flipping the key is valid....
key2 = f"{el2}-{el1}"
if subset is not None and key in subpairs:
md5sum = subpairs[key]["md5sum"]
elif key in pairs:
md5sum = pairs[key]["md5sum"]
elif subset is not None and key2 in subpairs:
md5sum = subpairs[key2]["md5sum"]
elif key2 in pairs:
md5sum = pairs[key2]["md5sum"]
else:
raise RuntimeError(
f"Could not find the Slater-Koster file for {key} "
f"for dataset {P['dataset']}, subset {P['subset']}."
)
parameters[key] = str(slako_dir / potentials[md5sum]["filename"])
# The maximum angular momentum
data = dataset["element data"]
if subset is not None and "element data" in subset:
subdata = subset["element data"]
else:
subdata = None
references = set()
max_momentum = {}
key = "maximum angular momentum"
for el in elements:
if subdata is not None and el in subdata and key in subdata[el]:
max_momentum[el] = subdata[el][key]
if "citations" in subdata[el]:
for reference in subdata[el]["citations"]:
references.add(reference)
else:
max_momentum[el] = data[el][key]
if "citations" in data[el]:
for reference in data[el]["citations"]:
references.add(reference)
result = {
"Hamiltonian": {
"DFTB": {
"SlaterKosterFiles": parameters,
"MaxAngularMomentum": max_momentum,
}
}
}
# Check if we have Hubbard derivatives
key = "Hubbard derivative"
derivative = {}
for el in elements:
if subdata is not None and el in subdata and key in subdata[el]:
derivative[el] = subdata[el][key]
elif el in data and key in data[el]:
derivative[el] = data[el][key]
if len(derivative) > 0:
result["Hamiltonian"]["DFTB"]["HubbardDerivs"] = derivative
# Check if we have reference energies
key = "reference energy"
tmp = {}
for el in elements:
if subdata is not None and el in subdata and key in subdata[el]:
tmp[el] = float(subdata[el][key])
elif el in data and key in data[el]:
tmp[el] = float(data[el][key])
else:
tmp = None
break
self.parent._reference_energies = tmp
# Add the references
for reference in references:
self.references.cite(
raw=self._bibliography[reference],
alias=reference,
module="dftb+ step",
level=1,
note="A reference for the DFTB+ Slater-Koster parameters.",
)
elif model == "xTB":
# Broadcast to the parent so that other substeps can use
self.model = P["dataset"].replace(" - ", "/")
self.parent._dataset = dataset
self.parent._subset = None
parameter_set_name = parameter_set_name + "-xTB"
result = {
"Hamiltonian": {
"xTB": {
"Method": parameter_set_name,
}
}
}
# Add the references
references = dataset["citations"]
for reference in references:
self.references.cite(
raw=self._bibliography[reference],
alias=reference,
module="dftb+ step",
level=1,
note="A reference for the xTB method and parameters.",
)
return result
[docs]
def analyze(self, indent="", data={}, out=[]):
"""Parse the output and generating the text output and store the
data in variables for other stages to access
"""
pass