Source code for atomistics.calculators.lammps.libcalculator

from __future__ import annotations

from collections.abc import Iterable
from typing import TYPE_CHECKING, Any, Optional

import numpy as np
import pandas
from jinja2 import Template
from pylammpsmpi import LammpsASELibrary

from atomistics.calculators.interface import get_quantities_from_tasks
from atomistics.calculators.lammps.commands import (
    LAMMPS_ENSEMBLE_NPH,
    LAMMPS_ENSEMBLE_NPT,
    LAMMPS_ENSEMBLE_NVT,
    LAMMPS_LANGEVIN,
    LAMMPS_MINIMIZE,
    LAMMPS_NVE,
    LAMMPS_RUN,
    LAMMPS_THERMO,
    LAMMPS_THERMO_STYLE,
    LAMMPS_TIMESTEP,
    LAMMPS_VELOCITY,
)
from atomistics.calculators.lammps.helpers import (
    lammps_calc_md,
    lammps_run,
    lammps_shutdown,
    lammps_thermal_expansion_loop,
)
from atomistics.calculators.lammps.shared import get_box_relax_command
from atomistics.calculators.wrapper import as_task_dict_evaluator
from atomistics.shared.output import OutputMolecularDynamics, OutputStatic
from atomistics.shared.thermal_expansion import OutputThermalExpansion

if TYPE_CHECKING:
    from ase import Atoms
    from pandas import DataFrame
    from pylammpsmpi import LammpsASELibrary

    from atomistics.calculators.interface import TaskName


[docs] def optimize_positions_and_volume_with_lammpslib( structure: Atoms, potential_dataframe: DataFrame, min_style: str = "cg", etol: float = 0.0, ftol: float = 0.0001, maxiter: int = 100000, maxeval: int = 10000000, thermo: int = 10, pressure: float | Iterable[float | None] = 0.0, vmax: float | None = None, lmp=None, **kwargs, ) -> Atoms: """ Relax atomic positions and cell using the LAMMPS library interface. Args: structure (Atoms): The input structure. potential_dataframe (DataFrame): DataFrame with ``"Species"`` and ``"Config"`` columns. min_style (str): LAMMPS minimisation style. Defaults to ``"cg"``. etol (float): Energy tolerance for minimisation. Defaults to ``0.0``. ftol (float): Force tolerance in eV/Å. Defaults to ``0.0001``. maxiter (int): Maximum number of minimisation iterations. Defaults to ``100000``. maxeval (int): Maximum number of force evaluations. Defaults to ``10000000``. thermo (int): Thermo output frequency. Defaults to ``10``. pressure (float | Iterable[float | None]): Target pressure for ``box/relax`` in bar. vmax (float | None): Maximum fractional volume change per step for ``box/relax``. lmp: Existing LAMMPS library instance to reuse. A new instance is created if ``None``. **kwargs: Additional keyword arguments forwarded to ``lammps_run``. Returns: Atoms: A copy of the input structure with relaxed positions and cell. """ template_str = "\n".join( [ get_box_relax_command(pressure=pressure, vmax=vmax), LAMMPS_THERMO_STYLE, LAMMPS_THERMO, LAMMPS_MINIMIZE, ] ) lmp_instance = lammps_run( structure=structure, potential_dataframe=potential_dataframe, input_template=Template(template_str).render( min_style=min_style, etol=etol, ftol=ftol, maxiter=maxiter, maxeval=maxeval, thermo=thermo, ), lmp=lmp, **kwargs, ) structure_copy = structure.copy() structure_copy.set_cell(lmp_instance.interactive_cells_getter(), scale_atoms=True) structure_copy.positions = lmp_instance.interactive_positions_getter() lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return structure_copy
[docs] def optimize_positions_with_lammpslib( structure: Atoms, potential_dataframe: DataFrame, min_style: str = "cg", etol: float = 0.0, ftol: float = 0.0001, maxiter: int = 100000, maxeval: int = 10000000, thermo: int = 10, lmp=None, **kwargs, ) -> Atoms: """ Relax atomic positions using the LAMMPS library interface (cell fixed). Args: structure (Atoms): The input structure. potential_dataframe (DataFrame): DataFrame with ``"Species"`` and ``"Config"`` columns. min_style (str): LAMMPS minimisation style. Defaults to ``"cg"``. etol (float): Energy tolerance for minimisation. Defaults to ``0.0``. ftol (float): Force tolerance in eV/Å. Defaults to ``0.0001``. maxiter (int): Maximum number of minimisation iterations. Defaults to ``100000``. maxeval (int): Maximum number of force evaluations. Defaults to ``10000000``. thermo (int): Thermo output frequency. Defaults to ``10``. lmp: Existing LAMMPS library instance to reuse. A new instance is created if ``None``. **kwargs: Additional keyword arguments forwarded to ``lammps_run``. Returns: Atoms: A copy of the input structure with relaxed atomic positions. """ template_str = "\n".join([LAMMPS_THERMO_STYLE, LAMMPS_THERMO, LAMMPS_MINIMIZE]) lmp_instance = lammps_run( structure=structure, potential_dataframe=potential_dataframe, input_template=Template(template_str).render( min_style=min_style, etol=etol, ftol=ftol, maxiter=maxiter, maxeval=maxeval, thermo=thermo, ), lmp=lmp, **kwargs, ) structure_copy = structure.copy() structure_copy.positions = lmp_instance.interactive_positions_getter() lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return structure_copy
[docs] def calc_static_with_lammpslib( structure: Atoms, potential_dataframe: pandas.DataFrame, lmp=None, output_keys=OutputStatic.keys(), **kwargs, ) -> dict: """ Run a static calculation using the LAMMPS library interface. Args: structure (Atoms): The input structure. potential_dataframe (pandas.DataFrame): DataFrame with ``"Species"`` and ``"Config"`` columns. lmp: Existing LAMMPS library instance to reuse. A new instance is created if ``None``. output_keys: Which output quantities to return. Defaults to all ``OutputStatic`` keys. **kwargs: Additional keyword arguments forwarded to ``lammps_run``. Returns: dict: Requested output quantities keyed by name. """ template_str = "\n".join([LAMMPS_THERMO_STYLE, LAMMPS_THERMO, LAMMPS_RUN]) lmp_instance = lammps_run( structure=structure, potential_dataframe=potential_dataframe, input_template=Template(template_str).render( run=0, thermo=100, ), lmp=lmp, **kwargs, ) result_dict = OutputStatic( forces=lmp_instance.interactive_forces_getter, energy=lmp_instance.interactive_energy_pot_getter, stress=lmp_instance.interactive_pressures_getter, volume=lmp_instance.interactive_volume_getter, ).get(output_keys=output_keys) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict
[docs] def calc_molecular_dynamics_nvt_with_lammpslib( structure: Atoms, potential_dataframe: pandas.DataFrame, Tstart: float = 100.0, Tstop: float = 100.0, Tdamp: float = 0.1, run: int = 100, thermo: int = 10, timestep: float = 0.001, seed: int = 4928459, dist: str = "gaussian", velocity_rescale_factor: float | None = 2.0, lmp=None, output_keys=OutputMolecularDynamics.keys(), **kwargs, ) -> dict: """ Run NVT (canonical ensemble) molecular dynamics using the LAMMPS library interface. Args: structure (Atoms): The input structure. potential_dataframe (pandas.DataFrame): DataFrame with ``"Species"`` and ``"Config"`` columns. Tstart (float): Starting temperature in K. Defaults to ``100.0``. Tstop (float): Target temperature in K at the end of the run. Defaults to ``100.0``. Tdamp (float): Nosé-Hoover thermostat damping parameter in ps. Defaults to ``0.1``. run (int): Total number of MD timesteps. Defaults to ``100``. thermo (int): Number of timesteps between output snapshots. Defaults to ``10``. timestep (float): MD timestep in ps. Defaults to ``0.001``. seed (int): Random seed for velocity initialisation. Defaults to ``4928459``. dist (str): Velocity distribution type (``"gaussian"`` or ``"uniform"``). Defaults to ``"gaussian"``. velocity_rescale_factor (float | None): Scaling factor for initial velocity rescaling. No rescaling is applied when ``None``. Defaults to ``2.0``. lmp: Existing LAMMPS library instance to reuse. A new instance is created if ``None``. output_keys: Which output quantities to return. Defaults to all ``OutputMolecularDynamics`` keys. **kwargs: Additional keyword arguments forwarded to ``lammps_run``. Returns: dict: Output quantities as numpy arrays with one entry per snapshot, keyed by quantity name. """ if velocity_rescale_factor is not None: init_str = "\n".join( [ LAMMPS_THERMO_STYLE, LAMMPS_TIMESTEP, LAMMPS_THERMO, LAMMPS_VELOCITY, LAMMPS_ENSEMBLE_NVT, ] ) input_template = Template(init_str).render( thermo=thermo, Tstart=Tstart, temp=Tstart, Tstop=Tstop, Tdamp=Tdamp, timestep=timestep, seed=seed, dist=dist, velocity_rescale_factor=velocity_rescale_factor, ) else: init_str = "\n".join( [ LAMMPS_THERMO_STYLE, LAMMPS_TIMESTEP, LAMMPS_THERMO, LAMMPS_ENSEMBLE_NVT, ] ) input_template = Template(init_str).render( thermo=thermo, Tstart=Tstart, temp=Tstart, Tstop=Tstop, Tdamp=Tdamp, timestep=timestep, ) run_str = LAMMPS_RUN + "\n" lmp_instance = lammps_run( structure=structure, potential_dataframe=potential_dataframe, input_template=input_template, lmp=lmp, **kwargs, ) result_dict = lammps_calc_md( lmp_instance=lmp_instance, run_str=run_str, run=run, thermo=thermo, output_keys=output_keys, ) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict
[docs] def calc_molecular_dynamics_npt_with_lammpslib( structure: Atoms, potential_dataframe: pandas.DataFrame, Tstart: float = 100.0, Tstop: float = 100.0, Tdamp: float = 0.1, run: int = 100, thermo: int = 100, timestep: float = 0.001, Pstart: float = 0.0, Pstop: float = 0.0, Pdamp: float = 1.0, seed: int = 4928459, dist: str = "gaussian", couple_xyz: bool = False, velocity_rescale_factor: float | None = 2.0, lmp=None, output_keys=OutputMolecularDynamics.keys(), **kwargs, ) -> dict: """ Run NPT (isothermal-isobaric ensemble) molecular dynamics using the LAMMPS library interface. Args: structure (Atoms): The input structure. potential_dataframe (pandas.DataFrame): DataFrame with ``"Species"`` and ``"Config"`` columns. Tstart (float): Starting temperature in K. Defaults to ``100.0``. Tstop (float): Target temperature in K at the end of the run. Defaults to ``100.0``. Tdamp (float): Thermostat damping parameter in ps. Defaults to ``0.1``. run (int): Total number of MD timesteps. Defaults to ``100``. thermo (int): Number of timesteps between output snapshots. Defaults to ``100``. timestep (float): MD timestep in ps. Defaults to ``0.001``. Pstart (float): Starting pressure in bar. Defaults to ``0.0``. Pstop (float): Target pressure in bar at the end of the run. Defaults to ``0.0``. Pdamp (float): Barostat damping parameter in ps. Defaults to ``1.0``. seed (int): Random seed for velocity initialisation. Defaults to ``4928459``. dist (str): Velocity distribution type. Defaults to ``"gaussian"``. couple_xyz (bool): Whether to couple all three box dimensions (isotropic pressure). Defaults to ``False``. velocity_rescale_factor (float | None): Scaling factor for initial velocity rescaling. No rescaling is applied when ``None``. Defaults to ``2.0``. lmp: Existing LAMMPS library instance to reuse. A new instance is created if ``None``. output_keys: Which output quantities to return. Defaults to all ``OutputMolecularDynamics`` keys. **kwargs: Additional keyword arguments forwarded to ``lammps_run``. Returns: dict: Output quantities as numpy arrays with one entry per snapshot, keyed by quantity name. """ if couple_xyz: LAMMPS_ENSEMBLE_NPT_XYZ = LAMMPS_ENSEMBLE_NPT + " couple xyz" else: LAMMPS_ENSEMBLE_NPT_XYZ = LAMMPS_ENSEMBLE_NPT if velocity_rescale_factor is not None: init_str = "\n".join( [ LAMMPS_THERMO_STYLE, LAMMPS_TIMESTEP, LAMMPS_THERMO, LAMMPS_VELOCITY, LAMMPS_ENSEMBLE_NPT_XYZ, ] ) input_template = Template(init_str).render( thermo=thermo, Tstart=Tstart, temp=Tstart, Tstop=Tstop, Tdamp=Tdamp, Pstart=Pstart, Pstop=Pstop, Pdamp=Pdamp, timestep=timestep, seed=seed, dist=dist, velocity_rescale_factor=velocity_rescale_factor, ) else: init_str = "\n".join( [ LAMMPS_THERMO_STYLE, LAMMPS_TIMESTEP, LAMMPS_THERMO, LAMMPS_ENSEMBLE_NPT_XYZ, ] ) input_template = Template(init_str).render( thermo=thermo, Tstart=Tstart, temp=Tstart, Tstop=Tstop, Tdamp=Tdamp, Pstart=Pstart, Pstop=Pstop, Pdamp=Pdamp, timestep=timestep, ) run_str = LAMMPS_RUN + "\n" lmp_instance = lammps_run( structure=structure, potential_dataframe=potential_dataframe, input_template=input_template, lmp=lmp, **kwargs, ) result_dict = lammps_calc_md( lmp_instance=lmp_instance, run_str=run_str, run=run, thermo=thermo, output_keys=output_keys, ) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict
[docs] def calc_molecular_dynamics_nph_with_lammpslib( structure: Atoms, potential_dataframe: pandas.DataFrame, run: int = 100, thermo: int = 100, timestep: float = 0.001, Tstart: float = 100.0, Pstart: float = 0.0, Pstop: float = 0.0, Pdamp: float = 1.0, seed: int = 4928459, dist: str = "gaussian", velocity_rescale_factor: float | None = 2.0, lmp=None, output_keys=OutputMolecularDynamics.keys(), **kwargs, ) -> dict: """ Run NPH (isoenthalpic-isobaric ensemble) molecular dynamics using the LAMMPS library interface. Args: structure (Atoms): The input structure. potential_dataframe (pandas.DataFrame): DataFrame with ``"Species"`` and ``"Config"`` columns. run (int): Total number of MD timesteps. Defaults to ``100``. thermo (int): Number of timesteps between output snapshots. Defaults to ``100``. timestep (float): MD timestep in ps. Defaults to ``0.001``. Tstart (float): Initial temperature in K used for velocity initialisation. Defaults to ``100.0``. Pstart (float): Starting pressure in bar. Defaults to ``0.0``. Pstop (float): Target pressure in bar at the end of the run. Defaults to ``0.0``. Pdamp (float): Barostat damping parameter in ps. Defaults to ``1.0``. seed (int): Random seed for velocity initialisation. Defaults to ``4928459``. dist (str): Velocity distribution type. Defaults to ``"gaussian"``. velocity_rescale_factor (float | None): Scaling factor for initial velocity rescaling. No rescaling is applied when ``None``. Defaults to ``2.0``. lmp: Existing LAMMPS library instance to reuse. A new instance is created if ``None``. output_keys: Which output quantities to return. Defaults to all ``OutputMolecularDynamics`` keys. **kwargs: Additional keyword arguments forwarded to ``lammps_run``. Returns: dict: Output quantities as numpy arrays with one entry per snapshot, keyed by quantity name. """ if velocity_rescale_factor is not None: init_str = "\n".join( [ LAMMPS_THERMO_STYLE, LAMMPS_TIMESTEP, LAMMPS_THERMO, LAMMPS_VELOCITY, LAMMPS_ENSEMBLE_NPH, ] ) input_template = Template(init_str).render( thermo=thermo, temp=Tstart, Pstart=Pstart, Pstop=Pstop, Pdamp=Pdamp, timestep=timestep, seed=seed, dist=dist, velocity_rescale_factor=velocity_rescale_factor, ) else: init_str = "\n".join( [ LAMMPS_THERMO_STYLE, LAMMPS_TIMESTEP, LAMMPS_THERMO, LAMMPS_ENSEMBLE_NPH, ] ) input_template = Template(init_str).render( thermo=thermo, temp=Tstart, Pstart=Pstart, Pstop=Pstop, Pdamp=Pdamp, timestep=timestep, ) run_str = LAMMPS_RUN + "\n" lmp_instance = lammps_run( structure=structure, potential_dataframe=potential_dataframe, input_template=input_template, lmp=lmp, **kwargs, ) result_dict = lammps_calc_md( lmp_instance=lmp_instance, run_str=run_str, run=run, thermo=thermo, output_keys=output_keys, ) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict
[docs] def calc_molecular_dynamics_langevin_with_lammpslib( structure: Atoms, potential_dataframe: pandas.DataFrame, run: int = 100, thermo: int = 100, timestep: float = 0.001, Tstart: float = 100.0, Tstop: float = 100, Tdamp: float = 0.1, seed: int = 4928459, dist: str = "gaussian", velocity_rescale_factor: float | None = 2.0, lmp=None, output_keys=OutputMolecularDynamics.keys(), **kwargs, ) -> dict: """ Run Langevin (NVE + Langevin thermostat) molecular dynamics using the LAMMPS library interface. Args: structure (Atoms): The input structure. potential_dataframe (pandas.DataFrame): DataFrame with ``"Species"`` and ``"Config"`` columns. run (int): Total number of MD timesteps. Defaults to ``100``. thermo (int): Number of timesteps between output snapshots. Defaults to ``100``. timestep (float): MD timestep in ps. Defaults to ``0.001``. Tstart (float): Starting temperature for the Langevin thermostat in K. Defaults to ``100.0``. Tstop (float): Target temperature for the Langevin thermostat in K. Defaults to ``100``. Tdamp (float): Langevin thermostat damping parameter in ps. Defaults to ``0.1``. seed (int): Random seed for velocity initialisation and Langevin noise. Defaults to ``4928459``. dist (str): Velocity distribution type. Defaults to ``"gaussian"``. velocity_rescale_factor (float | None): Scaling factor for initial velocity rescaling. No rescaling is applied when ``None``. Defaults to ``2.0``. lmp: Existing LAMMPS library instance to reuse. A new instance is created if ``None``. output_keys: Which output quantities to return. Defaults to all ``OutputMolecularDynamics`` keys. **kwargs: Additional keyword arguments forwarded to ``lammps_run``. Returns: dict: Output quantities as numpy arrays with one entry per snapshot, keyed by quantity name. """ if velocity_rescale_factor is not None: init_str = "\n".join( [ LAMMPS_THERMO_STYLE, LAMMPS_TIMESTEP, LAMMPS_THERMO, LAMMPS_VELOCITY, LAMMPS_NVE, LAMMPS_LANGEVIN, ] ) input_template = Template(init_str).render( thermo=thermo, temp=Tstart, Tstart=Tstart, Tstop=Tstop, Tdamp=Tdamp, timestep=timestep, seed=seed, dist=dist, velocity_rescale_factor=velocity_rescale_factor, ) else: init_str = "\n".join( [ LAMMPS_THERMO_STYLE, LAMMPS_TIMESTEP, LAMMPS_THERMO, LAMMPS_NVE, LAMMPS_LANGEVIN, ] ) input_template = Template(init_str).render( thermo=thermo, temp=Tstart, Tstart=Tstart, Tstop=Tstop, Tdamp=Tdamp, seed=seed, timestep=timestep, ) run_str = LAMMPS_RUN + "\n" lmp_instance = lammps_run( structure=structure, potential_dataframe=potential_dataframe, input_template=input_template, lmp=lmp, **kwargs, ) result_dict = lammps_calc_md( lmp_instance=lmp_instance, run_str=run_str, run=run, thermo=thermo, output_keys=output_keys, ) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict
[docs] def calc_molecular_dynamics_thermal_expansion_with_lammpslib( structure: Atoms, potential_dataframe: pandas.DataFrame, Tstart: float = 15.0, Tstop: float = 1500.0, Tstep: int = 5, Tdamp: float = 0.1, run: int = 100, thermo: int = 100, timestep: float = 0.001, Pstart: float = 0.0, Pstop: float = 0.0, Pdamp: float = 1.0, seed: int = 4928459, dist: str = "gaussian", couple_xyz: bool = False, lmp: LammpsASELibrary | None = None, output_keys: Iterable[str] = OutputThermalExpansion.keys(), **kwargs, ) -> dict: """ Compute thermal expansion via NPT MD across a temperature range using the LAMMPS library interface. Runs ``lammps_thermal_expansion_loop`` over temperatures from ``Tstart`` to ``Tstop`` in steps of ``Tstep``. Args: structure (Atoms): The input structure. potential_dataframe (pandas.DataFrame): DataFrame with ``"Species"`` and ``"Config"`` columns. Tstart (float): Starting temperature in K. Defaults to ``15.0``. Tstop (float): Ending temperature in K (inclusive). Defaults to ``1500.0``. Tstep (int): Temperature increment in K. Defaults to ``5``. Tdamp (float): Thermostat damping parameter in ps. Defaults to ``0.1``. run (int): Number of MD timesteps per temperature point. Defaults to ``100``. thermo (int): Thermo output frequency in timesteps. Defaults to ``100``. timestep (float): MD timestep in ps. Defaults to ``0.001``. Pstart (float): Starting pressure in bar. Defaults to ``0.0``. Pstop (float): Ending pressure in bar. Defaults to ``0.0``. Pdamp (float): Barostat damping parameter in ps. Defaults to ``1.0``. seed (int): Random seed for velocity initialisation. Defaults to ``4928459``. dist (str): Velocity distribution type. Defaults to ``"gaussian"``. couple_xyz (bool): Whether to couple all three box dimensions (isotropic pressure). Defaults to ``False``. lmp (LammpsASELibrary | None): Existing LAMMPS library instance to reuse. output_keys (Iterable[str]): Which output quantities to return. **kwargs: Additional keyword arguments forwarded to ``lammps_thermal_expansion_loop``. Returns: dict: Thermal expansion output (temperatures and volumes) keyed by quantity name. """ init_str = "\n".join( [ LAMMPS_THERMO_STYLE, LAMMPS_TIMESTEP, LAMMPS_THERMO, LAMMPS_VELOCITY, "", ] ) if couple_xyz: LAMMPS_ENSEMBLE_NPT_XYZ = LAMMPS_ENSEMBLE_NPT + " couple xyz" else: LAMMPS_ENSEMBLE_NPT_XYZ = LAMMPS_ENSEMBLE_NPT run_str = "\n".join([LAMMPS_ENSEMBLE_NPT_XYZ, LAMMPS_RUN]) temperature_lst = np.arange(Tstart, Tstop + Tstep, Tstep).tolist() return lammps_thermal_expansion_loop( structure=structure, potential_dataframe=potential_dataframe, init_str=init_str, run_str=run_str, temperature_lst=temperature_lst, run=run, thermo=thermo, timestep=timestep, Tdamp=Tdamp, Pstart=Pstart, Pstop=Pstop, Pdamp=Pdamp, seed=seed, dist=dist, lmp=lmp, output_keys=output_keys, **kwargs, )
@as_task_dict_evaluator def evaluate_with_lammpslib_library_interface( structure: Atoms, tasks: list[TaskName], potential_dataframe: DataFrame, lmp: LammpsASELibrary, lmp_optimizer_kwargs: dict | None = None, ) -> dict: """ Evaluate a single structure for a list of tasks using an existing LAMMPS library instance. Decorated with ``as_task_dict_evaluator`` to handle task dict conversion. Used internally by ``evaluate_with_lammpslib`` which manages the LAMMPS instance lifecycle. Args: structure (Atoms): The input structure. tasks (list[TaskName]): List of task names to evaluate. potential_dataframe (DataFrame): DataFrame with ``"Species"`` and ``"Config"`` columns. lmp (LammpsASELibrary): An active LAMMPS library instance. lmp_optimizer_kwargs (dict | None): Extra keyword arguments forwarded to the underlying calculation functions. Returns: dict: Results keyed by output quantity name. Raises: ValueError: If none of the requested tasks are implemented by this calculator. """ if lmp_optimizer_kwargs is None: lmp_optimizer_kwargs = {} results: dict[str, Any] = {} if "optimize_positions_and_volume" in tasks: results["structure_with_optimized_positions_and_volume"] = ( optimize_positions_and_volume_with_lammpslib( structure=structure, potential_dataframe=potential_dataframe, lmp=lmp, **lmp_optimizer_kwargs, ) ) elif "optimize_positions" in tasks: results["structure_with_optimized_positions"] = ( optimize_positions_with_lammpslib( structure=structure, potential_dataframe=potential_dataframe, lmp=lmp, **lmp_optimizer_kwargs, ) ) elif "calc_molecular_dynamics_thermal_expansion" in tasks: results_dict = calc_molecular_dynamics_thermal_expansion_with_lammpslib( structure=structure, potential_dataframe=potential_dataframe, lmp=lmp, **lmp_optimizer_kwargs, ) results["volume_over_temperature"] = ( results_dict["temperatures"], results_dict["volumes"], ) elif "calc_energy" in tasks or "calc_forces" in tasks or "calc_stress" in tasks: return calc_static_with_lammpslib( structure=structure, potential_dataframe=potential_dataframe, lmp=lmp, output_keys=get_quantities_from_tasks(tasks=tasks), ) else: raise ValueError("The LAMMPS calculator does not implement:", tasks) return results
[docs] def evaluate_with_lammpslib( task_dict: dict[str, dict[str, Atoms]], potential_dataframe: DataFrame, working_directory: str | None = None, cores: int = 1, comm: object | None = None, logger: object | None = None, log_file: str | None = None, library: object | None = None, disable_log_file: bool = True, lmp_optimizer_kwargs: dict | None = None, ) -> dict: """ Evaluate a task dictionary using the LAMMPS library interface, managing the instance lifecycle. Creates a ``LammpsASELibrary`` instance, delegates to ``evaluate_with_lammpslib_library_interface``, then closes the instance. Args: task_dict (dict[str, dict[str, Atoms]]): Task dictionary mapping task names to structure dicts. potential_dataframe (DataFrame): DataFrame with ``"Species"`` and ``"Config"`` columns. working_directory (str | None): Working directory for LAMMPS. Defaults to ``None``. cores (int): Number of MPI cores to use. Defaults to ``1``. comm: MPI communicator object. Defaults to ``None``. logger: Logger object. Defaults to ``None``. log_file (str | None): Path to the LAMMPS log file. Defaults to ``None``. library: Pre-loaded LAMMPS shared library object. Defaults to ``None``. disable_log_file (bool): Whether to suppress the LAMMPS log file. Defaults to ``True``. lmp_optimizer_kwargs (dict | None): Extra keyword arguments forwarded to the underlying calculation functions. Returns: dict: Results keyed by output quantity name. """ if lmp_optimizer_kwargs is None: lmp_optimizer_kwargs = {} lmp = LammpsASELibrary( working_directory=working_directory, cores=cores, comm=comm, logger=logger, log_file=log_file, library=library, disable_log_file=disable_log_file, ) results_dict = evaluate_with_lammpslib_library_interface( task_dict=task_dict, potential_dataframe=potential_dataframe, lmp=lmp, lmp_optimizer_kwargs=lmp_optimizer_kwargs, ) lmp.close() return results_dict