Skip to content

Commit

Permalink
Fix orbital moments (#166)
Browse files Browse the repository at this point in the history
* Fix: VASP does not write charge component for orbital moments
* Rename Calculations -> Batch
* Rename topology -> stoichiometry
  • Loading branch information
martin-schlipf authored Jan 28, 2025
1 parent b1009cd commit c4e5cd3
Show file tree
Hide file tree
Showing 78 changed files with 888 additions and 888 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test_full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
run: |
python --version
python -m pip install --progress-bar=off --upgrade pip
pip install --progress-bar=off "poetry!=1.4.1"
pip install --progress-bar=off "poetry<2"
- name: Install py4vasp
shell: bash -el {0}
run: |
Expand Down
5 changes: 2 additions & 3 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/py4vasp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Copyright © VASP Software GmbH,
# Licensed under the Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
from py4vasp._analysis.mlff import MLFFErrorAnalysis
from py4vasp._calculations import Calculations
from py4vasp._batch import Batch
from py4vasp._calculation import Calculation, calculation
from py4vasp._third_party.graph import plot
from py4vasp._third_party.interactive import set_error_handling
from py4vasp.calculation._class import Calculation

__version__ = "0.10.0"
set_error_handling("Minimal")
32 changes: 14 additions & 18 deletions src/py4vasp/_analysis/mlff.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ def __init__(self, *args, **kwargs):
self.dft = SimpleNamespace()

@classmethod
def _from_data(cls, _calculations):
def _from_data(cls, batch):
mlff_error_analysis = cls(_internal=True)
mlff_error_analysis._calculations = _calculations
mlff_error_analysis._batch = batch
set_appropriate_attrs(mlff_error_analysis)
return mlff_error_analysis

Expand All @@ -72,10 +72,8 @@ def from_paths(cls, dft_data, mlff_data):
Path to the MLFF data. Accepts wildcards.
"""
mlff_error_analysis = cls(_internal=True)
calculations = py4vasp.Calculations.from_paths(
dft_data=dft_data, mlff_data=mlff_data
)
mlff_error_analysis._calculations = calculations
batch = py4vasp.Batch.from_paths(dft_data=dft_data, mlff_data=mlff_data)
mlff_error_analysis._batch = batch
set_appropriate_attrs(mlff_error_analysis)
return mlff_error_analysis

Expand All @@ -95,10 +93,8 @@ def from_files(cls, dft_data, mlff_data):
Path to the MLFF data. Accepts wildcards.
"""
mlff_error_analysis = cls(_internal=True)
calculations = py4vasp.Calculations.from_files(
dft_data=dft_data, mlff_data=mlff_data
)
mlff_error_analysis._calculations = calculations
batch = py4vasp.Batch.from_files(dft_data=dft_data, mlff_data=mlff_data)
mlff_error_analysis._batch = batch
set_appropriate_attrs(mlff_error_analysis)
return mlff_error_analysis

Expand Down Expand Up @@ -213,7 +209,7 @@ def set_number_of_configurations(cls):
cls : MLFFErrorAnalysis
An instance of MLFFErrorAnalysis.
"""
number_of_calculations = cls._calculations.number_of_calculations()
number_of_calculations = cls._batch.number_of_calculations()
cls.dft.nconfig = number_of_calculations["dft_data"]
cls.mlff.nconfig = number_of_calculations["mlff_data"]

Expand All @@ -229,7 +225,7 @@ def set_number_of_ions(cls):
cls : MLFFErrorAnalysis
An instance of MLFFErrorAnalysis.
"""
force_data = cls._calculations.forces.read()
force_data = cls._batch.forces.read()
structures_dft = _dict_to_list(force_data["dft_data"], "structure")
structures_mlff = _dict_to_list(force_data["mlff_data"], "structure")
elements_dft = _dict_to_array(structures_dft, "elements")
Expand All @@ -252,11 +248,11 @@ def set_paths_and_files(cls):
cls : MLFFErrorAnalysis
An instance of MLFFErrorAnalysis.
"""
paths = cls._calculations.paths()
paths = cls._batch.paths()
cls.dft.paths = paths["dft_data"]
cls.mlff.paths = paths["mlff_data"]
if hasattr(cls._calculations, "_files"):
files = cls._calculations.files()
if hasattr(cls._batch, "_files"):
files = cls._batch.files()
cls.dft.files = files["dft_data"]
cls.mlff.files = files["mlff_data"]

Expand All @@ -273,7 +269,7 @@ def set_energies(cls):
An instance of MLFFErrorAnalysis.
"""
tag = "free energy TOTEN"
energies_data = cls._calculations.energies.read()
energies_data = cls._batch.energies.read()
cls.mlff.energies = _dict_to_array(energies_data["mlff_data"], tag)
cls.dft.energies = _dict_to_array(energies_data["dft_data"], tag)

Expand All @@ -298,7 +294,7 @@ def set_force_related_attributes(cls):
cls : MLFFErrorAnalysis
An instance of MLFFErrorAnalysis.
"""
force_data = cls._calculations.forces.read()
force_data = cls._batch.forces.read()
cls.dft.forces = _dict_to_array(force_data["dft_data"], "forces")
cls.mlff.forces = _dict_to_array(force_data["mlff_data"], "forces")
dft_structures = _dict_to_list(force_data["dft_data"], "structure")
Expand All @@ -320,6 +316,6 @@ def set_stresses(cls):
cls : MLFFErrorAnalysis
An instance of MLFFErrorAnalysis.
"""
stress_data = cls._calculations.stresses.read()
stress_data = cls._batch.stresses.read()
cls.dft.stresses = _dict_to_array(stress_data["dft_data"], "stress")
cls.mlff.stresses = _dict_to_array(stress_data["mlff_data"], "stress")
16 changes: 8 additions & 8 deletions src/py4vasp/_calculations.py → src/py4vasp/_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@
from py4vasp._util import convert


class Calculations:
"""A class to handle multiple Calculations all at once.
class Batch:
"""A class to handle batch of multiple calculations at once.
This class combines the functionality of the Calculation class for more than one
calculation. Create a Calculations object using either a wildcard for a set of
calculation. Create a Batch object using either a wildcard for a set of
paths or files or pass in paths and files directly. Then you can access the
properties of all calculations via the attributes of the object.
Examples
--------
>>> calcs = Calculations.from_paths(calc1="path_to_calc1", calc2="path_to_calc2")
>>> calcs = Batch.from_paths(calc1="path_to_calc1", calc2="path_to_calc2")
>>> calcs.energies.read() # returns a dictionary with the energies of calc1 and calc2
>>> calcs.forces.read() # returns a dictionary with the forces of calc1 and calc2
>>> calcs.stresses.read() # returns a dictionary with the stresses of calc1 and calc2
Expand All @@ -34,8 +34,8 @@ class Calculations:
def __init__(self, *args, **kwargs):
if not kwargs.get("_internal"):
message = """\
Please setup new CompareCalculations instance using the classmethod CompareCalculations.from_paths()
or CompareCalculations.from_files() instead of the constructor CompareCalculations()."""
Please setup new Batch instance using the classmethod Batch.from_paths()
or Batch.from_files() instead of the constructor Batch()."""
raise exception.IncorrectUsage(message)

def _path_finder(**kwargs):
Expand All @@ -53,7 +53,7 @@ def _path_finder(**kwargs):

@classmethod
def from_paths(cls, **kwargs):
"""Set up a Calculations object for paths.
"""Set up a Batch object for paths.
Setup a calculation for paths by passing in a dictionary with the name of the
calculation as key and the path to the calculation as value.
Expand All @@ -75,7 +75,7 @@ def from_paths(cls, **kwargs):

@classmethod
def from_files(cls, **kwargs):
"""Set up a Calculations object from files.
"""Set up a Batch object from files.
Setup a calculation for files by passing in a dictionary with the name of the
calculation as key and the path to the calculation as value. Note that this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# Copyright © VASP Software GmbH,
# Licensed under the Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
from py4vasp import calculation
from py4vasp._calculation import base, structure
from py4vasp._third_party import view
from py4vasp._util import convert
from py4vasp.calculation import _base, _structure


class CONTCAR(_base.Refinery, view.Mixin, _structure.Mixin):
class CONTCAR(base.Refinery, view.Mixin, structure.Mixin):
"""CONTCAR contains structural restart-data after a relaxation or MD simulation.
The CONTCAR contains the final structure of the VASP calculation. It can be used as
input for the next calculation if desired. Depending on the particular setup the
CONTCAR might contain additional information about the system such as the ion
and lattice velocities."""

@_base.data_access
@base.data_access
def to_dict(self):
"""Extract the structural data and the available additional data to a dictionary.
Expand All @@ -36,7 +36,7 @@ def _read(self, key):
data = getattr(self._raw_data, key)
return {key: data[:]} if not data.is_none() else {}

@_base.data_access
@base.data_access
def to_view(self, supercell=None):
"""Generate a visualization of the final structure.
Expand All @@ -52,7 +52,7 @@ def to_view(self, supercell=None):
"""
return self._structure.plot(supercell)

@_base.data_access
@base.data_access
def __str__(self):
return "\n".join(self._line_generator())

Expand All @@ -62,16 +62,18 @@ def _line_generator(self):
selective_dynamics = self._raw_data.selective_dynamics
yield convert.text_to_string(self._raw_data.system)
yield from _cell_lines(cell)
yield self._topology().to_POSCAR()
yield self._stoichiometry().to_POSCAR()
if not selective_dynamics.is_none():
yield "Selective dynamics"
yield "Direct"
yield from _ion_position_lines(positions, selective_dynamics)
yield from _lattice_velocity_lines(self._raw_data.lattice_velocities, cell)
yield from _ion_velocity_lines(self._raw_data.ion_velocities)

def _topology(self):
return calculation.topology.from_data(self._raw_data.structure.topology)
def _stoichiometry(self):
return calculation._stoichiometry.from_data(
self._raw_data.structure.stoichiometry
)


def _cell_lines(cell):
Expand Down
Loading

0 comments on commit c4e5cd3

Please sign in to comment.