勘探震源引发平板模态分析
- 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()
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |