4. 蒙特卡洛模拟:随机数生成与正态分布、模拟次数与置信度、蒙特卡洛模拟流程
蒙特卡洛模拟,说白了就是“用大量随机抽样来逼近真实结果”。
我在做光学系统公差分析时,最怕的就是“拍脑袋”定公差。你想想看,一个镜头几十个镜片,每个镜片有曲率、厚度、偏心、倾斜……如果每个参数都按最坏情况叠加,那公差预算根本没法做。蒙特卡洛模拟就是用来解决这个问题的——它告诉你:在真实生产条件下,你的系统到底能有多大概率满足指标。
4.1 随机数生成与正态分布
蒙特卡洛模拟的第一步,是生成符合实际生产分布的随机数。
我见过不少新手直接拿均匀分布来模拟公差,结果算出来的良率虚高。为什么?因为实际生产中,大多数工艺参数服从的是正态分布(也叫高斯分布)。
核心概念:
- 均匀分布:每个值出现的概率相等。适合模拟“未知分布”或“最坏情况”的边界检查。
- 正态分布:中间值概率高,两端概率低。适合模拟实际加工误差。
在光学设计软件(如Zemax、Code V)中,通常内置了正态分布随机数生成器。但如果你自己写脚本,比如用Python,可以这样生成:
import numpy as np
# 生成10000个符合正态分布的随机数
# 均值=0,标准差=1(标准正态分布)
samples = np.random.normal(loc=0, scale=1, size=10000)
# 实际应用中,你需要根据公差范围映射
# 比如:厚度公差 ±0.05mm,3σ对应这个范围
thickness_tolerance = 0.05 # 半宽
sigma = thickness_tolerance / 3 # 假设3σ覆盖99.7%
actual_thickness = nominal + np.random.normal(0, sigma, size=N)
我的经验:
我个人习惯用3σ原则来设定标准差。也就是说,如果图纸上标了±0.05mm的公差,我默认这个范围对应3σ(覆盖99.7%的样本)。这样模拟出来的结果更贴近实际产线数据。
这里有个坑:截断正态分布。实际加工中,超出公差范围的产品会被筛选掉。所以如果你直接生成正态分布,可能会得到一些“超差”的样本。我一般会加一个判断:
# 截断:超出公差范围的重新生成
while True:
delta = np.random.normal(0, sigma)
if abs(delta) <= thickness_tolerance:
break
嗯,这样更符合实际。
4.2 模拟次数与置信度
蒙特卡洛模拟里有个灵魂问题:到底要跑多少次?
你跑100次和跑10000次,结果可能差很多。但跑太多又浪费时间。我记得有一次帮客户做投影镜头公差分析,他要求良率精度到±0.5%。我一开始跑了500次,结果置信区间太宽,根本没法用。后来加到5000次,才稳定下来。
这里有个经验公式:
模拟次数 N 与置信度的关系:
对于二项分布(良率/不良率),置信区间半宽 ≈ 1.96 × √(p(1-p)/N)
其中 p 是估计的良率,1.96 对应 95% 置信度。
举个例子:
- 假设你预估良率 p = 90%
- 想要置信区间半宽 ≤ 1%
- 那么 N ≥ (1.96² × 0.9 × 0.1) / 0.01² ≈ 3457 次
所以,3000-5000次是光学系统公差分析中比较常见的模拟次数。如果系统特别复杂(比如几十个镜片),我可能会跑到10000次。
注意:
模拟次数不是越多越好。当N超过一定值后,精度提升非常缓慢,但计算时间线性增长。我个人建议:先跑500次看看趋势,再根据置信度需求调整到3000-5000次。
4.3 蒙特卡洛模拟流程
好了,我们把整个流程串起来。我在实际项目中,通常按下面这五步走:
- 定义输入参数及其分布
- 列出所有公差项:曲率、厚度、偏心、倾斜、折射率、阿贝数等
- 为每个参数指定分布类型(正态/均匀)和标准差
- 生成随机样本
- 根据分布类型生成N组随机数
- 每组代表一个“虚拟镜头”
- 执行光学仿真
- 对每组参数,计算系统性能指标(MTF、波前差、畸变等)
- 记录每个样本是否满足指标
- 统计分析
- 计算良率:满足指标的样本数 / 总样本数
- 计算性能分布的均值、标准差、P95/P5等
- 灵敏度分析与优化
- 找出对性能影响最大的公差项(“罪魁祸首”)
- 收紧关键公差,放宽非关键公差
下面这张图是我自己总结的蒙特卡洛模拟流程,你可以对照着看:
流程看起来简单,但实际执行时有很多细节。我举一个真实案例:
案例:手机镜头模组公差分析
我曾经做过一个6P(6片塑料镜片)的手机镜头。初始设计时,MTF在中心视场能到0.6。但按常规公差跑蒙特卡洛,良率只有40%。
我通过灵敏度分析发现:第3片镜片的偏心公差是罪魁祸首。于是我把这个偏心公差从±0.03mm收紧到±0.015mm,同时把其他几个不敏感的公差放宽了20%。
调整后,良率从40%提升到了85%。这就是蒙特卡洛模拟的价值——用数据说话,而不是凭感觉。
避坑指南:
我曾经犯过一个错误:在生成随机数时,没有设置随机种子(random seed)。结果每次跑出来的结果都不一样,导致我花了半天时间在“找规律”,其实只是随机波动。后来我养成了习惯:每次模拟前固定随机种子,这样结果可复现,方便调试。
最后说一句:蒙特卡洛模拟不是万能的。它假设所有公差项是独立的,但实际生产中,有些参数是相关的(比如曲率和厚度可能同时受温度影响)。如果你遇到这种情况,可以考虑用拉丁超立方抽样或相关随机数生成来改进。不过那是进阶内容了,今天先聊到这里。
公众号:蓝海资料掘金营,微信deep3321