01先把表达式写出来
Abaqus 里一点的热应变不是简单的 α·ΔT,它带一个把初始状态扣掉的项:
ε_th = α(T) · (T − T⁰) − α(Tᴵ) · (Tᴵ − T⁰)
T 当前温度
Tᴵ 该点的初始温度(*INITIAL CONDITIONS, TYPE=TEMPERATURE)
T⁰ 零应变参考温度(*EXPANSION 的 ZERO,插件里的 zeroTemperature)
α 膨胀系数,可以是常数,也可以是温度的函数三个温度各管各的事,很多混乱来自把它们当成一回事:
| 量 | 是什么 | 在哪里定义 |
|---|---|---|
| T0 | 材料属性的一部分:α 是以哪个温度为基准标定的 | 材料里,Expansion 的 zero |
| TI | 模型状态:分析开始时这个点多少度 | 载荷模块的 Predefined Field,Initial 步 |
| T | 模型状态:当前增量步这个点多少度 | 后续步里的温度场,或者传热分析算出来的 |
02常数 α:参考温度完全抵消
把 α 当常数(也就是 JSON 里只给一个 alpha 值、 不给温度表),两项里的 α 是同一个数,直接提出来:
ε_th = α · (T − T⁰) − α · (Tᴵ − T⁰)
= α·T − α·T⁰ − α·Tᴵ + α·T⁰
└────┬────┘
抵消
= α · (T − Tᴵ)T⁰ 不见了。 剩下的式子里只有当前温度和初始温度之差, 这正是直觉里的 α·ΔT。
zeroTemperature 填 0、填 20、填 293,甚至完全不填, 算出来的热应变一模一样。 改这个值去调试凭空热应力,是在改一个不参与计算的量。这一条值得自己验一遍,成本很低:建一个单元、给一组约束、 用常数 α 跑两次,一次 zero 填 0、一次填 100, 对比应力云图。两次结果应当完全相同。
03那 ZERO 什么时候有用:α 随温度变的时候
α 给成温度表之后,表达式里两项的 α 取值不同 —— 一个是 α(T),一个是 α(Tᴵ) —— 就提不出来了,T⁰ 留在式子里:
ε_th = α(T) · (T − T⁰) − α(Tᴵ) · (Tᴵ − T⁰)
↑ ↑
不同的两个值,抵消不掉一个算例
设初始温度 TI = 20,当前温度 T = 400, 膨胀系数取 α(20) = 1.2×10−5、α(400) = 1.4×10−5。
Steel_Q345 的alpha(演示值);1.4e-5 是我为了让这个算例有两个不同的 α 而假设的示意值,不代表任何材料在 400 °C 的真实膨胀系数。 这一节要说明的是「差多少」这个结构,不是这两个数本身。| T⁰ 取值 | 第一项 α(T)(T − T⁰) | 第二项 α(Tᴵ)(Tᴵ − T⁰) | ε_th |
|---|---|---|---|
| 20 | 1.4e-5 × 380 = 5.320e-3 | 1.2e-5 × 0 = 0 | 5.320e-3 |
| 0 | 1.4e-5 × 400 = 5.600e-3 | 1.2e-5 × 20 = 2.400e-4 | 5.360e-3 |
0.75% 的应变差,在一个受约束的构件里换算成应力是 E 乘这个差 —— 不算大,但也不是舍入噪声。结论是:α 给成表时,T⁰ 必须填成 α 标定时用的那个基准温度, 不能随手填 0。这个基准温度应当和 α 数据一起来源, 两者分开就没法用了。
04凭空热应力:真正的来源
既然常数 α 时 T⁰ 不参与,那第一个增量步就冒出来的热应力是哪来的? 回到那个式子 —— 它只剩 α·(T − Tᴵ)。 要让它非零,只能是 T 和 Tᴵ 不相等。
来源一:初始温度场压根没定义(最常见)
没有 *INITIAL CONDITIONS, TYPE=TEMPERATURE 时, Abaqus 认为 TI = 0。这时你在第一个分析步里给一个 「室温 20 °C」的温度场 —— 你以为什么都没变, 模型认为温度升了 20 度,于是老老实实算出了对应的热应变。 应力是真的,逻辑也是对的,错的是那个没写的初始条件。
来源二:温度场只给了一部分区域
装配体里一部分零件有温度场、一部分没有,没有的那部分按 0 处理。 两边一接触,界面上就是一个几百度的虚假温差, 接触面附近会出现一圈量级离谱的应力。
来源三:温标不统一
初始条件按摄氏给了 20,后续温度场按开氏给了 293。 模型看到的是温度从 20 升到 293,涨了 273 度。这一类见下一节。
- 先确认 α 是常数还是表。是常数就不要动 ZERO, 它不参与。
- 查 Initial 步里有没有温度 Predefined Field,覆盖范围是不是全模型。
- 查初始温度场和后续温度场的数值是不是同一个标度。
- 以上都对,α 又是表,这时才回头看 T⁰ 填的是不是 α 的标定基准。
05摄氏还是开氏:示例库里两种都有
插件示例库 materials_sample.json 里有两条带zeroTemperature 的材料,它们用的不是同一个温标:
| 示例库条目 | alpha | zeroTemperature | 看起来是 |
|---|---|---|---|
Steel_Q345 | 1.2e-05 | 20.0 | 摄氏 |
Al_6061_T6 | 2.36e-05 | 293.0 | 开氏 |
Steel_S355_TempDep | 1.2e-05 | 20.0 | 摄氏 |
这不是文件写错了,示例库的目的是演示各种写法。 但它恰好演示了一个真实的坑:同一个模型里三个温度必须同标度。 材料的 T⁰ 用开氏、模型的温度场用摄氏,那个 273 的偏移会直接进结果。
什么时候两种都行,什么时候必须开氏
- 只涉及温差的分析(纯热膨胀、导热), 摄氏和开氏等价 —— 温差的数值一样,α 的数值也一样 (α 的单位是「每度」,一个摄氏度和一个开尔文是同样大的间隔)。 统一即可。
- 出现绝对温度的地方必须开氏:辐射换热(正比于 T⁴)、 Johnson-Cook 里的同调温度。这些式子里 T 本身进运算, 填 20 和填 293 不是一回事。
06JSON 里怎么写:一个裸数字写法的坑
expansion 是单列属性(只有 alpha 一列), 所以它和密度一样允许裸数字。但这里有个别处没有的后果:
"thermal": {
"expansion": 1.2e-5 ← 合法,但没有地方放 zeroTemperature
}
"thermal": {
"expansion": {
"alpha": 1.2e-5,
"zeroTemperature": 20.0 ← 只有对象写法才带得上
}
}type、zeroTemperature)的方式是: 这一块是对象就读它的键,不是对象就当没有选项。 所以写成裸数字时,你没法附带参考温度,也不会有任何提示 ——Expansion 会以 Abaqus 的默认参考温度建出来。table 键里。温度相关的 α
"expansion": {
"table": [
[1.2e-5, 20.0],
[1.3e-5, 200.0],
[1.4e-5, 400.0]
],
"zeroTemperature": 20.0
}规则和别的属性一致:膨胀本身要一列,行有两列就意味着第二列是温度。 上面这组 α 是为了演示表格写法编的示意值, 不是任何材料的实测数据 —— 真要用,α 和它的标定基准温度必须一起来自同一份可核对的数据源。
负的 α 不会被拦
插件对好几列做了「必须为正」或「必须非负」的检查(模量、屈服应力、 热导率、比热、密度),但 alpha 这一列没有。 这是有意的:负热膨胀材料真实存在,受热收缩是合法的物理行为。 所以 α 填成负数不会有任何提示,得自己确认那是不是笔误。
| 报错 | 触发条件 | 改法 |
|---|---|---|
thermal.expansion: missing key(s) alpha | 对象写法里没有 alpha 键 | 补上 alpha,或者改成裸数字写法 |
thermal.expansion: values must be numbers | 值是字符串 | 去掉引号;从 Excel 导出的 JSON 最容易带引号 |
thermal.expansion: all rows must have the same length | table 里有的行带温度列有的不带 | 要么全部一列,要么全部两列 |
thermal.expansion: "table" is empty | table 键在但是空数组 | 补数据,或者整块删掉 |
unknown Abaqus constant "ORTHO" | type 拼错了 | 名字要和 Abaqus 常量一致,插件会先转成大写再找 |
JSON 各字段的完整定义在帮助文档第 05 节,报错对照表在第 08 节。同一个 thermal 块里另外两项(热导率、比热) 的单位换算见单位对照表—— 那两项一个数值不变、一个要乘 106, 是热分析里最容易一起搞错的一组。瞬态传热还要用到密度,见密度那篇的第 04 节。