diff --git a/AGENTS.md b/AGENTS.md index b1f1e593b06c2c8a03db06c71dfb3ee28c0f424b..36216d337cc3e6a675dbc9db1a23e665a491412d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -68,5 +68,8 @@ $REST_HOME/ | `develop-with-rstsr` | 任务涉及张量运算、矩阵操作、线性代数或使用 `rstsr` / `rest_tensors` crate 时必须加载。 | | `rest-doc-guide` | 任务涉及编写、修改、翻译文档(`rest_doc/` 目录)时必须加载。 | | `rest-regression-guide` | 任务涉及新增、更新或运行回归测试(`rest_regression/` 目录)时必须加载。 | +| `rest-libcint-knowledge` | 修改 `rest_libcint/` 或涉及大量 rest_libcint 调用时加载。 | +| `rest-feedstock-guide` | 任务涉及 Conda 打包、修改 recipe、管理依赖、调试 conda 构建或修改 `rest-feedstock/` 目录时必须加载。 | +| `create-skill` | 任务涉及创建、修改或设计 Agent Skill(`rest-dev-ai-agent/skills/` 目录)时必须加载。 | **步骤**:识别任务 → 加载匹配的 skill(s) → 按 skill 指导工作。若任务的多个方面匹配不同 skill,逐一加载。 diff --git a/skills/create-skill/SKILL.md b/skills/create-skill/SKILL.md new file mode 100644 index 0000000000000000000000000000000000000000..c922d5fbfd6f8f559ae4bb80e3ad0ec14bbf2774 --- /dev/null +++ b/skills/create-skill/SKILL.md @@ -0,0 +1,116 @@ +--- +name: create-skill +description: 如何为 REST 项目创建新的 Agent Skill — 文件格式、存放位置、注册到 AGENTS.md 以及编写规范。 +--- + +# 创建 REST 项目 Skill + +> 本 Skill 教你如何为 REST 项目新增一个 Agent Skill。 + +## 1. 什么是 Skill + +Skill 是面向 AI agent 的领域知识文件(Markdown + YAML),agent 在遇到匹配任务时自动加载。Skill 帮助 agent 理解代码架构、开发流程和领域约定,无需在每个对话中重新解释。 + +**适合创建 Skill 的场景**: +- 某个 crate/模块的架构与代码模式需要 AI 快速理解 +- 反复出现但需要领域知识的开发任务(如添加测试、写文档、处理 FFI) +- 希望 AI 遵循特定的代码约定或工作流程 + +## 2. Skill 文件格式 + +### 必需结构 + +```markdown +--- +name: +description: <一句话描述 Skill 的作用> +--- + +# <中文标题> + +> 简短摘要 +``` + +### 完整示例 + +```markdown +--- +name: my-skill +description: 描述这个 Skill 解决什么问题,什么场景下加载。 +--- + +# 我的 Skill 标题 + +> 一行概述 + +## 1. 概述 +... +## 2. 核心内容 +... +``` + +**要求**: +- `name` 使用 kebab-case(小写 + 连字符),如 `rest-libcint-knowledge`、`create-skill` +- `description` 一句话说明用途与加载条件,会被写入系统提示的 skill 表 +- 正文使用 Markdown,支持表格、代码块、列表 + +## 3. 存放位置 + +本项目 Skill 统一放在: + +``` +rest-dev-ai-agent/skills// +``` + +每个 Skill 一个子目录,目录名与 `name` 字段一致,文件名为 `SKILL.md`。 + +## 4. 注册 Skill + +Skill 创建后,必须在 `AGENTS.md` 的 skill 表中注册,agent 才能按条件加载。 + +### 编辑 AGENTS.md + +在文件末尾的 skill 表中新增一行: + +```markdown +| `skill-name` | **触发条件描述** | +``` + +例如: + +```markdown +| `rest-libcint-knowledge` | 任务涉及 `rest_libcint/` crate 的代码修改、积分逻辑、内存分配、FFI 绑定、并行填充或架构理解时必须加载。 | +``` + +### 加载机制 + +Agent 启动时读取 `AGENTS.md` 中的 skill 表。当用户任务匹配触发条件时,agent 调用 `skill(name="skill-name")` 加载对应的 `SKILL.md`。Skill 内容被注入到当前对话上下文中作为指令。 + +**不需要在 AGENTS.md 中写 `file://` URI** — agent 会根据 skill 名称自动查找。 + +## 5. 编写规范 + +基于现有 Skill(`rest-libcint-knowledge`、`rest-regression-guide`、`rest-knowledge-graph` 等)总结: + +| 规范 | 说明 | +|------|------| +| 语言 | 中文为主(REST 项目约定)。技术术语保留英文 | +| 长度 | 控制在 200–400 行。过于冗长 agent 难以高效消费 | +| 结构 | 使用 `## N. 标题` 编号分节。每节聚焦一个主题 | +| 表格优先 | 对比信息(类型列表、文件对应关系等)优先用表格而非段落 | +| 代码块 | 精确引用源码中的签名/结构体,标注文件路径与行号 | +| 避免复杂图表 | 不用大型 ASCII 流程图。用有序列表(1. 2. 3.)或编号步骤替代 | +| 聚焦 AI 视角 | 只写 AI 开发时需要知道的信息,省略面向人类初学者的教程内容 | +| 与源码一致 | 引用行号、模块名、函数签名必须与当前源码匹配(写 Skill 前先读代码验证) | + +## 6. 检查清单 + +创建 Skill 后逐项确认: + +- [ ] `SKILL.md` 位于 `rest-dev-ai-agent/skills//SKILL.md` +- [ ] YAML frontmatter 包含 `name` 和 `description` +- [ ] `name` 使用 kebab-case,与目录名一致 +- [ ] 已在 `AGENTS.md` 中新增一行触发条件 +- [ ] 引用的源码路径和行号已核实 +- [ ] 无复杂 ASCII 图 +- [ ] 中文为主,长度控制在 200–400 行 diff --git a/skills/rest-feedstock-guide/SKILL.md b/skills/rest-feedstock-guide/SKILL.md new file mode 100644 index 0000000000000000000000000000000000000000..6bd765782abc93ebdf2ba70022f4f08c74e7e2b4 --- /dev/null +++ b/skills/rest-feedstock-guide/SKILL.md @@ -0,0 +1,285 @@ +--- +name: rest-feedstock-guide +description: REST 程序 Conda 打包指南。涵盖 rattler-build recipe 维护、依赖管理、版本更新、跨平台构建(linux/osx/win)以及构建失败调试。 +--- + +# REST Conda 打包指南 + +## 1. 项目总览 + +`rest-feedstock` 是 REST 程序的 Conda 打包仓库。使用 **rattler-build**(通过 pixi 管理)构建三个 conda 包: + +| 包名 | Recipe 目录 | 内容 | +|------|------------|------| +| `rest` | `recipe_rattler/` | REST 主程序(二进制 + pyrest 库 + 基组) | +| `rest_regression` | `recipe_rest_reg/` | 回归测试二进制 | +| `rest-util` | `recipe_rest_util/` | Python 工具脚本 | + +构建产物输出到 `output/` 目录。 + +## 2. 目录结构 + +``` +rest-feedstock/ +├── pixi.toml # 项目配置: channels, platforms, tasks +├── recipe_rattler/ # rest 主包 recipe +│ ├── recipe.yaml # 包元数据 + 依赖 + 测试 +│ ├── build.sh # 构建脚本 (unix) +│ ├── build.bat # 构建脚本 (win) +│ ├── conda_build_config.yaml# 依赖版本 pinning +│ └── run_tests.sh # 回归测试脚本 +├── recipe_rest_reg/ # rest_regression 包 recipe +├── recipe_rest_util/ # rest-util 包 recipe +├── actions/ # CI 辅助 action +│ ├── cache-setup-conda/ # conda 缓存 +│ └── setup-rattle/ # rattler-build 安装 +├── scripts/ +│ └── analyze_changes.py # recipe 变更分析 +├── .github/workflows/ # CI 流水线 +│ ├── conda_rattler.yml # 主构建流水线 (rattler-build) +│ ├── conda.yml # 旧版 conda-build 流水线 +│ └── rest_reg.yml # 回归测试专用流水线 +├── output/ # 构建产物 (gitignored) +└── README.md +``` + +## 3. 构建系统 + +### pixi 入口 + +```toml +# pixi.toml +[project] +name = "rest-feedstock" +channels = ["conda-forge", "mokit", "restgroup"] +platforms = ["win-64", "linux-64", "osx-arm64"] + +[tasks] +build = "rattler-build build --recipe-dir recipe_rattler --output-dir output --skip-existing=all" + +[dependencies] +rattler-build = "*" +``` + +构建命令:`pixi run build`(自动激活 conda 环境并运行 rattler-build)。 + +### CI 流水线 (`conda_rattler.yml`) + +CI 构建所有平台和变体,使用 `actions/setup-rattle/` 安装 rattler-build,上传产物到 anaconda.org。 + +## 4. Recipe 结构 (`recipe_rattler/recipe.yaml`) + +Recipe 是 rattler-build 格式的 YAML 文件,非 conda-build 的 meta.yaml。 + +### 4.1 package 段 + +```yaml +package: + name: "rest" + version: "2026.1.0.1" +``` + +### 4.2 source 段 — 多 git 仓库 + +REST workspace 由 4 个独立 git 仓库组成,recipe 中分别指定: + +```yaml +source: + - git: https://gitee.com/restgroup/rest.git + rev: + target_directory: rest + - git: https://gitee.com/restgroup/rest_tensors.git + rev: + target_directory: rest_tensors + - git: https://gitee.com/restgroup/rest_libcint.git + rev: + target_directory: rest_libcint + - git: https://gitee.com/restgroup/rest_regression.git + rev: + target_directory: rest_regression +``` + +**更新版本流程**:更新各 `rev` 为最新 commit SHA → 更新 `version` → 重置 `build.number` 为 0 或递增。 + +### 4.3 build 段 + +```yaml +build: + number: 1 + files: + exclude: + - "**/__pycache__" + - "**/test-files" + script: + env: + REST_HOME: ${SRC_DIR} +``` + +- `number`: 同一版本下的构建迭代号 +- `script.env`: 环境变量注入到 build.sh + +### 4.4 requirements 段 + +三个依赖层级: + +| 层级 | 用途 | +|------|------| +| `build` | 构建时需要的工具(编译器、构建系统、Python)和链接所需的库 | +| `host` | 需要在 `$PREFIX` 中可用的库(与 build 基本对称) | +| `run` | 运行时依赖(自动从 host 继承,显式列出确保安装) | + +平台条件语法: + +```yaml +- if: osx + then: llvm-openmp # 仅在 macOS 添加 +- if: win + then: m2w64-sysroot_win-64 # 仅在 Windows 添加 +- if: not win + then: openmpi 4.* # 仅在非 Windows 添加 +``` + +### 4.5 compiler 宏 + +```yaml +- ${{ compiler('c') }} # → clang_osx-arm64 (macOS) / gcc (linux) / m2w64 (win) +- ${{ compiler('cxx') }} # → clangxx_osx-arm64 / gxx / m2w64 +- ${{ compiler('fortran') }} # → gfortran(所有平台) +- ${{ compiler('rust') }} # → rust + rust-std-$target +- ${{ stdlib('c') }} # → 系统 C 标准库 +``` + +### 4.6 tests 段 + +```yaml +tests: + - if: not win + then: + script: run_tests.sh + requirements: + run: + - restgroup::rest_regression + files: + source: + - rest_regression +``` + +## 5. 构建脚本 (`build.sh`) + +### 5.1 Workspace 组装 + +`build.sh` 首先生成临时 `Cargo.toml` 将 4 个源码目录组装为 workspace: + +```bash +cat > Cargo.toml << 'EOF' +[workspace] +resolver = "2" +members = ["rest_tensors", "rest_libcint", "rest", "rest_regression"] +[profile.release] +opt-level = 3 +lto = "fat" +codegen-units = 1 +EOF +``` + +### 5.2 平台路径 + +```bash +if [[ "$target_platform" == win-64 ]]; then + LIB_EXT="dll" + REST_EXT_DIR="${PREFIX}/Library/bin" # Windows: .dll 在 Library/bin +else + if [[ "$target_platform" == osx-* ]]; then + LIB_EXT="dylib" + else + LIB_EXT="so" + fi + REST_EXT_DIR="${PREFIX}/lib" +fi +``` + +### 5.3 MOKIT 桥接库 + +MOKIT 的 Fortran FFI 库需要在编译前复制到 `REST_EXT_DIR`: + +```bash +MOKIT_LIB="${BUILD_PREFIX}/lib/python${PY_VER}/site-packages/mokit/lib/librest2fch.${LIB_EXT}" +cp "${MOKIT_LIB}" "${REST_EXT_DIR}" +``` + +### 5.4 Cargo 构建 + +```bash +# macOS / Linux: +cargo install --path . --profile release --root ${PREFIX} + +# Windows: +cargo install --path . --profile release --target x86_64-pc-windows-gnu \ + --no-default-features --features "dftd3,dftd4" --root ${PREFIX} +``` + +### 5.5 macOS CFLAGS 处理 + +macOS 上 conda 的 `CFLAGS` 会绕过 cc crate 的默认警告标志(见 §7)。如需注入编译旗标,在 `build.sh` 中附加: + +```bash +if [[ "$target_platform" == osx-* ]]; then + export CFLAGS="${CFLAGS} -Wno-implicit-function-declaration" +fi +``` + +## 6. 依赖版本 Pinning + +`conda_build_config.yaml` 固定关键依赖版本: + +```yaml +c_stdlib_version: + - 11.0 # [osx] +fortran_compiler: + - gfortran # [win] +python: + - 3.11 +rust_compiler_version: + - "1.94" +simple-dftd3: + - 1.* +dftd4: + - 4.* +hdf5: + - 1.14.* +openmpi: + - 4.* +``` + +## 7. 已知问题与调试 + +### 7.1 CFLAGS 与 cc crate 的相互作用 + +conda 激活脚本始终设置 `CFLAGS`。cc crate (`rest_libcint/build.rs`) 检测到 `CFLAGS` 环境变量后,**跳过**默认的 `-Wall -Wextra`(假定 CFLAGS 已包含所需的警告旗标)。同时 `flag_if_supported()` 旗标在 CFLAGS 之前被处理,可能被 CFLAGS 的后续旗标覆盖。若需特定编译器旗标,直接在 `build.sh` 中修改 `CFLAGS`。 + +### 7.2 macOS gcc_osx-arm64 激活 + +`${{ compiler('fortran') }}` 引入 `gfortran_osx-arm64`,其依赖 `gcc_osx-arm64`(激活包)。gcc 激活脚本在 clang 激活前运行,设置初始 `CC` 和 `CFLAGS`。gcc 激活包版本变更可能影响最终的编译器旗标组合。调试时检查 CI 日志中 `activate-gcc_osx-arm64.sh` 和 `activate_clang_osx-arm64.sh` 的环境变量变更。 + + +## 8. 常见任务 + +### 更新版本 + +1. 在 `recipe_rattler/recipe.yaml` 更新各 source 段的 `rev` (commit SHA) +2. 更新 `package.version` +3. 重置 `build.number` 为 0(或递增若仅修复 recipe) +4. 同步更新 `recipe_rest_reg/recipe.yaml` 和 `recipe_rest_util/recipe.yaml` + +### 添加新依赖 + +1. 确认 `conda-forge` channel 中存在该包 +2. 若有版本约束,在 `conda_build_config.yaml` 添加 +3. 在 `recipe.yaml` 的 build/host/run 段添加 +4. 如需链接,在 `build.sh` 中设置 `LIBRARY_PATH` 或相关环境变量 + +### 调试构建失败 + +1. 查看 CI 日志中 `activate-*.sh` 的环境变量变更 +2. 对比不同平台/构建的 conda 包版本(`conda list` 输出) + diff --git a/skills/rest-libcint-knowledge/SKILL.md b/skills/rest-libcint-knowledge/SKILL.md new file mode 100644 index 0000000000000000000000000000000000000000..a470693c6aa1aa1a97fe8fea1a777d0bf3daefaa --- /dev/null +++ b/skills/rest-libcint-knowledge/SKILL.md @@ -0,0 +1,342 @@ +--- +name: rest-libcint-knowledge +description: rest_libcint crate 的结构、架构与关键代码模式,面向 AI 开发者 +--- + +# rest_libcint 知识图谱 + +> Rust 封装 libcint C 库 — 量子化学 GTO 分子积分引擎 + +## 1. 项目总览 + +| 属性 | 值 | +|------|-----| +| 路径 | `$REST_HOME/rest_libcint/` | +| 语言 | 纯 Rust, 封装 C 库 libcint | +| 构建 | Cargo + `build.rs` (编译 ECP C 源码) | +| 并行 | Rayon 线程池 | +| 核心依赖 | `rstsr-common`, `rayon`, `itertools`, `num`, `serde`, `derive_builder` 等 (共 9 个) | +| 外部链接 | libcint (C 库), ECP C 源码 (编译进 crate) | + +**职责**: 提供 Rust 风格 API 调用 libcint C 积分函数,处理并行调度、内存布局转换、对称性打包。 + +## 2. 目录结构 + +``` +rest_libcint/ +├── build.rs # 编译 src/cecp/*.c,可选链接 libcint +├── Cargo.toml # 9 个依赖, 5 个 feature flags +├── src/ +│ ├── lib.rs # 15 个 pub mod + pub use prelude::* +│ ├── prelude.rs # 公共与 crate-internal 重导出中枢 +│ ├── util.rs # 工具: aligned alloc, copy_f_*, get_f_index_* +│ ├── test_mol.rs # 测试用分子 + fingerprint +│ │ +│ ├── cint.rs # CInt 结构体 + CIntOutput, CIntSymm 等 +│ ├── cint_crafter.rs # 积分构建/分派: integral_block(), max_cache_size() +│ ├── cint_prop.rs # CInt 只读属性: ao_loc(), make_loc() +│ ├── cint_initialize.rs # serde + Builder 构造 +│ ├── cint_result.rs # CIntError 错误类型 + cint_error!/cint_raise! 宏 +│ ├── cint_change.rs # 数据修改: fakemol_for_charges 等 +│ ├── cint_fill_col_major.rs # 列优先并行填充 (Fortran 顺序) +│ ├── cint_fill_row_major.rs # 行优先并行填充 +│ ├── cint_fill_grids.rs # 网格 GTO 积分填充 +│ ├── cint_old.rs # 遗留 CINTR2CDATA API +│ ├── cint_old_crafter.rs # 遗留积分构建 +│ │ +│ ├── ffi/ +│ │ ├── cint_ffi.rs # Tier 1: bindgen 原始 C 绑定 +│ │ ├── cecp_ffi.rs # Tier 1: ECP C 绑定 +│ │ ├── wrapper_traits.rs # Tier 2: Integrator trait + impl_integrator! 宏 +│ │ ├── cint_wrapper.rs # Tier 3: 100+ 积分器结构体 + 查找表 +│ │ └── cecp_wrapper.rs # Tier 3: ECP 积分器 +│ │ +│ └── gto/ +│ ├── gto_crafter.rs # GTO 网格求值构建器 +│ ├── grid_ao_drv.rs # GtoEvalAPI trait +│ ├── deriv_util.rs # FpSimd SIMD 工具 +│ ├── deriv_impl/ # 14 个导数实现文件 +│ └── prelude_dev.rs # 重导出所有 deriv 项 +│ +└── tests/ # 11 个集成测试 +``` + +## 3. 模块组织 + +| 模块 | 职责 | +|------|------| +| `cint.rs` | 核心 `CInt` 结构体 + `integrate()` 方法实现 | +| `cint_crafter.rs` | 积分构建与分派,通过 `Integrator` trait 调用 C 函数;实现 `integral_block()`, `max_cache_size()` | +| `cint_fill_*.rs` (3 files) | Rayon 并行填充 (列优先/行优先/网格),线程本地 buffer 写入共享输出 | +| `cint_prop.rs` | `CInt` 属性查询: `ao_loc()`, `make_loc()` | +| `cint_result.rs` | `CIntError` 错误类型 + `cint_error!`/`cint_raise!` 宏 | +| `cint_initialize.rs` | Builder 模式构造 + serde 序列化 | +| `cint_change.rs` | `CInt` 数据修改: `with_rinv_origin`, `with_range_coulomb`, `fakemol_for_charges` 等 | +| `cint_old.rs` + `cint_old_crafter.rs` | 遗留 `CINTR2CDATA` API (独立于 CInt) | +| `ffi/` | FFI 三层封装 (详见 §5) | +| `gto/` | GTO 网格求值 (`eval_gto`, `eval_gto_spinor`)、导数实现 (14 文件)、SIMD 工具 | +| `util.rs` | 64 字节对齐分配、列优先索引计算、`copy_f_*` 函数 | +| `prelude.rs` | `pub use` 公共类型 + `pub(crate) use` crate 内全局可见项 | + +**关键依赖关系**: +- `cint.rs` 的 6 个扩展模块通过 `impl CInt { ... }` 添加方法 +- `cint_crafter.rs` ↔ `ffi/wrapper_traits.rs`: 通过 `Box` 分派到 C 函数 +- `cint_fill_*.rs` ↔ `util.rs`: 使用 `copy_f_*d_s*()` 从线程本地 buffer 复制到输出 +- `gto/` ↔ `cint.rs`: `CInt` 通过 `gto_crafter.rs` 实现 GTO 网格求值方法 + +## 4. 核心类型 + +### CInt (cint.rs:42) + +核心数据结构,映射 libcint C 库的 AOS (Array of Structs) 内存布局: + +```rust +pub struct CInt { + pub atm: Vec<[c_int; 6]>, // 原子: 电荷, 坐标指针, 核模型, ... + pub bas: Vec<[c_int; 8]>, // 壳层: 原子, 角动量, nprim, nctr, 指数/系数指针 + pub ecpbas: Vec<[c_int; 8]>, // ECP 壳层 (含 RADI_POWER, SO_TYPE_OF) + pub env: Vec, // 浮点变量: 坐标, 指数, 系数, 截断, omega, ... + pub cint_type: CIntType, // Spheric(默认) / Cartesian / Spinor + pub c_opt: Option>, +} +``` + +### 其他关键枚举/结构体 + +| 类型 | 位置 | 说明 | +|------|------|------| +| `CIntKind` | `cint.rs:131` | 积分类别: `Int` (普通), `Ecp` (有效芯势) | +| `CIntType` | `cint.rs:145` | 输出类型: `Spheric`→f64, `Cartesian`→f64, `Spinor`→Complex\ | +| `CIntSymm` | `cint.rs:166` | 对称性: `S1`(无), `S2ij`(μ↔ν), `S2kl`(κ↔λ), `S4`, `S8` | +| `CIntOutput` | `cint.rs:199` | 输出: `out: Option>` + `shape: Vec`, 可 `.into()` 转元组 | +| `CIntOptimizer` | `cint.rs:188` | 优化器: `Int(*mut CINTOpt)` / `Ecp(*mut ECPOpt)`, `Drop` 调用 C 释放 | +| `CIntError` | `cint_result.rs:16` | `{ kind: CIntErrorBase, backtrace }`, 7 种变体, 通过 `cint_error!`/`cint_raise!` 构造 | + +### CIntSymm 细节 + +| 变体 | 含义 | 典型场景 | +|------|------|----------| +| `S1` | 无对称性 | 默认 | +| `S2ij` | μ↔ν 对称 | 3 中心积分 | +| `S2kl` | κ↔λ 对称 | 4 中心积分 | +| `S4` | S2ij + S2kl | 4 中心积分 | +| `S8` | 完全 8 重对称 | 4 中心 eri 积分 | + +### CIntError 变体 + +`IntegratorNotFound`, `IntegratorNotAvailable`, `RuntimeError`, `InvalidValue`, `UninitializedFieldError`, `ParseError`, `Miscellaneous` — 均包含 backtrace。 + +## 5. FFI 三层封装 + +**三层结构**: + +1. **Tier 1 — 原始绑定** (`cint_ffi.rs`, `cecp_ffi.rs`): bindgen 生成的 `extern "C"` 函数声明,直接映射 C 库 API。 + +2. **Tier 2 — 抽象 trait** (`wrapper_traits.rs`): 定义 `Integrator` trait 统一接口,提供 `impl_integrator!` 宏生成零大小结构体 + trait 实现。 + +3. **Tier 3 — 胶水层** (`cint_wrapper.rs`, `cecp_wrapper.rs`): 100+ 积分器结构体(每个对应一种 C 积分函数)+ `get_cint_integrator(name)` / `get_ecp_integrator(name)` 查找函数。 + +### Integrator trait 核心方法 + +```rust +pub trait Integrator: Send + Sync { + unsafe fn optimizer(&self, opt: *mut *mut c_void, atm: *const c_int, natm: c_int, + bas: *const c_int, nbas: c_int, env: *const f64); + unsafe fn integral_sph(&self, out: *mut f64, dims: *const c_int, shls: *const c_int, ...) -> c_int; + unsafe fn integral_cart(&self, out: *mut f64, ...) -> c_int; + unsafe fn integral_spinor(&self, out: *mut c_void, ...) -> c_int; + fn is_sph_available(&self) -> bool; + fn is_cart_available(&self) -> bool; + fn is_spinor_available(&self) -> bool; + fn n_comp(&self) -> usize; + fn n_spinor_comp(&self) -> usize; + fn n_center(&self) -> usize; + fn ng(&self) -> Vec; + fn integrator_category(&self) -> &'static str; + fn name(&self) -> &'static str; + fn kind(&self) -> CIntKind; + fn as_any(&self) -> &dyn Any; +} +``` + +### impl_integrator! 宏 + +```rust +impl_integrator!( + int2e, // 结构体名 (零大小) + int2e_optimizer, // C 优化器函数 + int2e_sph, int2e_cart, // C sph/cart 积分函数 + int2e_spinor, // C spinor 积分函数 + true, true, true, // sph/cart/spinor 可用 + 1, 1, 4, // n_comp, n_spinor_comp, n_center + vec![0,0,0,0,0,1,1,1], // ng (导数阶数) + "int2e", "int2e", // 类别, 名称 + CIntKind::Int // 种别 +); +``` + +展开生成 `pub struct int2e` + `impl Integrator for int2e` + `impl Default`。`integral_sph` 等方法直接调用对应 C FFI 函数。 + +## 6. 积分调用流程 + +### 主 API 入口 + +PR #3 将普通积分、ECP 积分、spinor 积分统一为一致的 API 家族。每个函数均有 `_f` (fallible) 和 `_spinor` 变体: + +| 函数 | 返回类型 | 说明 | +|------|----------|------| +| `integrate(intor, aosym, shls_slice)` | `CIntOutput` | 主积分驱动,列优先。统一处理普通/ECP/含 grids 的 1e 积分 | +| `integrate_spinor(...)` | `CIntOutput>` | Spinor 积分,列优先 | +| `integrate_row_major(...)` | `CIntOutput` | 行优先变体,形状与 PySCF 一致 | +| `integrate_cross(intor, mols, ...)` | `CIntOutput` | 跨分子积分 (**静态方法**),多 `CInt` 实例间计算(如 dimers) | +| `integrate_cross_spinor(...)` | `CIntOutput>` | 跨分子 spinor 积分 | +| `integrate_with_args(args)` | `CIntOutput` | 高级积分,Builder (`IntegrateArgs`) 支持自定义输出 buffer、网格 | +| `integrate_cross_with_args(args)` | `CIntOutput` | 跨分子高级积分 (Builder: `IntorCrossArgs`) | +| `eval_gto(eval_name, coord)` | `CIntOutput` | GTO 网格求值,列优先 shape `(ngrid, nao, ncomp)` | +| `eval_gto_spinor(eval_name, coord)` | `CIntOutput>` | Spinor GTO 网格求值 | + +### 临时修改分子属性 + +`cint_change.rs` 提供 `with_*` 模式 — 临时修改 `CInt` 字段,在闭包内执行操作后自动恢复原始值: + +| 函数 | 用途 | +|------|------| +| `with_rinv_origin(origin, func)` | 临时设置 $1/r$ 原点 | +| `with_rinv_origin_atom(atm_id, func)` | 临时指认原子为 $1/r$ 原点 (ECP 导数) | +| `with_range_coulomb(range, func)` | 临时设置 range-separated Coulomb ω 参数 | +| `fakemol_for_charges(atm_id, charges, func)` | 临时修改原子电荷 | + +### 调用流程剖析 + +以 `cint.integrate("int2e", "s1", None)` 为例: + +1. **查找积分器**: `get_cint_integrator("int2e")` → `Box` (返回 `int2e` 结构体) + +2. **创建优化器** (`cint_crafter.rs:33`): `integrator.optimizer()` → 调用 C 函数 `int2e_optimizer(...)`,返回 `CIntOptimizer` + +3. **计算缓冲区**: `max_cache_size()` 通过 null 输出指针查询 libcint 所需 doubles 数;`max_buffer_size()` = `n_comp × ∏ max(cgto_i)` + +4. **并行填充** (`cint_fill_col_major.rs`): Rayon `for_each_init` 迭代 shell pairs,每个线程持有 `(cache: Vec, buf: Vec)` 复用 + +5. **单 block 计算** (`cint_crafter.rs:1195`): `integral_block(out=buf, shls, cache)` → 根据 `CIntType` 分派: + - `Spheric` → `integrator.integral_sph(out as *mut f64, ...)` + - `Cartesian` → `integrator.integral_cart(...)` + - `Spinor` → `integrator.integral_spinor(out as *mut c_void, ...)` + +6. **复制到输出**: `copy_f_3d_s1()` / `copy_f_4d_s1()` 等按列优先 (Fortran) 索引将 `buf` 复制到共享 `output` + +7. **返回** `CIntOutput { out: Some(vec), shape }` + +**关键约定**: cache 为 libcint 临时空间;buf 为线程本地输出;列优先为内部表示,行优先由 `_row_major` 变体处理。 + +## 7. 关键代码模式 + +### 线程本地缓冲区 (所有 fill 模块) + +```rust +let thread_init = || (aligned_uninitialized_vec::(cache_size), aligned_uninitialized_vec::(buffer_size)); +iter_par.for_each_init(thread_init, |(cache, buf), indices| { /* 迭代间复用 */ }); +``` + +### 共享可变输出 (cast_mut_slice) + +```rust +let out = unsafe { cast_mut_slice(&*out) }; +``` +从 `&[F]` 转为 `&mut [F]`,所有线程共享。安全前提: 各迭代写入不重叠区域。 + +### 对齐分配 (util.rs:843) + +`aligned_uninitialized_vec` 分配 **64 字节对齐**内存 (AVX-512 最低要求)。**已知 UB**: 分配布局 (align=64) 与释放布局 (align=align_of::\()) 不匹配 (见 §10)。 + +### 列优先索引 (util.rs) + +```rust +fn get_f_index_3d(i: &[usize; 3], s: &[usize; 3]) -> usize { + i[0] + s[0] * (i[1] + s[1] * i[2]) +} +``` +libcint 按 Fortran 顺序写积分。对称性变体 (`get_f_index_3d_s2ij` 等) 添加下三角打包。 + +### 对称性打包 + +- **S2ij**: 仅存储 μ ≥ ν,三角数 `n*(n+1)/2`,`unravel_s2_indices()` 解包 +- **S8**: 生成所有 `(ij, kl)` 但跳过 `l < j` 时冗余迭代 (更好的 Rayon 并行化) + +## 8. 构建系统 + +### build.rs + +```rust +fn build_ecp() { + cc::Build::new() + .file("src/cecp/f2c_dgemm.c").file("src/cecp/nr_ecp.c").file("src/cecp/nr_ecp_deriv.c") + .compile("cecp"); +} +fn main() { + build_ecp(); // 始终编译 ECP C 源码 + if env::var("CINT_DEV").unwrap_or_default() == "1" { // 开发捷径: 链接预构建 libcint + println!("cargo:rustc-link-search=native={}", env::var("CINT_DIR").unwrap()); + println!("cargo:rustc-link-lib=cint"); + } +} +``` + +### Feature Flags + +| Feature | 效果 | +|---------|------| +| `with_f12` | 启用 F12 积分 | +| `with_4c1e` | 启用 4 分量 1 电子积分 | +| `build_from_source` | 从源码构建 libcint | +| `static` | 静态链接 | +| `qcint` | QCINT 接口变体 | + +### 开发配置: `[profile.dev] opt-level = 3` — debug 构建需优化以获可接受的积分性能。 + +## 9. 测试 + +### 集成测试 (tests/ — 11 个文件) + +测试使用 4 个测试分子 (定义于 `src/test_mol.rs`, 通过 prelude 导出): +- `init_h2o_def2_tzvp()` — H2O, def2-TZVP +- `init_h2o_def2_jk()` — H2O, def2-universal-jkfit +- `init_sb2me4_cc_pvtz()` — Sb2Me4 + ECP +- `init_c10h22_def2_qzvp()` — C10H22 (压力测试) + +数值验证通过预计算参考值 + `FingerPrint` trait 指纹计算。 + +```bash +cd $REST_HOME/rest_libcint && cargo test +``` + +## 10. 已知问题 + +### aligned_uninitialized_vec 布局不匹配 (⚠️ 活动 Bug) + +`src/util.rs:843` — 分配时 `Layout { align: 64 }`,释放时 `Layout { align: align_of::() }` (f64 为 8)。Windows 上可能导致堆损坏 (分配器特殊对齐处理);Linux glibc 上 `free()` 忽略对齐故无表现。 + + +## 11. 扩展开发指南 + +### 添加新积分器 + +1. 在 `src/ffi/cint_ffi.rs` 添加 `extern "C"` 声明 (如 bindgen 未生成) +2. 在 `src/ffi/cint_wrapper.rs` 添加 `impl_integrator!` 调用 +3. 在 `get_cint_integrator()` 中添加查找条目 + +### 修改积分输出布局 + +1. 修改对应 `cint_fill_*.rs` 中的并行填充逻辑 +2. 在 `src/util.rs` 添加新的 `get_f_index_*` + `copy_f_*` 函数 (如有新打包方案) +3. 更新对应 `cgto_shape_*` 计算正确输出形状 + +### 代码约定 + +| 方面 | 约定 | +|------|------| +| 错误处理 | `CIntError` + `cint_error!` / `cint_raise!` 宏 | +| 并行 | Rayon `for_each_init` + 线程本地缓存 | +| 索引 | 列优先 (Fortran) 内部表示;行优先由 `_row_major` 变体处理 | +| 不安全 | 所有 `unsafe` 块注释安全前置条件;FFI 调用均为 `unsafe` | +| 命名 | libcint 风格: `n_center`, `cgto_i`, `shl_i`, `idx_ij` |