lin_mode=0),力立刻精确等于 kₙ·2αRΔT,分毫不差。 这篇文章记录一次针对 PFC 6.0 热力耦合的定向验证:三个待证论断、16 组固定双球算例、4 组自由双球对照,外加过程中挖出来的四个"不报错的坑"。其中第四个坑我从 C++ 源码里找到了根因,结论可能和你现在的认知不太一样。
热力耦合的链条是这样的:温度场 → 颗粒热膨胀(半径变大)→ 接触重叠改变 → 接触力改变 → 应力重分布 → 胶结破坏。
这条链上,胶结模型(PB 平行胶结 / CB 接触胶结)是最常被用在岩石类材料上的。所以问题很具体:
这三条都是"经验判断",值得用最干净的算例钉死。而最干净的算例就是——两颗球。
两颗半径 R = 0.5 m 的球,球心距 d = 2R + gs0,gs0 < 0 就是重叠量。关键设计是把两颗球的速度全部固定——完全约束。
参数(全部取整数值,方便手算复核):
kₙ = kₛ = 1e9 N/mk̄ₙ·A = 1e9 N/m(A 为 2D 键截面积 2R̄,取 pb_rmul=1)α = 3e-6 /°C,升温 ΔT = 100 °C对应的闭式值:
ΔR = αRΔT | ||
Δg = −2ΔR | ||
ΔFˡ = kₙ·2αRΔT | 3.0e5 N |
这三个数就是后面的判据。算例脚本由 AI 自动生成(16 组参数矩阵一次跑完),全程零报错。
图 1 是 16 组算例里 15 组(另一组没形成接触,见第六节)的线性力变化。红色虚线是理论值 3.0e5 N。
图 1 固定双球算例的线性部分法向力变化。横轴是力,红色虚线为闭式解 kₙ·2αRΔT = 3.0e5 N;深蓝为 PB、绿色为 CB、紫色为无胶结对照组。
只要球的膨胀系数不为零,每一组算例里球的半径都长了 150 μm、间隙都压紧了 300 μm、键的状态都还是"完好"(state=3)。 也就是说,几何层面温度确实起作用了。(唯一的例外是那个把球 α 设成 0 的对照例,它的半径当然不变,力自然也是 0。)
但力只有一半的算例有反应。
最直接的对照是前两组:
lin_mode=0 | +300000 N | ||
lin_mode=1 | 0 |
几何变化逐位相同,力一个 3.0e5、一个 0。 而且 3.0e5 和闭式解 kₙ·2αRΔT 的偏差是 0 位有效数字——不是"接近",是完全相等。
换成 CB、换成没有胶结的纯 linear 模型,规律一模一样:全量模式 3.0e5,增量模式 0。这说明这条规律跟有没有胶结无关,是线性部分自己的事。
再看两组细节:
lin_mode=0 完全一致——所以 PFC 6.0 的默认值就是全量模式。但正因为默认是对的,一旦有人手动把它改成 1,症状会极其隐蔽:模型照跑、温度照升、半径照长、什么都不报错,只是力不出来了。固定双球说明的是"力出不来"。把球放开、让它们自己找平衡,能看到更直观的版本——膨胀量本身也没了。
图 2 是四组自由双球算例的球心距变化。
图 2 自由双球(无外载)的球心距变化。理论自由热膨胀量 2αRΔT = 300 μm 用红色虚线标出。深蓝为 PB、绿色为 CB。
2αRΔT,同时接触力回到 0。这是教科书式的自由热膨胀。lin_mode 从 0 改成 1,球心距变化 0。半径长了 150 μm,两颗球纹丝不动。同一套参数、同一个模型,唯一的差别是 lin_mode。结果一个动、一个完全不动。
这是最开始卡了我最久的地方。按直觉写:
结果什么都不发生:半径不变、温度不变、力不变,而且没有任何报错。
原因是:热力与力学两个进程同时开着的时候,model cycle 只驱动力学进程,热步根本不走。正确写法是把力学关掉,让热步单独跑:
model mechanical slave on 也能跑通。官方 3D 验证算例 datafiles3d/thermal/free_expansion 和 constrained_expansion 用的就是这套流程。
判据:跑完 model cycle 后,如果日志里只打印了力学时间步、没有热时间步和热时间,那热步就没走。
两颗球都 ball fix 之后,模型里没有任何自由体,PFC 直接报:
解决很简单:model mechanical timestep fix 1.0e-8。球本来就不动,时间步取多少都稳定。
lin_mode 的语义和默认值官方属性表写得很清楚,但很容易记反:
lin_mode = 0:全量(绝对)更新 ← 默认值lin_mode = 1:增量更新官方文档在属性表下面还有一句关键的注意事项:
When
M_l = 0, the normal component of the linear force is automatically overridden during the next force-displacement calculation.
翻译过来就是:全量模式下,每一步都按当前几何(包括热膨胀之后的半径)重新计算法向力;增量模式只累加相对位移增量,而热膨胀不是相对位移增量,所以被完全忽略。
这就是"半径长了、力没出来"的全部原因。
这一条最出乎意料。
PFC 文档在热力模块里专门写了一节:平行胶结模型的键材料本身也会热膨胀,公式是
其中 ᾱ 取两端颗粒膨胀系数的平均值,L̄ 是两球心距。按这个公式,上面那组算例里键力应该变化 3e5 N 左右。
实测:一点变化都没有。 我把球的 α 设成 3e-6、把热管(ThermalPipe)的 thexp 属性设成 3e-6(两种设置写法都试了),键力始终是 0。反过来把球的 α 设成 0、只留 thexp,结果也是 0——说明这条路径根本没被触发。
我去翻了安装目录里的接触模型 C++ 源码(ContactModelLinearPBond::thermalCoupling),原因在这里:
关键在 dthick:它只在端部曲率为零(也就是平面,比如 rblock 那种块体)的时候才被赋值。球-球接触的曲率是 1/R,不等于零,于是 dthick 保持 0,pbArea 算出来是 0,力增量恒等于 0。
(dthick 那个分支是给块体/rblock 留的,我这次没有在 rblock 上验证,先按源码这么记。)
论断二在实践中是对的,但精确表述要修正一下。
contact method bond 的默认成键区间是 gap ∈ (−∞, 0],也就是只给重叠或相切的接触成键。实测三组:
gs0 = +1e-3(有间隙)+ 默认成键:连接触对象都不存在,contact.list 是空的。没有接触,自然没有胶结,也谈不上热响应。gs0 = +1e-3 + contact method bond gap 1e-3(强行跨间隙成键):接触和键都建起来了,但升温后线性力仍然是 0。因为间隙只从 +1e-3 压到 +7e-4,还没闭合;线性模型不能受拉,所以不出力。键那一路又是坑 4 的恒零。gs0 = 0(相切):只要接触被检出,工作正常,全量模式同样给出 3.0e5 N。顺便说一句相切:本次两颗球的算例里,gs0 = 0 恰好被检出了接触。但相切球对的接触检出本身不可靠(规则排列下实测约有一半漏检),工程上还是老老实实用受控重叠更稳。
lin_mode = 0。 本机默认就是 0,但别去改成 1——改了热就彻底不起作用,而且不报错。thexp。 2D 球-球 PB 的键材料热膨胀项算出来就是 0,热响应只能来自线性部分。mechanical off)+ 力学步"交替。 一次性施加很大的 ΔT 会让半径突变、产生冲击,分步升温更稳。contact cmat default 和 contact cmat thermal default 设好;specific-heat 必须在任何 model cycle 之前给,否则报 Specific Heat is 0。值得单独说一句:上面这套东西——16 组参数矩阵的脚本生成、无头运行、结果解析成表、出图、以及那四个坑的定位——都是 AI 自动完成的。人给的需求只有一句话。
四个坑里有三个是"不报错的错误":热步不推进、增量模式忽略膨胀、thexp 恒零。这类问题靠"程序正常结束"是判不出来的,必须挂客观判据——这次用的是闭式解 kₙ·2αRΔT 和 2αRΔT。判据对得上,说明模型对;对不上,就得往下挖。
坑 4 最后是靠读安装目录里的 C++ 源码定案的。这也是我觉得 AI 做这类活儿的价值所在:它不会嫌翻源码麻烦。
763388012,备注"vibePFC"即可。 参考资料
ContactModelLinearPBond::thermalCoupling。