3. 自由曲面建模方法

好,咱们进入第三章。说实话,这一章是整个课程里最「数学」的部分,但也是最有用的部分。你想想看,不管算法多花哨,最后落到代码里,无非就是三个东西:变量、目标、约束。把这三样搞清楚,优化问题就解决了一半。

我在项目里见过太多人,算法调得飞起,结果建模就错了。变量选多了算不动,选少了曲面变形不到位。目标函数写错了,优化半天出来个废品。嗯,咱们今天就把这事掰扯清楚。

3.1 设计变量:自由曲面的「可调旋钮」

设计变量,说白了就是你能调的那些参数。在自由曲面里,最常见的变量就是控制点坐标。

比如你用 NURBS 曲面,有 m×n 个控制点,每个点有 x、y、z 三个坐标。那设计变量的总数就是 3×m×n。我习惯把这个数记作 n_design。

核心原则:变量越多,曲面越灵活,但优化越难收敛。

举个例子。一个 4×4 的控制点网格,变量数是 3×16 = 48。如果你用 10×10 的网格,变量数就变成 300。优化时间可能从几分钟变成几小时。

所以我的建议是:从少到多。先用粗网格跑通流程,再逐步加密。

控制点网格 变量数 适用场景
3×3 27 概念设计、快速验证
5×5 75 中等精度曲面
10×10 300 高精度光学/气动曲面

小技巧:我习惯把变量归一化到 [0,1] 区间。这样不管曲面多大,算法步长都好调。

3.2 目标函数:你要优化什么?

目标函数就是你要最小化或最大化的那个值。在自由曲面里,常见的目标有:

  • 曲面光顺度:比如曲率变化率最小化
  • 贴合度:曲面到目标点云的距离最小
  • 物理性能:比如气动阻力最小、光学像差最小

我一般把目标函数写成 f(x),其中 x 是设计变量向量。优化就是要找到 x* 使得 f(x*) 最小。

# 一个简单的目标函数示例
def objective(x):
    # x 是控制点坐标向量
    # 计算曲面到目标点云的距离
    surface = build_surface(x)
    distances = compute_distances(surface, target_points)
    return np.mean(distances**2)  # 均方误差

注意:目标函数必须是标量。如果你有多个目标,需要用加权或 Pareto 方法合并。

3.3 约束条件:别让曲面「飞了」

约束条件就是你不能越过的红线。在自由曲面优化里,常见的约束有:

  • 几何约束:控制点不能超出边界、曲面不能自交
  • 制造约束:曲率半径不能小于刀具半径、拔模角不能太小
  • 性能约束:最大应力不超过材料极限

我习惯把约束分成两类:

类型 形式 例子
等式约束 h(x) = 0 曲面必须通过某个固定点
不等式约束 g(x) ≤ 0 曲率半径 ≥ 5mm

我曾经踩过一个坑:约束写得太紧,导致可行域为空,优化器直接报错。后来我学乖了,先跑一次无约束优化,看看自然解在哪,再慢慢加约束。

避坑指南:我曾经把不等式约束的方向写反了,优化了三天才发现。建议每次写完约束,先手动验证一个已知可行点。

3.4 多目标优化:鱼和熊掌怎么兼得?

现实中的问题很少只有一个目标。比如你要曲面既光顺又贴合目标点云,这两个目标往往是冲突的。光顺了就不贴合,贴合了就不光顺。

多目标优化的核心概念是Pareto 前沿。简单说,就是一组解,其中任何一个目标都不能在不损害其他目标的情况下改进。

我常用的方法有两种:

  1. 加权求和法:给每个目标一个权重,合并成单目标。简单,但权重不好调。
  2. NSGA-II:直接求 Pareto 前沿。效果好,但计算量大。
# 加权求和法示例
def multi_objective(x):
    f1 = smoothness(x)   # 光顺度
    f2 = fitness(x)      # 贴合度
    w1, w2 = 0.6, 0.4   # 权重
    return w1 * f1 + w2 * f2

我的经验:如果只有两个目标,用加权法就够了。三个以上目标,建议用 NSGA-II 或 MOEA/D。

3.5 知识体系总览

下面这张图把本章的核心逻辑串起来了。你可以看到,从设计变量出发,经过目标函数和约束条件,最终走向单目标或多目标优化。

优化问题建模知识体系 设计变量 目标函数 约束条件 单目标优化 多目标优化 Pareto 前沿 一组互不支配的最优解

3.6 本章小结

好,咱们捋一下这章的核心:

  • 设计变量:控制点坐标,从少到多逐步增加
  • 目标函数:标量,代表你要优化的性能
  • 约束条件:等式或不等式,限制可行域
  • 多目标优化:Pareto 前沿,加权法或 NSGA-II

我个人觉得,建模这一步花再多时间都值得。模型建好了,后面就是调参的事。模型建歪了,后面全是白干。

最后提醒一句:每次建模前,先问自己三个问题——变量选够了吗?目标写对了吗?约束合理吗?这三个问题答清楚了,再开始写代码。