thermoelasticsim.potentials.lennard_jones 源代码

#!/usr/bin/env python3
r"""
ThermoElasticSim - Lennard-Jones 势模块

.. moduleauthor:: Gilbert Young

Lennard–Jones (12–6) 势用于近似描述惰性原子间的范德华作用:

.. math::
   V(r) = 4\,\varepsilon\Big[\Big(\frac{\sigma}{r}\Big)^{12} - \Big(\frac{\sigma}{r}\Big)^6\Big]

其中 :math:`\varepsilon` 为势阱深度(eV),:math:`\sigma` 为零势能点对应长度(Å)。

References
----------
- J. E. Jones (1924), On the Determination of Molecular Fields.
  I. From the Variation of the Viscosity of a Gas with Temperature.
  Proceedings of the Royal Society A, 106(738), 441–462. doi:10.1098/rspa.1924.0081
"""

import logging

import numpy as np

from thermoelasticsim.core.structure import Cell
from thermoelasticsim.interfaces.cpp_interface import CppInterface
from thermoelasticsim.utils.utils import NeighborList

from .base import Potential

logger = logging.getLogger(__name__)


[文档] class LennardJonesPotential(Potential): r"""Lennard–Jones (12–6) 对势实现。 Parameters ---------- epsilon : float 势阱深度 epsilon(eV)。 sigma : float 零势能点对应长度 sigma(Å)。 cutoff : float 截断距离(Å)。 Notes ----- - 势函数见模块 References 中的 Jones (1924)。 - 单位:能量 eV,长度 Å,力 eV/Å。 """
[文档] def __init__(self, epsilon: float, sigma: float, cutoff: float): parameters = {"epsilon": epsilon, "sigma": sigma} super().__init__(parameters, cutoff) self.cpp_interface = CppInterface("lennard_jones") logger.debug( f"Lennard-Jones Potential initialized with epsilon={epsilon}, sigma={sigma}, cutoff={cutoff}." )
[文档] def calculate_forces(self, cell: Cell, neighbor_list: NeighborList) -> None: """计算作用力并写入 :code:`cell.atoms[i].force` (eV/Å)。 Parameters ---------- cell : Cell 晶胞与原子集合。 neighbor_list : NeighborList 预先构建的邻居列表。 """ num_atoms = cell.num_atoms positions = np.ascontiguousarray( cell.get_positions(), dtype=np.float64 ).flatten() box_lengths = np.ascontiguousarray(cell.get_box_lengths(), dtype=np.float64) neighbor_pairs = [ (i, j) for i in range(num_atoms) for j in neighbor_list.get_neighbors(i) if j > i ] neighbor_list_flat = [index for pair in neighbor_pairs for index in pair] neighbor_list_array = np.ascontiguousarray(neighbor_list_flat, dtype=np.int32) forces = np.zeros_like(positions, dtype=np.float64) self.cpp_interface.calculate_lj_forces( num_atoms, positions, forces, self.parameters["epsilon"], self.parameters["sigma"], self.cutoff, box_lengths, neighbor_list_array, len(neighbor_pairs), ) forces = forces.reshape((num_atoms, 3)) for i, atom in enumerate(cell.atoms): atom.force = forces[i]
[文档] def calculate_energy(self, cell: Cell, neighbor_list: NeighborList) -> float: """计算系统总势能(eV)。 Parameters ---------- cell : Cell 晶胞与原子集合。 neighbor_list : NeighborList 预先构建的邻居列表。 Returns ------- float 系统总势能(eV)。 """ num_atoms = cell.num_atoms positions = np.ascontiguousarray( cell.get_positions(), dtype=np.float64 ).flatten() box_lengths = np.ascontiguousarray(cell.get_box_lengths(), dtype=np.float64) neighbor_pairs = [ (i, j) for i in range(num_atoms) for j in neighbor_list.get_neighbors(i) if j > i ] neighbor_list_flat = [index for pair in neighbor_pairs for index in pair] neighbor_list_array = np.ascontiguousarray(neighbor_list_flat, dtype=np.int32) energy = self.cpp_interface.calculate_lj_energy( num_atoms, positions, self.parameters["epsilon"], self.parameters["sigma"], self.cutoff, box_lengths, neighbor_list_array, len(neighbor_pairs), ) return energy