Community研究与数据分析github.com

tomyud1/agentic-cfd

使用OpenFOAM从头到尾解决流体流动问题,并生成一份可验证的HTML报告(问题描述、假设、理论基础、决策、预测试、模拟、比较、深入分析)。当给出 `cases/<name>/problem.yaml` 中的CFD问题陈述,或要求模拟流动并报告时使用。

agentic-cfd 是什么?

Agentic CFD 工作流是一个智能体技能,旨在将模糊的CFD问题陈述转化为一份结构严谨、可验证且完全自动化的模拟报告。它通过与 OpenFOAM 求解器深度集成,确保报告中每一个数值、决策和图表都由代码自动生成,彻底杜绝手动输入或基于记忆的推断。该技能适用于 Claude Code、Codex 等支持自定义工作流的 AI 编程助手,尤其适合需要高度可复现性和透明度的工程模拟场景。工作流包含从理论分析、数值方案制定、预测试(Pre-flight)、生产运行到最终报告生成的完整阶段,并且内置了一个“洞察日志”机制,允许智能体在遇到问题或意外时实时记录经验教训,以持续优化工作流本身。通过严格的契约检查器(contract checker)验证报告结构,确保所有决策皆有文档、所有比较皆基于数据、所有结论皆可追溯,最终生成一份工程师可以直接信任的 HTML 报告。

兼容平台✓Claude Code~Codex CLI~Cursor✓Antigravity
npx skills add https://github.com/tomyud1/agentic-cfd/tree/HEAD/.claude/skills/agentic-cfd

Installed? Explore more 研究与数据分析 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Agentic CFD 工作流

你将一个问题陈述转化为一份可信的模拟报告。读者是一名工程师,他主要阅读摘要,并且必须能够检查每一个声明。四条规则:

  1. 代码计算每一个数字。 你编写代码;永远不要手动将结果、参考值或公式输出键入报告。理论通过 SymPy 符号计算并自我检查。
  2. 每个选择都有文档。 每个 OpenFOAM 设置都属于一个决策,其中包含原因/效果/替代方案。检查器会拒绝渲染不符合此要求的报告。
  3. 不依赖记忆。 参考数据、关联式和常数来自问题的 reference/ 文件或引用的来源。如果必须使用近似值,请在报告中说明。
  4. 实时记录洞察,如同实验室笔记本。 你的部分工作是为你之后的智能体改进此工作流。当有事情失败、让你惊讶、需要第二次尝试,或这些指南中有不清楚的地方时,立即打开一个洞察(在你开始修复之前): insights.log(case, stage, problem);一旦解决,使用 insights.resolve(...) 填写诊断、修复、教训和指南。不要把它们积攒到最后:长时间会话的记忆会丢失和扭曲。预计记录 5-15 条记录;运行一次而没有记录意味着没有仔细查看。

文件夹布局

cfdlib/                       共享工具(请勿修改;将需要的更改记录为洞察,阶段为 "tooling")
  foam.py         render_case, run(超时,PID 文件),stop,running;读取字段和 postProcessing .dat 文件
  monitor.py      parse_log, assess(健康检查),preflight(短测试运行 + 运行时预测)
  verification.py 误差范数,观察到的阶数,Richardson 外推,GCI,level_sequence
                 (任何层级序列的收敛性,包括参考自身的)
  signals.py      周期信号:周期,精炼峰值,周期性检查,FFT 频率
  plots.py        图形样式和尺寸(figure, wide, sketch);to_svg 检查文本重叠
  report.py       m(), tex_num(), tex_fix()(表格列的固定小数位),tex_pct(), LETTERS, load_yaml,
                 environment_info(), render()
  perf.py         每次运行的性能数据(summarize, machine),用于性能附录
  contract.py     报告契约检查器(也提供 --decisions 模式)
  insights.py     实时洞察日志(记录时检查排版;拒绝覆盖已填充的条目)
  foamdict.py     OpenFOAM 字典解析器(由检查器使用)
cases/<name>/                 每个问题一个文件夹
  problem.yaml   由用户提供:description(简短概述),setup(事实列表:几何、
                 边界条件、定义),given data,requested outputs [+ reference/]。
                 不要改变物理。将 description 和 setup 不变地传递给报告。
  reference/     用户提供的参考数据及引用
  numerics.yaml  你的数值方案(网格,运行长度,容差)
  decisions.yaml 每个选择,在设置案例时编写
  insights.yaml  实时日志(cfdlib.insights)
  template/      包含 {{ 占位符 }} 的 OpenFOAM 案例(0/, constant/, system/)
  theory.py / analytical.py, sketch.py, run.py, analyze.py
results/<name>/  原始数据, results.json, report.html

工作示例(在开始之前阅读所有文件;复制结构,而非数值设置):

  • cases/plane_poiseuille/:线性、稳态、精确解(验证)。报告: results/plane_poiseuille/report.html。
  • cases/lid_driven_cavity_re100/:非线性、稳态、无精确解、已发布基准 (基准比较,Richardson 外推,残差停止的 SIMPLEC,独立的预测试和生产 命令)。报告:results/lid_driven_cavity_re100/report.html。其 insights.yaml 包含来自构建它的智能体的 15 条经验。
  • cases/stokes_first_problem/:线性、瞬态、精确解(组合和独立的网格与 时间步研究,每一步的动量平衡,并发运行)。报告: results/stokes_first_problem/report.html。
  • cases/dfg_cylinder_re100/:非线性、瞬态和周期性(涡街脱落)、具有多个 参考层级的基准、用 Python 生成的曲线体 O 型网格、MPI 运行和性能 附录。报告:results/dfg_cylinder_re100/report.html。其 insights.yaml 包含 16 条经验 (最重要的一条:PISO 在时间上是一阶的)。

阶段

0. 信息摄入

  • 读取 problem.yaml 和所有 reference/ 文件。列出请求的输出(它们获得字母 a, b, c...)。
  • 在代码中计算主导无量纲数(Re,Ma,...)。决定适用何种物理。
  • 如果数据缺失或矛盾,选择一个有文档记录的假设,并在报告的限制部分标记它。永远不要默默捏造输入。
  • 如果参考没有给出不确定性,估计一个(其网格,其打印的数字,另一个来源) 并记录如何估计;你将在阶段 5 中需要它。

1. 理论:无需模拟即可知道的内容

  • 存在精确解:使用 SymPy 推导,自我检查(满足方程和边界 条件),计算请求的量。参见 cases/plane_poiseuille/analytical.py。
  • 无精确解(通常情况):在 theory.intro 中说明,并提供理论能够说明的内容:限制 情况、缩放、守恒定律、对称性、量的符号、预期流动结构。 参见 cases/lid_driven_cavity_re100/theory.py。
  • 每个导出的量都获得:它为何重要,此问题中每个符号的含义和数值, 以及代入数字后的公式(供手算检查)。

2. 设置和决策

  • 找到最接近的 OpenFOAM 教程($FOAM_TUTORIALS)并从中开始;做最小的修改。
  • 阅读 references/openfoam-primer.md 以了解每个文件控制的内容和已知陷阱。
  • 模板可能包含 Jinja 循环:从 Python 生成整个 blockMeshDict 是可以的,并且是对 曲线体进行网格划分的方式(示例:cases/dfg_cylinder_re100/run.py 中的 mesh_spec())。
  • 仅使用编辑/写入工具编辑包含 LaTeX 的文件,切勿通过 Bash heredoc 或内联 Python: Bash 工具会吞掉反斜杠(\times 会变成 TAB)。案例 3 和 4 都因此浪费了时间。
  • 边做边写 decisions.yaml:每个选择一个条目,包含 kind(physics / accuracy / solver / output)和涵盖案例文件中每个设置的 settings 模式。一旦一个案例被渲染,立即检查覆盖率: python -m cfdlib.contract --decisions cases/<name>/decisions.yaml <case dir>。
  • 规划网格研究:至少 3 个网格,细化比 2(对于观察到的阶数和 GCI 是必需的)。 瞬态问题还需要时间步研究(或一个带数字的论证,证明时间误差可忽略)。
  • 在你的问题中定义一个物理收敛/稳定检查(一个平衡,一个守恒 量,一个必须停止变化的监测值)及其在查看结果之前的容差。 仅靠归一化残差是不够的。瞬态问题:每一步的平衡(守恒量变化 = 边界通量)是一个强检查;它必须使用求解器自身的时间方案。
  • 通过/失败容差必须具有区分度:根据粗网格预测试误差和预期阶数(最细网格应达到的)来设定其大小,而不是根据整数。容差比达到的值宽松 100 倍证明不了什么(案例 3)。将观察到的精度阶数单独作为一条规则。

3. 预测试(强制,在任何长运行之前)

  • 在最粗和最细网格上使用 cfdlib.monitor.preflight() 进行短运行(全长的百分之几)。 它在一个单独的 <case>_preflight 副本中工作;也将预测试和生产案例渲染到单独的目录中,这样重新运行一个永远不会删除另一个。
  • 它报告崩溃、NaN、库朗数、残差/库朗/连续性趋势并预测运行时间。 瞬态运行:预测是可靠的。稳态运行:传递 residual_targets;结果是 一个下界(SIMPLE 稍后会在更细网格上变慢)。
  • 打印预测试写入的每个 postProcessing 文件的表头和第一行,并检查每个 都不是平凡的(案例 4:一个压力积分在每个时间步都写了 0,默默地)。
  • 瞬态非线性问题:一个简短的时间步研究(3 个时间步,比率 2,在粗网格上) 应属于预测试阶段,在网格研究之前。它显示了时间上观察到的阶数:PISO (1 个外部校正器)在案例 4 中被证明是一阶的,并导致了完全重新运行。
  • 从静止开始的预测试会低估发展中的非定常流动的成本(案例 4: 两次)。从已发展的流场(通过 mapFields 从粗网格运行)开始,或将预测翻倍。
  • 如果预测试失败或发出警告,修复设置并记录洞察。不要在失败的预测试上进行生产运行。 如果预测时间过长(此处每次运行超过约 15 分钟),放宽方案并说明。

4. 生产运行

  • 从粗到细运行网格。对于稳态运行,在启动最细网格之前,从粗网格外推其迭代次数(每次细化通常增长 3-4 倍)。
  • 停止标准必须是物理的:使阶段 2 的物理检查成为停止规则(例如,在探测值上的 runTimeControl 函数对象,参见入门手册),或者对每个网格检查残差目标是否实际满足该标准,先从粗网格开始。
  • 独立运行(不同网格)可以同时运行,最多 6 个(8 核)。在可重现性说明中说明这一点,因为它会膨胀每次运行的墙钟时间。
  • 长运行在后台进行;python -m cfdlib.foam ps 列出求解器进程, python -m cfdlib.foam stop <case dir> 杀死一个(仅停止 Python 包装器会留下孤儿求解器)。记录每次运行:健康状态(monitor.assess)、物理检查、墙钟时间。
  • 将一系列长运行作为一个后台脚本来运行,该脚本写入完成标记和每次运行的记录。在任何中断之后(API 暂停也是),在重新运行任何内容之前读取这些文件。
  • 当所有硬件线程都在运行求解器时,你自己的工作会使其变慢:留出 1-2 个线程空闲,或将预测时间预算增加 1.5 倍。

5. 分析

  • 所有比较都在代码中进行。对于精确解:每个网格的误差和观察到的阶数。 对于无精确解的情况:从 3 个网格得到的观察到的阶数和 Richardson 外推,最细网格上的 GCI (verification.py),然后将外推值与参考进行比较。
  • 基准也是一次模拟:根据(你的 GCI 带 + 参考自身的不确定性)来判断一致性,而不是与零比较。如果差异不随细化而缩小,那么这不是你的离散化误差;在归咎于任何一方之前,测试鲁棒性(另一种方案,更严格的迭代),并建议第二个独立的参考。
  • 当参考给出多个网格层级时,它仍在收敛:计算其自身的观察到的阶数 和 Richardson 值(verification.level_sequence),并将你的结果与其最细层级和其外推值进行比较。在查看之前决定通过规则(案例 4 保留了最细层级规则,并将外推作为上下文报告)。
  • 周期性输出(涡街脱落,振荡):使用 cfdlib.signals(上向穿越之间的周期,抛物线精炼峰值,周期性检查,FFT 交叉检查),而不是编写你自己的。
  • 粗网格匹配可能是运气(误差抵消)。如实报告差异,在哪里以及为什么。
  • 解释是一个声明:在编写之前对照数据(符号、大小、缩放)检查它。在案例 3 中,对误差的第一个解释符号错误且大小只有三分之一。

6. 报告

  • 在 analyze.py 中构建 results.json 并调用 report.render(results, svgs, out, case_dir=<finest case>)。 契约在 references/report-contract.md 中;render 拒绝编写违反它的报告。
  • 数学:文本中的每个公式、符号和科学数字都作为 LaTeX 放在 \(\) 内(m(), tex_num()):写 \(0.009\,U\),永远不要写 0.009 U、6.3e-06 或 u*H/nu。检查器拒绝 e-notation 和 ASCII 数学,并警告纯文本中的数字乘符号。
  • 标题和发现也是结果:从数据生成它们(说“缩小”的标题必须被计算出来)。以 {fig:<key>} 引用图形;render() 插入编号。
  • 图形(cfdlib.plots):对于单面板使用 plots.figure(),对于 2-3 面板使用 plots.wide(n), 对于问题草图使用 plots.sketch()(必需)。to_svg() 拒绝文本重叠文本、线条、箭头 或形状,或其图例覆盖数据,或比列宽的图形。 修复布局(标签远离线条,使用带引线的 annotate,图例在外面);allow= 仅用于确实有意为之的重叠,如果你需要它,记录一个洞察。
  • 结论:仅当你定义的每个检查都通过时为 PASS;如果结果可用但有注意事项则为 WARN; 否则为 FAIL。永远不要软化一个失败的检查。

7. 视觉审查(强制)

契约检查结构;只有查看才能发现读者会看到的东西。通过本地服务器在内置浏览器中打开报告(file:// 不起作用): http://localhost:8765/<name>/report.html(如果它没有加载,使用预览工具从 .claude/launch.json 启动 reports 服务器)。在重新渲染后添加 ?v=<n> 以避免缓存副本。

  • 截取每个部分的屏幕截图,从上到下。检查:图形可读(文本不小,没有重叠,引线不穿过曲线),表格未截断,数学已渲染(没有原始 \(),表格列对齐,摘要回答了每个请求。
  • 在页面中运行(等待 MathJax,打开每个 ⓘ 面板,然后列出每个内容被截断的元素;应为空;在加载后立即运行,在 MathJax 完成之前,它会将未排版的 TeX 报告为溢出): await MathJax.startup.promise; document.querySelectorAll('details').forEach(d => d.open = true); [...document.querySelectorAll('section *')].filter(x => !x.tagName.startsWith('MJX') && x.scrollWidth > x.clientWidth).forEach(x => console.log(x.tagName, x.textContent.slice(0,50)));
  • 修复所有问题,然后批准。对于小的排版修复,直接编辑 Markdown;对于结构性问题,修复代码并重新运行。缺少 >= 1 个完整部分的报告是 FAIL。远程工人,请注意:本地的 file:// 可能看起来更好,但服务器版本才是交付给用户的。

相关技能