Source code for dpdata.plugins.lammps
from __future__ import annotations
from typing import TYPE_CHECKING
import numpy as np
import dpdata.lammps.dump
import dpdata.lammps.lmp
from dpdata.data_type import Axis, DataType
from dpdata.format import Format
from dpdata.utils import open_file
if TYPE_CHECKING:
from dpdata.utils import FileType
[docs]
def register_spin(data):
if "spins" in data:
dt = DataType(
"spins",
np.ndarray,
(Axis.NFRAMES, Axis.NATOMS, 3),
required=False,
deepmd_name="spin",
)
dpdata.System.register_data_type(dt)
[docs]
def register_charge(data: dict) -> None:
if "charges" in data:
dt = DataType(
"charges",
np.ndarray,
(Axis.NFRAMES, Axis.NATOMS),
required=False,
deepmd_name="charge",
)
dpdata.System.register_data_type(dt)
[docs]
@Format.register("lmp")
@Format.register("lammps/lmp")
class LAMMPSLmpFormat(Format):
[docs]
@Format.post("shift_orig_zero")
def from_system(
self, file_name: FileType, type_map=None, atom_style="auto", **kwargs
):
"""Load LAMMPS data file to system data format.
This method supports multiple LAMMPS atom styles with automatic charge extraction
and maintains backward compatibility. The parser can automatically detect the atom
style from the LAMMPS data file header when possible.
Parameters
----------
file_name : str or Path
Path to LAMMPS data file
type_map : list, optional
Mapping from atom types to element names
atom_style : str, optional
The LAMMPS atom style. Default is "auto" which attempts to detect
the style automatically from the file. Can also be explicitly set to:
atomic, full, charge, bond, angle, molecular, dipole, sphere
**kwargs : dict
Other parameters
Returns
-------
dict
System data dictionary with additional data based on atom style:
- charges: For styles with charge information (full, charge, dipole)
- molecule_ids: For styles with molecule information (full, bond, angle, molecular)
Examples
--------
Load LAMMPS data with automatic detection:
>>> system = dpdata.System("data.lmp", type_map=["O", "H"])
Load with specific atom styles:
>>> # Full style with charges and molecule IDs
>>> system = dpdata.System("data.lmp", type_map=["O", "H"], atom_style="full")
>>> print(system["charges"]) # Access extracted charges
>>> # Charge style with charges only
>>> system = dpdata.System("data.lmp", type_map=["O", "H"], atom_style="charge")
>>> # Bond/molecular styles with molecule IDs
>>> system = dpdata.System("data.lmp", type_map=["O", "H"], atom_style="bond")
Notes
-----
Atom Style Column Layouts:
- atomic: atom-ID atom-type x y z (default)
- full: atom-ID molecule-ID atom-type charge x y z
- charge: atom-ID atom-type charge x y z
- bond: atom-ID molecule-ID atom-type x y z
- angle: atom-ID molecule-ID atom-type x y z
- molecular: atom-ID molecule-ID atom-type x y z
- dipole: atom-ID atom-type charge x y z mux muy muz
- sphere: atom-ID atom-type diameter density x y z
"""
with open_file(file_name) as fp:
lines = [line.rstrip("\n") for line in fp]
data = dpdata.lammps.lmp.to_system_data(lines, type_map, atom_style=atom_style)
register_spin(data)
register_charge(data)
return data
[docs]
def to_system(self, data, file_name: FileType, frame_idx=0, **kwargs):
"""Dump the system in lammps data format.
Parameters
----------
data : dict
System data
file_name : str
The output file name
frame_idx : int
The index of the frame to dump
**kwargs : dict
other parameters
"""
assert frame_idx < len(data["coords"])
w_str = dpdata.lammps.lmp.from_system_data(data, frame_idx)
with open_file(file_name, "w") as fp:
fp.write(w_str)
[docs]
@Format.register("dump")
@Format.register("lammps/dump")
class LAMMPSDumpFormat(Format):
[docs]
@Format.post("shift_orig_zero")
def from_system(
self,
file_name: str,
type_map: list[str] = None,
begin: int = 0,
step: int = 1,
unwrap: bool = False,
input_file: str = None,
**kwargs,
):
"""Read the data from a lammps dump file.
Parameters
----------
file_name : str
The dump file name
type_map : List[str], optional
The atom type list
begin : int, optional
The begin step
step : int, optional
The step
unwrap : bool, optional
Whether to unwrap the coordinates
input_file : str, optional
The input file name
Returns
-------
dict
The system data
"""
lines = dpdata.lammps.dump.load_file(file_name, begin=begin, step=step)
data = dpdata.lammps.dump.system_data(
lines, type_map, unwrap=unwrap, input_file=input_file
)
register_spin(data)
return data
[docs]
def to_system(self, data, file_name: FileType, frame_idx=0, timestep=0, **kwargs):
"""Dump the system in LAMMPS dump format.
Parameters
----------
data : dict
System data
file_name : str
The output file name
frame_idx : int
The index of the frame to dump
timestep : int
The timestep number for the dump
**kwargs : dict
other parameters
"""
assert frame_idx < len(data["coords"])
w_str = dpdata.lammps.dump.from_system_data(data, frame_idx, timestep)
with open_file(file_name, "w") as fp:
fp.write(w_str)