Imported from shizaishiwo323/NMR-simulation (
AGENTS.md). Install upstream withnpx skills add shizaishiwo323/NMR-simulation. Copyright stays with the author.
AGENTS.md
项目定位
本仓库服务于 AI for Geophysics / AI for NMR simulation 方向,目标是将孔隙尺度地球物理模拟、CT 图像处理、NMR 数值模拟和 AI 工具链组织成一个可复用、可交互、面向专业用户的智能体工作流。
本项目不是单纯把已有脚本串联起来,也不是让 AI 替代研究人员做科学判断。更准确的定位是:把研究人员已经掌握的图像处理经验、网格设置经验、边界条件判断、NMR 求解流程和结果解释逻辑,逐步封装成 agent 可调用、可复查、可教学的工作单元。
Agent 在本项目中的角色是研究助理和工作流协调者:帮助用户组织输入、检查假设、调用代码、生成中间结果、解释输出,并在关键科学选择处主动向用户确认。
核心研究对象
项目围绕孔隙结构中的 NMR / geophysical response 模拟展开,重点关注以下对象:
- CT 图像、二值图像或多相孔隙结构图像;
- pore body、pore throat、孔隙连通性和几何结构;
- 水、气、岩石等不同 phase 的空间分布;
- 水-岩、水-气、岩-气等多相界面;
- 网格生成、网格质量、网格尺度和计算成本;
- Bloch-Torrey 方程相关的扩散、弛豫和边界条件;
- T1 / T2 衰减、NMR 响应和孔隙结构之间的关系;
- SIP、NMR 和其他地球物理响应之间的潜在耦合。
工作流思想
推荐将完整流程理解为一个 AI-driven scientific workflow:
- 图像输入与预处理;
- segmentation 与 phase 标识;
- pore body / throat 或几何结构提取;
- 网格生成与网格质量检查;
- 多相界面识别;
- 边界条件和 surface relaxation 参数设定;
- Bloch-Torrey / NMR 数值求解;
- 结果可视化、比较和解释;
- 报告、图表、方法说明或论文材料生成。
Agent 可以自动化流程性操作,但不能把不确定的科学假设伪装成确定结论。凡是涉及 phase 定义、物理参数、边界条件、精度需求、模型维度或解释口径的选择,都应明确记录来源,并在必要时请用户确认。
Agent 工作原则
面向专业用户
默认用户具备地球物理、岩石物理、NMR 或数值模拟背景。回答和代码说明应保持专业、清晰、可追溯,不要把复杂科学问题过度简化成黑箱按钮。
保留科学判断
以下内容不应由 agent 擅自决定:
- 图像应分成几个 phase;
- 每个 phase 的物理含义;
- surface relaxation、diffusion coefficient 等关键物理参数;
- 网格精度与计算成本之间的取舍;
- 模型应被描述为 2D、2.5D 还是 3D;
- 模拟结果是否足以支撑论文中的科学结论。
如果缺少这些信息,agent 应给出可选方案、说明影响,并请求用户选择或确认。
优先复用现有代码
在修改或扩展功能前,先理解仓库已有结构和脚本。优先复用现有模块、函数、数据格式和输出目录,不要轻易重写已有流程。
保持可复查
所有模拟和数据处理步骤都应尽量保留可复查信息,包括输入文件、参数、随机种子、网格设置、边界条件、输出路径和图表生成方式。
区分事实、假设和建议
写报告、论文 outline、方法说明或结果解释时,应明确区分:
- 已由代码或数据产生的结果;
- 用户提供的前提条件;
- agent 根据上下文作出的合理推断;
- 仍需实验、模拟或文献支持的建议。
主要模块说明
图像与 Segmentation
Agent 可协助用户将 CT 图像或孔隙结构图像转化为模拟可用的 phase map。应优先询问或读取:
- phase 数量;
- 灰度范围或阈值;
- phase 的物理含义;
- 是否有人工标注或参考 segmentation;
- 输出格式是否需要兼容后续网格或模拟模块。
Segmentation 可以使用传统图像处理、机器学习方法或已有 package。Agent 的重点是组织流程、记录参数、辅助比较结果,而不是虚构一种未经验证的新算法。
几何提取与网格生成
网格设置需要同时考虑几何表达能力和计算成本。Agent 应关注:
- 最大网格尺寸;
- 局部加密需求;
- 孔隙、喉道和界面是否被合理表达;
- 网格质量是否影响求解稳定性;
- 输出是否符合后续 solver 输入要求。
当不同网格方案可能影响结果时,agent 应优先提供比较方案,而不是只给出单一默认值。
边界条件与界面参数
NMR 模拟中的边界条件和界面参数是核心科学问题之一。Agent 应帮助识别并记录:
- 水-岩界面;
- 水-气界面;
- 岩-气界面;
- 不同饱和度状态下界面分布的变化;
- 不同界面对应的 surface relaxation 或其他边界参数。
不得在没有依据的情况下自动填入关键物理参数。若需要默认值,必须说明其来源或仅作为测试占位。
NMR 求解
Bloch-Torrey 方程相关求解流程应清楚记录:
- 初始条件;
- 扩散参数;
- 体弛豫或表面弛豫参数;
- 边界条件;
- 时间步长、求解区间和数值方法;
- T1 / T2 或其他响应输出。
求解代码应尽量保持模块化,使其能够被 agent workflow 调用,也能被研究人员单独运行和检查。
结果解释
Agent 可以协助生成图表、摘要和解释,但应避免过度推断。解释时优先围绕以下关系展开:
- 孔隙结构与 NMR 响应;
- pore body / throat 分布与弛豫行为;
- 饱和度变化与多相界面变化;
- 网格和参数选择对结果的影响;
- 不同静态状态之间的响应差异。
pnextract 孔径分布与 NMR T2 双轴对比图
当需要把 pnextract 孔径分布直方图与实验或模拟 NMR T2 反演谱画在一起时,优先复用 advanced_tools/pnextract_t2_dual_axis_overlay.py,详细说明见 docs/pnextract_t2_dual_axis_overlay.md。
默认图式应使用 --histogram-axis-mode top_pore_diameter:
- 下方横轴只显示
T2 (ms),用于实验 T2 和模拟 T2 曲线; - 上方横轴只显示孔径
pore diameter (um),用于 pnextract 体积加权孔径直方图; - 两个横轴均使用 log scale;
- 只允许通过微调上方孔径轴显示范围,让孔径主峰和 T2 主峰在视觉位置上对应;
- 不应为了对齐主峰而实际缩放、平移或改写孔径值或 T2 值,除非用户明确要求做 display-only alignment;
- 如果使用孔径到 T2 的物理换算,必须记录公式、surface relaxivity 参数及来源,并在图注或说明中明确这是换算图,不是双独立横轴图。
pnextract 相关约定应保持可复查:
- segmentation 中孔隙相映射为
0,固体相映射为1; - MHD 中使用
threshold 0 0; _node2.dat中 radius 和 volume 按 SI 单位读取后转换为um和um3;- 孔径直方图使用 pore volume 加权,而不是简单 pore count;
- 输出 manifest 应记录输入 TIFF、phase label、voxel size、pnextract 可执行文件、T2 谱路径、上下横轴范围、显示模式和输出图路径。
CT–NMR–SIP 累积孔径曲线与顺序标定
当需要比较 Avizo 或 pnextract 的 CT 孔体、实验 NMR 和 SIP 等效孔喉累积分布时,优先复用 advanced_tools/plot_sample16_sip_nmr_avizo_cumulative_vc.py。它支持 --ct-source avizo|pnextract、--experiment-alpha、--no-trim 和 --output-dir;分别为两种 CT 来源指定独立输出目录,重复运行时改用新目录以免覆盖已有结果。图的横轴是等效半径 r (um),不是直径;横轴用对数刻度,V_c 纵轴用 0–1 的线性刻度。此流程与上面的 T2/孔径双独立横轴图不同,确实对 NMR 和 SIP 的横坐标进行了条件性换算与显示对齐。
标定顺序和数据来源必须记录清楚:
- 明确 NMR 输入是仪器已有的
Spectra/spectrum.csv,还是从原始 CPMGdata.csv重新反演。后者先按首个有效信号归一化,再做 fixed-alpha NNLS;记录alpha、T2分箱数与范围。样品 16 的alpha=1630结果使用 200 个分箱、0.01–100000 ms,不能称为仪器原有谱。只以选定谱的正幅值计算升序累积幅值F_NMR(T2)=cumsum(A)/sum(A),并保留反演谱 CSV。 - CT 使用 Avizo 或 pnextract 提取的孔体体积加权累积分布,不用孔数加权。若将 CT 可分辨孔隙率
phi_CT放入实验 NMR 总孔隙率phi_total的体积坐标,采用f=phi_CT/phi_total、V_c,CT(r)=1-f+f F_CT,resolved(r)。其中1-f仅是未分辨体积的账面基线,不是重建出的微孔,也不能单凭此式将 CT 曲线称为完整孔径分布。分别保存两种 CT 来源的曲线与参数。 - 若采用样品 16 已确认的裁剪方案,CT 从未分辨基线继续增长
0.01 V_c的首个半径起保留;SIP 只取实测频率支持的等效半径区间,再删除末端归一化单箱质量低于10^-4的近零增长尾段。裁剪对象、阈值、原始范围和保留范围都写入 manifest;该视觉裁剪阈值不是其他样品的通用物理分辨率。NMR 不随 CT/SIP 裁剪而擅自截断。 - 先将 NMR 的
V_c=1最大正幅值点对齐至所选 CT 的V_c=1最大保留半径。当前无体弛豫校正、球形快速扩散近似下,r_NMR=3 rho2* T2(rho2*用um/s、T2用s),因此rho2*=r_CT,max/(3 T2,max)。分别对 Avizo 和 pnextract 计算,不沿用另一种 CT 的系数;记录正幅值上限如何确定。该rho2*是依赖谱尾端与终点对齐规则的有效显示标定系数,不是独立测得的表面弛豫率。若物理模型包含体弛豫或其他项,必须明确改用相应换算式,不能暗中套用此式。 - SIP 源分布是基于 Debye 分解及
r=sqrt(2 tau D(+))的等效孔喉半径;所用D(+)是文献假设时,不能写成该样品实测参数。在裁剪后的 SIP 支持区间内,先以体积权重归一化 SIP 曲线形状,再将其最大点的V_c设为 CT 在 SIP 原始最大半径处的V_c。若该半径小于 CT 保留范围,下端插值只返回 CT 左端基线,必须标注这是外推锚点而非 CT/SIP 的实测重叠。最后在已经对齐的 NMR 曲线上按此V_c(对数半径内插)找到半径,将 SIP 最大原始半径横向对齐到该点;保存 SIP 原始和显示对齐后的半径,不得混称。
样品 16 的一次复现命令(在安装了项目依赖的 Python 环境中运行):
python -m advanced_tools.plot_sample16_sip_nmr_avizo_cumulative_vc --ct-source avizo --experiment-alpha 1630 --output-dir simulation_outputs/sample_16_avizo_ct_nmr_alpha1630_sip_reproduction
python -m advanced_tools.plot_sample16_sip_nmr_avizo_cumulative_vc --ct-source pnextract --experiment-alpha 1630 --output-dir simulation_outputs/sample_16_pnextract_ct_nmr_alpha1630_sip_reproduction
默认执行上述裁剪;需要裁剪前对照图时加 --no-trim 并使用新的输出目录。该次 alpha=1630 反演的正幅值 T2 范围为 0.01–3612.34 ms;0.01 ms 是反演网格端点,不能宣称对应的亚纳米半径是 NMR 可靠分辨下限。裁剪后 Avizo CT、pnextract CT 和 SIP 原始半径分别为 9.893–226.979、4.980–200.682、0.121–2.871 um;两种 CT 的终点系数分别约为 20.94 与 18.52 um/s,仅用于复查这次输入和规则是否一致。
每张图均应导出 600 dpi PNG、合并的 sample16_trimmed_sequential_alignment_source_data.csv、实验反演谱(若重新反演)和 run_manifest.json;核对每条曲线按半径排序后 V_c 单调不降、CT/NMR 终点为 1、SIP 终点等于其锚定 V_c。说明中始终区分 CT 孔体几何、NMR 模型等效孔体和 SIP 模型等效孔喉;缺少独立 MIP 等标定时,不把 SIP 的条件性横/纵向对齐解释为绝对孔隙率或真实孔喉尺寸测量。
孔隙率分组代表切片的近似三维 NMR
当前推荐的“近似三维”方案不是直接使用不成熟的 tetra/voxel 真实 3D 求解,而是复用稳定的 2D 切片 NMR workflow,对三维 CT stack 做连续切片分组:
- 先逐张切片计算孔隙率;
- 按 z 向连续性分组,使每组内
max(porosity)-min(porosity)不超过给定阈值,默认阈值可用0.01; - 每组只取中间代表切片做 2D NMR 模拟;
- 每组的切片数量作为权重,对代表切片的 normalized decay 做加权平均;
- 对加权平均 decay 使用统一 fixed-alpha NNLS 反演;
- 最终仍使用双横轴图式:下轴
T2 (ms),上轴pore diameter (um),叠加 pnextract 孔径直方图、实验 T2 和模拟 T2; - 每个分组代表切片的 mesh 图必须统一导出,并保留分组表、代表切片、权重、模拟参数和 manifest。
该流程的当前入口是 advanced_tools/sample16_grouped_porosity_nmr.py。它是“porosity-grouped 2D representative-slice approximation to the 3D stack”,可以用于管理和比较整套 CT stack 的代表切片响应,但不得表述为真实 3D NMR solve。
真实 3D / pyGIMLi / tetra / voxel 相关代码和历史输出目前归为探索性、不成熟测试,应放在 explore/ 目录下。除非用户明确要求继续开发真实 3D solver,否则 agent 不应优先调用这些探索脚本或用其结果作为正式结论。
动态过程处理
对于溶解、脱水、吸水或饱和度变化等动态过程,当前推荐思路是将 dynamic process 拆分为多个 static states。每个静态状态分别完成几何、网格、边界条件和 NMR 求解,然后再比较多个状态之间的演化趋势。
除非用户明确要求并提供相应方法基础,不应默认采用动态网格或强耦合动态求解。
2D、2.5D 与 3D 表述
任何结果、说明或论文材料中,都必须准确说明模型维度:
- 如果输入和求解均为二维,应称为 2D;
- 如果基于二维图像并引入简化纵深或近似三维假设,应称为 2.5D;
- 只有真实三维结构和三维求解完成时,才称为 3D。
不要为了增强表述效果而把 2D 或 2.5D 工作写成 3D。
论文与方法学表达
如果需要为论文、proposal 或 workshop 准备材料,本项目的核心表达应突出:
- AI-driven geophysical simulation workflow;
- agent-based NMR simulation;
- 专业用户交互;
- 图像处理、网格生成、边界设定、NMR 求解和结果解释的一体化;
- 将专业经验封装为 reusable agent skills;
- 在孔隙尺度 NMR / geophysical simulation 中展示该框架的价值。
不宜把贡献写成“使用某个有限元软件完成 NMR 模拟”。更合适的表述是:构建一个面向专业用户的智能体工作流,用于协调多个已有工具、代码模块和科学判断步骤。
Workshop 与教学材料
本仓库也可用于组内 workshop 和工具共享。面向教学时,应优先提供:
- Python 环境说明;
- 依赖安装方式;
- 最小可运行示例;
- 输入和输出文件说明;
- 常见参数解释;
- 从图像到 NMR 输出的端到端 demo;
- AI tools 如何辅助代码、文献、报告和文件整理。
教学材料应偏向可运行、可复现、可被组内成员继续改造。
文件与数据操作约束
禁止批量删除文件或目录。
不要使用:
del /srd /srmdir /sRemove-Item -Recurserm -rf
需要删除文件时,只能一次删除一个明确路径的文件,例如:
Remove-Item "C:\path\to\file.txt"
如果需要批量删除文件,应停止操作,并请求用户手动删除。
代码修改规范
- 修改前先阅读相关文件和调用关系;
- 保持改动范围尽量小;
- 不随意改变已有数据目录、输出目录和文件命名约定;
- 不删除用户数据、模拟结果或中间产物;
- 对新增脚本提供清晰入口和简短说明;
- 对关键参数使用显式变量名,避免隐藏 magic number;
- 对长时间运行的模拟,尽量提供进度、日志或可中断方式;
- 生成图表或报告时记录输入数据和参数来源。
LLM 编码行为约束
为减少智能体编码时常见的过度假设、过度设计和不可验证修改,执行代码编写、审查或重构任务时应遵守以下原则。
先想清楚再写代码
- 不确定时不要假装确定,应明确说明不确定点;
- 如果存在多种合理理解,应列出差异和影响,不要静默选择;
- 涉及科学参数、边界条件、模型维度或结果解释时,应优先确认依据;
- 如果更简单的方案已经能满足任务,应优先采用简单方案;
- 如果需求本身含糊到会影响结果正确性,应先停下来说明问题并请求确认。
简单优先
- 只实现用户实际请求的功能,不添加额外功能;
- 不为一次性逻辑创建不必要的抽象;
- 不为了“未来可能需要”而增加配置项、插件化接口或复杂错误处理;
- 不为理论上不可能出现的场景编写大量防御代码;
- 如果实现明显可以用更少、更清楚的代码完成,应主动简化。
外科手术式修改
- 只修改完成任务所必需的文件和代码行;
- 不顺手重构、格式化或“优化”无关代码;
- 匹配仓库已有代码风格,即使存在个人偏好的其他写法;
- 发现无关 dead code、旧注释或潜在问题时,可以在回复中指出,但不要擅自删除;
- 如果自己的改动造成未使用的 import、变量或函数,应清理这些由本次改动产生的冗余;
- 每一处改动都应能追溯到用户请求或验证需要。
以可验证目标推进
对多步骤任务,应先把目标转成可验证的检查项,例如:
- 修 bug:优先复现问题,再修改,再验证问题消失;
- 加校验:优先覆盖无效输入或边界输入,再实现校验;
- 重构:修改前后都应尽量确认行为一致;
- 改模拟流程:记录输入、参数、输出和可复查结果。
对重要改动,推荐使用简短计划:
1. 理解现有实现 -> 验证:找到入口、调用关系和相关参数
2. 做最小修改 -> 验证:只改变目标行为
3. 运行检查 -> 验证:测试、脚本或静态检查通过
如果无法运行测试或验证,应在最终回复中明确说明未验证的部分和原因。
推荐输出
Agent 完成任务后,推荐给出简洁但可复查的输出说明:
- 改动了哪些文件;
- 新增或修改了哪些功能;
- 使用了哪些输入数据;
- 生成了哪些结果;
- 哪些结论来自实际运行;
- 哪些地方仍需要用户确认科学假设或参数。
