结构优化设计-主题004-优化问题的数学表述
主题004:优化问题的数学表述
摘要
本教程系统介绍结构优化问题的数学表述方法,这是将工程优化问题转化为可计算数学模型的关键步骤。内容涵盖优化问题的标准形式、设计变量与约束条件的定义、目标函数的构建方法。详细讲解等式约束与不等式约束的处理技巧,以及约束函数的归一化方法。介绍灵敏度分析的基本概念及其在优化中的重要性。通过Python实现,演示如何将实际工程问题(如桁架重量最小化)转化为标准优化问题,并使用SciPy进行求解。本教程为后续各类结构优化算法的学习奠定数学基础。
关键词
优化问题;数学表述;设计变量;约束条件;目标函数;灵敏度分析;归一化;Python优化

1. 引言
1.1 为什么需要数学表述
工程优化问题往往以自然语言或物理描述的形式出现,例如:
- “设计一个重量最轻的桁架,使其能够承受给定载荷”
- “优化梁的截面尺寸,在满足强度要求的前提下降低成本”
- “确定最佳的结构形状,使应力分布均匀”
要将这些问题转化为计算机可以求解的形式,必须建立严格的数学模型。数学表述是连接工程需求与数值算法的桥梁。
1.2 优化问题的基本要素
任何优化问题都包含三个核心要素:
- 设计变量(Design Variables):可以调整的参数,如尺寸、形状、材料分布等
- 目标函数(Objective Function):需要最小化或最大化的性能指标
- 约束条件(Constraints):必须满足的限制条件,如强度、刚度、稳定性等
1.3 本教程的学习目标
通过本教程的学习,读者将能够:
-
掌握优化问题的标准数学形式:理解min-max问题的表述规范
-
正确选择设计变量:根据问题特点确定合适的优化参数
-
构建合理的目标函数:将工程需求转化为数学表达式
-
处理各类约束条件:掌握等式约束、不等式约束的数学表述
-
实现优化问题的Python建模:使用SciPy等工具求解标准优化问题
2. 优化问题的标准形式
2.1 一般数学表述
结构优化问题的标准数学形式为:
minimizexf(x)subject togj(x)≤0,j=1,2,…,mhk(x)=0,k=1,2,…,lxiL≤xi≤xiU,i=1,2,…,n \begin{aligned} & \underset{\mathbf{x}}{\text{minimize}} && f(\mathbf{x}) \\ & \text{subject to} && g_j(\mathbf{x}) \leq 0, \quad j = 1, 2, \ldots, m \\ & && h_k(\mathbf{x}) = 0, \quad k = 1, 2, \ldots, l \\ & && x_i^L \leq x_i \leq x_i^U, \quad i = 1, 2, \ldots, n \end{aligned} xminimizesubject tof(x)gj(x)≤0,j=1,2,…,mhk(x)=0,k=1,2,…,lxiL≤xi≤xiU,i=1,2,…,n
其中:
- x=[x1,x2,…,xn]T\mathbf{x} = [x_1, x_2, \ldots, x_n]^Tx=[x1,x2,…,xn]T:设计变量向量
- f(x)f(\mathbf{x})f(x):目标函数
- gj(x)g_j(\mathbf{x})gj(x):不等式约束函数
- hk(x)h_k(\mathbf{x})hk(x):等式约束函数
- xiL,xiUx_i^L, x_i^UxiL,xiU:设计变量的上下界
2.2 设计空间与可行域
设计空间(Design Space):由所有设计变量构成的nnn维空间,每个点代表一个设计方案。
可行域(Feasible Region):满足所有约束条件的设计点集合,记为:
F={x∈Rn∣gj(x)≤0,hk(x)=0,xiL≤xi≤xiU} \mathcal{F} = \{\mathbf{x} \in \mathbb{R}^n \mid g_j(\mathbf{x}) \leq 0, h_k(\mathbf{x}) = 0, x_i^L \leq x_i \leq x_i^U\} F={x∈Rn∣gj(x)≤0,hk(x)=0,xiL≤xi≤xiU}
2.3 最优解的分类
局部最优解(Local Optimum):在邻域内目标函数值最小的可行解
全局最优解(Global Optimum):在整个可行域内目标函数值最小的解
凸优化问题:若目标函数和可行域都是凸的,则局部最优即为全局最优。
3. 设计变量的选择
3.1 设计变量的类型
3.1.1 连续变量
可以在给定区间内取任意实数值,如:
- 杆件截面面积 A∈[Amin,Amax]A \in [A_{min}, A_{max}]A∈[Amin,Amax]
- 板件厚度 t∈[tmin,tmax]t \in [t_{min}, t_{max}]t∈[tmin,tmax]
- 节点坐标 (x,y,z)(x, y, z)(x,y,z)
3.1.2 离散变量
只能取特定离散值,如:
- 标准型材规格(工字钢型号)
- 材料类型(钢、铝、复合材料)
- 加强筋数量(整数)
3.1.3 混合变量
同时包含连续和离散变量的优化问题,如拓扑优化中的0-1变量。
3.2 设计变量的尺度问题
无量纲化:当设计变量量纲和量级差异较大时,应进行归一化处理:
x~i=xi−xiLxiU−xiL \tilde{x}_i = \frac{x_i - x_i^L}{x_i^U - x_i^L} x~i=xiU−xiLxi−xiL
归一化后的变量 x~i∈[0,1]\tilde{x}_i \in [0, 1]x~i∈[0,1],有利于优化算法的收敛。
3.3 设计变量的耦合
显式耦合:变量间存在显式关系,如 x1+x2=Cx_1 + x_2 = Cx1+x2=C
隐式耦合:通过约束条件或物理方程间接关联
4. 目标函数的构建
4.1 常见目标函数类型
4.1.1 重量最小化
f(x)=∑e=1neρeVe(x)→min f(\mathbf{x}) = \sum_{e=1}^{n_e} \rho_e V_e(\mathbf{x}) \rightarrow \min f(x)=e=1∑neρeVe(x)→min
其中 ρe\rho_eρe 是材料密度,VeV_eVe 是单元体积。
4.1.2 刚度最大化(柔度最小化)
f(x)=FTU=UTKU→min f(\mathbf{x}) = \mathbf{F}^T \mathbf{U} = \mathbf{U}^T \mathbf{K} \mathbf{U} \rightarrow \min f(x)=FTU=UTKU→min
其中 F\mathbf{F}F 是载荷向量,U\mathbf{U}U 是位移向量,K\mathbf{K}K 是刚度矩阵。
4.1.3 频率优化
最大化基频:
f(x)=−ω1(x)→min f(\mathbf{x}) = -\omega_1(\mathbf{x}) \rightarrow \min f(x)=−ω1(x)→min
或使频率避开特定区间。
4.1.4 多目标优化
当存在多个冲突目标时,采用加权求和或Pareto最优:
f(x)=w1f1(x)+w2f2(x)+⋯+wmfm(x) f(\mathbf{x}) = w_1 f_1(\mathbf{x}) + w_2 f_2(\mathbf{x}) + \cdots + w_m f_m(\mathbf{x}) f(x)=w1f1(x)+w2f2(x)+⋯+wmfm(x)
4.2 目标函数的尺度变换
归一化处理:将不同量纲的目标函数归一化到同一量级:
f~(x)=f(x)−freffref \tilde{f}(\mathbf{x}) = \frac{f(\mathbf{x}) - f_{ref}}{f_{ref}} f~(x)=freff(x)−fref
其中 freff_{ref}fref 是参考值(如初始设计的函数值)。
5. 约束条件的处理
5.1 约束类型
5.1.1 应力约束
g(x)=σmax(x)[σ]−1≤0 g(\mathbf{x}) = \frac{\sigma_{max}(\mathbf{x})}{[\sigma]} - 1 \leq 0 g(x)=[σ]σmax(x)−1≤0
其中 [σ][\sigma][σ] 是许用应力。
5.1.2 位移约束
g(x)=∣ui(x)∣[u]−1≤0 g(\mathbf{x}) = \frac{|u_i(\mathbf{x})|}{[u]} - 1 \leq 0 g(x)=[u]∣ui(x)∣−1≤0
其中 [u][u][u] 是许用位移。
5.1.3 稳定性约束
g(x)=1−Pcr(x)Papplied≤0 g(\mathbf{x}) = 1 - \frac{P_{cr}(\mathbf{x})}{P_{applied}} \leq 0 g(x)=1−PappliedPcr(x)≤0
其中 PcrP_{cr}Pcr 是临界屈曲载荷。
5.1.4 几何约束
制造和装配要求:
g(x)=xmin−xi≤0或xi−xmax≤0 g(\mathbf{x}) = x_{min} - x_i \leq 0 \quad \text{或} \quad x_i - x_{max} \leq 0 g(x)=xmin−xi≤0或xi−xmax≤0
5.2 约束归一化
重要性:不同约束的量纲和量级差异很大,需要归一化处理。
归一化方法:
g~(x)=g(x)gallow−1≤0 \tilde{g}(\mathbf{x}) = \frac{g(\mathbf{x})}{g_{allow}} - 1 \leq 0 g~(x)=gallowg(x)−1≤0
归一化后,所有约束都在同一量级,便于优化算法处理。
5.3 约束的激活与违反
激活约束(Active Constraint):gj(x)=0g_j(\mathbf{x}) = 0gj(x)=0,在最优解处通常存在激活约束
违反约束(Violated Constraint):gj(x)>0g_j(\mathbf{x}) > 0gj(x)>0,不可行解
松弛约束(Inactive Constraint):gj(x)<0g_j(\mathbf{x}) < 0gj(x)<0,不起限制作用
6. 灵敏度分析
6.1 灵敏度的定义
设计灵敏度:目标函数或约束函数对设计变量的导数:
∂f∂xi,∂gj∂xi \frac{\partial f}{\partial x_i}, \quad \frac{\partial g_j}{\partial x_i} ∂xi∂f,∂xi∂gj
6.2 灵敏度的计算方法
6.2.1 有限差分法
∂f∂xi≈f(xi+Δxi)−f(xi)Δxi \frac{\partial f}{\partial x_i} \approx \frac{f(x_i + \Delta x_i) - f(x_i)}{\Delta x_i} ∂xi∂f≈Δxif(xi+Δxi)−f(xi)
优点:实现简单;缺点:计算量大,精度受步长影响。
6.2.2 解析法
利用链式法则直接推导解析表达式,精度高但推导复杂。
6.2.3 伴随法(Adjoint Method)
对于大量设计变量的情况,伴随法效率最高:
∂f∂x=∂f∂u∂u∂x \frac{\partial f}{\partial \mathbf{x}} = \frac{\partial f}{\partial \mathbf{u}} \frac{\partial \mathbf{u}}{\partial \mathbf{x}} ∂x∂f=∂u∂f∂x∂u
6.3 灵敏度在优化中的作用
- 指导搜索方向:梯度信息用于确定优化方向
- 判断约束重要性:灵敏度大的约束对设计影响更大
- 近似分析:用于构建近似模型,减少重分析次数
7. Python实现:桁架重量优化
7.1 问题描述
考虑一个10杆平面桁架结构,优化目标是最小化结构重量,约束条件包括:
- 各杆件应力不超过许用应力
- 节点位移不超过许用位移
- 杆件截面积有上下限
7.2 完整Python代码
# -*- coding: utf-8 -*-
"""
主题004:优化问题的数学表述
案例:10杆桁架重量优化
"""
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from scipy.optimize import minimize
import warnings
warnings.filterwarnings('ignore')
import os
# 创建输出目录
output_dir = r'd:\文档\500仿真领域\工程仿真\结构优化设计\主题004'
os.makedirs(output_dir, exist_ok=True)
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
print("=" * 60)
print("优化问题的数学表述 - 10杆桁架重量优化")
print("=" * 60)
# ==================== 1. 问题参数定义 ====================
print("\n【步骤1】定义优化问题参数...")
# 材料参数
E = 1e7 # 弹性模量,psi
rho = 0.1 # 密度,lb/in³
# 许用应力(拉压相同)
sigma_allow = 25000 # psi
# 许用位移
u_allow = 2.0 # in
# 几何参数
L = 360.0 # in,水平杆件长度
H = 360.0 # in,竖直方向高度
print(f" 弹性模量 E = {E/1e6:.1f} × 10⁶ psi")
print(f" 材料密度 ρ = {rho} lb/in³")
print(f" 许用应力 [σ] = {sigma_allow/1000:.1f} ksi")
print(f" 许用位移 [u] = {u_allow} in")
print(f" 杆件长度 L = {L} in")
# ==================== 2. 定义有限元分析函数 ====================
print("\n【步骤2】定义有限元分析函数...")
def truss_10bar_fea(A):
"""
10杆桁架有限元分析
返回:节点位移、杆件应力
"""
# 节点坐标 (6个节点,2维)
nodes = np.array([
[2*L, H], # 节点1
[L, H], # 节点2
[0, H], # 节点3
[2*L, 0], # 节点4
[L, 0], # 节点5
[0, 0] # 节点6
])
# 杆件连接关系 (10根杆)
elements = np.array([
[0, 1], # 杆1
[1, 2], # 杆2
[2, 5], # 杆3
[5, 4], # 杆4
[4, 3], # 杆5
[3, 0], # 杆6
[1, 4], # 杆7
[2, 4], # 杆8
[1, 5], # 杆9
[0, 4] # 杆10
])
n_nodes = len(nodes)
n_elements = len(elements)
n_dofs = 2 * n_nodes
# 组装整体刚度矩阵
K = np.zeros((n_dofs, n_dofs))
for e in range(n_elements):
node_i, node_j = elements[e]
xi, yi = nodes[node_i]
xj, yj = nodes[node_j]
L_e = np.sqrt((xj - xi)**2 + (yj - yi)**2)
c = (xj - xi) / L_e
s = (yj - yi) / L_e
# 单元刚度矩阵(局部坐标)
k_local = (E * A[e] / L_e) * np.array([[1, -1], [-1, 1]])
# 转换矩阵
T = np.array([[c, s, 0, 0], [0, 0, c, s]])
# 单元刚度矩阵(全局坐标)
k_global = T.T @ k_local @ T
# 自由度映射
dof_i = [2*node_i, 2*node_i+1]
dof_j = [2*node_j, 2*node_j+1]
dof_map = dof_i + dof_j
# 组装
for i in range(4):
for j in range(4):
K[dof_map[i], dof_map[j]] += k_global[i, j]
# 载荷向量
F = np.zeros(n_dofs)
F[2*1+1] = -1e5 # 节点2的y方向载荷
F[2*3+1] = -1e5 # 节点4的y方向载荷
# 边界条件(固定节点5和6)
fixed_dofs = [2*4, 2*4+1, 2*5, 2*5+1] # 节点5和6的所有自由度
free_dofs = [i for i in range(n_dofs) if i not in fixed_dofs]
# 求解位移
K_ff = K[np.ix_(free_dofs, free_dofs)]
F_f = F[free_dofs]
try:
U_f = np.linalg.solve(K_ff, F_f)
except:
return None, None
U = np.zeros(n_dofs)
U[free_dofs] = U_f
# 计算杆件应力
stresses = np.zeros(n_elements)
for e in range(n_elements):
node_i, node_j = elements[e]
xi, yi = nodes[node_i]
xj, yj = nodes[node_j]
L_e = np.sqrt((xj - xi)**2 + (yj - yi)**2)
c = (xj - xi) / L_e
s = (yj - yi) / L_e
# 提取单元位移
u_e = np.array([U[2*node_i], U[2*node_i+1], U[2*node_j], U[2*node_j+1]])
# 应变 = (u_j - u_i) / L
epsilon = np.array([-c, -s, c, s]) @ u_e / L_e
# 应力
stresses[e] = E * epsilon
return U, stresses
# 测试有限元分析
A_test = np.ones(10) * 10.0 # 初始截面积
U_test, stress_test = truss_10bar_fea(A_test)
if U_test is not None:
print(f" ✓ 有限元分析函数测试成功")
print(f" 初始设计最大位移:{np.max(np.abs(U_test)):.4f} in")
print(f" 初始设计最大应力:{np.max(np.abs(stress_test))/1000:.2f} ksi")
else:
print(f" ✗ 有限元分析失败")
# ==================== 3. 定义优化问题 ====================
print("\n【步骤3】定义优化问题...")
# 设计变量:10根杆的截面积
# 约束:应力约束(20个,每根杆拉压各一个)
# 位移约束(4个,节点1和3的x,y方向)
# 设计变量边界
A_min = 0.1 # in²
A_max = 50.0 # in²
bounds = [(A_min, A_max) for _ in range(10)]
print(f" 设计变量数:10(杆件截面积)")
print(f" 截面积范围:[{A_min}, {A_max}] in²")
print(f" 不等式约束数:24(20个应力约束 + 4个位移约束)")
def objective(A):
"""目标函数:结构总重量"""
# 杆件长度
lengths = np.array([
L, L, L, L, L, L, # 杆1-6
np.sqrt(2)*L, np.sqrt(2)*L, # 杆7-8
np.sqrt(2)*L, np.sqrt(2)*L # 杆9-10
])
# 总重量 = 密度 × 截面积 × 长度
weight = rho * np.sum(A * lengths)
return weight
def stress_constraints(A):
"""应力约束:g_i = |σ_i|/[σ] - 1 ≤ 0"""
U, stresses = truss_10bar_fea(A)
if U is None:
return np.ones(20) * 1e10 # 返回大值表示不可行
# 应力约束(拉压各一个)
g_stress = np.abs(stresses) / sigma_allow - 1.0
return g_stress
def displacement_constraints(A):
"""位移约束:g_i = |u_i|/[u] - 1 ≤ 0"""
U, stresses = truss_10bar_fea(A)
if U is None:
return np.ones(4) * 1e10
# 提取节点1和3的位移
u1x, u1y = U[0], U[1] # 节点1
u3x, u3y = U[4], U[5] # 节点3
# 位移约束
g_disp = np.array([
np.abs(u1x) / u_allow - 1.0,
np.abs(u1y) / u_allow - 1.0,
np.abs(u3x) / u_allow - 1.0,
np.abs(u3y) / u_allow - 1.0
])
return g_disp
def all_constraints(A):
"""所有约束函数"""
g_stress = stress_constraints(A)
g_disp = displacement_constraints(A)
return np.concatenate([g_stress, g_disp])
# ==================== 4. 求解优化问题 ====================
print("\n【步骤4】使用SLSQP算法求解优化问题...")
# 初始设计
A0 = np.ones(10) * 10.0
# 约束条件(形式:g(x) ≤ 0)
constraints = {'type': 'ineq', 'fun': lambda A: -all_constraints(A)}
# 优化选项
options = {
'ftol': 1e-6,
'disp': True,
'maxiter': 200
}
print(f" 初始重量:{objective(A0):.2f} lb")
print(f" 开始优化...")
# 求解优化问题
result = minimize(
objective,
A0,
method='SLSQP',
bounds=bounds,
constraints=constraints,
options=options
)
# ==================== 5. 结果分析 ====================
print("\n【步骤5】分析优化结果...")
if result.success:
A_opt = result.x
weight_opt = result.fun
# 分析最优设计
U_opt, stress_opt = truss_10bar_fea(A_opt)
g_opt = all_constraints(A_opt)
print(f"\n ✓ 优化成功!")
print(f"\n 【最优设计】")
print(f" 最优重量:{weight_opt:.2f} lb")
print(f" 重量减轻:{(1 - weight_opt/objective(A0))*100:.1f}%")
print(f"\n 【最优截面积】")
for i in range(10):
print(f" 杆{i+1:2d}: A = {A_opt[i]:8.4f} in²")
print(f"\n 【应力分析】")
for i in range(10):
print(f" 杆{i+1:2d}: σ = {stress_opt[i]/1000:8.2f} ksi " +
f"({'激活' if np.abs(g_opt[i]) < 0.01 else '松弛'})")
print(f"\n 【位移分析】")
print(f" 节点1 x方向: u = {U_opt[0]:8.4f} in")
print(f" 节点1 y方向: u = {U_opt[1]:8.4f} in")
print(f" 节点3 x方向: u = {U_opt[4]:8.4f} in")
print(f" 节点3 y方向: u = {U_opt[5]:8.4f} in")
print(f"\n 【约束违反情况】")
max_violation = np.max(g_opt)
if max_violation <= 0:
print(f" 所有约束满足,最大约束值:{max_violation:.6f}")
else:
print(f" 警告:存在约束违反,最大违反:{max_violation:.6f}")
else:
print(f" ✗ 优化失败:{result.message}")
# ==================== 6. 可视化 ====================
print("\n【步骤6】生成可视化结果...")
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 子图1:截面积对比
ax1 = axes[0, 0]
x_pos = np.arange(1, 11)
width = 0.35
ax1.bar(x_pos - width/2, A0, width, label='Initial', alpha=0.7)
if result.success:
ax1.bar(x_pos + width/2, A_opt, width, label='Optimal', alpha=0.7)
ax1.set_xlabel('Bar Number', fontsize=11)
ax1.set_ylabel('Cross-sectional Area (in²)', fontsize=11)
ax1.set_title('Cross-sectional Area Comparison', fontsize=12, fontweight='bold')
ax1.legend()
ax1.grid(True, alpha=0.3)
# 子图2:应力分布
ax2 = axes[0, 1]
if result.success:
colors = ['red' if np.abs(g_opt[i]) < 0.01 else 'blue' for i in range(10)]
ax2.bar(x_pos, np.abs(stress_opt)/1000, color=colors, alpha=0.7)
ax2.axhline(y=sigma_allow/1000, color='r', linestyle='--', label='Allowable')
ax2.set_xlabel('Bar Number', fontsize=11)
ax2.set_ylabel('Stress (ksi)', fontsize=11)
ax2.set_title('Stress Distribution (Red = Active Constraint)', fontsize=12, fontweight='bold')
ax2.legend()
ax2.grid(True, alpha=0.3)
# 子图3:优化迭代历史
ax3 = axes[1, 0]
if hasattr(result, 'nfev'):
ax3.text(0.1, 0.8, f'Function evaluations: {result.nfev}', fontsize=12, transform=ax3.transAxes)
ax3.text(0.1, 0.7, f'Iterations: {result.nit}', fontsize=12, transform=ax3.transAxes)
ax3.text(0.1, 0.6, f'Initial weight: {objective(A0):.2f} lb', fontsize=12, transform=ax3.transAxes)
if result.success:
ax3.text(0.1, 0.5, f'Optimal weight: {result.fun:.2f} lb', fontsize=12, transform=ax3.transAxes)
ax3.text(0.1, 0.4, f'Weight reduction: {(1 - result.fun/objective(A0))*100:.1f}%', fontsize=12, transform=ax3.transAxes)
ax3.set_xlim(0, 1)
ax3.set_ylim(0, 1)
ax3.axis('off')
ax3.set_title('Optimization Summary', fontsize=12, fontweight='bold')
# 子图4:约束违反情况
ax4 = axes[1, 1]
if result.success:
# 应力约束
g_stress = g_opt[:10]
ax4.barh(x_pos, g_stress, alpha=0.7, label='Stress')
ax4.axvline(x=0, color='r', linestyle='--')
ax4.set_xlabel('Constraint Value', fontsize=11)
ax4.set_ylabel('Bar Number', fontsize=11)
ax4.set_title('Stress Constraint Violation', fontsize=12, fontweight='bold')
ax4.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(f'{output_dir}/truss_optimization_results.png', dpi=150, bbox_inches='tight')
plt.close()
print(f" ✓ 结果图已保存至: {output_dir}/truss_optimization_results.png")
# ==================== 7. 灵敏度分析 ====================
print("\n【步骤7】灵敏度分析...")
def compute_sensitivities(A, h=1e-4):
"""使用有限差分计算灵敏度"""
n = len(A)
# 目标函数灵敏度
df_dA = np.zeros(n)
f0 = objective(A)
for i in range(n):
A_perturbed = A.copy()
A_perturbed[i] += h
df_dA[i] = (objective(A_perturbed) - f0) / h
return df_dA
if result.success:
sensitivities = compute_sensitivities(A_opt)
print(f"\n 目标函数对设计变量的灵敏度:")
print(f" {'杆件':<8} {'灵敏度':<15}")
print(f" {'-'*25}")
for i in range(10):
print(f" {i+1:<8} {sensitivities[i]:<15.4f}")
# 找出最敏感的设计变量
max_sens_idx = np.argmax(np.abs(sensitivities))
print(f"\n 最敏感的设计变量:杆{max_sens_idx+1}")
print(f" 说明:改变该杆的截面积对总重量影响最大")
# ==================== 8. 结果总结 ====================
print("\n" + "=" * 60)
print("10杆桁架重量优化结果总结")
print("=" * 60)
print(f"\n【优化问题表述】")
print(f" 最小化:f(A) = Σ(ρ × A_i × L_i)")
print(f" 约束条件:")
print(f" - 应力约束:|σ_i| ≤ {sigma_allow/1000:.1f} ksi")
print(f" - 位移约束:|u_j| ≤ {u_allow} in")
print(f" - 几何约束:{A_min} ≤ A_i ≤ {A_max} in²")
print(f"\n【求解方法】")
print(f" 算法:SLSQP (Sequential Least Squares Programming)")
print(f" 收敛准则:ftol = 1e-6")
if result.success:
print(f"\n【优化结果】")
print(f" 初始重量:{objective(A0):.2f} lb")
print(f" 最优重量:{weight_opt:.2f} lb")
print(f" 重量减轻:{(1 - weight_opt/objective(A0))*100:.1f}%")
print(f" 迭代次数:{result.nit}")
print(f" 函数评估次数:{result.nfev}")
print("=" * 60)
print("\n✓ 10杆桁架重量优化完成!")
print(f"✓ 所有结果已保存至: {output_dir}")
7.3 代码深度解析
7.3.1 有限元分析函数
truss_10bar_fea函数实现了10杆桁架的有限元分析,包括:
- 节点坐标和单元连接关系定义
- 整体刚度矩阵组装
- 边界条件处理
- 位移和应力计算
def truss_10bar_fea(A):
"""10杆桁架有限元分析"""
# 节点坐标定义
nodes = np.array([...])
# 单元连接关系
elements = np.array([...])
# 组装刚度矩阵并求解
...
return U, stresses
7.3.2 目标函数定义
目标函数计算结构总重量,是设计变量(截面积)的线性函数:
def objective(A):
"""目标函数:结构总重量"""
lengths = np.array([...]) # 各杆长度
weight = rho * np.sum(A * lengths)
return weight
7.3.3 约束函数定义
约束函数采用归一化形式,便于优化算法统一处理:
def stress_constraints(A):
"""应力约束:g_i = |σ_i|/[σ] - 1 ≤ 0"""
U, stresses = truss_10bar_fea(A)
g_stress = np.abs(stresses) / sigma_allow - 1.0
return g_stress
7.3.4 优化求解
使用SciPy的minimize函数,选择SLSQP算法:
result = minimize(
objective, # 目标函数
A0, # 初始值
method='SLSQP', # 优化算法
bounds=bounds, # 变量边界
constraints=constraints, # 约束条件
options=options # 优化选项
)
7.4 运行结果预期
运行代码后,将得到:
-
优化前后对比:
- 初始重量 vs 最优重量
- 各杆截面积的变化
- 重量减轻百分比
-
约束分析:
- 哪些约束被激活(达到边界)
- 应力分布云图
- 位移分布
-
灵敏度信息:
- 各设计变量对目标函数的影响程度
- 指导进一步的设计改进
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)