核心模块 (core)
本模块提供分子动力学模拟的基础数据结构。
结构模块
分子动力学结构模块
该模块提供分子动力学模拟中的基础数据结构,包括原子和晶胞的表示。 实现了周期性边界条件、最小镜像约定等关键算法。
理论基础
分数/笛卡尔坐标定义(采用列向量记号):
其中:
- \(\mathbf{r}\)
笛卡尔坐标
- \(\mathbf{s}\)
分数坐标
- \(\mathbf{L}\)
晶格矢量矩阵(列向量为基矢)
最小镜像约定 (Minimum Image Convention):
实现说明:本模块内部在代码中使用“行向量右乘”的等价实现。 例如上式可写作 \(\mathbf{s}^{\top} = \mathbf{r}^{\top}\,\mathbf{L}^{-1}\) 与 \(\mathbf{r}^{\top} = \mathbf{s}^{\top}\,\mathbf{L}^{\top}\)。
Classes
- Atom
表示单个原子,包含位置、速度、力等属性
- Cell
表示晶胞结构,管理原子集合和晶格矢量
Functions
- _apply_pbc_numba
JIT优化的周期性边界条件应用函数
备注
本模块是ThermoElasticSim的核心组件,为分子动力学模拟提供基础数据结构。 所有长度单位为埃(Å),时间单位为飞秒(fs),能量单位为电子伏特(eV)。
示例
创建简单的铝晶胞:
>>> from thermoelasticsim.core.structure import Atom, Cell
>>> import numpy as np
>>> # 创建FCC铝的原胞
>>> a = 4.05 # 晶格常数
>>> lattice = np.array([[a, 0, 0], [0, a, 0], [0, 0, a]])
>>> atoms = [
... Atom(0, "Al", 26.98, [0, 0, 0]),
... Atom(1, "Al", 26.98, [a/2, a/2, 0]),
... Atom(2, "Al", 26.98, [a/2, 0, a/2]),
... Atom(3, "Al", 26.98, [0, a/2, a/2])
... ]
>>> cell = Cell(lattice, atoms)
- class thermoelasticsim.core.structure.Atom(id, symbol, mass_amu, position, velocity=None)[源代码]
基类:
object原子对象,分子动力学模拟的基本单元
表示一个原子的完整状态,包括位置、速度、受力等物理属性。 在MD模拟中,原子遵循牛顿运动方程:
\[m \frac{d^2\mathbf{r}}{dt^2} = \mathbf{F}\]- 参数:
- position
当前位置向量 (3,)
- Type:
- velocity
当前速度向量 (3,)
- Type:
- force
当前受力向量 (3,)
- Type:
备注
质量与常数采用全局统一定义(参见
thermoelasticsim.utils.utils模块):AMU_TO_EVFSA2质量单位转换常量(amu → eV·fs²/Ų)。
KB_IN_EV玻尔兹曼常数(eV/K)。
示例
创建铝原子:
>>> atom = Atom(id=1, symbol="Al", mass_amu=26.98, position=[0, 0, 0]) >>> atom.velocity = np.array([1.0, 0.0, 0.0]) # 设置速度 >>> print(f"动能: {0.5 * atom.mass * np.dot(atom.velocity, atom.velocity):.4f} eV")
- move_by(displacement)[源代码]
通过位置增量移动原子
- 参数:
displacement (numpy.ndarray | array_like) -- 位置增量向量,形状为 (3,)
- 抛出:
ValueError -- 如果位置增量不是3D向量
- 返回类型:
None
示例
>>> atom = Atom(1, 'H', 1.0, [0, 0, 0]) >>> atom.move_by([0.1, 0.2, 0.3]) >>> print(atom.position) [0.1 0.2 0.3]
- accelerate_by(velocity_change)[源代码]
通过速度增量改变原子速度
- 参数:
velocity_change (numpy.ndarray | array_like) -- 速度增量向量,形状为 (3,)
- 抛出:
ValueError -- 如果速度增量不是3D向量
- 返回类型:
None
示例
>>> atom = Atom(1, 'H', 1.0, [0, 0, 0]) >>> atom.accelerate_by([0.1, 0.2, 0.3]) >>> print(atom.velocity) [0.1 0.2 0.3]
- class thermoelasticsim.core.structure.Cell(lattice_vectors, atoms, pbc_enabled=True)[源代码]
基类:
object晶胞对象,管理原子集合和晶格结构
晶胞是分子动力学模拟的基本容器,定义了模拟盒子的几何形状 和其中包含的原子。支持周期性边界条件和最小镜像约定。
晶格矢量定义为行向量:
\[\begin{split}\mathbf{L} = \begin{pmatrix} \mathbf{a}_1 \\ \mathbf{a}_2 \\ \mathbf{a}_3 \end{pmatrix}\end{split}\]晶胞体积计算:
\[V = |\mathbf{a}_1 \cdot (\mathbf{a}_2 \times \mathbf{a}_3)|\]- 参数:
- lattice_vectors
晶格矢量矩阵 (3, 3)
- Type:
- lattice_inv
晶格逆矩阵,用于坐标转换
- Type:
备注
分数/笛卡尔坐标转换(列向量记号):
\[\mathbf{r} = \mathbf{L}\,\mathbf{s},\qquad \mathbf{s} = \mathbf{L}^{-1}\,\mathbf{r}\]实现采用“行向量右乘”的等价式:
\[\mathbf{s}^{\top} = \mathbf{r}^{\top}\,\mathbf{L}^{-1},\qquad \mathbf{r}^{\top} = \mathbf{s}^{\top}\,\mathbf{L}^{\top}\]示例
创建FCC铝晶胞:
>>> a = 4.05 # 晶格常数 >>> lattice = a * np.eye(3) # 立方晶格 >>> atoms = [ ... Atom(0, "Al", 26.98, [0, 0, 0]), ... Atom(1, "Al", 26.98, [a/2, a/2, 0]), ... Atom(2, "Al", 26.98, [a/2, 0, a/2]), ... Atom(3, "Al", 26.98, [0, a/2, a/2]) ... ] >>> cell = Cell(lattice, atoms) >>> print(f"晶胞体积: {cell.volume:.2f} ų")
- calculate_stress_tensor(potential)[源代码]
计算应力张量
- 参数:
potential (Potential) -- 用于计算应力的势能对象
- 返回:
3×3 应力张量矩阵 (eV/ų)
- 返回类型:
- lock_lattice_vectors()[源代码]
锁定晶格向量,防止在优化过程中被修改
备注
锁定后,晶格向量将不能被修改,直到调用
unlock_lattice_vectors()。- 返回类型:
None
- unlock_lattice_vectors()[源代码]
解锁晶格向量,允许在需要时修改
备注
解锁后,晶格向量可以被修改,直到再次调用
lock_lattice_vectors()。- 返回类型:
None
- apply_deformation(deformation_matrix)[源代码]
对晶格与原子坐标施加形变矩阵 \(\mathbf{F}\)
- 参数:
deformation_matrix (numpy.ndarray) -- 形变矩阵 \(\mathbf{F}\),形状为 (3, 3)
- 返回类型:
None
备注
采用列向量约定的连续介质力学记号:
晶格未锁定(允许变胞)时:
\[\mathbf{L}_{\text{new}} = \mathbf{F}\, \mathbf{L}_{\text{old}},\qquad \mathbf{r}_{\text{new}} = \mathbf{F}\, \mathbf{r}_{\text{old}}\]晶格已锁定(固定胞形)时:
\[\mathbf{L}_{\text{new}} = \mathbf{L}_{\text{old}},\qquad \mathbf{r}_{\text{new}} = \mathbf{F}\, \mathbf{r}_{\text{old}}\]
实现细节:本实现使用“行向量右乘”形式,等价写法为
\[\mathbf{r}_{\text{new}}^{\top} = \mathbf{r}_{\text{old}}^{\top} \mathbf{F}^{\top}.\]示例
>>> import numpy as np >>> F = np.array([[1.01, 0, 0], [0, 1, 0], [0, 0, 1]]) >>> cell.apply_deformation(F)
- apply_periodic_boundary(positions)[源代码]
应用周期性边界条件
将原子位置映射回主晶胞内,使用标准的最小镜像约定。
算法(列向量记号):
\[\mathbf{s} = \mathbf{L}^{-1}\,\mathbf{r},\qquad \mathbf{s}' = \mathbf{s} - \lfloor \mathbf{s} + 0.5 \rfloor,\qquad \mathbf{r}' = \mathbf{L}\,\mathbf{s}'\]- 参数:
positions (numpy.ndarray) -- 原子位置坐标,形状为 (3,) 或 (N, 3)
- 返回:
应用PBC后的位置,保持输入形状
- 返回类型:
- 抛出:
ValueError -- 如果位置数组形状不正确或包含非有限值
备注
该实现使用分数坐标进行周期性映射,确保数值稳定性。 对于三斜晶系也能正确处理。
示例
>>> # 单个原子位置 >>> pos = np.array([5.0, 6.0, 7.0]) >>> new_pos = cell.apply_periodic_boundary(pos) >>> # 批量处理 >>> positions = np.random.randn(100, 3) * 10 >>> new_positions = cell.apply_periodic_boundary(positions)
- calculate_temperature()[源代码]
计算系统的瞬时温度
使用均分定理计算温度,扣除质心运动贡献:
\[T = \frac{2 E_{kin}}{k_B \cdot N_{dof}}\]其中动能(扣除质心):
\[E_{kin} = \sum_i \frac{1}{2} m_i |\mathbf{v}_i - \mathbf{v}_{cm}|^2\]自由度数定义:
\[\begin{split}N_{\mathrm{dof}} = \begin{cases} 3N - 3, & N > 1, \\ 3, & N = 1. \end{cases}\end{split}\]- 返回:
系统温度,单位为 \(\mathrm{K}\)
- 返回类型:
备注
瞬时温度会有涨落,通常需要时间平均来获得稳定值。 对于NVE系综,温度是守恒量的函数。
示例
>>> temp = cell.calculate_temperature() >>> print(f"瞬时温度: {temp:.1f} K") >>> # 计算时间平均温度 >>> temps = [cell.calculate_temperature() for _ in range(1000)] >>> avg_temp = np.mean(temps)
参见
calculate_kinetic_energy计算总动能(含质心运动)
- calculate_kinetic_energy()[源代码]
计算当前系统的总动能
- 返回:
系统总动能,单位为 \(\mathrm{eV}\)
- 返回类型:
备注
计算所有原子的动能总和,包含质心运动
示例
>>> cell = Cell(lattice_vectors, atoms) >>> kinetic = cell.calculate_kinetic_energy() >>> print(f"系统动能: {kinetic:.6f} eV")
- get_positions()[源代码]
获取所有原子的位置信息
- 返回:
原子位置数组,形状为 (num_atoms, 3)
- 返回类型:
示例
>>> positions = cell.get_positions() >>> print(f"原子数量: {positions.shape[0]}")
- set_velocities(velocities)[源代码]
设置所有原子的速度
- 参数:
velocities (numpy.ndarray) -- 速度数组,形状为 (num_atoms, 3)
- 抛出:
ValueError -- 当输入数组形状与原子数不匹配时抛出
- 返回类型:
None
- minimum_image(displacement)[源代码]
计算最小镜像位移向量
根据最小镜像约定,找到最近的周期镜像之间的位移。 这对于正确计算周期性系统中的距离和力至关重要。
数学原理(列向量记号):
\[\mathbf{d}_{\min} = \mathbf{d} - \mathbf{L}\, \operatorname{round}(\mathbf{L}^{-1} \mathbf{d})\]- 参数:
displacement (numpy.ndarray) -- 原始位移向量 (3,)
- 返回:
最小镜像位移向量 (3,)
- 返回类型:
- 抛出:
ValueError -- 如果位移向量不是3D或包含非有限值
备注
该方法确保返回的位移向量长度最小,对应于最近的周期镜像。 在计算原子间相互作用时必须使用此方法。
示例
>>> # 计算两原子间的最小距离 >>> r12 = atom2.position - atom1.position >>> r12_min = cell.minimum_image(r12) >>> distance = np.linalg.norm(r12_min)
参见
apply_periodic_boundary应用周期性边界条件
- property num_atoms
返回原子数量
- set_lattice_vectors(lattice_vectors)[源代码]
设置新的晶格矢量并更新相关属性。
- 参数:
lattice_vectors (np.ndarray) -- 新的 3x3 晶格矢量矩阵。
- get_fractional_coordinates()[源代码]
获取所有原子的分数坐标
- 返回:
原子分数坐标数组,形状为(num_atoms, 3)
- 返回类型:
备注
坐标关系(列向量记号):
\[\mathbf{s} = \mathbf{L}^{-1}\,\mathbf{r}\]代码实现采用行向量右乘:\(\mathbf{s}^{\top} = \mathbf{r}^{\top}\,\mathbf{L}^{-1}\)。
- set_fractional_coordinates(fractional_coords)[源代码]
根据分数坐标设置所有原子的笛卡尔坐标
- 参数:
fractional_coords (numpy.ndarray) -- 分数坐标数组,形状为(num_atoms, 3)
- 返回类型:
None
备注
坐标关系(列向量记号):
\[\mathbf{r} = \mathbf{L}\,\mathbf{s}\]代码实现采用行向量右乘:\(\mathbf{r}^{\top} = \mathbf{s}^{\top}\,\mathbf{L}^{\top}\)。
- set_positions(positions)[源代码]
设置所有原子的笛卡尔坐标
- 参数:
positions (numpy.ndarray) -- 笛卡尔坐标数组,形状为(num_atoms, 3)
- 返回类型:
None
结构构建器
晶体结构生成器模块
该模块提供统一的晶体结构生成接口,支持多种晶格类型和材料元素, 用于为弹性常数计算和分子动力学模拟创建标准晶体结构。
支持的晶格类型:
FCC(面心立方):如 Al、Cu、Au 等
BCC(体心立方):如 Fe、Cr 等(预留)
HCP(密排六方):如 Zn、Mg 等(预留)
示例
创建 3×3×3 的铝 FCC 超胞:
>>> builder = CrystallineStructureBuilder()
>>> cell = builder.create_fcc("Al", 4.05, (3, 3, 3))
>>> cell.num_atoms
108
- class thermoelasticsim.core.crystalline_structures.CrystallineStructureBuilder[源代码]
基类:
object统一的晶体结构生成器
提供多种晶格类型的标准化生成方法,支持任意超胞尺寸和材料参数。 所有生成的结构都经过周期性边界条件优化,适用于分子动力学计算。
示例
创建3×3×3的铝FCC超胞:
>>> builder = CrystallineStructureBuilder() >>> al_cell = builder.create_fcc("Al", 4.05, (3, 3, 3)) >>> print(f"原子数: {al_cell.num_atoms}") 原子数: 108
创建不同尺寸的铜结构:
>>> cu_cell = builder.create_fcc("Cu", 3.615, (4, 4, 4)) >>> print(f"晶胞体积: {cu_cell.volume:.1f} ų") 晶胞体积: 1885.4 ų
- ATOMIC_MASSES = {'Ag': 107.8682, 'Al': 26.9815, 'Ar': 39.95, 'Au': 196.966569, 'C': 12.0107, 'Cr': 51.9961, 'Cu': 63.546, 'Fe': 55.845, 'Mg': 24.305, 'Ni': 58.6934, 'Pb': 207.2, 'Ti': 47.867, 'V': 50.9415, 'Zn': 65.38}
- create_fcc(element, lattice_constant, supercell)[源代码]
创建面心立方(FCC)结构
FCC结构特点: - 原胞包含4个原子 - 基矢:(0,0,0), (0.5,0.5,0), (0.5,0,0.5), (0,0.5,0.5) - 配位数:12 - 致密度:74%
- 参数:
- 返回:
包含FCC结构的晶胞对象
- 返回类型:
- 抛出:
ValueError -- 如果元素不在支持列表中
TypeError -- 如果参数类型不正确
示例
创建标准Al FCC结构:
>>> builder = CrystallineStructureBuilder() >>> cell = builder.create_fcc("Al", 4.05, (2, 2, 2)) >>> cell.num_atoms 32
备注
生成的结构特性:
原子数计算:总原子数 = 4 × nx × ny × nz
晶胞矢量:正交晶胞,a = b = c = lattice_constant
周期边界:默认启用,适用于无限系统模拟
原子编号:从0开始连续编号
- create_diamond(element, lattice_constant, supercell)[源代码]
创建金刚石(diamond cubic)结构的常规立方胞(8原子/胞)并复制成超胞。
- create_bcc(element, lattice_constant, supercell)[源代码]
创建体心立方(BCC)结构
BCC结构特点: - 原胞包含2个原子 - 基矢:(0,0,0), (0.5,0.5,0.5) - 配位数:8 - 致密度:68%
- 参数:
- 返回:
包含BCC结构的晶胞对象
- 返回类型:
备注
此方法为预留接口,完整实现待后续版本。 当前主要支持FCC结构的弹性常数计算。
- create_hcp(element, lattice_constant, supercell)[源代码]
创建密排六方(HCP)结构
HCP结构特点: - 原胞包含2个原子 - 六方晶系,c/a ≈ 1.633 - 配位数:12 - 致密度:74%
- 参数:
- 返回:
包含HCP结构的晶胞对象
- 返回类型:
备注
此方法为预留接口,完整实现待后续版本。 当前主要支持FCC结构的弹性常数计算。
- static get_atomic_mass(element)[源代码]
获取指定元素的原子质量
- 参数:
element (str) -- 元素符号
- 返回:
原子质量 (amu)
- 返回类型:
- 抛出:
ValueError -- 如果元素不在支持列表中
配置模块
配置加载模块(MVP)
提供轻量的 YAML 配置加载与工具函数,满足教学与示例场景:
递归合并多份 YAML(后者覆盖前者)
点路径访问(如
md.timestep)统一设置随机种子(numpy/random)
基于模板创建输出目录并保存配置快照
备注
本模块刻意不引入 Hydra,以保持依赖简单与行为透明;后续若需要 更复杂的组合与命令行覆盖,可在不破坏兼容性的前提下扩展。
- thermoelasticsim.core.config.dataclass(cls=None, /, *, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, weakref_slot=False)[源代码]
Add dunder methods based on the fields defined in the class.
Examines PEP 526 __annotations__ to determine fields.
If init is true, an __init__() method is added to the class. If repr is true, a __repr__() method is added. If order is true, rich comparison dunder methods are added. If unsafe_hash is true, a __hash__() method is added. If frozen is true, fields may not be assigned to after instance creation. If match_args is true, the __match_args__ tuple is added. If kw_only is true, then by default all fields are keyword-only. If slots is true, a new class with a __slots__ attribute is returned.
- class thermoelasticsim.core.config.Path(*args, **kwargs)[源代码]
基类:
PurePathPurePath subclass that can make system calls.
Path represents a filesystem path but unlike PurePath, also offers methods to do system calls on path objects. Depending on your system, instantiating a Path will return either a PosixPath or a WindowsPath object. You can also instantiate a PosixPath or WindowsPath directly, but cannot instantiate a WindowsPath on a POSIX system or vice versa.
- absolute()[源代码]
Return an absolute version of this path by prepending the current working directory. No normalization or symlink resolution is performed.
Use resolve() to get the canonical path to a file.
- classmethod cwd()[源代码]
Return a new path pointing to the current working directory (as returned by os.getcwd()).
- expanduser()[源代码]
Return a new path with expanded ~ and ~user constructs (as returned by os.path.expanduser)
- glob(pattern)[源代码]
Iterate over this subtree and yield all existing files (of any kind, including directories) matching the given relative pattern.
- hardlink_to(target)[源代码]
Make this path a hard link pointing to the same file as target.
Note the order of arguments (self, target) is the reverse of os.link's.
- classmethod home()[源代码]
Return a new path pointing to the user's home directory (as returned by os.path.expanduser('~')).
- is_file()[源代码]
Whether this path is a regular file (also True for symlinks pointing to regular files).
- iterdir()[源代码]
Iterate over the files in this directory. Does not yield any result for the special paths '.' and '..'.
- lchmod(mode)[源代码]
Like chmod(), except if the path points to a symlink, the symlink's permissions are changed, rather than its target's.
- link_to(target)[源代码]
Make the target path a hard link pointing to this path.
Note this function does not make this path a hard link to target, despite the implication of the function and argument names. The order of arguments (target, link) is the reverse of Path.symlink_to, but matches that of os.link.
Deprecated since Python 3.10 and scheduled for removal in Python 3.12. Use hardlink_to() instead.
- lstat()[源代码]
Like stat(), except if the path points to a symlink, the symlink's status information is returned, rather than its target's.
- open(mode='r', buffering=-1, encoding=None, errors=None, newline=None)[源代码]
Open the file pointed by this path and return a file object, as the built-in open() function does.
- read_text(encoding=None, errors=None)[源代码]
Open the file in text mode, read it, and close the file.
- rename(target)[源代码]
Rename this path to the target path.
The target path may be absolute or relative. Relative paths are interpreted relative to the current working directory, not the directory of the Path object.
Returns the new Path instance pointing to the target path.
- replace(target)[源代码]
Rename this path to the target path, overwriting if that path exists.
The target path may be absolute or relative. Relative paths are interpreted relative to the current working directory, not the directory of the Path object.
Returns the new Path instance pointing to the target path.
- resolve(strict=False)[源代码]
Make the path absolute, resolving all symlinks on the way and also normalizing it.
- rglob(pattern)[源代码]
Recursively yield all existing files (of any kind, including directories) matching the given relative pattern, anywhere in this subtree.
- samefile(other_path)[源代码]
Return whether other_path is the same or not as this file (as returned by os.path.samefile()).
- stat(*, follow_symlinks=True)[源代码]
Return the result of the stat() system call on this path, like os.stat() does.
- symlink_to(target, target_is_directory=False)[源代码]
Make this path a symlink pointing to the target path. Note the order of arguments (link, target) is the reverse of os.symlink.
- touch(mode=438, exist_ok=True)[源代码]
Create this file with the given access mode, if it doesn't exist.
- class thermoelasticsim.core.config.Any(*args, **kwargs)[源代码]
基类:
objectSpecial type indicating an unconstrained type.
Any is compatible with every type.
Any assumed to have all methods.
All values assumed to be instances of Any.
Note that all the above statements are true from the point of view of static type checkers. At runtime, Any should not be used with instance checks.
- class thermoelasticsim.core.config.ConfigManager(files=None)[源代码]
基类:
object配置管理器
加载一组 YAML 配置文件并进行递归合并,提供点路径访问与常用工具。