工程师平台
Abaqus 实战2026-09-08

材料参数十有八九先躺在 Excel 里,坑也在那儿

材料参数十有八九是先躺在 Excel 里的:供应商给的表、从手册抄下来的、 试验数据算完的。问题是 Abaqus 不吃 xlsx,也不吃 csv。 这篇讲怎么把它变成能导的东西 —— 重点不在「怎么转」,而在Excel 特有的那几个坑: 另存编码、单元格里的逗号和单位、以及排序按钮那一下。 每一条都配上导入时会看到的原话,好对号入座。
编码错了报的是 JSON 不合法
Excel 在中文 Windows 上默认存的不是 UTF-8。 文件里有一个中文,就会得到一句和编码无关的报错。
数字带引号其实能过
"206000" 是合法的。 真正过不去的是千分位逗号、带单位后缀、空单元格。
排序按钮会毁掉塑性表
塑性应变必须沿表递增。 按屈服应力排一遍序,这条就断了,而且报错指向的是行号。

01为什么不能直接把 Excel 存成 CSV 就导

材料数据在 Excel 里是二维的:一行一种材料, 一列一个参数。但 Abaqus 的材料不是二维的 —— 塑性是一张多行的曲线表,温度相关的每个属性又各自是一张表, 损伤起始下面还挂着演化。一张扁平的表格装不下这个结构, 所以中间必然要有一次结构转换。

目标格式是 JSON。它的顶层可以是两种写法,插件都收:

{"materials": [ ... ]}     带外壳
[ ... ]                    直接一个数组

第二种就是插件导出材料时写出来的形状 —— 所以「先导出一份看看格式」是最省事的起点, 尤其是当你已经在 CAE 里手工建好了一个材料当样板。 这条路和它的边界在材料复用到别的模型那篇里讲了。

一个最小的目标文件

下面是从 Excel 里那一行「密度、模量、泊松比 + 一条硬化曲线」 转出来之后该有的样子:

{
  "materials": [
    {
      "name": "Steel_Q345",
      "description": "structural steel",
      "density": 7.85e-09,
      "elastic": { "youngsModulus": 206000.0, "poissonsRatio": 0.3 },
      "plastic": {
        "table": [
          [345.0, 0.0],
          [420.0, 0.02],
          [480.0, 0.06],
          [520.0, 0.15]
        ]
      }
    }
  ]
}
这些数字是演示值
上面的数值取自插件自带示例库里的演示材料,用来跑通格式,不是材料数据。 单位制是 tonne-mm-s。

注意 density 那一行:只有一列的属性块 可以直接写一个数,不用包成对象。 这一点在从 Excel 转的时候很实用 —— 密度、比热、导热系数、热膨胀系数都是单列,一格对一个值, 省掉一层嵌套。字段的完整清单在帮助文档的格式一节

02坑一:另存编码 —— 报错和编码没关系

这是从 Excel 出发时的头号坑, 因为它的报错一个字都没提编码

materials.json 不是合法的 JSON:...

文件明明是从一个能打开的 JSON 编辑器里存出来的, 括号也数对了,怎么就不合法? 原因是插件读文件时按 UTF-8 解, 而在中文 Windows 上 Excel 和记事本的默认编码不是 UTF-8。 只要文件里有一个中文字符(最常见的就是 description 里那句说明), 解码就会失败,而失败被归到了「JSON 不合法」这一类里。

两种都行的存法
存成 UTF-8,或者存成带 BOM 的 UTF-8(记事本里叫「UTF-8」, Excel 导 CSV 时叫「CSV UTF-8」)。 插件读文件时会先把开头那三个 BOM 字节吃掉再解析 —— 这一步就是专门为「Excel 存出来的文件」加的, 所以不用为了 BOM 去折腾。

换个角度:如果整个文件一个中文都没有, 那么 GBK 和 UTF-8 存出来的字节是一样的,怎么存都能读。 所以这个坑只在你写了中文的材料名或说明时才会踩到。 也就是说,它专挑「认真写了注释的人」下手。

03坑二:单元格里到底什么算数字

Excel 单元格里看着是数字的东西,转成 JSON 之后不一定是数。 这一栏的报错有三句,都很短:

elastic: values must be numbers
plastic: row [345.0, '0.02 '] is not a list of numbers
elastic: missing key(s) poissonsRatio

但哪些真的会挂、哪些其实没事,跟直觉不太一样。 先说不用管的两种:

单元格里的东西转成 JSON 后结果
206000(正常数字)206000.0正常
206000(Excel 存成了文本,左上角有绿三角)"206000"能过 —— 数字字符串会被转成数
前后带空格的 206000" 206000 "能过 —— 空白被吃掉
206,000(千分位)"206,000"挂:values must be numbers
206000 MPa(带单位)"206000 MPa"挂:values must be numbers
空单元格null 或 ""挂:values must be numbers
#N/A、#DIV/0!(公式没算出来)"#N/A"挂:values must be numbers
2.06E+05206000.0正常 —— 科学计数法本来就合法
第二行是很多教程写错的地方:并不需要把引号去掉,数字字符串是收的。真正的杀手是第四行往下那几种「里面混了非数字字符」的。

所以在 Excel 侧要做的清理其实只有三件:

  1. 关掉千分位。单元格格式里的「使用千位分隔符」会在导出时把逗号带出去。 数值格式统一设成常规或科学计数。
  2. 单位不要写在数字旁边。单位写在表头里,别写在单元格里。 「206000 MPa」这种写法在 Excel 里看着清楚,转出去就是一个字符串。
  3. 把公式错误和空格清干净。整列筛一遍有没有 #N/A#REF!、 以及看不出来的空单元格。

另外一句报错值得单独说:missing key(s) poissonsRatio这类是整个键没写,而不是值不对。 从 Excel 转的时候,某一列在源表里根本不存在(比如泊松比那一列被同事删了) 就会得到这一句,它会明确点名缺哪个键。

04坑三:排序按钮,和塑性表的两条硬规则

这一坑最隐蔽,因为它不是打字错误,是一次无害的操作造成的。

塑性表有两条硬规则:每条硬化曲线的第一行塑性应变必须正好是 0, 并且塑性应变必须沿表严格递增。 在 Excel 里,只要你按屈服应力那一列点了一下排序, 第二条通常就断了:

plastic: plasticStrain must increase down the table, got 0.02 after 0.06
plastic: the first plastic strain must be 0, got 0.02

报错会把两个数都写出来,所以定位不难 —— 难的是意识到「我什么时候排过序」。 对策很土但有效:塑性曲线那几列单独放一张工作表, 并且永远按塑性应变升序存放, 排序只在这一列上做。

这两条规则各自为什么必须成立、以及第一行为什么是 0 而不是一个很小的数, 在塑性表三类报错里逐条讲了;从拉伸曲线换算到能填的表在真应力真应变换算

还有一条:所有行的列数必须一样

plastic: all rows must have the same length

Excel 侧的成因几乎总是同一个:温度那一列只填了一部分行。 前面几行有温度,后面几行忘了填, 转出来就是有的行三个数、有的行两个数。

温度列不必挨在一起,但组内顺序要对
温度相关的塑性表是按温度值分组检查的, 不要求同一个温度的行在表里相邻。 所以按温度列排序打乱了顺序,本身不致命。 致命的是同一个温度那一组内部的塑性应变顺序被打乱, 或者某一组的第一行不是 0。 温度表怎么排、区间外怎么取值,在温度相关材料表那篇里。

05单位换算就在 Excel 里做完

手册和供应商给的数据基本都是 SI:密度 kg/m³、模量 Pa 或 GPa、 比热 J/(kg·K)。Abaqus 里更常用的是 tonne-mm-s: 密度那个量级变成 1e-09、模量用 MPa、比热要乘 1e6。

这一步在 Excel 里做,不要在脑子里做,也不要在转换脚本里做。理由很实际:Excel 里多加一列公式,换算结果和原始值并排放着, 肉眼扫一遍就知道量级对不对; 埋进脚本里就看不见了,而这一栏错了的代价是 「静力结果看着正常,一做模态差几十倍」。

SI 里常见的样子mm 制里该是什么在 Excel 里乘什么
密度7850 kg/m³7.85e-09乘 1e-12
弹性模量206 GPa206000(MPa)GPa 乘 1000
比热460 J/(kg·K)4.6e+08乘 1e6
导热系数45 W/(m·K)45数值不变
热膨胀系数1.2e-05 /K1.2e-05数值不变
高亮的两项是漏得最多的:密度差 12 个数量级、比热差 6 个,而导热系数和膨胀系数数值不变,这种「有的要换有的不换」正是手工换算最容易出错的形状。

十项换算的完整对照和每一项的推导在Abaqus 单位制怎么选,比热那个 1e6 是怎么来的在导热系数与比热帮助文档的单位一节有同一张表可以直接对。

换算漏一半的下场
导入前插件会拿密度、比热、弹性模量三个量比对一次: 如果模型里已有的材料像 SI、要导入的像 mm 制(或者反过来), 会整批拒绝并把双方的具体数值都列出来当依据。 这个检查救得了「整批漏换」,救不了「换了一半」 —— 所以 Excel 里那一列并排的原始值,还是得自己扫一眼。

06一个能跑的 CSV 转 JSON 脚本

公式拼 JSON 那条路(用 TEXTJOIN 之类在单元格里拼字符串) 在只有几种材料、只填密度和弹性的时候够用, 一旦要带塑性曲线就会变成一团没法维护的公式。 超过这个规模就该用脚本。

下面这个脚本只用 Python 标准库,跑在普通 Python 里,不需要 Abaqus —— 所以可以在自己机器上反复试,不占许可证。 它吃两个 CSV:一个一行一种材料,一个装塑性曲线。

materials.csv
name,description,density,E,nu
Steel_Q345,structural steel,7.85e-09,206000,0.3

plastic.csv
name,yieldStress,plasticStrain
Steel_Q345,345,0
Steel_Q345,420,0.02
Steel_Q345,480,0.06
Steel_Q345,520,0.15
# -*- coding: utf-8 -*-
"""csv_to_json.py —— 把两张 CSV 转成材料库 JSON。普通 Python 就能跑。"""
import csv
import json
from collections import OrderedDict


def read_csv(path):
    # utf-8-sig:Excel 存出来的 BOM 在这里就吃掉了
    with open(path, newline='', encoding='utf-8-sig') as f:
        return list(csv.DictReader(f))


def number(text, where):
    """一格转一个数。这里挂掉,比导入时挂掉便宜得多。"""
    cleaned = (text or '').strip()
    if not cleaned:
        raise ValueError('%s 是空的' % where)
    try:
        return float(cleaned)
    except ValueError:
        raise ValueError('%s 不是数字:%r' % (where, text))


def build(materials_path, plastic_path):
    curves = OrderedDict()
    for i, row in enumerate(read_csv(plastic_path), start=2):
        name = row['name'].strip()
        curves.setdefault(name, []).append([
            number(row['yieldStress'], 'plastic.csv 第 %d 行 yieldStress' % i),
            number(row['plasticStrain'], 'plastic.csv 第 %d 行 plasticStrain' % i),
        ])

    out = []
    for i, row in enumerate(read_csv(materials_path), start=2):
        name = row['name'].strip()
        spec = OrderedDict()
        spec['name'] = name
        if row.get('description', '').strip():
            spec['description'] = row['description'].strip()
        spec['density'] = number(row['density'], '第 %d 行 density' % i)
        spec['elastic'] = OrderedDict([
            ('youngsModulus', number(row['E'], '第 %d 行 E' % i)),
            ('poissonsRatio', number(row['nu'], '第 %d 行 nu' % i)),
        ])
        rows = curves.get(name)
        if rows:
            # 按塑性应变升序 —— Excel 里排过序也不怕
            rows = sorted(rows, key=lambda r: r[1])
            if rows[0][1] != 0.0:
                raise ValueError('%s 的第一行塑性应变不是 0' % name)
            spec['plastic'] = {'table': rows}
        out.append(spec)
    return out


if __name__ == '__main__':
    specs = build('materials.csv', 'plastic.csv')
    with open('materials.json', 'w', encoding='utf-8') as f:
        json.dump({'materials': specs}, f, indent=2, ensure_ascii=False)
        f.write('\n')
    print('wrote %d material(s)' % len(specs))

几个刻意的选择,都是为了让错误尽早暴露:

  • encoding='utf-8-sig' 读、encoding='utf-8' 写, 加上 ensure_ascii=False —— 中文说明按原字符写出去,第 02 节那个坑一次解决。
  • 每一格转数字都带上「哪个文件第几行哪一列」。 CSV 的行号从 2 起算,因为第 1 行是表头 —— 这样报出来的行号和 Excel 里看到的行号是同一个数。
  • 塑性曲线在脚本里重新按塑性应变排一次序, 并且当场检查第一行是不是 0。 这两条本来是导入时才查的,提前到这里查, 是因为这时候你还开着 Excel。
要加别的属性怎么办
照着同一个模式往 spec 里加键就行: 热的三样放进 thermal,损伤放进 damage。 属性块的键名和每一列的顺序在帮助文档的格式一节,如果你想跳过文件直接建材料, 对应的 Abaqus 接口调用在用 Python 批量建材料那篇的属性块对照表里。

07报错对照:这句话对应 Excel 里的哪一格

文件转好了导进去,还是可能被拦。 下面这张表把导入时会看到的原话映射回 Excel 侧的成因, 按「先看文件层、再看材料层、最后看数值层」的顺序排。

导入时看到的Excel 侧的成因
找不到材料库文件路径写错,或者文件还开在 Excel 里没保存出来
不是合法的 JSON两种:一是编码不是 UTF-8 且文件里有中文(最常见);二是拼字符串时漏了逗号或多了尾逗号
材料库的顶层必须是一个对象或数组。写成了单个材料对象,外面忘了套数组
里没有任何材料。数组是空的 —— 通常是源表最后一行是空行,被跳过之后什么都没剩
第 N 个材料不是一个对象。数组里混进了字符串或数字,常见于手工拼字符串时多了一个逗号
第 N 个材料缺少 "name" 字段。源表里那一行的名称列是空的;N 是从 1 数的第几个材料
材料名重复拖公式或复制粘贴导致两行同名。插件在读文件阶段就拒,不会先导一个再覆盖
values must be numbers单元格里混了非数字字符:千分位逗号、单位后缀、公式错误值、空格
is not a list of numbers同上,但发生在表格类属性的某一行里,报错会把这一行原样打出来
all rows must have the same length温度列只填了一部分行
"table" is empty曲线那张工作表里这个材料一行都没有
missing key(s) ...整列在源表里不存在,报错会点名缺哪个键
must be positive, got ...数值是 0 或负数。密度允许 0,模量、比热、导热系数不允许
poissonsRatio must be between -1 and 0.5 (exclusive)泊松比填了 0.5 —— 这是这一栏唯一一处会当场拦下的物理检查
the first plastic strain must be 0曲线表排过序,或者第一行填了一个很小的数当起点
plasticStrain must increase down the table曲线表按屈服应力排过序
三行高亮是从 Excel 出发时最高频的三个:编码、重名、排序。前两个和材料学没有半点关系,第三个是一次点击造成的。

泊松比那一条为什么是硬边界、0.4999 为什么比 0.5 更麻烦,在弹性模量与泊松比里推过。

还有一条路:不经过 Excel

如果你要的材料本来就是常见牌号, 那么从站上的在线材料库直接取,比自己维护一张 Excel 省事 —— 数值带出处,单位制也已经是统一的。 要说清楚的是能力边界:在线材料库需要 Abaqus 2023 或更新的版本; 2022 及更早的版本没有激活途径,只能走本地 JSON 文件这条路, 也就是这篇讲的做法。两条来源的差别列在产品页的数据来源一节

常见问题

Excel 里的材料表怎么导入 Abaqus?

Abaqus 不直接读 xlsx 或 csv,中间要转成 JSON 材料库文件,再用材料参数导入插件导进模型。转换有两条路:材料少且只有密度和弹性时可以在 Excel 里用公式拼字符串;带塑性曲线之后应该写一个 CSV 转 JSON 的脚本,用 Python 标准库就够,不需要 Abaqus 环境。目标 JSON 的顶层可以是带 materials 外壳的对象,也可以直接是一个数组,插件两种都收。

材料库文件报「不是合法的 JSON」怎么办?

先查编码,这是最常见的原因而且报错里完全没提。插件按 UTF-8 读文件,而中文 Windows 上 Excel 和记事本的默认编码不是 UTF-8,只要文件里有一个中文字符(通常是描述那句话)解码就会失败,而失败被归到了 JSON 不合法这一类里。存成 UTF-8 或者带 BOM 的 UTF-8 都可以,插件读的时候会先把开头三个 BOM 字节吃掉。如果整个文件一个中文都没有,那这个坑踩不到,这时要查的就是括号和逗号了。

JSON 里的数字要不要去掉引号?

不用。数字外面带引号是合法的,插件会把数字字符串转成数,前后带空格也没事。真正过不去的是单元格里混了非数字字符的情况:千分位逗号写成的 206,000、带单位后缀的 206000 MPa、空单元格、以及 #N/A 这类公式错误值,这些都会得到 values must be numbers。所以 Excel 侧要做的是关掉千分位、把单位写在表头而不是单元格里、把公式错误清干净,而不是纠结引号。

为什么塑性表导入时报应变不递增?

大概率是在 Excel 里按屈服应力那一列点过排序。塑性表有两条硬规则:每条硬化曲线第一行的塑性应变必须正好是 0,且塑性应变必须沿表严格递增,排序会破坏第二条,有时连第一条一起破坏。报错会把前后两个数都打出来所以定位不难,难的是意识到自己排过序。对策是把塑性曲线单独放一张工作表并永远按塑性应变升序存放,或者在转换脚本里重新排一次序。

温度相关的材料表在 Excel 里要按温度排好吗?

不必相邻。温度相关的塑性表是按温度值分组检查的,同一个温度的行散落在表里也能正确分组。真正的要求是每一组内部的塑性应变要递增、并且每一组的第一行都要从 0 开始。另一个和温度列相关的高频错是列数不一致:温度那一列只填了一部分行,转出来就是有的行三个数有的行两个数,报错是所有行的列数必须一致。

从 Excel 转过去的时候单位换算在哪一步做?

在 Excel 里做,用一列公式,把换算结果和原始值并排放着。不要在脑子里算,也不要埋进转换脚本:换算结果肉眼可见才能扫一眼确认量级。SI 转 tonne-mm-s 时密度乘 1e-12、GPa 转 MPa 乘 1000、比热乘 1e6,而导热系数和热膨胀系数数值不变。这种有的要换有的不换的形状,正是手工换算最容易漏的。插件导入前会拿密度、比热、弹性模量比对一次单位制并整批拒绝明显冲突的,但它救不了只换了一半的情况。

这一步可以不自己做

单位换算那一列留在 Excel 里,和原始值并排放着 —— 埋进脚本就看不见了,而这一栏错了的样子是「静力看着正常,一做模态差几十倍」。

在线材料库需要 Abaqus 2023 或更高版本;2022 及更早只能用本地 JSON 材料库。