Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use HasHDF in various Vasp objects #1139

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 43 additions & 72 deletions pyiron_atomistics/dft/waves/electronic.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import numpy as np

from pyiron_base import HasHDF

from pyiron_atomistics.atomistics.structure.atoms import (
Atoms,
structure_dict_to_hdf,
Expand All @@ -25,7 +27,7 @@
__date__ = "Sep 1, 2017"


class ElectronicStructure(object):
class ElectronicStructure(HasHDF):
"""
This is a generic module to store electronic structure data in a clean way. Kpoint and Band classes are used to
store information related to kpoints and bands respectively. Every spin configuration has a set of k-points and
Expand Down Expand Up @@ -477,21 +479,22 @@ def grand_dos_matrix(self, val):
def __getitem__(self, item):
return self._output_dict[item]

def to_hdf(self, hdf, group_name="electronic_structure"):
def _get_hdf_group_name(self):
return "electronic_structure"

def _to_hdf(self, hdf):
"""
Store the object to hdf5 file

Args:
hdf: Path to the hdf5 file/group in the file
group_name: Name of the group under which the attributes are o be stored
"""
electronic_structure_dict_to_hdf(
data_dict=self.to_dict(), hdf=hdf, group_name=group_name
data_dict=self.to_dict(), hdf=hdf
)

def to_dict(self):
h_es = {
"TYPE": str(type(self)),
"k_points": self.kpoint_list,
"k_weights": self.kpoint_weights,
"eig_matrix": self.eigenvalue_matrix,
Expand All @@ -513,71 +516,42 @@ def to_dict(self):
h_es["dos"]["resolved_densities"] = self.resolved_densities
return h_es

def from_hdf(self, hdf, group_name="electronic_structure"):
def _from_hdf(self, hdf, version=None):
"""
Retrieve the object from the hdf5 file

Args:
hdf: Path to the hdf5 file/group in the file
group_name: Name of the group under which the attributes are stored
version: which version of this class was written to the HDF file
"""
if "dos" not in hdf[group_name].list_groups():
self.from_hdf_old(hdf=hdf, group_name=group_name)
if "dos" not in hdf.list_groups():
self.from_hdf_old(hdf=hdf[".."], group_name="electronic_structure")
else:
with hdf.open(group_name) as h_es:
if "TYPE" not in h_es.list_nodes():
h_es["TYPE"] = str(type(self))
nodes = h_es.list_nodes()
if self.structure is not None:
self.structure.to_hdf(h_es)
self.kpoint_list = h_es["k_points"]
self.kpoint_weights = h_es["k_weights"]
if len(h_es["eig_matrix"].shape) == 2:
self.eigenvalue_matrix = np.array([h_es["eig_matrix"]])
self.occupancy_matrix = np.array([h_es["occ_matrix"]])
else:
self._eigenvalue_matrix = h_es["eig_matrix"]
self._occupancy_matrix = h_es["occ_matrix"]
self.n_spins = len(self._eigenvalue_matrix)
if "efermi" in nodes:
self.efermi = h_es["efermi"]
with h_es.open("dos") as h_dos:
nodes = h_dos.list_nodes()
self.dos_energies = h_dos["energies"]
self.dos_densities = h_dos["tot_densities"]
self.dos_idensities = h_dos["int_densities"]
if "grand_dos_matrix" in nodes:
self.grand_dos_matrix = h_dos["grand_dos_matrix"]
if "resolved_densities" in nodes:
self.resolved_densities = h_dos["resolved_densities"]
self._output_dict = h_es.copy()
self.generate_from_matrices()

def to_hdf_old(self, hdf, group_name="electronic_structure"):
"""
Store the object to hdf5 file

Args:
hdf: Path to the hdf5 file/group in the file
group_name: Name of the group under which the attributes are o be stored
"""
with hdf.open(group_name) as h_es:
h_es["TYPE"] = str(type(self))
nodes = hdf.list_nodes()
if self.structure is not None:
self.structure.to_hdf(h_es)
h_es["k_points"] = self.kpoint_list
h_es["k_point_weights"] = self.kpoint_weights
h_es["eigenvalue_matrix"] = self.eigenvalue_matrix
h_es["occupancy_matrix"] = self.occupancy_matrix
h_es["dos_energies"] = self.dos_energies
h_es["dos_densities"] = self.dos_densities
h_es["dos_idensities"] = self.dos_idensities
if self.efermi is not None:
h_es["fermi_level"] = self.efermi
if self.grand_dos_matrix is not None:
h_es["grand_dos_matrix"] = self.grand_dos_matrix
if self.resolved_densities is not None:
h_es["resolved_densities"] = self.resolved_densities
self.structure.to_hdf(hdf)
self.kpoint_list = hdf["k_points"]
self.kpoint_weights = hdf["k_weights"]
if len(hdf["eig_matrix"].shape) == 2:
self.eigenvalue_matrix = np.array([hdf["eig_matrix"]])
self.occupancy_matrix = np.array([hdf["occ_matrix"]])
else:
self._eigenvalue_matrix = hdf["eig_matrix"]
self._occupancy_matrix = hdf["occ_matrix"]
self.n_spins = len(self._eigenvalue_matrix)
if "efermi" in nodes:
self.efermi = hdf["efermi"]
with hdf.open("dos") as hdf_dos:
nodes = hdf_dos.list_nodes()
self.dos_energies = hdf_dos["energies"]
self.dos_densities = hdf_dos["tot_densities"]
self.dos_idensities = hdf_dos["int_densities"]
if "grand_dos_matrix" in nodes:
self.grand_dos_matrix = hdf_dos["grand_dos_matrix"]
if "resolved_densities" in nodes:
self.resolved_densities = hdf_dos["resolved_densities"]
self._output_dict = hdf.copy()
self.generate_from_matrices()

def from_hdf_old(self, hdf, group_name="electronic_structure"):
"""
Expand Down Expand Up @@ -607,8 +581,6 @@ def from_hdf_old(self, hdf, group_name="electronic_structure"):
self.grand_dos_matrix = h_es["grand_dos_matrix"]
if "resolved_densities" in nodes:
self.resolved_densities = h_es["resolved_densities"]
self._output_dict = h_es.copy()
self.generate_from_matrices()

def generate_from_matrices(self):
"""
Expand Down Expand Up @@ -856,13 +828,12 @@ def resolved_dos_matrix(self, val):
self._resolved_dos_matrix = val


def electronic_structure_dict_to_hdf(data_dict, hdf, group_name):
with hdf.open(group_name) as h_es:
for k, v in data_dict.items():
if k not in ["structure", "dos"]:
h_es[k] = v
def electronic_structure_dict_to_hdf(data_dict, hdf):
for k, v in data_dict.items():
if k not in ["structure", "dos"]:
hdf[k] = v

if "structure" in data_dict.keys():
structure_dict_to_hdf(data_dict=data_dict["structure"], hdf=h_es)
if "structure" in data_dict.keys():
structure_dict_to_hdf(data_dict=data_dict["structure"], hdf=hdf)

dict_group_to_hdf(data_dict=data_dict, hdf=h_es, group="dos")
dict_group_to_hdf(data_dict=data_dict, hdf=hdf, group="dos")
12 changes: 4 additions & 8 deletions pyiron_atomistics/vasp/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2571,8 +2571,7 @@ def generic_output_dict_to_hdf(data_dict, hdf, group_name="generic"):
if "bands" in data_dict["dft"].keys():
electronic_structure_dict_to_hdf(
data_dict=data_dict["dft"]["bands"],
hdf=hdf_dft,
group_name="bands",
hdf=hdf_dft.create_group("bands")
)


Expand Down Expand Up @@ -2606,22 +2605,19 @@ def output_dict_to_hdf(data_dict, hdf, group_name="output"):
if "electrostatic_potential" in data_dict.keys():
volumetric_data_dict_to_hdf(
data_dict=data_dict["electrostatic_potential"],
hdf=hdf5_output,
group_name="electrostatic_potential",
hdf=hdf5_output.create_group("electrostatic_potential")
)

if "charge_density" in data_dict.keys():
volumetric_data_dict_to_hdf(
data_dict=data_dict["charge_density"],
hdf=hdf5_output,
group_name="charge_density",
hdf=hdf5_output.create_group("charge_density")
)

if "electronic_structure" in data_dict.keys():
electronic_structure_dict_to_hdf(
data_dict=data_dict["electronic_structure"],
hdf=hdf5_output,
group_name="electronic_structure",
hdf=hdf5_output.create_group("electronic_structure")
)

dict_group_to_hdf(data_dict=data_dict, hdf=hdf5_output, group="outcar")
24 changes: 13 additions & 11 deletions pyiron_atomistics/vasp/outcar.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import scipy.constants
import re

from pyiron_base import HasHDF

__author__ = "Sudarsan Surendralal"
__copyright__ = (
"Copyright 2021, Max-Planck-Institut für Eisenforschung GmbH - "
Expand All @@ -24,7 +26,7 @@
)


class Outcar(object):
class Outcar(HasHDF):
"""
This module is used to parse VASP OUTCAR files.

Expand Down Expand Up @@ -132,17 +134,18 @@ def from_file(self, filename="OUTCAR"):
except IndexError:
self.parse_dict["pressures"] = np.zeros(len(steps))

def to_hdf(self, hdf, group_name="outcar"):
def _get_hdf_group_name(self):
return "outcar"

def _to_hdf(self, hdf):
"""
Store output in an HDF5 file

Args:
hdf (pyiron_base.generic.hdfio.FileHDFio): HDF5 group or file
group_name (str): Name of the HDF5 group
"""
with hdf.open(group_name) as hdf5_output:
for key in self.parse_dict.keys():
hdf5_output[key] = self.parse_dict[key]
for key in self.parse_dict:
hdf[key] = self.parse_dict[key]

def to_hdf_minimal(self, hdf, group_name="outcar"):
"""
Expand Down Expand Up @@ -173,17 +176,16 @@ def to_dict_minimal(self):
hdf5_output[key] = self.parse_dict[key]
return hdf5_output

def from_hdf(self, hdf, group_name="outcar"):
def _from_hdf(self, hdf, version=None):
"""
Load output from an HDF5 file

Args:
hdf (pyiron_base.generic.hdfio.FileHDFio): HDF5 group or file
group_name (str): Name of the HDF5 group
version (str): version of the class that was written to the HDF5 file
"""
with hdf.open(group_name) as hdf5_output:
for key in hdf5_output.list_nodes():
self.parse_dict[key] = hdf5_output[key]
for key in hdf.list_nodes():
self.parse_dict[key] = hdf[key]

def get_vasp_version(self, filename="OUTCAR", lines=None):
return lines[0].lstrip().split(sep=" ")[0]
Expand Down
29 changes: 14 additions & 15 deletions pyiron_atomistics/vasp/volumetric_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import numpy as np
import os
from pyiron_base import state
from pyiron_base import state, HasHDF
from pyiron_atomistics.vasp.structure import (
atoms_from_string,
get_species_list_from_potcar,
Expand All @@ -25,7 +25,7 @@
__date__ = "Sep 1, 2017"


class VaspVolumetricData(VolumetricData):
class VaspVolumetricData(VolumetricData, HasHDF):
"""
General class for parsing and manipulating volumetric static within VASP. The basic idea of the Base class is
adapted from the pymatgen vasp VolumtricData class
Expand Down Expand Up @@ -286,40 +286,39 @@ def to_dict(self):
volumetric_data_dict["diff"] = self.diff_data
return volumetric_data_dict

def to_hdf(self, hdf, group_name="volumetric_data"):
def _get_hdf_group_name(self):
return "volumetric_data"

def _to_hdf(self, hdf):
"""
Writes the data as a group to a HDF5 file

Args:
hdf (pyiron_base.generic.hdfio.ProjectHDFio): The HDF file/path to write the data to
group_name (str): The name of the group under which the data must be stored as

"""
volumetric_data_dict_to_hdf(
data_dict=self.to_dict(),
hdf=hdf,
group_name=group_name,
)

def from_hdf(self, hdf, group_name="volumetric_data"):
def _from_hdf(self, hdf, version=None):
"""
Recreating the VolumetricData instance by reading data from the HDF5 files

Args:
hdf (pyiron_base.generic.hdfio.ProjectHDFio): The HDF file/path to write the data to
group_name (str): The name of the group under which the data must be stored as
version (str): version of the class that was written to the HDF5 file

Returns:
pyiron.atomistics.volumetric.generic.VolumetricData: The VolumetricData instance

"""
with hdf.open(group_name) as hdf_vd:
self._total_data = hdf_vd["total"]
if "diff" in hdf_vd.list_nodes():
self._diff_data = hdf_vd["diff"]
self._total_data = hdf["total"]
if "diff" in hdf.list_nodes():
self._diff_data = hdf["diff"]


def volumetric_data_dict_to_hdf(data_dict, hdf, group_name="volumetric_data"):
with hdf.open(group_name) as hdf_vd:
for k, v in data_dict.items():
hdf_vd[k] = v
def volumetric_data_dict_to_hdf(data_dict, hdf):
for k, v in data_dict.items():
hdf[k] = v