Skip to content

Instantly share code, notes, and snippets.

@Siriusitzy
Created September 29, 2025 09:24
Show Gist options
  • Select an option

  • Save Siriusitzy/550f4d1ce8876c8f10acaa05da67a853 to your computer and use it in GitHub Desktop.

Select an option

Save Siriusitzy/550f4d1ce8876c8f10acaa05da67a853 to your computer and use it in GitHub Desktop.

基于图论的离子团簇分析技术规范

定义基于图论的离子团簇分析方法与实现细节,涵盖距离判据、最近邻规则、团簇识别、结构判定、边界条件、验证规则与输出数据结构。 以下通过LiTFSI分子(包含O和N原子)与Li+的案例进行分析。


1. 距离判据详细定义

1.1 距离判据的物理基础

  • 判据来源:基于径向分布函数(RDF)的第一配位壳层。
  • 物理意义:第一峰后的最小值代表第一配位壳层的边界,超过此距离的离子对不再有强相互作用。

1.2 具体距离阈值

  • Li⁺-O(TFSI⁻) 判据:
    • 阈值:d_Li-O < 3.00 Å
    • 基于:RDF_Li-O(r) 第一峰后最小值位置
  • Li⁺-N(TFSI⁻) 判据:
    • 阈值:d_Li-N < 5.26 Å
    • 基于:RDF_Li-N(r) 第一峰后最小值位置

1.3 距离计算规则

函数 计算离子间最短距离(Li离子, TFSI离子):
    最短距离 = 无穷大
    
    对于 每个O原子 in TFSI离子.O原子列表:
        d = 欧几里得距离(Li离子.位置, O原子.位置)
        如果 d < 最短距离:
            最短距离 = d
            最短距离类型 = "Li-O"
    
    N原子距离 = 欧几里得距离(Li离子.位置, TFSI离子.N原子.位置)
    如果 N原子距离 < 最短距离:
        最短距离 = N原子距离
        最短距离类型 = "Li-N"
    
    返回 最短距离, 最短距离类型

2. 最近邻规则的严格定义

2.1 单向最近邻 vs 互为最近邻

根据 Figure S3 的说明,存在以下几种情况:

函数 判断边类型(节点A, 节点B):
    // A和B必须是不同类型的离子
    如果 (A.类型 == B.类型):
        返回 "无边"
    
    // 检查A到B的最近邻关系
    A的最近反离子 = 寻找最近反离子(A, 所有反离子)
    B的最近反离子 = 寻找最近反离子(B, 所有反离子)
    
    如果 (A的最近反离子 == B) 且 (B的最近反离子 == A):
        返回 "强边_互为最近"  // 最强的连接
    否则如果 (A的最近反离子 == B) 或 (B的最近反离子 == A):
        返回 "边_单向最近"    // 较强的连接
    否则:
        返回 "无边"           // 不形成边

3. 团簇识别算法细节

3.1 连通分量算法选择

推荐使用深度优先搜索(DFS)或广度优先搜索(BFS):

函数 DFS查找连通分量(图G):
    已访问 = 空集
    连通分量列表 = []
    
    对于 每个节点v in G.所有节点:
        如果 v 不在 已访问中:
            当前分量 = []
            栈 = [v]
            
            当 栈非空:
                当前节点 = 栈.弹出()
                如果 当前节点 不在 已访问中:
                    已访问.添加(当前节点)
                    当前分量.添加(当前节点)
                    
                    对于 每个邻居 in G.获取邻居(当前节点):
                        如果 邻居 不在 已访问中:
                            栈.添加(邻居)
            
            连通分量列表.添加(当前分量)
    
    返回 连通分量列表

3.2 团簇类型的精确分类

{
  "团簇类型定义": {
    "SSIP": {
      "定义": "完全被溶剂分离的单个离子",
      "判据": "连通分量大小 == 1",
      "子类型": ["SSIP_Li+", "SSIP_TFSI-"]
    },
    "CIP": {
      "定义": "接触离子对",
      "判据": "连通分量大小 == 2 且 包含1个Li+ 和 1个TFSI-",
      "化学式": "Li·TFSI"
    },
    "AGG": {
      "定义": "聚集体",
      "判据": "连通分量大小 >= 3",
      "子类型": {
        "小型AGG": {
          "大小": "3-5个离子",
          "示例": ["Li₂TFSI⁺", "LiTFSI₂⁻", "Li₂TFSI₂", "Li₃TFSI₂⁺"]
        },
        "中型AGG": {
          "大小": "6-10个离子"
        },
        "大型AGG": {
          "大小": ">10个离子",
          "特征": "可能形成离子网络"
        }
      }
    }
  }
}

4. AGG(聚集体)的详细判定规则

4.1 AGG的结构特征

AGG 必须满足以下条件:

  • 最小尺寸要求:至少包含 3 个离子
  • 连通性要求:所有离子通过边连接形成单一连通图
  • 稳定性要求:内部至少存在一条“强边_互为最近”

4.2 AGG的电荷计算

{
  "函数": "计算AGG属性(AGG团簇)",
  "实现": [
    "属性 = {",
    "  \"总离子数\": AGG团簇.节点数量,",
    "  \"Li+数量\": 统计(AGG团簇, 类型=\"Li+\"),",
    "  \"TFSI-数量\": 统计(AGG团簇, 类型=\"TFSI-\"),",
    "  \"净电荷\": Li+数量 - TFSI-数量,",
    "  \"电荷密度\": 净电荷 / 总离子数,",
    "  \"化学式\": 生成化学式(Li+数量, TFSI-数量)",
    "}",
    "",
    "// 判断AGG类型",
    "如果 属性.净电荷 == 0:",
    "    属性[\"类型\"] = \"中性AGG\"",
    "否则如果 属性.净电荷 > 0:",
    "    属性[\"类型\"] = \"阳离子AGG\"",
    "否则:",
    "    属性[\"类型\"] = \"阴离子AGG\"",
    "",
    "返回 属性"
  ]
}

4.3 特殊AGG模式识别(后续再开发)

函数 识别特殊AGG模式(AGG):
    // 线性链状结构
    如果 是线性链(AGG):
        返回 "链状AGG"
    
    // 环状结构
    如果 包含环(AGG):
        环大小 = 获取最小环大小(AGG)
        返回 f"环状AGG_环大小{环大小}"
    
    // 分支结构
    如果 存在分支点(AGG):
        分支度 = 计算最大分支度(AGG)
        返回 f"分支AGG_度{分支度}"
    
    返回 "不规则AGG"

5. 边界情况处理

5.1 周期性边界条件

考虑轨迹的输出格式为unwrap的坐标,因此这一步为可选项

{
  "函数": "考虑周期性边界(位置1, 位置2, 盒子尺寸)",
  "说明": "最小镜像约定",
  "实现": [
    "delta = 位置2 - 位置1",
    "对于 每个维度i in [x, y, z]:",
    "  如果 abs(delta[i]) > 盒子尺寸[i] / 2:",
    "    如果 delta[i] > 0: delta[i] -= 盒子尺寸[i]",
    "    否则: delta[i] += 盒子尺寸[i]",
    "返回 sqrt(delta.x² + delta.y² + delta.z²)"
  ]
}

5.2 时间演化中的团簇追踪(待开发,团簇的演化存活时间也需要进行统计)

{
  "函数": "团簇生存时间分析(轨迹)",
  "实现": [
    "团簇历史 = {}",
    "对于 每个时间步t in 轨迹:",
    "  当前团簇 = 识别所有团簇(轨迹[t])",
    "  对于 每个团簇 in 当前团簇:",
    "    团簇ID = 生成唯一ID(团簇)",
    "    如果 团簇ID in 团簇历史:",
    "      团簇历史[团簇ID].生存时间 += 时间步长",
    "    否则:",
    "      团簇历史[团簇ID] = {",
    "        \"起始时间\": t,",
    "        \"生存时间\": 时间步长,",
    "        \"类型\": 团簇.类型",
    "      }",
    "返回 团簇历史"
  ]
}

6. 验证规则

6.1 一致性检查

函数 验证团簇划分(所有团簇, 总离子数):
    // 检查1:所有离子都被分配
    已分配离子 = 0
    对于 每个团簇 in 所有团簇:
        已分配离子 += 团簇.离子数
    断言(已分配离子 == 总离子数, "存在未分配的离子")
    
    // 检查2:无重复分配
    离子集合 = 空集
    对于 每个团簇 in 所有团簇:
        对于 每个离子 in 团簇.离子列表:
            断言(离子 不在 离子集合中, f"离子{离子}被重复分配")
            离子集合.添加(离子)
    
    // 检查3:电荷守恒
    总电荷 = 0
    对于 每个团簇 in 所有团簇:
        总电荷 += 团簇.净电荷
    断言(总电荷 == 系统总电荷, "电荷不守恒")
    
    返回 True

6.2 物理合理性检查

函数 检查物理合理性(团簇):
    // 检查最大配位数
    对于 每个Li离子 in 团簇.Li离子列表:
        配位数 = 计算配位数(Li离子)
        断言(配位数 <= 6, f"Li+配位数{配位数}超过物理极限")
    
    // 检查TFSI的配位模式
    对于 每个TFSI in 团簇.TFSI列表:
        配位Li数 = 计算配位Li数(TFSI)
        断言(配位Li数 <= 4, f"TFSI配位{配位Li数}个Li+超过极限")
    
    返回 True

7. 输出数据结构规范

7.1 完整输出格式(可以再看看怎么存储方便和定义)

{
  "时间步": 1000,
  "系统信息": {
    "Li+总数": 180,
    "TFSI-总数": 180,
    "浓度": "10 mol/kg"
  },
  "团簇统计": {
    "SSIP": {
      "Li+": {
        "数量": 15,
        "离子ID": [1, 5, 12],
        "百分比": 8.33
      },
      "TFSI-": {
        "数量": 10,
        "离子ID": [2, 7, 19],
        "百分比": 5.56
      }
    },
    "CIP": {
      "数量": 45,
      "离子对": [
        { "Li": 3, "TFSI": 4, "距离": 2.85, "连接类型": "Li-O" }
      ],
      "百分比": 50.0
    },
    "AGG": {
      "总数": 25,
      "详细信息": [
        {
          "ID": "AGG_001",
          "尺寸": 5,
          "组成": "Li3TFSI2",
          "净电荷": 1,
          "类型": "阳离子AGG",
          "结构类型": "链状",
          "离子列表": [6, 8, 11, 15, 20]
        }
      ],
      "尺寸分布": {
        "3-5": 15,
        "6-10": 8,
        ">10": 2
      },
      "平均尺寸": 5.8,
      "最大尺寸": 15
    }
  }
}

TIPS

  • 距离计算必须考虑 PBC(周期性边界条件)的最小镜像约定。
  • 最近邻的判定应在满足距离阈值的前提下进行;可先构建候选边集(满足阈值),再应用最近邻规则筛边。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment