震源车:震源激发平板模态分析

发布于:2025-04-06 ⋅ 阅读:(14) ⋅ 点赞:(0)

勘探震源激发平板模态分析

import numpy as np
import scipy.linalg as la
from scipy.sparse import coo_matrix, csr_matrix, lil_matrix
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D


# ======================
# 有限元建模模块
# ======================
class PlateStructure:
    def __init__(self, Lx=2.0, Ly=1.5, h=0.05, E=210e9, rho=7850):
        """震源激发平板结构参数
        Args:
            Lx: 平板长度(m)
            Ly: 平板宽度(m)
            h: 厚度(m)
            E: 弹性模量(Pa)
            rho: 密度(kg/m³)
        """
        self.geometry = (Lx, Ly, h)
        self.material = (E, rho)

        # 网格参数
        self.nx = 8  # X方向单元数
        self.ny = 6  # Y方向单元数
        self.nodes = None
        self.elements = []

    def generate_mesh(self):
        """生成结构化四边形网格"""
        x = np.linspace(0, self.geometry[0], self.nx + 1)
        y = np.linspace(0, self.geometry[1], self.ny + 1)

        # 生成节点坐标 (Nx3数组: [x, y, z])
        self.nodes = np.array([[xi, yi, 0] for yi in y for xi in x])

        # 生成单元连接关系 (四节点单元)
        for j in range(self.ny):
            for i in range(self.nx):
                n1 = i + j * (self.nx + 1)
                n2 = n1 + 1
                n3 = n2 + (self.nx + 1)
                n4 = n3 - 1
                self.elements.append([n1, n2, n3, n4])

    def get_stiffness_matrix(self):
        """生成四节点板单元刚度矩阵(简化版本)"""
        E, nu = self.material[0], 0.3
        D = E * self.geometry[2] ** 3 / (12 * (1 - nu ** 2))

        # 简化的12x12刚度矩阵(弯曲主导)
        Ke = np.array([
            [12, 3, 0, -6, 3, 0, -12, -3, 0, 6, -3, 0],
            [3, 12, 0, -3, 6, 0, -3, -12, 0, 3, -6, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [-6, -3, 0, 12, -3, 0, 6, 3, 0, -12, 3, 0],
            [3, 6, 0, -3, 12, 0, -3, -6, 0, 3, -12, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [-12, -3, 0, 6, -3, 0, 12, 3, 0, -6, 3, 0],
            [-3, -12, 0, 3, -6, 0, 3, 12, 0, -3, 6, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [6, 3, 0, -12, 3, 0, -6, -3, 0, 12, -3, 0],
            [-3, -6, 0, 3, -12, 0, 3, 6, 0, -3, 12, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]) * D / (self.geometry[0] ** 3)

        return csr_matrix(Ke)

    def get_mass_matrix(self):
        """生成一致质量矩阵"""
        rho = self.material[1]
        h = self.geometry[2]
        area = (self.geometry[0] / self.nx) * (self.geometry[1] / self.ny)

        # 单元质量均分到各节点
        Me = np.eye(12) * (rho * h * area) / 4
        return csr_matrix(Me)


# ======================
# 模态分析模块
# ======================
class ModalAnalyzer:
    def __init__(self, structure):
        self.struct = structure
        self.K = None  # 全局刚度矩阵
        self.M = None  # 全局质量矩阵
        self.freqs = None  # 固有频率(Hz)
        self.modes = None  # 模态振型

    def assemble_matrices(self):
        """组装全局刚度矩阵和质量矩阵"""
        n_nodes = len(self.struct.nodes)
        ndof = 3 * n_nodes  # 总自由度

        # 初始化稀疏矩阵
        K = lil_matrix((ndof, ndof), dtype=np.float64)
        M = lil_matrix((ndof, ndof), dtype=np.float64)

        # 遍历所有单元进行组装
        for elem in self.struct.elements:
            Ke = self.struct.get_stiffness_matrix()
            Me = self.struct.get_mass_matrix()

            # 获取单元自由度索引
            dof_indices = []
            for node in elem:
                dof_indices.extend([3 * node, 3 * node + 1, 3 * node + 2])

            # 将单元矩阵添加到全局矩阵
            for i in range(12):
                for j in range(12):
                    K[dof_indices[i], dof_indices[j]] += Ke[i, j]
                    M[dof_indices[i], dof_indices[j]] += Me[i, j]

        self.K = K.tocsr()
        self.M = M.tocsr()

    def apply_boundary_conditions(self):
        """应用固定边界条件(四角节点全约束)"""
        fix_nodes = [0, self.struct.nx, -1, -self.struct.nx - 1]
        fixed_dofs = []

        for n in fix_nodes:
            fixed_dofs.extend([3 * n, 3 * n + 1, 3 * n + 2])  # 约束x,y,z方向

        # 创建自由度的掩码
        free_dofs = np.setdiff1d(np.arange(self.K.shape[0]), fixed_dofs)
        return free_dofs

    def solve_modes(self, num_modes=6):
        """求解特征值问题"""
        free_dofs = self.apply_boundary_conditions()

        # 提取缩减矩阵
        K_red = self.K[free_dofs, :][:, free_dofs]
        M_red = self.M[free_dofs, :][:, free_dofs]

        # 求解广义特征值问题
        evals, evecs = la.eigh(K_red.toarray(), M_red.toarray())

        # 重构全局模态振型
        self.freqs = np.sqrt(np.abs(evals[:num_modes])) / (2 * np.pi)
        self.modes = np.zeros((self.K.shape[0], num_modes))
        self.modes[free_dofs, :] = evecs[:, :num_modes]


# ======================
# 可视化模块
# ======================
class Visualizer:
    @staticmethod
    def plot_mode_shape(struct, mode, freq, ax=None):
        """绘制三维模态振型
        Args:
            mode: 模态振型向量
            freq: 对应频率
            ax: 可选的绘图轴对象
        """
        if ax is None:
            fig = plt.figure()
            ax = fig.add_subplot(111, projection='3d')

        nodes = struct.nodes.copy()
        scale = 0.2 * np.max(nodes[:, :2]) / np.max(np.abs(mode))

        # 将振型位移叠加到坐标
        nodes[:, 2] += mode[::3] * scale  # 取Z方向位移

        # 绘制变形后的网格
        x = nodes[:, 0]
        y = nodes[:, 1]
        z = nodes[:, 2]

        # 绘制单元面
        for elem in struct.elements:
            verts = nodes[elem, :]
            ax.plot_trisurf(verts[:, 0], verts[:, 1], verts[:, 2], alpha=0.6)

        ax.set_title(f'Mode Shape @ {freq:.1f}Hz')
        ax.set_xlabel('X')
        ax.set_ylabel('Y')
        return ax

    @staticmethod
    def compare_frequencies(freq_orig, freq_opt):
        """绘制频率对比柱状图"""
        plt.figure(figsize=(10, 6))
        x = np.arange(len(freq_orig))
        plt.bar(x - 0.2, freq_orig, 0.4, label='Original Design')
        plt.bar(x + 0.2, freq_opt, 0.4, label='Optimized Design')

        plt.xticks(x, [f'Mode {i + 1}' for i in x])
        plt.xlabel('Mode Order')
        plt.ylabel('Frequency (Hz)')
        plt.legend()
        plt.grid(True, alpha=0.3)
        plt.show()


# ======================
# 主程序
# ======================
if __name__ == "__main__":
    # 原始设计建模
    print("正在建立原始设计模型...")
    orig = PlateStructure(Lx=2.0, Ly=1.5, h=0.05)
    orig.generate_mesh()

    # 模态分析
    analyzer_orig = ModalAnalyzer(orig)
    analyzer_orig.assemble_matrices()
    analyzer_orig.solve_modes(num_modes=6)
    print("原始设计前6阶频率:", analyzer_orig.freqs)

    # 优化设计(增加厚度)
    print("\n正在建立优化设计模型...")
    optimized = PlateStructure(Lx=2.0, Ly=1.5, h=0.07)
    optimized.generate_mesh()

    analyzer_opt = ModalAnalyzer(optimized)
    analyzer_opt.assemble_matrices()
    analyzer_opt.solve_modes(num_modes=6)
    print("优化设计前6阶频率:", analyzer_opt.freqs)

    # 结果可视化
    print("\n生成可视化结果...")
    fig = plt.figure(figsize=(15, 10))

    # 原始设计前三阶振型
    for i in range(3):
        ax = fig.add_subplot(2, 3, i + 1, projection='3d')
        Visualizer.plot_mode_shape(orig, analyzer_orig.modes[:, i],
                                   analyzer_orig.freqs[i], ax)

    # 优化设计前三阶振型
    for i in range(3):
        ax = fig.add_subplot(2, 3, i + 4, projection='3d')
        Visualizer.plot_mode_shape(optimized, analyzer_opt.modes[:, i],
                                   analyzer_opt.freqs[i], ax)

    plt.tight_layout()

    # 频率对比
    Visualizer.compare_frequencies(analyzer_orig.freqs, analyzer_opt.freqs)
    plt.show()


网站公告

今日签到

点亮在社区的每一天
去签到