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

Feat: Add OSZICAR information to HDF5 #136

Merged
merged 46 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
7497775
Convert a Series to a frame through the to_frame method in Series
sudarshanv01 Aug 1, 2023
02d54b6
Implement to_frame for sequence of series
sudarshanv01 Aug 1, 2023
c557f72
Alter to_frame to allow it to take in multiple y-inputs
sudarshanv01 Aug 1, 2023
efca677
Refactor to_frame
sudarshanv01 Aug 1, 2023
9d180c7
Add width to series
sudarshanv01 Aug 1, 2023
18b268d
assert in to_frame that the dimension of weight and y is the same
sudarshanv01 Aug 2, 2023
0bd3f51
Allow different length series to to_frame
sudarshanv01 Aug 2, 2023
cda4814
Create the to_csv method
sudarshanv01 Aug 2, 2023
be04713
Implement to_csv method in the Mixin class
sudarshanv01 Aug 2, 2023
0b35fe1
Add to_csv and to_frame to the Mixin class
sudarshanv01 Aug 3, 2023
30b0b13
Apply black and isort
sudarshanv01 Aug 3, 2023
f5a4881
Added not_core to tests needing pandas
sudarshanv01 Aug 3, 2023
bafcb11
black and isort code formatting
sudarshanv01 Aug 3, 2023
b6db94c
Added more not_core to graph tests
sudarshanv01 Aug 3, 2023
ad66601
Change resolve to absolute when getting absolute path for mixin tests
sudarshanv01 Aug 3, 2023
92b51a4
Added documentation for the and methods
sudarshanv01 Aug 3, 2023
623124a
Update developer depedencies with ipykernel
sudarshanv01 Aug 3, 2023
bcb6f89
Merge branch 'vasp-dev:master' into master
sudarshanv01 Aug 3, 2023
a907827
Allow install github actions to run on pull requests
sudarshanv01 Aug 3, 2023
0d5838f
Merge branch 'master' of github.com:sudarshanv01/py4vasp
sudarshanv01 Aug 3, 2023
7f8739f
Added pip installation of ipykernel into install.yaml
sudarshanv01 Aug 3, 2023
f4f1515
Merge branch 'vasp-dev:master' into master
sudarshanv01 Aug 3, 2023
5c1240d
add pre-commit-config.yaml and pre-commit as a dependency
sudarshanv01 Aug 3, 2023
9a32998
Merge branch 'master' of github.com:sudarshanv01/py4vasp
sudarshanv01 Aug 3, 2023
0671d9e
Merge branch 'master' of github.com:vasp-dev/py4vasp
sudarshanv01 Sep 10, 2023
e5e244e
Merge branch 'master' of github.com:vasp-dev/py4vasp
sudarshanv01 Sep 25, 2023
f578627
Merge branch 'master' of github.com:vasp-dev/py4vasp
sudarshanv01 Oct 4, 2023
1af7627
Create raw and schema addition for OSZICAR
sudarshanv01 Feb 1, 2024
cacb5d1
Outline of oszicar to_dict
sudarshanv01 Feb 2, 2024
e1535f3
Outline of oszicar to_dict
sudarshanv01 Feb 2, 2024
9f8a0ae
Merge branch 'master' of github.com:vasp-dev/py4vasp
sudarshanv01 Feb 2, 2024
1f0cb70
Merge branch 'master' into oszicar-info
sudarshanv01 Feb 2, 2024
26b97a3
Make the OSZICAR capitalized
sudarshanv01 Feb 2, 2024
45166b7
Implement hdf5 to py4vasp oszicar _data
sudarshanv01 Feb 4, 2024
c4573a5
add test for factory method
sudarshanv01 Feb 4, 2024
6708984
Change implementation to take mixins
sudarshanv01 Feb 4, 2024
b7382ec
implement a to_graph method
sudarshanv01 Feb 4, 2024
455275b
Merge branch 'master' of github.com:vasp-dev/py4vasp
sudarshanv01 Feb 4, 2024
0908451
Merge branch 'master' into oszicar-info
sudarshanv01 Feb 4, 2024
5fe54e1
changes to make everything conform with recent changes in master
sudarshanv01 Feb 4, 2024
10454b1
Add documentation
sudarshanv01 Feb 5, 2024
781a4af
Remove error commit of data.py
sudarshanv01 Feb 12, 2024
3005e09
change y-label with selection
sudarshanv01 Feb 12, 2024
bf4a2bf
Fix label in tests
sudarshanv01 Feb 12, 2024
33c6f2a
Move OSZICAR schema
sudarshanv01 Feb 22, 2024
8d47dad
Fix slice issue with oszicar
sudarshanv01 Feb 22, 2024
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
12 changes: 12 additions & 0 deletions src/py4vasp/_raw/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,18 @@ class Magnetism:
"Contains the orbital magnetization for all atoms"


@dataclasses.dataclass
class OSZICAR:
"""The OSZICAR data as generated by VASP.

All data generated by VASP and traditionally stored in the OSZICAR file will be
stored here. See https://www.vasp.at/wiki/index.php/OSZICAR for more details about
what quantities to expect."""

convergence_data: VaspData
"All columns of the OSZICAR file stored for all ionic steps."


@dataclasses.dataclass
class PairCorrelation:
"""The pair-correlation function calculated during a MD simulation.
Expand Down
6 changes: 6 additions & 0 deletions src/py4vasp/_raw/definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,12 @@ def selections(quantity):
orbital_moments="intermediate/ion_dynamics/magnetism/orbital_moments/values",
)
#
schema.add(
raw.OSZICAR,
required=raw.Version(6, 5),
convergence_data="intermediate/ion_dynamics/oszicar",
)
#
group = "intermediate/pair_correlation"
schema.add(
raw.PairCorrelation,
Expand Down
2 changes: 1 addition & 1 deletion src/py4vasp/_util/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def to_complex(array):


def quantity_name(quantity):
if quantity == "CONTCAR":
if quantity in ["CONTCAR", "OSZICAR"]:
return quantity
else:
return _to_snakecase(quantity)
Expand Down
103 changes: 103 additions & 0 deletions src/py4vasp/calculation/_OSZICAR.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Copyright © VASP Software GmbH,
# Licensed under the Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)

import numpy as np

from py4vasp import exception, raw
from py4vasp._third_party import graph
from py4vasp._util import convert
from py4vasp.calculation import _base, _slice, _structure

INDEXING_OSZICAR = {
"iteration_number": 0,
"free_energy": 1,
"free_energy_change": 2,
"bandstructure_energy_change": 3,
"number_hamiltonian_evaluations": 4,
"norm_residual": 5,
"difference_charge_density": 6,
}


class OSZICAR(_slice.Mixin, _base.Refinery, graph.Mixin):
"""Access the convergence data for each electronic step.

The OSZICAR file written out by VASP stores information related to convergence.
Please check the vasp-wiki (https://www.vasp.at/wiki/index.php/OSZICAR) for more
details about the exact outputs generated for each combination of INCAR tags."""

@_base.data_access
def to_dict(self, selection=None):
"""Extract convergence data from the HDF5 file and make it available in a dict

Parameters
----------
selection: str
Choose from either iteration_number, free_energy, free_energy_change,
bandstructure_energy_change, number_hamiltonian_evaluations, norm_residual,
difference_charge_density to get specific columns of the OSZICAR file. In
case no selection is provided, supply all columns.

Returns
-------
dict
Contains a dict from the HDF5 related to OSZICAR convergence data
"""
return_data = {}
if selection is None:
keys_to_include = INDEXING_OSZICAR
else:
if keys_to_include not in INDEXING_OSZICAR:
message = """\
Please choose a selection including at least one of the following keywords:
iteration_number, free_energy, free_energy_change, bandstructure_energy_change,
number_hamiltonian_evaluations, norm_residual, difference_charge_density. Else do not
select anything and all OSZICAR outputs will be provided."""
raise exception.RefinementError(message)
keys_to_include = selection
for key in INDEXING_OSZICAR:
return_data[key] = self._read(key)
return return_data

def _read(self, key):
# data represents all of the electronic steps for all ionic steps
data = getattr(self._raw_data, "convergence_data")
iteration_number = data[:, 0]
split_index = np.where(iteration_number == 1)[0]
data = np.vsplit(data, split_index)[1:][self._steps]
if isinstance(self._steps, slice):
data = [raw.VaspData(_data) for _data in data]
else:
data = [raw.VaspData(data)]
data_index = INDEXING_OSZICAR[key]
return_data = [list(_data[:, data_index]) for _data in data]
is_none = [_data.is_none() for _data in data]
if len(return_data) == 1:
return_data = return_data[0]
return return_data if not np.all(is_none) else {}

def to_graph(self, selection="free_energy"):
"""Graph the change in parameter with iteration number.

Parameters
----------
selection: str
Choose from either iteration_number, free_energy, free_energy_change,
bandstructure_energy_change, number_hamiltonian_evaluations, norm_residual,
difference_charge_density to get specific columns of the OSZICAR file. In
case no selection is provided, the free energy is plotted.

Returns
-------
Graph
The Graph with the quantity plotted on y-axis and the iteration number of
the x-axis.
"""
data = self.to_dict()
series = graph.Series(data["iteration_number"], data[selection], selection)
ylabel = " ".join(select.capitalize() for select in selection.split("_"))
return graph.Graph(
series=[series],
xlabel="Iteration number",
ylabel=ylabel,
)
1 change: 1 addition & 0 deletions src/py4vasp/calculation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class provides a more flexible interface with which you can determine the source
"internal_strain",
"kpoint",
"magnetism",
"OSZICAR",
"pair_correlation",
"phonon_band",
"phonon_dos",
Expand Down
52 changes: 52 additions & 0 deletions tests/calculation/test_oszicar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright © VASP Software GmbH,
# Licensed under the Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)

import types

import pytest

from py4vasp import calculation


@pytest.fixture
def OSZICAR(raw_data):
raw_oszicar = raw_data.OSZICAR()
oszicar = calculation.OSZICAR.from_data(raw_oszicar)
oszicar.ref = types.SimpleNamespace()
convergence_data = raw_oszicar.convergence_data
oszicar.ref.iteration_number = convergence_data[:, 0]
oszicar.ref.free_energy = convergence_data[:, 1]
oszicar.ref.free_energy_change = convergence_data[:, 2]
oszicar.ref.bandstructure_energy_change = convergence_data[:, 3]
oszicar.ref.number_hamiltonian_evaluations = convergence_data[:, 4]
oszicar.ref.norm_residual = convergence_data[:, 5]
oszicar.ref.difference_charge_density = convergence_data[:, 6]
return oszicar


def test_read(OSZICAR, Assert):
actual = OSZICAR.read()
expected = OSZICAR.ref
Assert.allclose(actual["iteration_number"], expected.iteration_number)
Assert.allclose(actual["free_energy"], expected.free_energy)
Assert.allclose(actual["free_energy_change"], expected.free_energy_change)
Assert.allclose(
actual["bandstructure_energy_change"], expected.bandstructure_energy_change
)
Assert.allclose(
actual["number_hamiltonian_evaluations"],
expected.number_hamiltonian_evaluations,
)
Assert.allclose(actual["norm_residual"], expected.norm_residual)
Assert.allclose(
actual["difference_charge_density"], expected.difference_charge_density
)


def test_plot(OSZICAR, Assert):
graph = OSZICAR.plot()
assert graph.xlabel == "Iteration number"
assert graph.ylabel == "Free Energy"
assert len(graph.series) == 1
Assert.allclose(graph.series[0].x, OSZICAR.ref.iteration_number)
Assert.allclose(graph.series[0].y, OSZICAR.ref.free_energy)
12 changes: 12 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ def CONTCAR(selection):
else:
raise exception.NotImplemented()

@staticmethod
def OSZICAR(selection=None):
return _example_OSZICAR()

@staticmethod
def density(selection):
parts = selection.split()
Expand Down Expand Up @@ -649,6 +653,14 @@ def _Sr2TiO4_cell():
)


def _example_OSZICAR():
random_convergence_data = np.random.rand(9, 6)
iteration_number = np.arange(1, 10)[:, np.newaxis]
convergence_data = np.hstack([iteration_number, random_convergence_data])
convergence_data = raw.VaspData(convergence_data)
return raw.OSZICAR(convergence_data=convergence_data)


def _Sr2TiO4_CONTCAR():
structure = _Sr2TiO4_structure()
structure.cell.lattice_vectors = structure.cell.lattice_vectors[-1]
Expand Down
Loading