弹性力学基本方程及有限元编程

概述

在工程领域,无论是设计一座桥梁、制造一台精密机械,还是研发航空航天部件,都需要弄清楚材料在受力时会发生怎样的变化。弹性力学就是专门研究这个问题的学科,它通过微分平衡方程、几何方程和物理方程,为我们揭示材料内部应力、应变和位移的规律。而有限元方法,则是帮助我们把这些理论应用到实际工程计算中的强大工具。

提醒:个别地方公式识别有问题,感兴趣的读者可以到本人公众号阅读  冬生亦冬生(全网首发,欢迎一起交流学习)

一、弹性力学三大基本方程

  1. 微分平衡方程(力的平衡)

描述弹性体微元的力学平衡,基于小变形、连续均匀各向同性假设:

应用:求解结构应力场(如机械零件、建筑承重结构强度分析)。

  1. 几何方程(变形几何关系)

建立位移与应变的线性关系(小变形假设):

线应变: 切应变:(其余切应变类似)

应用举例:在分析建筑物在地震中的晃动时,通过测量建筑物各部分的位移,利用几何方程就能计算出建筑物的应变,判断是否会出现裂缝等损坏。

  1. 物理方程(本构关系)

各向同性弹性材料的胡克定律(矩阵形式):

应用:连接应力与应变,用于材料选型和实验应力计算。

二、边界条件

  1. 位移边界条件 指定边界位移值:在边界(如固定端。

  2. 应力边界条件 指定边界面力:在边界 上,

((l,m,n) 为边界外法线方向余弦,为面力分量)。 3. 混合边界条件 部分边界给定位移,部分边界给定应力(如简支梁两端约束)。

三、方程联合求解

三大方程与边界条件联立,形成定解问题: 几何方程将位移 转换为应变; 物理方程将应变转换为应力; 微分平衡方程结合体积力建立平衡关系; 边界条件约束解的唯一性。典型问题:简支梁受均布载荷,通过假设位移函数、代入方程并满足边界条件求解应力与挠度。

四、简单弹性问题的有限元编程方法

有限元方法是一种将复杂问题简单化的数值计算方法,它把连续的弹性体划分成许多小的单元,通过计算每个单元的特性,再把它们组合起来,得到整个弹性体的结果。下面以平面应力三角形单元为例,介绍有限元编程的核心步骤:

  1. 问题离散化 将弹性体划分为个单元(如三角形、四边形单元),节点总数为,节点位移向量(以平面问题为例)。

  2. 单元刚度矩阵 以平面应力三角形单元(3 节点,坐标 为例: 形函数为单元面积,为几何系数);

应变 - 位移关系 为应变矩阵);

单元刚度矩阵

  1. 整体刚度矩阵组装 将所有单元刚度矩阵按节点编号叠加,形成整体刚度矩阵 ,尺寸为。

  2. 载荷与边界条件处理 节点载荷向量 包含集中力、分布力等效节点力; 位移边界条件:直接约束中对应自由度(如固定节点设为 0); 应力边界条件:转化为节点载荷加入。

  3. 求解系统方程 通过稀疏矩阵求解器(如高斯消元法)解得节点位移,再计算应变和应力。 简单 Python 代码框架(平面应力三角形单元)

import numpy as np
import scipy.sparse as sp
import scipy.sparse.linalg as spla
import matplotlib.pyplot as plt
import matplotlib.tri as tri

# ============================
# 1. 网格生成模块
# ============================
def generate_mesh(L=10, H=2, nx=10, ny=4):
    """
    生成矩形区域的三角形网格
    参数:
        L : 长度 (mm)
        H : 高度 (mm)
        nx : x方向单元数
        ny : y方向单元数
    返回:
        nodes : 节点坐标数组 (N,2)
        elements : 单元节点索引数组 (M,3)
    """
    # 生成节点
    x = np.linspace(0, L, nx+1)
    y = np.linspace(0, H, ny+1)
    xx, yy = np.meshgrid(x, y)
    nodes = np.column_stack([xx.ravel(), yy.ravel()])
    
    # 生成三角形单元
    elements = []
    for i in range(ny):
        for j in range(nx):
            # 单个矩形分为两个三角形
            n0 = i*(nx+1) + j
            n1 = n0 + 1
            n2 = n0 + (nx+1) + 1
            n3 = n0 + (nx+1)
            
            # 添加两个三角形单元
            elements.append([n0, n1, n2])
            elements.append([n0, n2, n3])
    
    return np.array(nodes), np.array(elements)

# ============================
# 2. 材料参数和单元刚度矩阵计算
# ============================
def linear_triangle_stiffness(nodes, E=210e3, nu=0.3, t=1.0):
    """
    计算线性三角形单元的刚度矩阵(平面应力)
    参数:
        nodes : 单元节点坐标 (3,2)
        E : 弹性模量 (MPa)
        nu : 泊松比
        t : 厚度 (mm)
    返回:
        ke : 单元刚度矩阵 (6,6)
    """
    # 节点坐标
    x1, y1 = nodes[0]
    x2, y2 = nodes[1]
    x3, y3 = nodes[2]
    
    # 计算单元面积
    A = 0.5 * abs((x2-x1)*(y3-y1) - (x3-x1)*(y2-y1))
    
    # 弹性矩阵D
    D = E/(1-nu**2) * np.array([
        [1,  nu,         0       ],
        [nu, 1,          0       ],
        [0,  0,  (1-nu)/2]
    ])
    
    # 应变位移矩阵B
    b = np.array([y2-y3, y3-y1, y1-y2])
    c = np.array([x3-x2, x1-x3, x2-x1])
    B = 1/(2*A) * np.array([
        [b[0], 0,    b[1], 0,    b[2], 0   ],
        [0,    c[0], 0,    c[1], 0,    c[2]],
        [c[0], b[0], c[1], b[1], c[2], b[2]]
    ])
    
    # 单元刚度矩阵
    ke = (B.T @ D @ B) * A * t
    return ke

# ============================
# 3. 总刚度矩阵组装
# ============================
def assemble_global_stiffness(nodes, elements, E, nu, t):
    """
    组装全局刚度矩阵
    参数:
        nodes : 节点坐标数组
        elements : 单元连接数组
        E, nu, t : 材料参数
    返回:
        K : 全局刚度矩阵 (2N,2N) 稀疏格式
    """
    n_nodes = nodes.shape[0]
    n_dof = 2 * n_nodes
    K = sp.lil_matrix((n_dof, n_dof))
    
    for elem in elements:
        # 获取单元节点索引
        n1, n2, n3 = elem
        
        # 计算单元刚度矩阵
        elem_nodes = nodes[[n1, n2, n3]]
        ke = linear_triangle_stiffness(elem_nodes, E, nu, t)
        
        # 组装到全局矩阵
        dofs = [2*n1, 2*n1+1, 2*n2, 2*n2+1, 2*n3, 2*n3+1]
        for i in range(6):
            for j in range(6):
                K[dofs[i], dofs[j]] += ke[i,j]
    
    return K.tocsr()

# ============================
# 4. 边界条件和载荷施加
# ============================
def apply_boundary_conditions(K, F, nodes, fix_left=True):
    """
    应用边界条件(左侧固定,右侧施加集中力)
    返回:
        K_modified : 处理后的刚度矩阵
        F_modified : 处理后的载荷向量
    """
    # 找到左侧节点(x=0)
    left_nodes = np.where(nodes[:,0] == 0)[0]
    fixed_dofs = []
    for n in left_nodes:
        fixed_dofs.extend([2*n, 2*n+1])  # 固定x和y方向
    
    # 找到右侧节点(x=max)
    right_nodes = np.where(nodes[:,0] == nodes[:,0].max())[0]
    for n in right_nodes:
        F[2*n+1] = -100.0  # 施加y方向集中力
    
    # 处理固定自由度
    dofs = np.arange(K.shape[0])
    free_dofs = np.setdiff1d(dofs, fixed_dofs)
    
    K_modified = K[free_dofs, :][:, free_dofs]
    F_modified = F[free_dofs]
    
    return K_modified, F_modified, free_dofs, fixed_dofs

# ============================
# 5. 求解和后处理
# ============================
def post_process(nodes, elements, U, scale=100):
    """
    后处理:显示变形前后的网格和应力分布
    参数:
        scale : 变形放大系数
    """
    # 创建三角剖分对象
    triang = tri.Triangulation(nodes[:,0], nodes[:,1], elements)
    
    # 绘制原始网格
    plt.figure(figsize=(12,4))
    plt.subplot(121)
    plt.triplot(triang, color='gray', lw=0.5)
    plt.title("Original Mesh")
    
    # 绘制变形后网格
    plt.subplot(122)
    deformed_nodes = nodes + U[::2].reshape(-1,1) * scale  # 仅显示x方向位移
    deformed_triang = tri.Triangulation(deformed_nodes[:,0], 
                                      deformed_nodes[:,1], 
                                      elements)
    plt.triplot(deformed_triang, color='red', lw=0.5)
    plt.title(f"Deformed Mesh (Scale: {scale}X)")
    plt.show()

# ============================
# 主程序
# ============================
if __name__ == "__main__":
    # 参数设置
    E = 210000  # 弹性模量 (MPa)
    nu = 0.3     # 泊松比
    t = 10.0     # 厚度 (mm)
    L = 100      # 长度 (mm)
    H = 20       # 高度 (mm)
    nx, ny = 20, 4  # 网格划分

    # 1. 生成网格
    nodes, elements = generate_mesh(L, H, nx, ny)
    print(f"Generated mesh with {nodes.shape[0]} nodes and {elements.shape[0]} elements")

    # 2. 组装总刚度矩阵
    K = assemble_global_stiffness(nodes, elements, E, nu, t)
    print("Global stiffness matrix assembled")

    # 3. 初始化载荷向量
    F = np.zeros(2 * nodes.shape[0])

    # 4. 应用边界条件
    K_mod, F_mod, free_dofs, fixed_dofs = apply_boundary_conditions(K, F, nodes)
    print(f"Applied boundary conditions: fixed {len(fixed_dofs)} DOFs")

    # 5. 求解方程组
    U = np.zeros(2 * nodes.shape[0])
    U[free_dofs] = spla.spsolve(K_mod, F_mod)
    print("Displacement solution completed")

    # 6. 后处理
    post_process(nodes, elements, U, scale=500)

    # 显示最大位移
    max_ux = np.max(np.abs(U[::2]))
    max_uy = np.max(np.abs(U[1::2]))
    print(f"Maximum displacements: Ux={max_ux:.4f} mm, Uy={max_uy:.4f} mm")

五、总结

弹性力学三大方程与边界条件构成理论基础,有限元方法通过离散化实现工程问题的数值求解。实际应用中需根据结构复杂度选择单元类型(如梁、壳、三维实体单元),结合商业软件(ABAQUS、ANSYS)或自主编程实现精确分析,广泛应用于航空航天、机械、土木等领域的结构设计与优化。由于变分法是弹性力学的重要内容也是有限元的重要基础,有利于理解有限元的构造及编程方法,后续将介绍这部分内容。提醒:个别地方公式识别有问题,感兴趣的读者可以到本人公众号阅读  冬生亦冬生(全网首发,欢迎一起交流学习)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冬生亦东生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值