跳转至

Abaqus 刚度矩阵的导出与转换

约 1132 个字 226 行代码 4 张图片 预计阅读时间 7 分钟

Abaqus 的导出刚度矩阵方式是在 INP 文件中添加关键词,然后导出为 mtx 文件,但是这个 mtx 文件呢,不怎么“好看”,也就是矩阵形式不直观,不如像 Matlab、csv 文件那样全矩阵的形式来的直接,那我们现在就把它搞直接一点,方便人为观察。

本期内容主要包括:

  1. Abaqus 中各种刚度矩阵如何导出?
  2. 如何转换 mtx 文件为全矩阵的形式?

注意⚠️: 用到的脚本语言为 Python,原理搞明白后不限于编程语言。

1 刚度矩阵的导出

在 Abaqus/Standard 分析步类型中,可以通过在 inp 文件中添加关键词的形式将每一分析步、增量步的刚度矩阵、质量矩阵、载荷列阵输出到外部文件中。

Tip

对于非协调单元和杂交单元 Abaqus 只能输出单元质量矩阵

1.1 单元刚度矩阵

在 inp 文件中*End Step前面添加关键词:

*ELEMENT MATRIX OUTPUT, ELSET={stiff_elset}, STIFFNESS=YES, OUTPUT FILE=USER DEFINED, FILE NAME=ELEMK
  1. 需要指定输出刚度矩阵的单元集
  2. STIFFNESS=YES,表示打开刚度矩阵开关
  3. OUTPUT FILE=USER DEFINED, FILE NAME=ELEMK,这里我指定了输出文件的名字,也就是导出后的单元刚度矩阵文件为 ELEMK.mtx

打开 ELEMK.mtx 将会看到这样的情况:

单元集中每个刚度矩阵都被输出到了一个文件中,看上去有点乱,实则“乱中有序”,且听木木给你娓娓道来~

  1. 第一行就不用多解释了吧,单元号、分析步号、增量步号
  2. 第二行单元型号
  3. 第三行:单元节点数、线性单元
  4. 第四行:单元连接节点在全局中的编号,比如说我们看到的这个 C3D8R单元的八个节点是第 2521、2522、2543、2542、2479、2480、2501、2500 号节点
  5. *MATRIX,TYPE=STIFFNESS说明这是刚度矩阵
  6. 下面的数据行正是刚度矩阵的具体值了,Abaqus 是按照下三角矩阵存储刚度矩阵的

Abaqus 在输出大规模刚度矩阵、质量矩阵时,为节省存储空间和加快读写,常采用 存储下三角部分 的稀疏矩阵存储格式。因为刚度矩阵 \(K\) 是对称的,即 \(K_{ij}=K_{ji}\),所以只需存储矩阵的下三角区域(包括主对角线),即可完整恢复全矩阵。

来一个具体的例子吧,看下面的矩阵:

\[ K = { \left[ \begin{array} { l l l } { k _ { 1 1 } } & { k _ { 1 2 } } & { k _ { 1 3 } } \\ { k _ { 1 2 } } & { k _ { 2 2 } } & { k _ { 2 3 } } \\ { k _ { 1 3 } } & { k _ { 2 3 } } & { k _ { 3 3 } } \end{array} \right] } \]

存储为一维数组(按行展平):[k11, k12, k22, k13, k23, k33]

1.2 单元质量矩阵

关键词:

*ELEMENT MATRIX OUTPUT, ELSET={mass_elset}, MASS=YES, OUTPUT FILE=USER DEFINED, FILE NAME=ELEMM

这里我都指定的输出文件名字,不再赘述。需要注意的是,当材料属性中有 密度 这个参数的时候才会输出质量矩阵,而且主要用于动力类型的分析步中,静力分析不需要质量矩阵。

1.3 分布荷载矩阵

关键词:

*ELEMENT MATRIX OUTPUT, ELSET={dload_elset}, DLOAD=YES, OUTPUT FILE=USER DEFINED, FILE NAME=ELEMF

需要注意的是,当你施加分布荷载(如表面压强)的时候才会输出单元的分布等效节点荷载列阵,你如果施加节点力的形式,那就不用等效了,Abaqus 也就不会输出分布荷载列阵。

1.4 整体矩阵

整体矩阵的输出有点不太相同,需要单独再写一个分析步:

*STEP, NAME=MATRIX
*MATRIX GENERATE,STIFFNESS,MASS
*MATRIX OUTPUT,,STIFFNESS,MASS, FORMAT=COORDINATE
*END STEP
  1. 这里同时写入了刚度矩阵和质量矩阵,按需写入即可
  2. 我新增了FORMAT=COORDINATE,意思是输出的整体矩阵以 三元组 的形式展现

这样的形式会不会更直观呢,前两列是行列号,第三列是该位置的具体值。

2 转换 mtx 文件

对于下三角的矩阵形式,比如elemK.mtx

点击展开查看文件
66559038.461538    ,
-30048076.923077    ,  66559038.461538    
-30048076.923077    ,  30048076.923077    ,  66559038.461538    
41840673.076923    , -6009615.3846154    , -30048076.923077    ,  66559038.461538    
6009615.3846154    , -18255480.769231    , -6009615.3846154    ,  30048076.923077    
66559038.461538    ,
-30048076.923077    ,  6009615.3846154    ,  41840673.076923    , -30048076.923077    
-30048076.923077    ,  66559038.461538    
18028846.153846    , -6009615.3846154    , -6009615.3846154    ,  41840673.076923    
30048076.923077    , -6009615.3846154    ,  66559038.461538    
6009615.3846154    , -42067307.692308    , -30048076.923077    ,  30048076.923077    
41840673.076923    , -6009615.3846154    ,  30048076.923077    ,  66559038.461538    
6009615.3846154    , -30048076.923077    , -42067307.692308    ,  6009615.3846154    
6009615.3846154    , -18255480.769231    ,  30048076.923077    ,  30048076.923077    
66559038.461538    ,
41840673.076923    , -30048076.923077    , -6009615.3846154    ,  18028846.153846    
6009615.3846154    , -6009615.3846154    ,  41840673.076923    ,  6009615.3846154    
30048076.923077    ,  66559038.461538    
-30048076.923077    ,  41840673.076923    ,  6009615.3846154    , -6009615.3846154    
-42067307.692308    ,  30048076.923077    , -6009615.3846154    , -18255480.769231    
-6009615.3846154    , -30048076.923077    ,  66559038.461538    
6009615.3846154    , -6009615.3846154    , -18255480.769231    ,  6009615.3846154    
30048076.923077    , -42067307.692308    ,  30048076.923077    ,  6009615.3846154    
41840673.076923    ,  30048076.923077    , -30048076.923077    ,  66559038.461538    
-18255480.769231    ,  6009615.3846154    ,  6009615.3846154    , -42067307.692308    
-30048076.923077    ,  6009615.3846154    , -65879134.615385    , -30048076.923077    
-30048076.923077    , -42067307.692308    ,  6009615.3846154    , -30048076.923077    
66559038.461538    ,
-6009615.3846154    ,  41840673.076923    ,  30048076.923077    , -30048076.923077    
-42067307.692308    ,  6009615.3846154    , -30048076.923077    , -65879134.615385    
-30048076.923077    , -6009615.3846154    ,  18028846.153846    , -6009615.3846154    
30048076.923077    ,  66559038.461538    
-6009615.3846154    ,  30048076.923077    ,  41840673.076923    , -6009615.3846154    
-6009615.3846154    ,  18028846.153846    , -30048076.923077    , -30048076.923077    
-65879134.615385    , -30048076.923077    ,  6009615.3846154    , -42067307.692308    
30048076.923077    ,  30048076.923077    ,  66559038.461538    
-42067307.692308    ,  30048076.923077    ,  6009615.3846154    , -18255480.769231    
-6009615.3846154    ,  6009615.3846154    , -42067307.692308    , -6009615.3846154    
-30048076.923077    , -65879134.615385    ,  30048076.923077    , -30048076.923077    
41840673.076923    ,  6009615.3846154    ,  30048076.923077    ,  66559038.461538    
30048076.923077    , -42067307.692308    , -6009615.3846154    ,  6009615.3846154    
41840673.076923    , -30048076.923077    ,  6009615.3846154    ,  18028846.153846    
6009615.3846154    ,  30048076.923077    , -65879134.615385    ,  30048076.923077    
-6009615.3846154    , -18255480.769231    , -6009615.3846154    , -30048076.923077    
66559038.461538    ,
-6009615.3846154    ,  6009615.3846154    ,  18028846.153846    , -6009615.3846154    
-30048076.923077    ,  41840673.076923    , -30048076.923077    , -6009615.3846154    
-42067307.692308    , -30048076.923077    ,  30048076.923077    , -65879134.615385    
30048076.923077    ,  6009615.3846154    ,  41840673.076923    ,  30048076.923077    
-30048076.923077    ,  66559038.461538    
-65879134.615385    ,  30048076.923077    ,  30048076.923077    , -42067307.692308    
-6009615.3846154    ,  30048076.923077    , -18255480.769231    , -6009615.3846154    
-6009615.3846154    , -42067307.692308    ,  30048076.923077    , -6009615.3846154    
18028846.153846    ,  6009615.3846154    ,  6009615.3846154    ,  41840673.076923    
-30048076.923077    ,  6009615.3846154    ,  66559038.461538    
30048076.923077    , -65879134.615385    , -30048076.923077    ,  6009615.3846154    
18028846.153846    , -6009615.3846154    ,  6009615.3846154    ,  41840673.076923    
30048076.923077    ,  30048076.923077    , -42067307.692308    ,  6009615.3846154    
-6009615.3846154    , -42067307.692308    , -30048076.923077    , -30048076.923077    
41840673.076923    , -6009615.3846154    , -30048076.923077    ,  66559038.461538    
30048076.923077    , -30048076.923077    , -65879134.615385    ,  30048076.923077    
6009615.3846154    , -42067307.692308    ,  6009615.3846154    ,  30048076.923077    
41840673.076923    ,  6009615.3846154    , -6009615.3846154    ,  18028846.153846    
-6009615.3846154    , -30048076.923077    , -42067307.692308    , -6009615.3846154    
6009615.3846154    , -18255480.769231    , -30048076.923077    ,  30048076.923077    
66559038.461538    ,
-42067307.692308    ,  6009615.3846154    ,  30048076.923077    , -65879134.615385    
-30048076.923077    ,  30048076.923077    , -42067307.692308    , -30048076.923077    
-6009615.3846154    , -18255480.769231    ,  6009615.3846154    , -6009615.3846154    
41840673.076923    ,  30048076.923077    ,  6009615.3846154    ,  18028846.153846    
-6009615.3846154    ,  6009615.3846154    ,  41840673.076923    , -6009615.3846154    
-30048076.923077    ,  66559038.461538    
-6009615.3846154    ,  18028846.153846    ,  6009615.3846154    , -30048076.923077    
-65879134.615385    ,  30048076.923077    , -30048076.923077    , -42067307.692308    
-6009615.3846154    , -6009615.3846154    ,  41840673.076923    , -30048076.923077    
30048076.923077    ,  41840673.076923    ,  6009615.3846154    ,  6009615.3846154    
-42067307.692308    ,  30048076.923077    ,  6009615.3846154    , -18255480.769231    
-6009615.3846154    ,  30048076.923077    ,  66559038.461538    
30048076.923077    , -6009615.3846154    , -42067307.692308    ,  30048076.923077    
30048076.923077    , -65879134.615385    ,  6009615.3846154    ,  6009615.3846154    
18028846.153846    ,  6009615.3846154    , -30048076.923077    ,  41840673.076923    
-6009615.3846154    , -6009615.3846154    , -18255480.769231    , -6009615.3846154    
30048076.923077    , -42067307.692308    , -30048076.923077    ,  6009615.3846154    
41840673.076923    , -30048076.923077    , -30048076.923077    ,  66559038.461538  

通过下面脚本可以转化为全矩阵的形式,用 python 打印出的 24 行 24 列可能不是很直观,行列数有点多,可以直接输出到 csv 文件中,看上去更直观一点。

import numpy as np

def read_lower_triangular_mtx(file_path):
    # 读取所有浮点数(忽略换行和逗号)
    with open(file_path, 'r') as f:
        lines = f.readlines()

    data = []
    for line in lines:
        # 跳过空行或关键词行
        if line.strip() == "" or line.strip().startswith("*"):
            continue
        # 按逗号或空格分隔,逐个提取
        parts = [p.strip() for p in line.replace(',', ' ').split()]
        for p in parts:
            if p != '':
                data.append(float(p))
    return np.array(data)

def lower_tri_to_full(data):
    # 由下三角数据长度,计算矩阵阶数 n
    from math import sqrt
    n = int((-1 + sqrt(1 + 8 * len(data))) / 2)
    K = np.zeros((n, n))
    idx = 0
    for j in range(n):
        for i in range(j, n):
            K[i, j] = data[idx]
            K[j, i] = data[idx]  # 对称
            idx += 1
    return K

# ========== 主流程 ==========
file_path = "elemK.mtx"  
csv_path = "K_full.csv"  

data = read_lower_triangular_mtx(file_path)
K = lower_tri_to_full(data)

np.savetxt(csv_path, K, delimiter=",", fmt="%.8g")

输出至 csv 中:

当然我们也可以输出为 mat 文件,导入到 matlab 中:

import numpy as np
import scipy.io as sio
import scipy.sparse as sp

def read_lower_triangular_mtx(file_path):
    """读取 Abaqus 下三角刚度矩阵数据"""
    with open(file_path, 'r') as f:
        lines = f.readlines()
    data = []
    for line in lines:
        if line.strip() == "" or line.strip().startswith("*"):
            continue
        parts = [p.strip() for p in line.replace(',', ' ').split()]
        for p in parts:
            if p != '':
                data.append(float(p))
    return np.array(data)

def lower_tri_to_full(data):
    """由下三角数据恢复全矩阵"""
    from math import sqrt
    n = int((-1 + sqrt(1 + 8 * len(data))) / 2)
    K = np.zeros((n, n))
    idx = 0
    for j in range(n):
        for i in range(j, n):
            K[i, j] = data[idx]
            K[j, i] = data[idx]
            idx += 1
    return K

if __name__ == "__main__":
    file_path = "elemK.mtx"    # Input stiffness matrix file
    csv_path = "K_full.csv"    # Output csv file
    mat_path = "K_full.mat"    # Output mat file

    # === User config: dense or sparse mat file ===
    save_sparse_mat = False     # Set True for sparse, False for dense

    # === Read and reconstruct matrix ===
    data = read_lower_triangular_mtx(file_path)
    K = lower_tri_to_full(data)
    print(f"Matrix size: {K.shape[0]} x {K.shape[1]}")
    np.savetxt(csv_path, K, delimiter=",", fmt="%.8g")

    # === Save to .mat file ===
    if save_sparse_mat:
        K_sparse = sp.csr_matrix(K)
        sio.savemat(mat_path, {'K': K_sparse})
    else:
        sio.savemat(mat_path, {'K': K})

这里我增加了输出的 mat 文件为全矩阵或者稀疏矩阵的开关,save_sparse_mat = True表示格式为稀疏矩阵,save_sparse_mat = False表示输出格式为全矩阵。

对于三元组的形式,也可以通过下面脚本转换为 mat 文件或者 csv 文件:

import numpy as np
import scipy.io as sio
import scipy.sparse as sp

def read_triplet_file(file_path):
    """
    读取三元组稀疏矩阵文件,返回行、列、值数组和自动检测的矩阵大小
    """
    rows, cols, vals = [], [], []
    max_i, max_j = 0, 0
    with open(file_path, 'r') as f:
        for line in f:
            if line.strip() == '' or line.startswith('*'):
                continue
            parts = line.strip().split()
            if len(parts) < 3:
                continue
            i, j, v = int(parts[0]), int(parts[1]), float(parts[2])
            rows.append(i - 1)  # Matlab/Python index offset
            cols.append(j - 1)
            vals.append(v)
            max_i = max(max_i, i)
            max_j = max(max_j, j)
    nrow, ncol = max_i, max_j
    return np.array(rows), np.array(cols), np.array(vals), nrow, ncol

if __name__ == "__main__":
    file_path = "C3D8_STIF2.mtx"     # Your triplet file
    csv_path = "K_triplet.csv"
    mat_path = "K_triplet.mat"

    # === 读取三元组数据 ===
    rows, cols, vals, nrow, ncol = read_triplet_file(file_path)
    print(f"Detected matrix shape: {nrow} x {ncol}, nonzeros: {len(vals)}")

    # === 构建稀疏矩阵 ===
    K_sparse = sp.coo_matrix((vals, (rows, cols)), shape=(nrow, ncol))

    # === 保存为matlab稀疏格式 ===
    sio.savemat(mat_path, {'K': K_sparse})

    # === 保存为csv(全矩阵,稀疏元素补0,慎用大矩阵!) ===
    K_dense = K_sparse.toarray()
    np.savetxt(csv_path, K_dense, delimiter=",", fmt="%.8g")