Skip to content

[WIP] Better input set generator and sets for io.lammps #4368

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

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fecef55
fixed atom_style issue when converting from structure
vir-k01 Oct 31, 2024
159be72
BaseLammpsGenerator can def benefit from taking both raw strings and …
vir-k01 Dec 3, 2024
b6edc3d
Merge pull request #1 from materialsproject/master
vir-k01 Dec 3, 2024
cfac0bf
Need this to have a general way to write out FF (and other non-standa…
vir-k01 Dec 10, 2024
fd0cc72
Merge pull request #2 from materialsproject/master
vir-k01 Jan 6, 2025
410d4b4
Added new base lammps generator
vir-k01 Jan 8, 2025
37c387f
fixed atom_style issue when converting from structure
vir-k01 Oct 31, 2024
f736361
BaseLammpsGenerator can def benefit from taking both raw strings and …
vir-k01 Dec 3, 2024
fc0bb82
Need this to have a general way to write out FF (and other non-standa…
vir-k01 Dec 10, 2024
5d71ba2
Added new base lammps generator
vir-k01 Jan 8, 2025
74a2ce5
Add LammpsSettings to check convenience input
esoteric-ephemera Jan 8, 2025
c1f2ed6
Merge branch 'lammps_sets' of github.com:vir-k01/pymatgen into lammps…
vir-k01 Jan 8, 2025
608e889
Revert "Merge branch 'lammps_sets' of github.com:vir-k01/pymatgen int…
vir-k01 Jan 8, 2025
363fee6
Fixed commit merge issues
vir-k01 Jan 8, 2025
3f2d0b1
Removed LammpsInputSettings class, moved to convience LammpsSettings …
vir-k01 Jan 9, 2025
f88cc2d
Updated docstring for LammpsInput
vir-k01 Jan 9, 2025
edcfe39
Redid BaseLammpsGenerator
vir-k01 Apr 18, 2025
0ab2389
Merge remote-tracking branch 'upstream/master' into lammps_sets_templ…
vir-k01 Apr 19, 2025
d1dd967
Made input set validation far more general, updated minimize template
vir-k01 Apr 19, 2025
be77b06
removed debugging print statements
vir-k01 Apr 19, 2025
aa32a30
pre-commit auto-fixes
pre-commit-ci[bot] Apr 19, 2025
75b0637
Merge remote-tracking branch 'upstream/master' into lammps_sets_templ…
esoteric-ephemera Apr 21, 2025
f8f33b4
precommit / sync head
esoteric-ephemera Apr 21, 2025
3e2a5a0
Account for species specified through the FF dict
vir-k01 Apr 21, 2025
192dcb0
bug fix in latest commit
vir-k01 Apr 22, 2025
d8a5ae5
fix bug in specifying fixes
vir-k01 Apr 22, 2025
43647bf
Add thermostating options when using berendsen barostats
vir-k01 Apr 22, 2025
b4eb27c
added langevin barostat, fixed barostat init
vir-k01 Apr 22, 2025
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
1 change: 1 addition & 0 deletions docs/pymatgen.md

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

14 changes: 14 additions & 0 deletions src/pymatgen/core/periodic_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from typing import TYPE_CHECKING, overload

import numpy as np
from monty.dev import deprecated
from monty.json import MSONable

from pymatgen.core.units import SUPPORTED_UNIT_NAMES, FloatWithUnit, Ha_to_eV, Length, Mass, Unit
Expand Down Expand Up @@ -776,6 +777,19 @@ def is_rare_earth(self) -> bool:
"""
return self.is_lanthanoid or self.is_actinoid or self.symbol in {"Sc", "Y"}

@property
@deprecated(
Copy link
Contributor

@DanielYang59 DanielYang59 Apr 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess reverting changes to core.periodic_table and io.exciting is not intended?

If so you could revert those changes with (warning, this would drop all changes to that file, make sure this is what you need) git checkout upstream/master -- file_to_revert

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just behind the master branch, synced up now

is_rare_earth,
message="is_rare_earth is corrected to include Y and Sc.",
deadline=(2025, 1, 1),
)
def is_rare_earth_metal(self) -> bool:
"""True if element is a rare earth metal, Lanthanides (La) series and Actinides (Ac) series.

This property is Deprecated, and scheduled for removal after 2025-01-01.
"""
return self.is_lanthanoid or self.is_actinoid

@property
def is_metal(self) -> bool:
"""True if is a metal."""
Expand Down
131 changes: 66 additions & 65 deletions src/pymatgen/io/exciting/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from __future__ import annotations

import itertools
import warnings
import xml.etree.ElementTree as ET
from typing import TYPE_CHECKING

Expand All @@ -17,13 +16,10 @@
from pymatgen.symmetry.bandstructure import HighSymmKpath

if TYPE_CHECKING:
from typing import ClassVar, Literal
from pathlib import Path

from numpy.typing import ArrayLike, NDArray
from typing_extensions import Self

from pymatgen.util.typing import PathLike

__author__ = "Christian Vorwerk"
__copyright__ = "Copyright 2016"
__version__ = "1.0"
Expand All @@ -41,18 +37,10 @@ class ExcitingInput(MSONable):
Attributes:
structure (Structure): Associated Structure.
title (str): Optional title string.
lockxyz (Nx3 NDArray of booleans): Lockxyz attribute for each site if available.
lockxyz (numpy.ndarray): Lockxyz attribute for each site if available. A Nx3 array of booleans.
"""

# Conversion factor between Bohr radius and Angstrom
bohr2ang: ClassVar[float] = const.value("Bohr radius") / const.value("Angstrom star")

def __init__(
self,
structure: Structure,
title: str | None = None,
lockxyz: ArrayLike | None = None,
) -> None:
def __init__(self, structure: Structure, title=None, lockxyz=None):
"""
Args:
structure (Structure): Structure object.
Expand All @@ -64,19 +52,22 @@ def __init__(
if structure.is_ordered:
site_properties = {}
if lockxyz:
site_properties["selective_dynamics"] = np.asarray(lockxyz)
site_properties["selective_dynamics"] = lockxyz
self.structure = structure.copy(site_properties=site_properties)
self.title = structure.formula if title is None else title
else:
raise ValueError("Structure with partial occupancies cannot be converted into exciting input!")

# define conversion factor between Bohr radius and Angstrom
bohr2ang = const.value("Bohr radius") / const.value("Angstrom star")

@property
def lockxyz(self) -> NDArray:
def lockxyz(self):
"""Selective dynamics site properties."""
return self.structure.site_properties.get("selective_dynamics")

@lockxyz.setter
def lockxyz(self, lockxyz: ArrayLike) -> NDArray:
def lockxyz(self, lockxyz):
self.structure.add_site_property("selective_dynamics", lockxyz)

@classmethod
Expand Down Expand Up @@ -173,7 +164,7 @@ def from_str(cls, data: str) -> Self:
return cls(structure_in, title_in, lockxyz)

@classmethod
def from_file(cls, filename: PathLike) -> Self:
def from_file(cls, filename: str | Path) -> Self:
"""
Args:
filename: Filename.
Expand All @@ -187,27 +178,32 @@ def from_file(cls, filename: PathLike) -> Self:

def write_etree(
self,
celltype: Literal["unchanged", "conventional", "primitive"],
cartesian: bool = False,
bandstr: bool = False,
celltype,
cartesian=False,
bandstr=False,
symprec: float = 0.4,
angle_tolerance: float = 5,
angle_tolerance=5,
**kwargs,
) -> ET.Element:
"""Convert the exciting input parameters to an XML Element object.
):
"""Write the exciting input parameters to an XML object.

Args:
celltype (str): Choice of unit cell. Can be either the unit cell
from self.structure ("unchanged"), the conventional cell
("conventional"), or the primitive unit cell ("primitive").

cartesian (bool): Whether the atomic positions are provided in
Cartesian or unit-cell coordinates. Default is False.

bandstr (bool): Whether the bandstructure path along the
HighSymmKpath is included in the input file. Only supported if the
celltype is set to "primitive". Default is False.

symprec (float): Tolerance for the symmetry finding. Default is 0.4.

angle_tolerance (float): Angle tolerance for the symmetry finding.
Default is 5.
Default is 5.

**kwargs: Additional parameters for the input file.

Returns:
Expand Down Expand Up @@ -301,68 +297,77 @@ def write_etree(

def write_string(
self,
celltype: Literal["unchanged", "conventional", "primitive"],
cartesian: bool = False,
bandstr: bool = False,
celltype,
cartesian=False,
bandstr=False,
symprec: float = 0.4,
angle_tolerance: float = 5,
angle_tolerance=5,
**kwargs,
) -> str:
"""Convert exciting input to a string.
):
"""Write exciting input.xml as a string.

Args:
celltype (str): Choice of unit cell. Can be either the unit cell
from self.structure ("unchanged"), the conventional cell
("conventional"), or the primitive unit cell ("primitive").
from self.structure ("unchanged"), the conventional cell
("conventional"), or the primitive unit cell ("primitive").

cartesian (bool): Whether the atomic positions are provided in
Cartesian or unit-cell coordinates. Default is False.
Cartesian or unit-cell coordinates. Default is False.

bandstr (bool): Whether the bandstructure path along the
HighSymmKpath is included in the input file. Only supported if the
celltype is set to "primitive". Default is False.
HighSymmKpath is included in the input file. Only supported if the
celltype is set to "primitive". Default is False.

symprec (float): Tolerance for the symmetry finding. Default is 0.4.

angle_tolerance (float): Angle tolerance for the symmetry finding.
Default is 5.
Default is 5.

**kwargs: Additional parameters for the input file.

Returns:
str
String
"""
try:
root = self.write_etree(celltype, cartesian, bandstr, symprec, angle_tolerance, **kwargs)
self._indent(root)
# output should be a string not a bytes object
string = ET.tostring(root).decode("UTF-8")

except Exception:
raise ValueError("Incorrect celltype!")

return string

def write_file(
self,
celltype: Literal["unchanged", "conventional", "primitive"],
filename: PathLike,
cartesian: bool = False,
bandstr: bool = False,
celltype,
filename,
cartesian=False,
bandstr=False,
symprec: float = 0.4,
angle_tolerance: float = 5,
angle_tolerance=5,
**kwargs,
) -> None:
):
"""Write exciting input file.

Args:
celltype (str): Choice of unit cell. Can be either the unit cell
from self.structure ("unchanged"), the conventional cell
("conventional"), or the primitive unit cell ("primitive").
filename (PathLike): Filename for exciting input.
from self.structure ("unchanged"), the conventional cell
("conventional"), or the primitive unit cell ("primitive").

filename (str): Filename for exciting input.

cartesian (bool): Whether the atomic positions are provided in
Cartesian or unit-cell coordinates. Default is False.
Cartesian or unit-cell coordinates. Default is False.

bandstr (bool): Whether the bandstructure path along the
HighSymmKpath is included in the input file. Only supported if the
celltype is set to "primitive". Default is False.
HighSymmKpath is included in the input file. Only supported if the
celltype is set to "primitive". Default is False.

symprec (float): Tolerance for the symmetry finding. Default is 0.4.

angle_tolerance (float): Angle tolerance for the symmetry finding.
Default is 5.
Default is 5.

**kwargs: Additional parameters for the input file.
"""
try:
Expand All @@ -373,15 +378,15 @@ def write_file(
except Exception:
raise ValueError("Incorrect celltype!")

# Missing PrettyPrint option in the current version of xml.etree.cElementTree
@staticmethod
def _indent(elem: ET.Element, level: int = 0) -> None:
def _indent(elem, level=0):
"""
Helper method to indent elements, as missing PrettyPrint option
in the current version of xml.etree.cElementTree.
Helper method to indent elements.

Args:
elem (ET.Element): The Element to process.
level (int): The indentation level.
elem:
level:
"""
i = "\n" + level * " "
if len(elem):
Expand All @@ -396,23 +401,19 @@ def _indent(elem: ET.Element, level: int = 0) -> None:
elif level and (not elem.tail or not elem.tail.strip()):
elem.tail = i

def _dicttoxml(self, paramdict_: dict, element: ET.Element) -> None:
def _dicttoxml(self, paramdict_, element):
for key, value in paramdict_.items():
if isinstance(value, str) and key == "text()":
element.text = value

elif isinstance(value, str):
element.attrib[key] = value

elif isinstance(value, list):
for item in value:
self._dicttoxml(item, ET.SubElement(element, key))

elif isinstance(value, dict):
if element.findall(key) == []:
self._dicttoxml(value, ET.SubElement(element, key))
else:
self._dicttoxml(value, element.findall(key)[0])

else:
warnings.warn(f"cannot deal with {key} = {value}", stacklevel=2)
print("cannot deal with", key, "=", value)
Loading