首发于EQ减震
「Python与地震工程」复模态分析

「Python与地震工程」复模态分析

背景图:1906年4月地震和火灾后的美国圣弗朗西斯科

原理

运动方程的降阶处理

多自由度体系的运动方程(式中粗体为矩阵或向量)

\boldsymbol{M\ddot u + C\dot u + Ku = p}

增加恒等式

\boldsymbol{M\dot u} - \boldsymbol{M\dot u} = \boldsymbol{0}

写成广义矩阵的形式

\left[ \begin{matrix} \boldsymbol{C}& \boldsymbol{M}\\ \boldsymbol{M}& \boldsymbol{0}\\ \end{matrix} \right] \left\{ \begin{array}{c} \boldsymbol{\dot{u}}\\ \boldsymbol{\ddot{u}}\\ \end{array} \right\} +\left[ \begin{matrix} \boldsymbol{K}& \boldsymbol{0}\\ \boldsymbol{0}& -\boldsymbol{M}\\ \end{matrix} \right] \left\{ \begin{array}{c} \boldsymbol{u}\\ \boldsymbol{\dot{u}}\\ \end{array} \right\} =\left\{ \begin{array}{c} \boldsymbol{P}\\ \boldsymbol{0}\\ \end{array} \right\}

\boldsymbol{x}=\left\{ \begin{array}{c} \boldsymbol{u}\\ \boldsymbol{\dot{u}}\\ \end{array} \right\}

运动方程可改写为

{\boldsymbol{A\dot x}} + {\boldsymbol{B x}} = {\boldsymbol{f}}

其中

\boldsymbol{A} = \left[ \begin{matrix} \boldsymbol{C}& \boldsymbol{M}\\ \boldsymbol{M}& \boldsymbol{0}\\ \end{matrix} \right]

\boldsymbol{B} = \left[ \begin{matrix} \boldsymbol{K}& \boldsymbol{0}\\ \boldsymbol{0}& -\boldsymbol{M}\\ \end{matrix} \right]

\boldsymbol{f} = \left\{ \begin{array}{c} \boldsymbol{P}\\ \boldsymbol{0}\\ \end{array} \right\}

复模态分析

自由振动方程

{\boldsymbol{A\dot x}} + {\boldsymbol{B x}} = {\boldsymbol{0}}

\boldsymbol{u} = \boldsymbol{\phi}e^{\lambda t}

\boldsymbol{x}=\left\{ \begin{array}{c} \boldsymbol{u}\\ \boldsymbol{\dot{u}}\\ \end{array} \right\} =\left\{ \begin{array}{c} \boldsymbol{\phi }\\ \lambda \boldsymbol{\phi }\\ \end{array} \right\} e^{\lambda t}=\boldsymbol{\varphi }e^{\lambda t}

整理得广义特征值问题

\lambda {\boldsymbol{A}}\boldsymbol{\varphi}=-{\boldsymbol{B}}\boldsymbol{\varphi}

所求得特征值及特征向量均为复数,前 N 个特征值

\lambda_j = -a_j + \mathrm{i} \: b_j \quad \cdots \quad j=1,2,\cdots,N

N 个特征值与前 N 个特征值共轭

\lambda_{j+N} = -a_j - \mathrm{i} \: b_j \quad \cdots \quad j=1,2,\cdots,N

复特征值的实部和虚部有物理意义

\lambda_j = -\zeta_j \omega_j + \mathrm{i} \:\omega_j \sqrt{1-\zeta_j^2} \quad \cdots \quad j=1,2,\cdots,N

\lambda_{j+N} = -\zeta_j \omega_j - \mathrm{i} \:\omega_j \sqrt{1-\zeta_j^2} \quad \cdots \quad j=1,2,\cdots,N

模态圆频率

\omega_j = \sqrt{a_j^2+b_j^2}

模态阻尼比

\zeta _j = \frac{a_j}{\sqrt{a_j^2+b_j^2}}

程序代码

import numpy as np
import scipy.linalg as spl
import matplotlib.pyplot as plt

plt.style.use("ggplot")
plt.rcParams['font.sans-serif'] = ['Microsoft Yahei']
plt.rcParams['axes.unicode_minus'] = False

import sys
np.set_printoptions(precision=4, threshold=sys.maxsize,
                    linewidth=150)

class MDOF():
    def __init__(self, m, k, c, zeta=0.05) -> None:
        self.m = m
        self.k = k
        self.c = c
        self.zeta = zeta
        self.ndof = len(m)


    def build_matrix(self, damp_mat="D", i=1, j=2):
        '''
        建立质量、刚度、阻尼矩阵和荷载向量\\
        参数含义:
        damp_mat: 固有阻尼矩阵的建立方法。“D”为直接构造(默认),“R”为瑞利阻尼。
        i,j: 确定瑞利阻尼系数的两阶振型序号。默认i=1, j=2。
        '''
        self.M = np.diag(self.m)

        k1 = np.zeros_like(self.k)
        k1[:-1] = self.k[1:]
        self.K = np.diag(self.k+k1) + np.diag(-self.k[1:],1) + np.diag(-self.k[1:],-1)

        c1 = np.zeros_like(self.c)
        c1[:-1] = self.c[1:]
        self.C = np.diag(self.c+c1) + np.diag(-self.c[1:],1) + np.diag(-self.c[1:],-1)

        self.E = np.ones(self.ndof)

        if self.zeta > 0:
            self.mode_analyze()
            if damp_mat == "D":
                M_n = np.diag(self.phi.T.dot(self.M).dot(self.phi))
                C_ = np.diag(2.0*self.zeta*self.omega/M_n)
                self.C += self.M.dot(self.phi).dot(C_).dot(self.phi.T).dot(self.M)
            elif damp_mat == "R":
                w_i, w_j = self.omega[i-1], self.omega[j-1]
                a_0, a_1 = self.zeta*2.0*w_i*w_j/(w_i+w_j), self.zeta*2.0/(w_i+w_j)
                self.C += a_0*self.M + a_1*self.K
            else:
                self.C += np.zeros_like(self.M)


    def mode_analyze(self, check_orthogonality=False):
        omega2, self.phi = spl.eigh(self.K, self.M)
        self.omega = np.sqrt(omega2)
        self.period = 2.0*np.pi/self.omega
        
        # 验证正交性
        if check_orthogonality:
            print("正交性验证")
            print("ΦMΦ:")
            print(self.phi.T @ self.M @ self.phi)
            print("ΦKΦ:")
            print(self.phi.T @ self.K @ self.phi)

    
    def complex_mode_analyze(self, check_orthogonality=False):
        self.O = np.zeros((self.ndof, self.ndof))

        self.A = np.block( [
            [self.C, self.M], 
            [self.M, self.O] ] )
        self.B = np.block( [
            [self.K, self.O], 
            [self.O,-self.M] ] )
        
        lamda, Phi = spl.eig(-self.B, self.A)
        # eig 默认将复特征值按模从大到小排列,按结构分析惯例将其逆序排列
        self.lamda = lamda[::-1]
        self.Phi = np.flip(Phi, axis=1)
        
        # 计算自振圆频率及阻尼比
        tmp = self.lamda[::2]
        self.omega = abs(tmp)
        self.zeta = -tmp.real/self.omega
        
        # 验证正交性
        if check_orthogonality:
            print("正交性验证")
            print("ΦAΦ:")
            print(self.Phi.T @ self.A @ self.Phi)
            print("ΦBΦ:")
            print(self.Phi.T @ self.B @ self.Phi)


if __name__ == '__main__':

    ndof = 3
    m = np.ones(ndof)
    k = 1600.0*m
    c = np.zeros(ndof)
    zeta = 0.05 # 固有阻尼比
    mdof = MDOF(m, k, c, zeta)
    mdof.build_matrix("D")

    print("实模态分析:")
    mdof.mode_analyze()
    for i in range(ndof):
        print("第 %d 阶 自振圆频率:%f rad/s"%(i+1, mdof.omega[i]))

    print("复模态分析:")
    mdof.complex_mode_analyze(True)
    for i in range(ndof*2):
        print("第 %d 阶 复特征值:"%(i+1), mdof.lamda[i])
    
    for i in range(ndof):
        print("第 %d 阶 自振圆频率:%f rad/s    阻尼比:%f"%(i+1, mdof.omega[i], mdof.zeta[i]))

结果

实模态与复模态分析结果

实模态与复模态分析得到的自振圆频率完全一致。

通过复模态分析,证实了所构造的阻尼矩阵实现了预设的阻尼比。阻尼矩阵相关讨论参见: 「Python与地震工程」多自由度体系的阻尼矩阵

模态自振圆频率模态阻尼比
(直接构建阻尼矩阵)
模态阻尼比
(瑞利阻尼,1、2阶模态)
模态阻尼比
(瑞利阻尼,1、3阶模态)
模态阻尼比
(瑞利阻尼,2、3阶模态)
117.8016750.05000.05000.05000.0901
249.8791840.05000.05000.04200.0500
372.0775090.05000.06230.05000.0500

瑞利阻尼只能确保所选用两阶模态对应阻尼比为预定值。

复模态正交性验证

非对角线元素均为接近0的极小值,验证了模态的正交性。

转载本文请注明出处。科研成果中使用本文代码请引用作者课题组的研究论文:

作者课题组发表的研究论文列表(持续更新中……)


本文使用 Zhihu On VSCode 创作并发布

编辑于 2023-03-01 00:03・IP 属地山东