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

打印 上一主题 下一主题

主题 1602|帖子 1602|积分 4806


勘探震源引发平板模态分析
  1. import numpy as np
  2. import scipy.linalg as la
  3. from scipy.sparse import coo_matrix, csr_matrix, lil_matrix
  4. import matplotlib.pyplot as plt
  5. from mpl_toolkits.mplot3d import Axes3D
  6. # ======================
  7. # 有限元建模模块
  8. # ======================
  9. class PlateStructure:
  10.     def __init__(self, Lx=2.0, Ly=1.5, h=0.05, E=210e9, rho=7850):
  11.         """震源激发平板结构参数
  12.         Args:
  13.             Lx: 平板长度(m)
  14.             Ly: 平板宽度(m)
  15.             h: 厚度(m)
  16.             E: 弹性模量(Pa)
  17.             rho: 密度(kg/m³)
  18.         """
  19.         self.geometry = (Lx, Ly, h)
  20.         self.material = (E, rho)
  21.         # 网格参数
  22.         self.nx = 8  # X方向单元数
  23.         self.ny = 6  # Y方向单元数
  24.         self.nodes = None
  25.         self.elements = []
  26.     def generate_mesh(self):
  27.         """生成结构化四边形网格"""
  28.         x = np.linspace(0, self.geometry[0], self.nx + 1)
  29.         y = np.linspace(0, self.geometry[1], self.ny + 1)
  30.         # 生成节点坐标 (Nx3数组: [x, y, z])
  31.         self.nodes = np.array([[xi, yi, 0] for yi in y for xi in x])
  32.         # 生成单元连接关系 (四节点单元)
  33.         for j in range(self.ny):
  34.             for i in range(self.nx):
  35.                 n1 = i + j * (self.nx + 1)
  36.                 n2 = n1 + 1
  37.                 n3 = n2 + (self.nx + 1)
  38.                 n4 = n3 - 1
  39.                 self.elements.append([n1, n2, n3, n4])
  40.     def get_stiffness_matrix(self):
  41.         """生成四节点板单元刚度矩阵(简化版本)"""
  42.         E, nu = self.material[0], 0.3
  43.         D = E * self.geometry[2] ** 3 / (12 * (1 - nu ** 2))
  44.         # 简化的12x12刚度矩阵(弯曲主导)
  45.         Ke = np.array([
  46.             [12, 3, 0, -6, 3, 0, -12, -3, 0, 6, -3, 0],
  47.             [3, 12, 0, -3, 6, 0, -3, -12, 0, 3, -6, 0],
  48.             [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  49.             [-6, -3, 0, 12, -3, 0, 6, 3, 0, -12, 3, 0],
  50.             [3, 6, 0, -3, 12, 0, -3, -6, 0, 3, -12, 0],
  51.             [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  52.             [-12, -3, 0, 6, -3, 0, 12, 3, 0, -6, 3, 0],
  53.             [-3, -12, 0, 3, -6, 0, 3, 12, 0, -3, 6, 0],
  54.             [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  55.             [6, 3, 0, -12, 3, 0, -6, -3, 0, 12, -3, 0],
  56.             [-3, -6, 0, 3, -12, 0, 3, 6, 0, -3, 12, 0],
  57.             [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  58.         ]) * D / (self.geometry[0] ** 3)
  59.         return csr_matrix(Ke)
  60.     def get_mass_matrix(self):
  61.         """生成一致质量矩阵"""
  62.         rho = self.material[1]
  63.         h = self.geometry[2]
  64.         area = (self.geometry[0] / self.nx) * (self.geometry[1] / self.ny)
  65.         # 单元质量均分到各节点
  66.         Me = np.eye(12) * (rho * h * area) / 4
  67.         return csr_matrix(Me)
  68. # ======================
  69. # 模态分析模块
  70. # ======================
  71. class ModalAnalyzer:
  72.     def __init__(self, structure):
  73.         self.struct = structure
  74.         self.K = None  # 全局刚度矩阵
  75.         self.M = None  # 全局质量矩阵
  76.         self.freqs = None  # 固有频率(Hz)
  77.         self.modes = None  # 模态振型
  78.     def assemble_matrices(self):
  79.         """组装全局刚度矩阵和质量矩阵"""
  80.         n_nodes = len(self.struct.nodes)
  81.         ndof = 3 * n_nodes  # 总自由度
  82.         # 初始化稀疏矩阵
  83.         K = lil_matrix((ndof, ndof), dtype=np.float64)
  84.         M = lil_matrix((ndof, ndof), dtype=np.float64)
  85.         # 遍历所有单元进行组装
  86.         for elem in self.struct.elements:
  87.             Ke = self.struct.get_stiffness_matrix()
  88.             Me = self.struct.get_mass_matrix()
  89.             # 获取单元自由度索引
  90.             dof_indices = []
  91.             for node in elem:
  92.                 dof_indices.extend([3 * node, 3 * node + 1, 3 * node + 2])
  93.             # 将单元矩阵添加到全局矩阵
  94.             for i in range(12):
  95.                 for j in range(12):
  96.                     K[dof_indices[i], dof_indices[j]] += Ke[i, j]
  97.                     M[dof_indices[i], dof_indices[j]] += Me[i, j]
  98.         self.K = K.tocsr()
  99.         self.M = M.tocsr()
  100.     def apply_boundary_conditions(self):
  101.         """应用固定边界条件(四角节点全约束)"""
  102.         fix_nodes = [0, self.struct.nx, -1, -self.struct.nx - 1]
  103.         fixed_dofs = []
  104.         for n in fix_nodes:
  105.             fixed_dofs.extend([3 * n, 3 * n + 1, 3 * n + 2])  # 约束x,y,z方向
  106.         # 创建自由度的掩码
  107.         free_dofs = np.setdiff1d(np.arange(self.K.shape[0]), fixed_dofs)
  108.         return free_dofs
  109.     def solve_modes(self, num_modes=6):
  110.         """求解特征值问题"""
  111.         free_dofs = self.apply_boundary_conditions()
  112.         # 提取缩减矩阵
  113.         K_red = self.K[free_dofs, :][:, free_dofs]
  114.         M_red = self.M[free_dofs, :][:, free_dofs]
  115.         # 求解广义特征值问题
  116.         evals, evecs = la.eigh(K_red.toarray(), M_red.toarray())
  117.         # 重构全局模态振型
  118.         self.freqs = np.sqrt(np.abs(evals[:num_modes])) / (2 * np.pi)
  119.         self.modes = np.zeros((self.K.shape[0], num_modes))
  120.         self.modes[free_dofs, :] = evecs[:, :num_modes]
  121. # ======================
  122. # 可视化模块
  123. # ======================
  124. class Visualizer:
  125.     @staticmethod
  126.     def plot_mode_shape(struct, mode, freq, ax=None):
  127.         """绘制三维模态振型
  128.         Args:
  129.             mode: 模态振型向量
  130.             freq: 对应频率
  131.             ax: 可选的绘图轴对象
  132.         """
  133.         if ax is None:
  134.             fig = plt.figure()
  135.             ax = fig.add_subplot(111, projection='3d')
  136.         nodes = struct.nodes.copy()
  137.         scale = 0.2 * np.max(nodes[:, :2]) / np.max(np.abs(mode))
  138.         # 将振型位移叠加到坐标
  139.         nodes[:, 2] += mode[::3] * scale  # 取Z方向位移
  140.         # 绘制变形后的网格
  141.         x = nodes[:, 0]
  142.         y = nodes[:, 1]
  143.         z = nodes[:, 2]
  144.         # 绘制单元面
  145.         for elem in struct.elements:
  146.             verts = nodes[elem, :]
  147.             ax.plot_trisurf(verts[:, 0], verts[:, 1], verts[:, 2], alpha=0.6)
  148.         ax.set_title(f'Mode Shape @ {freq:.1f}Hz')
  149.         ax.set_xlabel('X')
  150.         ax.set_ylabel('Y')
  151.         return ax
  152.     @staticmethod
  153.     def compare_frequencies(freq_orig, freq_opt):
  154.         """绘制频率对比柱状图"""
  155.         plt.figure(figsize=(10, 6))
  156.         x = np.arange(len(freq_orig))
  157.         plt.bar(x - 0.2, freq_orig, 0.4, label='Original Design')
  158.         plt.bar(x + 0.2, freq_opt, 0.4, label='Optimized Design')
  159.         plt.xticks(x, [f'Mode {i + 1}' for i in x])
  160.         plt.xlabel('Mode Order')
  161.         plt.ylabel('Frequency (Hz)')
  162.         plt.legend()
  163.         plt.grid(True, alpha=0.3)
  164.         plt.show()
  165. # ======================
  166. # 主程序
  167. # ======================
  168. if __name__ == "__main__":
  169.     # 原始设计建模
  170.     print("正在建立原始设计模型...")
  171.     orig = PlateStructure(Lx=2.0, Ly=1.5, h=0.05)
  172.     orig.generate_mesh()
  173.     # 模态分析
  174.     analyzer_orig = ModalAnalyzer(orig)
  175.     analyzer_orig.assemble_matrices()
  176.     analyzer_orig.solve_modes(num_modes=6)
  177.     print("原始设计前6阶频率:", analyzer_orig.freqs)
  178.     # 优化设计(增加厚度)
  179.     print("\n正在建立优化设计模型...")
  180.     optimized = PlateStructure(Lx=2.0, Ly=1.5, h=0.07)
  181.     optimized.generate_mesh()
  182.     analyzer_opt = ModalAnalyzer(optimized)
  183.     analyzer_opt.assemble_matrices()
  184.     analyzer_opt.solve_modes(num_modes=6)
  185.     print("优化设计前6阶频率:", analyzer_opt.freqs)
  186.     # 结果可视化
  187.     print("\n生成可视化结果...")
  188.     fig = plt.figure(figsize=(15, 10))
  189.     # 原始设计前三阶振型
  190.     for i in range(3):
  191.         ax = fig.add_subplot(2, 3, i + 1, projection='3d')
  192.         Visualizer.plot_mode_shape(orig, analyzer_orig.modes[:, i],
  193.                                    analyzer_orig.freqs[i], ax)
  194.     # 优化设计前三阶振型
  195.     for i in range(3):
  196.         ax = fig.add_subplot(2, 3, i + 4, projection='3d')
  197.         Visualizer.plot_mode_shape(optimized, analyzer_opt.modes[:, i],
  198.                                    analyzer_opt.freqs[i], ax)
  199.     plt.tight_layout()
  200.     # 频率对比
  201.     Visualizer.compare_frequencies(analyzer_orig.freqs, analyzer_opt.freqs)
  202.     plt.show()
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户国营

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表