首页/文章/ 详情

有限元 | Python画三维框架的弯矩图

8月前浏览269

一般情况下,梁单元每个结点的位移具有6个自由度,它对应于6个结点力。在系统中取出结点为i和j的梁单元,如图1所示。取右手坐标系,x轴为单元轴线方向,而y轴和z轴为截面的主惯性轴。

▲图1

三维梁单元的内力是基于杆的位置    的函数    ,由一系列的离散点组成矩阵

 

在画某一单元的变形或内力图时,通常是以该单元起点为总体坐标系的坐标原点,杆轴沿着总体坐标系的    轴正方向,杆轴上的离散点便是矩阵A的第一行,离散点对应的函数值    便是矩阵A的第二行。这是默认图形在    面上,如果将图形画在    面上,矩阵A的第二行全为0

 

▲图2

用python演示图2的框架,在初始位置不同的平面内的弯矩图

import matplotlib.pyplot as plt
import numpy as np


def main():
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']    # 这个字体能够支持中英文字符
    plt.rcParams['axes.unicode_minus'] = False      # 正常显示负号



    # 三维框架
    xs = [0,0,0,1]
    ys = [0,0,2,2]
    zs = [0,2,2,2]

    xx = np.linspace(0, 2, 10)      # 梁单元划分为10个小段

    # 每一个离散点的弯矩值
    m = [0.5,0.5, 0.5, 0.5, 0.5,0.5,0.5, 0.5, 0.5, 0.5]

    xx1 = np.hstack( (xx[0], xx, xx[-1]) )
    m1 = np.hstack( (xx[0],m, xx[0]) )


    zeros = np.zeros(12)


    # 图形在xoy面,故第三行全为0
    A = np.vstack( ( xx1,  m1, zeros) )

    # 图形在xoz面,故第二行全为0
    A1 = np.vstack( ( xx1, zeros, m1) )


    fig,  axs = plt.subplots(nrows=1, ncols=2, sharex=True,
                                    figsize=(8, 4),subplot_kw={"projection": "3d"})
    
    
    # 绘制刚架图
    axs[0].plot(xs, ys, zs)

    # 绘制单元1在xoy面的弯矩图
    axs[0].plot( A[0,:],A[1,:],A[2,:])
    axs[0].set( title='xoy面的弯矩图')
    axs[0].set_xlim(-0.4, 2)

    # 绘制单元1在xoz面的弯矩图
    axs[1].plot(xs, ys, zs)
    axs[1].plot(A1[0,:], A1[1,:], A1[2,:] )
    axs[1].set( title='xoz面的弯矩图')
    axs[1].set_xlim(-0.4, 2)

       
    fig.savefig("z216.png",dpi=300)
    plt.show()


if __name__ == "__main__":
    main() 

▲图3

内力图要经过旋转、平移操作,使之回到对应的位置上去,即图形与局部坐标一致。对于图1中的单元1,则需要作两次旋转操作(RA),而单元2则需要作旋转平移操作(TA)。缩放操作则根据图形是否协调适当考虑。下面动手画图2中的各单元扭矩图(绕单元轴线的弯矩)

单元1的两次旋转操作

import matplotlib.pyplot as plt
import numpy as np


def main():
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']    # 这个字体能够支持中英文字符
    plt.rcParams['axes.unicode_minus'] = False      # 正常显示负号



    # 三维框架
    xs = [0,0,0,1]
    ys = [0,0,2,2]
    zs = [0,2,2,2]

    xx = np.linspace(0, 2, 10)      # 梁单元划分为10个小段

    # 每一个离散点的弯矩值
    m = [0.5,0.5, 0.5, 0.5, 0.5,0.5,0.5, 0.5, 0.5, 0.5]

    xx1 = np.hstack( (xx[0], xx, xx[-1]) )
    m1 = np.hstack( (xx[0],m, xx[0]) )

    ones = np.ones(12)
    zeros = np.zeros(12)

    # 矩阵A增加维度,即第四行全为1,图形在xoz面,故第二行全为0
    A = np.vstack( ( xx1, zeros, m1, ones) )



    # z轴旋转矩阵
    Rz = np.array([[0, -1,  0, 0],
                  [1,  0,  0, 0],
                  [0,  0,  1, 0],
                  [0,  0,  0, 1]  ])
    


    # x轴旋转矩阵
    Rx = np.array([[1, 0, 0, 0],
                  [0, 0, -1, 0],
                  [0, 1,  0, 0],
                  [0, 0, 0, 1]  ])
    

    # 旋转变换
    Rxyz = Rz @ A

    Rxyz1 = Rx @ Rxyz

    fig,  axs = plt.subplots(nrows=2, ncols=2, sharex=True,
                                    figsize=(8, 8),subplot_kw={"projection": "3d"})
    
    
    # 绘制刚架图
    axs[0,0].plot(xs, ys, zs)

    # 绘制单元1未旋转时的弯矩图
    axs[0,0].plot( xx1,zeros,m1)
    axs[0,0].set( title='旋转前的弯矩图')
    axs[0,0].set_xlim(-0.4, 2)

    # 绘制单元1绕z轴旋转后的弯矩图
    axs[0,1].plot(xs, ys, zs)
    axs[0,1].plot(Rxyz[0,:], Rxyz[1,:], Rxyz[2,:] )
    axs[0,1].set( title='绕Z轴旋转后的弯矩图')
    axs[0,1].set_xlim(-0.4, 2)

    # 绘制单元1绕x轴旋转后的弯矩图
    axs[1,0].plot(xs, ys, zs)
    axs[1,0].plot(Rxyz1[0,:], Rxyz1[1,:], Rxyz1[2,:] )
    axs[1,0].set( title='绕X轴旋转后的弯矩图')
    axs[1,0].set_xlim(-0.4, 2)

       
    fig.savefig("z211.png",dpi=300)
    plt.show()


if __name__ == "__main__":
    main() 

▲图4

单元2的旋转平移操作

import matplotlib.pyplot as plt
import numpy as np


def main():
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']    # 这个字体能够支持中英文字符
    plt.rcParams['axes.unicode_minus'] = False      # 正常显示负号



    # 三维框架
    xs = [0,0,0,1]
    ys = [0,0,2,2]
    zs = [0,2,2,2]

    xx = np.linspace(0, 2, 10)      # 梁单元划分为10个小段

    # 每一个离散点的弯矩值
    m = [0.5,0.5, 0.5, 0.5, 0.5,0.5,0.5, 0.5, 0.5, 0.5]

    xx1 = np.hstack( (xx[0], xx, xx[-1]) )
    m1 = np.hstack( (xx[0],m, xx[0]) )

    ones = np.ones(12)
    zeros = np.zeros(12)

    # 矩阵A增加维度,即第四行全为1.图形在xoz面,故第二行全为0
    A = np.vstack( ( xx1,zeros,m1, ones) )

    # z轴旋转矩阵
    Rz = np.array([[0, -1,  0, 0],
                  [1,  0,  0, 0],
                  [0,  0,  1, 0],
                  [0,  0,  0, 1]  ])
    
    # 平移矩阵
    T =  np.array([[1, 0,  0, 0],
                  [0,  1,  0, 0],
                  [0,  0,  1, 2],
                  [0,  0,  0, 1]  ])
    
    # 旋转平移变换
    Rxyz = Rz @ A

    Rxyz1 = T @ Rxyz



    fig,  axs = plt.subplots(nrows=2, ncols=2, sharex=True,
                                    figsize=(8, 8),subplot_kw={"projection": "3d"})
    
    
    # 绘制刚架图
    axs[0,0].plot(xs, ys, zs)

    # 绘制单元2未旋转时的弯矩图
    axs[0,0].plot( xx1,zeros,m1)
    axs[0,0].set( title='旋转前的弯矩图')
    axs[0,0].set_xlim(-0.4, 2)

    # 绘制单元2旋转后的弯矩图
    axs[0,1].plot(xs, ys, zs)
    axs[0,1].plot(Rxyz[0,:], Rxyz[1,:], Rxyz[2,:] )
    axs[0,1].set( title='旋转后的弯矩图')
    axs[0,1].set_xlim(-0.4, 2)

    # 绘制单元2平移后的弯矩图
    axs[1,0].plot(xs, ys, zs)
    axs[1,0].plot(Rxyz1[0,:], Rxyz1[1,:], Rxyz1[2,:] )
    axs[1,0].set( title='平移后的弯矩图')
    axs[1,0].set_xlim(-0.4, 2)

       
    fig.savefig("z22.png",dpi=300)
    plt.show()


if __name__ == "__main__":
    main()  

▲图5

实际上,扭矩图和轴力图一样,图形位置都可以自行定义。

附录:

三维空间中绕    轴旋转的旋转矩阵分别为

 
 
 

平移矩阵为

 

★★★★★★★ 往期 ★★★★★★★★

来源:数值分析与有限元编程
pythonUM
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2026-02-12
最近编辑:8月前
译码当先
本科 慢慢来
获赞 14粉丝 32文章 400课程 0
点赞
收藏
作者推荐

中心差分法的蛙跳(Leapfrog)格式

差分是用离散形式来近似函数变化率的方法,是数值计算中的一种重要工具。它将函数的连续变化用离散点上的差值表示。中心差分(CentralDifference)使用两侧的离散点来近似计算导数。这就像扁担一样,一前一后,两头都有。当步长为时若要求,则式(3)是本文的灵魂所在。如图1所示,使用蛙跳格式时,速度和加速度、位移不是同一个节拍。根据式(3),每一个时间步长的中点的速度为▲图1式(4)的速度来表示位移需要指出的是,蛙跳格式以加速度为基本变量,没有直接给出整数时刻的速度。在求解时,先根据运动方程来求解时刻的加速度▲图2以上一篇的小车的自由振动为例,用蛙跳格式模拟。直观感受动力学数值解法的误差根据图3,初始条件在时刻,此时的加速度可由式(6)求得。时刻的速度可由向前差分公式(仅用于起步)在时刻的位移可由式(5)求得接下来便可根据式(6)求时刻的加速度,进一步根据式(4)求时刻的速度。求解流程为▲图3importnumpyasnpimportmatplotlib.pyplotasplt#自由振动蛙跳格式defmain(steps,dt):k=0.5#弹簧刚度x=0.5#初始位移m=1#质量v1=0#初始速度x1=xxxx=np.zeros(steps)time=np.zeros(steps)foriinrange(steps):#注意蛙跳格式的区别a=-k*x1/m#加速度ifi==0:v2=v1+a*0.5*dt#起步时用向前差分公式else:v2=v1+a*dt#中心差分公式x2=x1+v2*dt#下一时刻的位移v1=v2x1=x2#以下的数据用于绘图xxx[i]=x2t=dt*itime[i]=tfig,ax=plt.subplots(1,1,figsize=(10,6))ax.plot(time,xxx,'r-')ax.set_xlabel('$t/s$',fontsize=14)ax.set_ylabel('$x2/m$',fontsize=14)fig.savefig('f46.png',dpi=400)plt.show()if__name__=="__main__":main(800,0.1)▲图4经过数千次迭代后,小车的振幅仍然接近。对于该案例而言,蛙跳法提供了良好的模拟效果,但在上万次迭代后误差会变得显著。蛙跳式中心差分法是显式有限元软件LS-DYNA的最常用的积分方法。来源:数值分析与有限元编程

未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈