tm - Troullier-Martins 伪化器

本模块实现 Troullier-Martins (TM) 方法,将全电子轨道伪化为光滑无节点的伪轨道,满足范数守恒条件。

Troullier-Martins (TM) 伪化器

实现 TM 方法生成赝轨道,满足范数守恒和连续性约束。

主要功能

tm_pseudize : 对给定 AE 轨道进行 TM 伪化 TMResult : 存储伪化结果的数据类

参考文献

Troullier & Martins, PRB 43, 1993 (1991)

算法文档

详见 docs/source/algorithm/tm_method.rst

class atomppgen.tm.TMResult(u_ps, a_coeff, rc, eps, l, norm_error, continuity_orders, continuity_check, solver_info)[源代码]

基类:object

TM 伪化结果

参数:
u_ps

伪轨道 u(r)(径向波函数,已拼接内外区)

Type:

np.ndarray

a_coeff

TM 多项式系数 [a_0, a_2, a_4, ...] 内区形式:u = r^{l+1} exp(Σ a_{2i} r^{2i})

Type:

np.ndarray

rc

伪化半径(Bohr)

Type:

float

eps

伪化能量(Hartree)

Type:

float

l

角动量量子数

Type:

int

norm_error

范数守恒相对误差 |Q_PS - Q_AE| / Q_AE

Type:

float

continuity_orders

连续性阶数(匹配到几阶导数,2 或 4)

Type:

int

continuity_check

rc 处的连续性检查结果 {'u': {...}, 'du': {...}, 'd2u': {...}}

Type:

Dict

solver_info

求解器收敛信息 {'ier': int, 'nfev': int, 'mesg': str, 'fallback': bool}

Type:

Dict

u_ps: ndarray
a_coeff: ndarray
rc: float
eps: float
l: int
norm_error: float
continuity_orders: int
continuity_check: Dict
solver_info: Dict
__init__(u_ps, a_coeff, rc, eps, l, norm_error, continuity_orders, continuity_check, solver_info)
参数:
返回类型:

None

atomppgen.tm.tm_pseudize(r, w, u_ae, eps, l, rc, continuity_orders=2)[源代码]

使用 Troullier-Martins 方法构造伪轨道

在 r ≤ rc 内区,伪轨道形式为:

u(r) = r^{l+1} · exp(Σ_{i=0}^{N} a_{2i} r^{2i})

约束条件: 1. 在 r = rc 处,u 及其导数(到 continuity_orders 阶)与 AE 轨道连续 2. 内区范数守恒:∫_0^{rc} |u|^2 dr = ∫_0^{rc} |u_ae|^2 dr

参数:
  • r (np.ndarray) -- 径向网格(Bohr)

  • w (np.ndarray) -- 积分权重

  • u_ae (np.ndarray) -- 全电子径向波函数 u(r)(已归一化)

  • eps (float) -- 伪化能量(Hartree)

  • l (int) -- 角动量量子数

  • rc (float) -- 伪化半径(Bohr)

  • continuity_orders (int, optional) -- 导数连续性阶数,默认 2(匹配 u, u', u'' + 范数) 可选 4(匹配到 u'''' + 范数)

返回:

包含伪轨道、系数、范数误差等信息

返回类型:

TMResult

抛出:

ValueError -- 如果 rc 不在网格范围内 如果 continuity_orders 不是 2 或 4

备注

TM 方法关键点: 1. 系数数量由连续性条件决定:

  • continuity_orders = 2: 需要 4 个系数 [a_0, a_2, a_4, a_6]

  • continuity_orders = 4: 需要 6 个系数 [a_0, ..., a_10]

  1. 数值稳定性:使用对数形式避免指数溢出

  2. 范数守恒通过非线性方程组保证(scipy.optimize.fsolve)

  3. 网格推荐:强烈建议使用 exp_transformedlog 网格类型。 linear 网格的导数精度不足,可能导致 TM 非线性方程组不收敛。

引用

Troullier & Martins, PRB 43, 1993 (1991), 方程 (14)-(18)

主要函数

atomppgen.tm.tm_pseudize(r, w, u_ae, eps, l, rc, continuity_orders=2)[源代码]

使用 Troullier-Martins 方法构造伪轨道

在 r ≤ rc 内区,伪轨道形式为:

u(r) = r^{l+1} · exp(Σ_{i=0}^{N} a_{2i} r^{2i})

约束条件: 1. 在 r = rc 处,u 及其导数(到 continuity_orders 阶)与 AE 轨道连续 2. 内区范数守恒:∫_0^{rc} |u|^2 dr = ∫_0^{rc} |u_ae|^2 dr

参数:
  • r (np.ndarray) -- 径向网格(Bohr)

  • w (np.ndarray) -- 积分权重

  • u_ae (np.ndarray) -- 全电子径向波函数 u(r)(已归一化)

  • eps (float) -- 伪化能量(Hartree)

  • l (int) -- 角动量量子数

  • rc (float) -- 伪化半径(Bohr)

  • continuity_orders (int, optional) -- 导数连续性阶数,默认 2(匹配 u, u', u'' + 范数) 可选 4(匹配到 u'''' + 范数)

返回:

包含伪轨道、系数、范数误差等信息

返回类型:

TMResult

抛出:

ValueError -- 如果 rc 不在网格范围内 如果 continuity_orders 不是 2 或 4

备注

TM 方法关键点: 1. 系数数量由连续性条件决定:

  • continuity_orders = 2: 需要 4 个系数 [a_0, a_2, a_4, a_6]

  • continuity_orders = 4: 需要 6 个系数 [a_0, ..., a_10]

  1. 数值稳定性:使用对数形式避免指数溢出

  2. 范数守恒通过非线性方程组保证(scipy.optimize.fsolve)

  3. 网格推荐:强烈建议使用 exp_transformedlog 网格类型。 linear 网格的导数精度不足,可能导致 TM 非线性方程组不收敛。

引用

Troullier & Martins, PRB 43, 1993 (1991), 方程 (14)-(18)

数据类

class atomppgen.tm.TMResult(u_ps, a_coeff, rc, eps, l, norm_error, continuity_orders, continuity_check, solver_info)[源代码]

TM 伪化结果

参数:
u_ps

伪轨道 u(r)(径向波函数,已拼接内外区)

Type:

np.ndarray

a_coeff

TM 多项式系数 [a_0, a_2, a_4, ...] 内区形式:u = r^{l+1} exp(Σ a_{2i} r^{2i})

Type:

np.ndarray

rc

伪化半径(Bohr)

Type:

float

eps

伪化能量(Hartree)

Type:

float

l

角动量量子数

Type:

int

norm_error

范数守恒相对误差 |Q_PS - Q_AE| / Q_AE

Type:

float

continuity_orders

连续性阶数(匹配到几阶导数,2 或 4)

Type:

int

continuity_check

rc 处的连续性检查结果 {'u': {...}, 'du': {...}, 'd2u': {...}}

Type:

Dict

solver_info

求解器收敛信息 {'ier': int, 'nfev': int, 'mesg': str, 'fallback': bool}

Type:

Dict

u_ps: ndarray
a_coeff: ndarray
rc: float
eps: float
l: int
norm_error: float
continuity_orders: int
continuity_check: Dict
solver_info: Dict
__init__(u_ps, a_coeff, rc, eps, l, norm_error, continuity_orders, continuity_check, solver_info)
参数:
返回类型:

None

使用示例

基础用法

from atomppgen import solve_ae_atom, tm_pseudize
import numpy as np

# 1. 获取全电子解
ae_result = solve_ae_atom(
    Z=13,  # Al
    spin_mode="LDA",
    lmax=0,
    grid_type="exp_transformed",
    grid_params={"n": 800, "rmax": 100.0},
    scf_params={"tol": 1e-6}
)

# 2. 提取 3s 轨道
r = ae_result.r
w = ae_result.w
u_ae_3s = ae_result.u_by_l[0][2]
eps_3s = ae_result.eps_by_l[0][2]

# 3. TM 伪化
result = tm_pseudize(
    r=r,
    w=w,
    u_ae=u_ae_3s,
    eps=eps_3s,
    l=0,
    rc=2.1,  # Bohr
    continuity_orders=2,
)

# 4. 查看结果
print(f"范数守恒误差: {result.norm_error:.2e}")
print(f"TM 系数: {result.a_coeff}")

# 5. 绘图对比
import matplotlib.pyplot as plt
plt.plot(r, u_ae_3s, label='AE')
plt.plot(r, result.u_ps, '--', label='PS')
plt.axvline(result.rc, color='k', ls=':', alpha=0.5, label=f'rc={result.rc}')
plt.legend()
plt.show()

不同连续性阶数

# 二阶连续性(4 个系数)
result_2nd = tm_pseudize(
    r=r, w=w, u_ae=u_ae, eps=eps, l=0, rc=2.1,
    continuity_orders=2
)
print(f"系数数量: {len(result_2nd.a_coeff)}")  # 4
print(f"范数误差: {result_2nd.norm_error:.2e}")

# 四阶连续性(6 个系数,更严格)
result_4th = tm_pseudize(
    r=r, w=w, u_ae=u_ae, eps=eps, l=0, rc=2.1,
    continuity_orders=4
)
print(f"系数数量: {len(result_4th.a_coeff)}")  # 6
print(f"范数误差: {result_4th.norm_error:.2e}")

多通道伪化

# Al 的 s, p, d 通道
ae_result = solve_ae_atom(Z=13, spin_mode="LDA", lmax=2)

rc_by_l = {0: 2.1, 1: 2.2, 2: 2.4}  # 推荐截断半径
tm_results = {}

for l in range(3):  # s, p, d
    # 价层轨道索引(Al: 3s, 3p, 3d)
    n_valence = {0: 2, 1: 1, 2: 0}  # 对应 u_by_l 的索引

    u_ae = ae_result.u_by_l[l][n_valence[l]]
    eps = ae_result.eps_by_l[l][n_valence[l]]

    result = tm_pseudize(
        r=ae_result.r, w=ae_result.w,
        u_ae=u_ae, eps=eps, l=l,
        rc=rc_by_l[l],
        continuity_orders=2
    )
    tm_results[l] = result

    print(f"l={l}: norm_error={result.norm_error:.2e}")

连续性检查

result = tm_pseudize(r=r, w=w, u_ae=u_ae, eps=eps, l=0, rc=2.0)

# 检查各阶导数的连续性
for key in ['u', 'du', 'd2u']:
    check = result.continuity_check[key]
    print(f"{key}:")
    print(f"  PS = {check['ps']:.6e}")
    print(f"  AE = {check['ae']:.6e}")
    print(f"  相对误差 = {check['rel_error']:.2e}")

技术细节

截断半径选择指南

推荐值(单位:Bohr):

元素

通道

rc 推荐值

Al (Z=13)

s

2.0-2.2

p

2.1-2.3

d

2.3-2.5

选择原则:

  1. 最小值:rc 必须大于最外层节点半径(确保内区无节点)

  2. 最大值:rc 应小于共价半径的 1.5 倍(避免过软)

  3. 平衡点:较小的 rc 产生更硬的赝势(可转移性好),但计算成本高

连续性阶数对比

continuity_orders

系数数量

约束条件

典型精度

2

4

u, u', u'', 范数

1e-6

4

6

u, u', ..., u'''', 范数

1e-7

说明:

  • **二阶**(推荐):平衡精度与求解速度,适合大多数情况

  • 四阶:更平滑的伪势,适合高精度计算或重元素

数值稳定性

TM 伪化内部采用以下保护措施:

  1. 指数溢出保护:在 exp(p(r)) 中,如果 p(r) > 100,自动调整初值

  2. 范数积分精度:使用 Simpson 法则,精度 O(h^4)

  3. 非线性求解器容差:xtol=1e-10,自动重试不收敛情况

如果遇到收敛问题:

  • 尝试调整 rc(±0.1 Bohr)

  • 检查 AE 解是否正确(converged=True)

  • 降低 continuity_orders(从 4 降到 2)

范数守恒验收标准

教学标准:norm_error < 1e-5

生产标准:norm_error < 1e-6(推荐用于发表)

典型误差水平:

rc (Bohr)

范数误差(Al 3s)

1.8

~1e-7

2.0

~5e-7

2.2

~2e-6

2.4

~8e-6

说明:较大的 rc 会增加范数守恒误差,但通常仍在可接受范围内。

参考文献