# PyPOSTB 代码架构文档

## 概述

PyPOSTB 是一个用于紧束缚模型（Tight-Binding Model）计算的 Python 包。它基于 `pythtb` 库，**直接从 POSCAR 文件读取所有参数**，建立紧束缚模型并计算能带结构。

**版本**: 0.3.0

**重要变化**: 
- ✅ 完全移除 TOML 配置文件依赖
- ✅ 所有参数从 POSCAR 文件第一行读取
- ✅ 磁矩信息从 POSCAR 坐标行读取
- ✅ k 路径从 KPATH.in 或 KPOINTS 文件读取（必需）
- ✅ 最大跃迁距离自动设置为最大晶格常数

## 目录结构

```
old_pyamtb/
├── __init__.py              # 包入口，导出主要接口
├── cli.py                   # 命令行接口
├── parameters.py            # 参数管理类
├── read_datas.py            # 数据读取模块（POSCAR、TOML、KPATH）
├── tight_binding_model.py   # 核心模型计算模块
├── check_distance.py        # 距离计算工具
├── tbparas.toml             # 参数配置文件示例
├── tbparas_template.toml    # 参数配置模板
└── KPATH.in                 # k路径文件示例
```

## 核心模块详解

### 1. `__init__.py` - 包入口

**功能**: 定义包的公共接口，导出主要类和函数

**导出的主要接口**:
- `Parameters`: 参数管理类（从 POSCAR 读取）
- `read_poscar`: 读取扩展的 POSCAR 文件
- `read_kpath`: 读取 k 路径文件
- `calculate_band_structure`: 计算能带结构
- `create_pythtb_model`: 创建 pythtb 模型

### 2. `cli.py` - 命令行接口

**功能**: 提供命令行工具，支持三种操作模式

**命令结构**:
```bash
pyamtb <command> [options]
```

**可用命令**:

#### 2.1 计算能带结构
```bash
pypostb [--poscar POSCAR] [--output OUTPUT]
```
- `--poscar, -p`: POSCAR 文件路径（默认：`POSCAR`）
- `--output, -o`: 输出文件名（默认：`band_structure`）

**工作流程**:
1. 从 POSCAR 文件读取所有参数（dimk, dimr, hopping_decay, 磁矩等）
2. 从 KPATH.in 或 KPOINTS 读取 k 路径（必需，否则报错）
3. 创建 pythtb 模型
4. 计算能带结构
5. 保存结果图像

**要求**:
- POSCAR 文件必须存在
- KPATH.in 或 KPOINTS 文件必须存在（否则报错）

### 3. `parameters.py` - 参数管理

**核心类**: `Parameters`

**功能**: 
- 从 POSCAR 文件读取所有参数
- 自动计算最大跃迁距离（最大晶格常数）
- 从 KPATH.in 或 KPOINTS 读取 k 路径
- 验证参数有效性

**参数来源**:

#### 3.1 从 POSCAR 第一行读取
- `dimk`: k空间维度（1, 2, 或 3）
- `dimr`: r空间维度（通常为3）
- `hopping_decay`: 跃迁衰减系数 λ

**格式支持**:
- `dimr=3 dimk=3 hopping_decay=1.0`
- `3 3 1` (dimk dimr hopping_decay)

#### 3.2 从 POSCAR 结构读取
- `lattice`: 晶格向量（3x3 数组）
- `max_lattice_constant`: 最大晶格常数（自动计算）
- `elements`: 元素列表
- `atom_counts`: 各元素原子数量
- `coordinates`: 原子坐标（分数坐标）
- `magnetic_moments`: 磁矩数组（从坐标行第4列读取）

#### 3.3 固定参数
- `min_distance`: 0.1 埃（固定值）
- `max_distance`: 最大晶格常数（自动计算）
- `max_R_range`: 2（固定值）
- `t0`: -1.0（默认参考跃迁强度）
- `t0_distance`: 2.5 埃（默认参考距离）
- `nspin`: 2（有自旋）

#### 3.4 从 KPATH.in 或 KPOINTS 读取
- `kpath`: k点路径坐标列表（必需，否则报错）
- `klabel`: k点标签列表
- `num_k_points`: 100（默认值）

#### 3.5 默认参数
- `output_filename`: "band_structure"
- `output_format`: "png"
- `savedir`: "."
- `ylim`: [-2, 2]
- `is_black_degenerate_bands`: True
- `energy_threshold`: 1e-4
- `is_print_tb_model_hop`: False
- `is_print_tb_model`: True

**关键方法**:
- `__init__(poscar_filename)`: 从 POSCAR 文件初始化所有参数
- `get_maglist()`: 获取磁矩列表（从 POSCAR 读取）
- `_read_kpath()`: 读取 k 路径文件（必需）
- `_validate_parameters()`: 验证参数有效性

### 4. `read_datas.py` - 数据读取模块

**主要函数**:

#### 4.1 `read_poscar(filename, to_direct, use_scale)`
**功能**: 读取扩展的 POSCAR 文件格式

**新的 POSCAR 格式**:
```
第1行: dimr=3 dimk=3 [hopping_decay=1.0] 或 3 3 1
第2行: scale factor
第3-5行: 晶格向量
第6行: 元素列表
第7行: 元素数量
第8行: Direct/Cartesian
第9行开始: 原子坐标 (x y z [magmom])
```

**参数**:
- `filename`: POSCAR 文件路径
- `to_direct`: 是否转换为分数坐标
- `use_scale`: 是否使用比例因子

**返回**: 包含结构信息和参数的字典
```python
{
    "comment": 注释行,
    "scale": 比例因子,
    "lattice": 晶格向量 (3x3 numpy数组),
    "elements": 元素类型列表,
    "atom_counts": 各元素原子数量列表,
    "total_atoms": 总原子数,
    "coordinates": 原子坐标数组 (筛选后),
    "selected_atom_symbols": 筛选后的原子符号列表,
    "selected_indices": 筛选后的原子索引,
    "selected_total_atoms": 筛选后的原子总数,
    # ... 更多字段
}
```

**特性**:
- 支持 Direct 和 Cartesian 坐标
- 支持 Selective dynamics 行
- 自动处理坐标转换
- 支持元素筛选

#### 4.2 `read_kpath(filename)`
**功能**: 从 KPATH.in 文件读取 k 路径（VASP KPOINTS 格式）

**返回**: `(kpath, klabels)` 元组
- `kpath`: k点坐标列表
- `klabels`: k点标签列表

**格式支持**: VASP KPOINTS line-mode 格式

**重要**: 如果找不到 KPATH.in 或 KPOINTS 文件，会抛出 `FileNotFoundError`

### 5. `tight_binding_model.py` - 核心模型计算

**核心功能**: 建立紧束缚模型并计算能带结构

#### 5.1 距离计算函数

**`calculate_distance(coord1, coord2, lattice)`**
- 计算两个原子之间的距离（考虑周期性边界条件）
- 使用最小镜像约定

**`hopping_strength(distance, params)`**
- 计算跃迁强度与距离的关系
- 公式: `t = t0 * exp(-λ*(d-d0)/d0)`
- 其中 λ = `hopping_decay`, d0 = `t0_distance`

#### 5.2 耦合计算函数

**`get_coupling_strength(atom1_index, atom2_index, poscar_data, params)`**
- 计算两个原子之间的耦合强度
- 考虑周期性边界条件和相邻格点
- 生成所有可能的格矢量 R
- 返回: `(coupling_values, R_vectors, distance_values)`

**`calculate_all_couplings(poscar_data, params)`**
- 计算所有原子对之间的耦合
- 返回耦合信息列表

**`remove_duplicate_hoppings(couplings)`**
- 消除重复的跃迁对
- 如果两个跃迁的原子对和 R 矢量相同或仅相差负号，则认为是重复的

#### 5.3 模型创建函数

**`create_pythtb_model(params)`**
**工作流程**:
1. 使用 `params.poscar_data`（已从 POSCAR 读取）
2. 提取晶格向量和原子坐标
3. 创建 `tb_model` 实例
4. 计算所有原子对之间的耦合
5. 去除重复跃迁
6. 设置在位能（初始化为0）
7. 设置磁性（从 POSCAR 读取的磁矩）
8. 设置跃迁参数（`set_hop`）

**关键步骤**:
- 磁性设置: `model.set_onsite(magmom * sigma_z, ind, "add")`（从 POSCAR 读取）
- 跃迁设置: `model.set_hop(t, i, j, [R_x, R_y, R_z])`
- 最大距离: 自动使用 `params.max_distance`（最大晶格常数）

#### 5.4 能带计算函数

**`calculate_band_structure(model, params)`**
**工作流程**:
1. 生成 k 路径: `model.k_path(kpath, num_k_points)`
2. 求解本征值: `model.solve_all(k_vec, eig_vectors=True)`
3. 调整简并能带（如果启用）
4. 计算自旋投影
5. 绘制能带图（红色=自旋上，蓝色=自旋下）
6. 保存图像

**辅助函数**:
- `adjust_degenerate_bands()`: 修改简并能带的自旋投影
- `check_flat_bands()`: 检查是否存在平带

### 6. `check_distance.py` - 距离检查工具

**主要函数**: `calculate_distances(poscar_filename, element1, element2)`

**功能**:
- 计算所有原子对之间的距离
- 考虑周期性边界条件（搜索范围：-1 到 +1）
- 按距离排序
- 统计距离分布
- 打印前10个最常见的距离

**输出格式**:
```
距离(a.u.)    出现次数    原子对示例
--------------------------------------------------
1.2345        10          Mn1-Mn2 R=[0 0 0]
...
```

## 数据流

### 计算能带结构的完整流程

```
1. 用户调用 CLI 或直接使用 API
   ↓
2. Parameters 类从 POSCAR 文件读取所有参数
   - 解析第一行: dimk, dimr, hopping_decay
   - 读取晶格向量和原子坐标
   - 读取磁矩（从坐标行第4列）
   - 计算最大晶格常数（作为 max_distance）
   ↓
3. read_kpath() 读取 k 路径文件
   - 尝试读取 KPATH.in
   - 如果不存在，尝试读取 KPOINTS
   - 如果都不存在，报错退出
   ↓
4. create_pythtb_model() 创建模型
   - 使用所有原子（不再筛选元素）
   - 计算所有原子对之间的耦合
   - 应用距离衰减公式（max_distance = 最大晶格常数）
   - 设置在位能（初始化为0）
   - 设置磁性（从 POSCAR 读取）
   - 设置跃迁参数
   ↓
5. calculate_band_structure() 计算能带
   - 生成 k 路径
   - 求解本征值
   - 计算自旋投影
   - 绘制并保存图像
```

## 关键算法

### 1. 距离基跃迁强度计算

跃迁强度随距离指数衰减：
```
t(r) = t0 * exp(-λ * (r - r0) / r0)
```

其中：
- `t0`: 参考距离 `r0` 处的跃迁强度
- `λ`: 衰减系数 (`hopping_decay`)
- `r`: 实际距离
- `r0`: 参考距离 (`t0_distance`)

### 2. 周期性边界条件处理

在计算原子间距离时，考虑所有可能的格矢量偏移：
```python
for R in Rlist:  # R = [i, j, k], i,j,k ∈ [-max_R_range, max_R_range]
    diff = coord2 + R - coord1
    distance = ||diff · lattice||
```

### 3. 简并能带处理

如果两个能带能量差小于阈值且自旋投影相反，则将自旋投影设为0（涂黑）。

### 4. 自旋投影计算

对于每个能带和每个 k 点：
```python
spin_up_projection = Σ|ψ_orbital,spin_up|² / (Σ|ψ_orbital,spin_up|² + Σ|ψ_orbital,spin_down|²)
spin_down_projection = Σ|ψ_orbital,spin_down|² / (Σ|ψ_orbital,spin_up|² + Σ|ψ_orbital,spin_down|²)
```

## POSCAR 文件格式

### 扩展的 POSCAR 格式

PyPOSTB 使用扩展的 POSCAR 格式，所有参数都从文件中读取：

```vasp
dimr=3 dimk=3 hopping_decay=1.0    # 第1行：参数（或使用 "3 3 1" 格式）
   1.00000000000000                 # 第2行：scale factor
     5.8896136042106519  0.0  0.0   # 第3行：晶格向量1
     0.0  7.7193960717810146  0.0   # 第4行：晶格向量2
     0.0  0.0  5.5735571936146364   # 第5行：晶格向量3
   Mn   La   O                      # 第6行：元素列表
     4     4    12                   # 第7行：各元素原子数量
Direct                               # 第8行：坐标类型
  0.0  0.0  0.5     1               # 第9行开始：原子坐标 (x y z magmom)
  0.5  0.5  0.0    -1               # 第4列：磁矩（可选，默认为0）
  ...
```

**关键点**:
- 第1行必须包含 `dimk` 和 `dimr`（可选 `hopping_decay`）
- 第4列（如果存在）为磁矩值
- 最大跃迁距离自动设置为最大晶格常数

### KPATH.in 或 KPOINTS 文件格式

k 路径文件必须存在，支持 VASP KPOINTS line-mode 格式：

```
K-Path Generated by VASPKIT.
   20
Line-Mode
Reciprocal
   0.0000000000   0.0000000000   0.0000000000     GAMMA
   0.5000000000   0.0000000000   0.0000000000     M
 ...
```

## 常见问题定位指南

### 1. 参数相关错误

**问题**: `找不到 k 路径文件`
- **位置**: `read_datas.py:read_kpath()` 或 `parameters.py:_read_kpath()`
- **原因**: KPATH.in 和 KPOINTS 文件都不存在
- **解决**: 创建 KPATH.in 或 KPOINTS 文件（必需）

**问题**: `POSCAR 第一行格式错误`
- **位置**: `read_datas.py:_parse_first_line()`
- **原因**: 第一行必须包含 dimk 和 dimr
- **解决**: 检查第一行格式，应为 `dimr=3 dimk=3` 或 `3 3 1`

**问题**: `磁矩数量与原子数不匹配`
- **位置**: `parameters.py:_validate_parameters()`
- **原因**: POSCAR 中磁矩列的数量与原子数不一致
- **解决**: 检查 POSCAR 文件，确保每行坐标都有4列（或都没有）

### 2. POSCAR 读取错误

**问题**: `POSCAR 文件格式错误`
- **位置**: `read_datas.py:read_poscar()`
- **常见原因**:
  - 缺少元素符号行
  - 坐标类型行格式错误
  - 原子数不足
- **解决**: 检查 POSCAR 文件格式是否符合 VASP 标准

**问题**: `坐标类型未识别`
- **位置**: `read_datas.py:read_poscar()`
- **解决**: 确保第8行（或第9行，如果有 Selective dynamics）为 "Direct" 或 "Cartesian"

### 3. 模型计算错误

**问题**: `没有找到跃迁`
- **位置**: `tight_binding_model.py:get_coupling_strength()`
- **原因**: `max_distance`（最大晶格常数）太小或 `max_R_range`（固定为2）太小
- **解决**: 检查晶格向量，确保系统尺寸合理

**问题**: `能带图异常`
- **位置**: `tight_binding_model.py:calculate_band_structure()`
- **可能原因**:
  - k路径维度与 `dimk` 不匹配（会自动调整）
  - `ylim` 设置不合理
- **解决**: 检查 k 路径文件和 `dimk` 设置

### 4. k路径相关错误

**问题**: `KPATH.in 或 KPOINTS 文件解析失败`
- **位置**: `read_datas.py:read_kpath()`
- **原因**: 文件格式不符合 VASP KPOINTS line-mode 格式
- **解决**: 检查文件格式，确保坐标行格式正确（前3列为浮点数，第4列为标签）

## 代码修改指南

### 添加新的参数到 POSCAR

1. **在 `read_datas.py:read_poscar()` 中添加解析逻辑**:
   ```python
   # 在第1行解析中添加
   new_param = _parse_new_param(first_line)
   ```

2. **在 `read_datas.py:_parse_first_line()` 中添加解析**:
   ```python
   # 支持 key=value 格式
   if 'new_param' in first_line:
       new_param = extract_value(first_line, 'new_param')
   ```

3. **在 `parameters.py:_initialize_from_poscar()` 中添加**:
   ```python
   self.new_param = data.get("new_param", default_value)
   ```

### 修改跃迁公式

**位置**: `tight_binding_model.py:hopping_strength()`

当前公式：
```python
return params.t0 * np.exp(-params.hopping_decay*(distance - params.t0_distance) / params.t0_distance)
```

可以修改为其他衰减形式，如幂律衰减等。

### 修改能带绘图样式

**位置**: `tight_binding_model.py:calculate_band_structure()`

当前使用红色（自旋上）和蓝色（自旋下）的渐变。可以修改颜色映射或添加其他可视化选项。

### 添加新的输出格式

1. 在 `calculate_band_structure()` 中添加格式判断
2. 使用不同的 matplotlib 后端或库（如 plotly）生成交互式图像

## 依赖库

- `pythtb`: 紧束缚模型计算库
- `numpy`: 数值计算
- `matplotlib`: 绘图
- `tomlkit`: TOML 文件解析

## 使用示例

### 命令行使用

```bash
# 1. 准备 POSCAR 文件（包含参数行）
# 第1行: dimr=3 dimk=3 hopping_decay=1.0

# 2. 准备 KPATH.in 或 KPOINTS 文件（必需）

# 3. 计算能带结构
pypostb --poscar POSCAR --output band_structure

# 或使用默认文件名
pypostb
```

### Python API 使用

```python
from pypostb import Parameters, create_pythtb_model, calculate_band_structure

# 从 POSCAR 读取参数（自动读取 k 路径）
params = Parameters("POSCAR")

# 创建模型
model = create_pythtb_model(params)

# 计算能带
calculate_band_structure(model, params)
```

### POSCAR 文件示例

```vasp
dimr=3 dimk=3 hopping_decay=1.0
   1.00000000000000
     5.8896136042106519    0.0000000000000000    0.0000000000000000
     0.0000000000000000    7.7193960717810146    0.0000000000000000
     0.0000000000000000    0.0000000000000000    5.5735571936146364
   Mn   La   O
     4     4    12
Direct
  0.0000000000000000  0.0000000000000000  0.5000000000000000     1
  0.5000000000000000  0.5000000000000000  0.0000000000000000    -1
  ...
```

## 注意事项

1. **参数来源**: 所有参数从 POSCAR 文件读取，不再使用 TOML 配置文件
2. **k 路径文件**: KPATH.in 或 KPOINTS 文件必须存在，否则程序会报错退出
3. **坐标系统**: POSCAR 文件中的坐标会被转换为分数坐标（Direct coordinates）
4. **距离单位**: 所有距离参数的单位为埃（Angstrom）
5. **最大距离**: 自动设置为最大晶格常数，无需手动配置
6. **最大相邻格点**: 固定为 2，不可配置
7. **磁矩**: 从 POSCAR 坐标行第4列读取，如果不存在则默认为0
8. **周期性**: 代码自动处理周期性边界条件
9. **自旋**: 默认 `nspin=2`（有自旋），支持自旋投影可视化
10. **内存**: 对于大系统，`max_R_range=2` 和 `max_distance` 的设置会影响计算时间和内存使用

## 版本历史

- **0.3.0**: 当前版本（重构版）
  - ✅ 完全移除 TOML 配置文件依赖
  - ✅ 所有参数从 POSCAR 文件读取
  - ✅ 磁矩从 POSCAR 坐标行读取
  - ✅ k 路径从 KPATH.in 或 KPOINTS 读取（必需）
  - ✅ 最大跃迁距离自动设置为最大晶格常数
  - ✅ 最大相邻格点固定为 2
  - ✅ 简化命令行接口

- **0.2.1**: 旧版本（参考 `old_pyamtb/`）
  - 支持 TOML 配置文件
  - 支持距离基跃迁强度计算
  - 支持磁性计算
  - 支持自旋投影可视化
  - 支持简并能带处理

