thermoelasticsim.elastic.deformation 源代码

# 文件名: deformation.py
# 作者: Gilbert Young
# 修改日期: 2025-03-27
# 文件描述: 实现对晶胞施加微小应变的 Deformer 类。

r"""
变形模块

用于生成并对晶胞施加小形变矩阵的工具。

理论基础
--------
小形变近似下,形变梯度可写为:

.. math::
    \mathbf{F} = \mathbf{I} + \boldsymbol{\varepsilon}

其中 :math:`\boldsymbol{\varepsilon}` 为对称的小应变张量。为便于逐分量扫描,
本模块构造 6 个基方向(Voigt 记号)::math:`\varepsilon_{11}, \varepsilon_{22}, \varepsilon_{33}, \varepsilon_{23}, \varepsilon_{13}, \varepsilon_{12}`。
"""

import logging

import numpy as np

from thermoelasticsim.core.structure import Cell


[文档] class Deformer: """生成变形矩阵并应用于晶胞 Attributes ---------- delta : float 应变幅度,默认0.01 num_steps : int 每个应变分量的步数,默认10 logger : logging.Logger 日志记录器 """
[文档] def __init__(self, delta: float = 0.01, num_steps: int = 10): """初始化Deformer Parameters ---------- delta : float, optional 应变幅度,建议范围0.001-0.05 (默认: 0.01) num_steps : int, optional 每个应变分量的步数,必须大于0 (默认: 10) Raises ------ ValueError 如果delta超出合理范围或num_steps非正 """ if not 0.001 <= delta <= 0.05: raise ValueError("delta必须在0.001到0.05之间") if num_steps <= 0: raise ValueError("num_steps必须大于0") self.delta = delta self.num_steps = num_steps
# 类常量定义应变分量基 STRAIN_COMPONENTS = [ np.array([[1, 0, 0], [0, 0, 0], [0, 0, 0]]), # εxx np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]]), # εyy np.array([[0, 0, 0], [0, 0, 0], [0, 0, 1]]), # εzz np.array([[0, 0, 0], [0, 0, 1], [0, 1, 0]]), # εyz np.array([[0, 0, 1], [0, 0, 0], [1, 0, 0]]), # εxz np.array([[0, 1, 0], [1, 0, 0], [0, 0, 0]]), # εxy ]
[文档] def generate_deformation_matrices(self) -> list[np.ndarray]: r"""生成形变矩阵列表 为 6 个 Voigt 分量依次生成均匀分布的形变序列,采用: .. math:: \mathbf{F}(\delta) = \mathbf{I} + \delta\,\mathbf{E}_k 其中 :math:`\mathbf{E}_k` 为第 :math:`k` 个分量的基矩阵(剪切为对称填充)。 Returns ------- list of numpy.ndarray 形变矩阵列表,每个为 (3, 3) Notes ----- 预分配结果列表以减少内存分配开销。 """ delta_values = np.linspace(-self.delta, self.delta, self.num_steps) total_matrices = len(self.STRAIN_COMPONENTS) * len(delta_values) F_list = [None] * total_matrices # 预分配空间 for i, epsilon in enumerate(self.STRAIN_COMPONENTS): for j, delta in enumerate(delta_values): strain = delta * epsilon F = np.identity(3) + strain F_list[i * len(delta_values) + j] = F return F_list
[文档] def apply_deformation(self, cell: Cell, deformation_matrix: np.ndarray) -> None: r"""对晶胞施加形变矩阵 :math:`\mathbf{F}` Parameters ---------- cell : Cell 包含原子的晶胞对象 deformation_matrix : numpy.ndarray 3×3 形变矩阵 Raises ------ ValueError 如果变形矩阵不是3x3矩阵或行列式接近零 """ if deformation_matrix.shape != (3, 3): raise ValueError("变形矩阵必须是3x3矩阵") det = np.linalg.det(deformation_matrix) if np.isclose(det, 0, atol=1e-10): raise ValueError("变形矩阵行列式接近零,可能导致数值不稳定") try: # 委托给 Cell 方法,保持坐标与晶格约定一致 cell.apply_deformation(deformation_matrix) logging.info(f"成功应用变形矩阵: {deformation_matrix}") except Exception as e: logging.error(f"应用变形矩阵失败: {str(e)}") raise