在轮毂电机、风机这类低速直驱的应用里,外转子开关磁阻电机出镜的频率越来越高。这电机没有永磁体,成本低、耐高温、结构还特别结实,但性能优化是真让人头疼——效率、转矩脉动、启动转矩这些指标经常是互相打架的。你把定子极弧调大一点,效率上去了,转矩脉动立马给你脸色看;你把气隙缩小,平均转矩倒是上来了,可装配难度和噪声问题又跟着冒头。这种多指标互相牵制的调参过程,用单目标优化算法根本没法收场。
我最近完整跑了一个外转子SRM的尺寸参数优化项目,用的是NSGA-II算法,整个优化循环、性能计算和结果可视化全都在Matlab里完成。这篇就把当时的整体思路、算法落地方式、可视化方案,以及踩过的坑一条一条整理出来。不管你是正在做电机多目标优化,还是想把NSGA-II迁移到自己方向上的研究者,这篇内容都能给你省下不少试错的时间。
1. 项目整体设计与目标函数拆解
1.1 外转子SRM的优化问题为什么天生是多目标
先把这个项目的研究对象说清楚。外转子开关磁阻电机,通俗理解就是把传统电机的定子装到里面、转子套在外面的结构。转子的外侧直接连接负载轮毂或者风机叶轮,省掉了减速机构,转矩密度高,特别适合低速大转矩的直驱场景。
但这种结构在电磁设计上有一个绕不开的矛盾。电机的平均转矩、转矩脉动、效率这三个核心性能指标,对同一组设计参数的响应方向是不一致的。拿转子极弧来说,极弧开得大一些,磁阻效应更充分,平均转矩能提高;可是极弧一旦超过某个临界值,转矩曲线的峰谷差反而拉大,转矩脉动指标迅速恶化,同时定子铜耗增加,效率又掉下去了。这就意味着你根本找不到一个极弧值让三个目标同时达到最优。
这种问题在数学上叫多目标优化。我在项目里用的处理方式不是把三个目标简单加权成一个数,而是保留它们之间的竞争关系,最后输出一组帕累托最优解供决策者挑选。用一句大白话解释,帕累托最优解就是"任何指标的单方面改善都必然导致至少另一个指标恶化"的那类解。车库停车选车位是一个很好的类比——没有一个车位同时满足离电梯最近、出入通道最宽、旁边没有柱子这三个条件,你能做的只是在几个候选车位里选一个自己最能接受的折中。
1.2 目标函数、设计变量与约束条件的数学定义
这个项目把优化对象锁定在电机本体的尺寸参数上,没有涉及控制策略层面的优化。设计变量选择了6个,分别是定子极弧系数、转子极弧系数、气隙长度、绕组匝数、定子轭厚和转子轭厚。前两个变量决定极弧的几何形状,气隙长度直接影响磁路磁阻和转矩输出能力,绕组匝数决定磁动势和铜耗,两个轭厚决定磁路饱和程度和结构强度。
目标函数这边定义了3个,分别是平均转矩最大化、转矩脉动最小化、额定工况效率最大化。因为NSGA-II算法默认处理的是最小化问题,效率最大化就转化为负效率最小化来处理。转矩脉动的计算用的是峰谷差值除以平均转矩的比值,公式表达为:
TorqueRipple = (T_max - T_min) / T_avg效率计算则要考虑铜耗和铁耗两部分。铜耗由电流有效值和绕组电阻计算,铁耗通过改进的Steinmetz公式估算,需要考虑定转子铁芯体积和磁场交变频率的影响。
约束条件的设置是这个项目的关键。极弧系数不能超过一个极距对应的几何占空比,气隙长度有最小工艺值约束,轭厚必须保证磁路易饱和区的磁密不超过1.8T,绕组匝数还必须是整数。这类约束在处理时没有简单粗暴地丢弃不可行解,而是采用罚函数策略把违反约束的程度叠加到目标函数上,保证种群可以沿着不可行域边缘逐步逼近可行域。
2. NSGA-II核心机制与Matlab实现要点
2.1 为什么不用加权和法或单目标遗传算法
很多做电机设计的朋友拿到多目标优化需求,第一反应是把转矩脉动和效率各乘一个权重加起来,当成单目标问题去跑。这种做法不是不行,但是有两个非常现实的困局。
第一个困局是权重系数极难设定。转矩脉动和效率的量纲不同、数值范围不同,物理重要性也不同,你很难事先知道0.7和0.3的权重分配是不是真的对应你内心想要的折中比例。第二个困局更致命——加权和法在帕累托前沿是凹形的时候,根本没有办法找到位于凹区间的解。我在实际项目里用加权遗传算法先试过一轮,种群里从头到尾都在两三个极端解附近打转,中间部位的"甜点区"完全搜索不到。
NSGA-II走的是另一条路。它不预设权重,而是让种群中每个个体按照帕累托支配关系分层排序,层越靠前的个体越优。再加上拥挤度距离机制维持解的分布性,最后能从一次运行中拿到一串覆盖整个前沿面的候选解。这套机制不要求你先想清楚哪个目标更重要,而是把所有可能的折中方案摆在桌面上,让最后决策阶段再去做取舍,对工程设计场景来说实用得多。
2.2 非支配排序、拥挤度距离与精英保留逐一拆解
NSGA-II之所以经典,核心就三个机制。第一个是非支配排序。种群中如果一个解A的所有目标都不劣于解B,并且至少有一个目标严格优于B,那么A支配B。把所有不被任何其他解支配的个体划为第一层前沿,去掉它们之后重复这个操作,得到第二层、第三层,以此类推。这样种群就被分成了多个带优先级的层,选择操作时优先保留层级靠前的个体。
第二个机制是拥挤度距离。同属一个前沿层的解,要保证多样性,不能挤在一小片区域里。拥挤度计算的方法是,对每个目标排序,计算相邻两个解的归一化距离,把三个目标方向的距离累加,距离越大说明这个解周围越空旷,越有保留价值。这个机制就保证了种群会均匀铺开在整个帕累托前沿上,不会出现群落聚集现象。
第三个机制是精英保留策略。每一代算法会把父代和子代合成一个大种群,先做非支配排序,再计算拥挤度,之后按层按距离依次填充下一代种群。因为父代中的优秀个体不会在迭代过程中丢失去往下一代的机会,所以整个优化过程的收敛性保障更强。
这三个机制配合起来,效果是种群既朝着真正的帕累托前沿方向推进,又在前沿面上保持均匀铺开。我在实际运行中观察到,大约迭代到第80代左右,整体前沿面的形态就已经稳定了,之后主要是在细节位置做微调。
2.3 关键参数设置与代码骨架
NSGA-II在Matlab里的实现并不复杂,核心参数有四个:种群规模、最大迭代代数、交叉概率、变异概率。我在这套电机优化问题里的参数组合是种群150个个体、迭代200代、交叉概率0.9、变异概率0.1,多项式变异分布指数取20,模拟二进制交叉分布指数取20。
这些数字不是乱拍的。电机目标函数计算一次大约需要0.3秒,150个个体的种群迭代200代,总评估次数是3万次,算下来优化主循环大约需要两个半小时。如果再增大种群规模,时间成本直线上升,但从结果看边际收益很小。交叉概率取0.9可以让基因片段在个体间充分交换,变异概率取0.1防止算法过早收敛到局部前沿。
Matlab代码骨架大致是这样:
% 初始化种群 pop = initializePopulation(popSize, dim, lb, ub); for gen = 1:maxGen % 计算目标函数 for i = 1:popSize [pop(i).f, pop(i).g] = evaluateSRM(pop(i).x); end % 非支配排序 [pop, frontNumber] = nonDominatedSort(pop); % 计算拥挤度距离 pop = crowdingDistance(pop, frontNumber); % 锦标赛选择 pool = tournamentSelection(pop, frontNumber); % 模拟二进制交叉与多项式变异 offspring = sbx_crossover(pool, pc, etaC); offspring = polynomial_mutation(offspring, pm, etaM, lb, ub); % 精英保留,父代子代合并后筛选 combined = [pop, offspring]; pop = environmentalSelection(combined, popSize); end有两点需要提醒。第一,目标函数评估是整个优化过程最耗时的环节,尽量写成向量化形式,避免在循环里反复计算重复量。第二,随机数种子要在每次实验前设置好,否则算法每次运行结果差异很大,不利于复现和调试。我当时在脚本开头固定使用rng(42),所有后续对比实验都基于同一随机序列。
3. 电机性能评估模型与优化闭环搭建
3.1 模型选型:解析模型、代理模型与有限元的配合
电机性能评估是整个优化闭环的核心支撑,模型的精度和速度直接决定了优化的可行性和结果可信度。这个项目里最终采用的是磁路解析模型为主、有限元校验为辅的组合方式。
直接拿有限元软件嵌入优化循环在理论上可行,但实际跑起来非常痛苦。一次二维电磁场瞬态仿真大概要几分钟,150个个体的种群迭代200代,意味着3万次有限元计算,时间成本完全不可接受。因此优化循环内部必须用毫秒级的快速模型。磁路解析模型把电机主磁路拆分成气隙、定子齿、定子轭、转子齿、转子轭五个磁阻段,通过迭代求解磁路方程得到不同转子位置下的磁链和电感曲线,进而计算转矩曲线和损耗。这套模型在额定工作点附近的误差控制在5%以内,单次评估只要0.3秒,刚好满足优化循环的需求。
解析模型毕竟是简化模型,在高饱和工况下精度会下降。所以项目分两步走:先用解析模型跑完整轮优化,选出帕累托前沿上的10个代表解,再用有限元软件对这10个解做精确校核。实测下来,解析模型选出的解和有限元校核结果的趋势完全一致,效率指标的绝对偏差约3%,转矩脉动偏差约6%,在工程可接受范围内。
3.2 目标评估函数的结构与实现逻辑
核心的目标评估函数evaluateSRM.m承担了从几何参数到三个优化目标的全部换算工作。函数内部按照磁路计算、损耗计算、性能指标提取三个层次组织,结构大致如下:
function [objectives, constraints] = evaluateSRM(x) % x = [alphaS, alphaR, gap, turns, hsy, hry] % 第一步:几何计算 geometry = computeGeometry(x); % 第二步:磁路计算,得到不同转子位置角的磁链 [fluxLinkage, inductance] = magneticCircuit(geometry); % 第三步:电流波形计算 currentWave = computeCurrent(inductance, geometry); % 第四步:转矩与损耗计算 [T_avg, T_max, T_min] = computeTorque(fluxLinkage, currentWave); [copperLoss, ironLoss] = computeLosses(currentWave, fluxLinkage, geometry); % 第五步:目标函数输出 efficiency = ratedPower / (ratedPower + copperLoss + ironLoss); objectives = [-efficiency, (T_max - T_min) / T_avg, -T_avg]; % 约束条件输出 constraints = computeConstraints(geometry); end磁路计算这个环节最需要小心。开关磁阻电机的磁场饱和现象非常显著,如果直接把磁阻当成常数处理,转矩估算会严重失真。我在磁路求解时加入了迭代寻优过程,每一次先假设铁芯磁密,查B-H曲线得到对应磁导率,再计算磁阻,更新磁密,反复迭代直到前后两次磁密误差小于1E-4。这个迭代步骤虽然让单次评估时间多了0.1秒,但换来的精度提升对优化结果的影响是决定性的。
3.3 优化循环耦合与并行加速的实践
NSGA-II算法种群和电机模型之间的耦合方式,本质上是把6个设计变量传给evaluateSRM函数,拿回3个目标值和若干约束值。这个接口设计得非常薄,换任何其他电机模型都可以无缝对接。我试过把评估函数内部替换成有限元仿真软件的命令行调用接口,虽然速度慢到基本没法完整跑完优化,但接口本身完全不需要改动。
时间优化方面有几个立竿见影的操作。第一个是在Matlab里用parfor并行池替代外层for循环,在同一台8核处理器上直接缩短了大约5倍的计算时间。需要注意的是,并行池的随机数管理要用parfor的流式随机数,否则每个worker生成的随机序列可能完全相同,粒子群容易陷入区域聚集。第二个操作是把电感数据提前缓存下来,避免在目标函数内部重复计算同一组参数组合。因为NSGA-II的交叉和变异算子产生的子代有时和父代重复,缓存命中率实测能达到10%左右,也能节省部分时间。第三个操作是在主循环外部预计算B-H曲线插值表,在evaluateSRM内部直接用interp1查表代替每步的插值计算,这一步减少了磁路迭代约40%的耗时。
4. Matlab多维可视化展示思路
4.1 帕累托前沿图与三目标权衡的实际读法
做过优化的人都有体会,算法跑完只是第一步,把结果讲清楚才是真正见功力的时候。这个项目最核心的输出图是帕累托前沿图。三个目标函数分布在三维空间里,直接画成三轴散点图很难读出有效信息。我最终采用的是两两组合加颜色映射的方式。
为了同时表达三个目标的信息,我选横轴为平均转矩、纵轴为效率,第三维转矩脉动用colorbar颜色映射表示。这个布局的逻辑是,平均转矩和效率是决定设计可行性的两个首要指标,转矩脉动作为辅助指标用颜色表达。绘制代码不复杂,核心就是scatter函数:
figure scatter(avgTorque, efficiency, 40, torqueRipple, 'filled') xlabel('平均转矩 (N.m)') ylabel('效率 (%)') cb = colorbar; ylabel(cb, '转矩脉动 (%)')实际图上可以看到一个非常明显的规律:帕累托前沿呈现出L形曲线特征,这说明平均转矩和效率之间也存在着强约束关系,转矩要达到一定水平之后,效率的提升空间急剧收窄。工程设计上这意味着如果用户的硬性指标是平均转矩不低于20N.m,那么效率的设计上限基本就锁定在91%附近,再怎么优化也只是在细节层面做文章。
读帕累托前沿图还有个技巧,就是关注前沿面上的拐点和稀疏区。拐点对应的解往往是综合性能最均衡的方案,稀疏区则说明这段设计区间存在较大的性能跃变,可能是某个几何参数跨过了关键临界值。我在最终方案筛选时就是先从图上圈出拐点附近的解,再综合工艺约束做进一步对比。
4.2 收敛曲线、决策变量分布与几何可视化
除了帕累托前沿图,优化过程的可视化同样重要。收敛曲线展示的是每一代最优前沿的进展,横轴是迭代代数,纵轴可以是最优个体对应的效率,或者前沿面的超体积指标。从曲线形态上可以直观判断算法是否已经收敛。我在项目里同时绘制了平均转矩的箱线图分布和效率的箱线图分布,用来观察种群在各个目标维度上的分布是否逐渐收窄集中,这比只看一条前端曲线可靠得多。
决策变量的分布情况用平行坐标图来表达效果很好。六维设计变量并排排列成六个纵轴,每个帕累托解在轴上连成一条折线。Matlab的parallelcoords函数可以直接实现。这张图最大的价值是可以直观看出不同帕累托解在设计变量上的离散范围。比如从平行坐标图上能一眼看到所有前端解的绕组匝数都集中在28到36匝之间,而气隙长度的跨度则特别大。这提示绕组匝数这个参数已经收敛到了可行区间的瓶颈位置,想要继续突破性能,得从其他变量上想办法。
电机几何形状的可视化也别忽略。用patch函数把外转子SRM的截面画出来,每个优化方案对应一张电机截面图,把关键尺寸标注在旁边。这比单纯看数据直观得多,汇报时放几张截面图对比,听众一下子就能理解不同方案在几何层面的差异。比如转子轭厚从15mm增加到20mm的方案,截面图上电机外形明显变厚重,对应的转矩脉动水平也显著改善。
4.3 出图规范与矢量导出
结果图再好看,导出格式不对也是白搭。我之前交过一篇使用png格式截图的报告,放到论文里一放大锯齿非常明显,被审稿人点名批评过。后来统一改用exportgraphics函数输出矢量格式,这个做法建议保留。Matlab里使用tiledlayout和exportgraphics的组合,一次可以把多张子图汇总成一张矢量图输出,嵌入式字体也问题不大:
f = figure('Position', [100 100 1200 900]); t = tiledlayout(2, 2, 'TileSpacing', 'compact', 'Padding', 'compact'); % 依次绘制各张子图 nexttile; % ... 绘图代码 % 导出矢量图 exportgraphics(f, 'pareto_results.eps', 'ContentType', 'vector');需要注意新版Matlab导出eps有时遇到文本转曲问题,可以在导出前检查一下图窗字体设置。另一个常被忽略的点是线条和标记的尺寸设置,做汇报投屏时用小字号小标记,远看几乎看不清。我在最终出图前会统一把字号调到14磅以上,标记大小调到40以上,这样能保证PPT投影和大屏展示时的可读性。
5. 常见问题排查与经验速查
5.1 算法收敛与分布性相关的坑
这个项目运行过程中遇到的第一类问题来自算法本身。第一个典型的坑是种群早期全部集中到极端解区域,帕累托前沿图的分布性极差。排查后发现原因是初始种群生成时没有使用拉丁超立方采样,导致大量个体集中在设计空间的一角。改用lhsdesign函数生成初始种群后,问题立刻缓解。
第二个坑是迭代后期出现了前沿面退化现象。也就是后代个体在精英保留机制下不断填充某些区域,前沿面的某些段逐渐失去了代表个体。原因在于拥挤度距离计算没有考虑各目标的量纲差异。转矩脉动数值普遍在30%到60%之间,而效率数值集中在88%到93%,两个维度的拥挤度距离直接被效率维度主导,转矩脉动维度的分布约束失效了。解决方法是先把三个目标归一化到0到1区间,再做拥挤度距离计算。
第三个值得注意的现象是算法在200代之后基本停滞,但停滞不等于收敛到全局最优。NSGA-II在连续变量优化中表现不错,但对于绕组匝数这类整数变量,标准交叉变异算子的搜索效率很低。项目里对整数变量采用随机取整加邻域搜索组合的方式,在交叉变异后对匝数变量做5%概率的邻域扰动,实测找到的帕累托前沿提升了一截。
5.2 建模与仿真现场的坑
电机解析模型在低转矩工况点的估算偏差比额定工况点大。主要原因是低电流下铁耗计算模型中的磁滞损耗系数不够准确。项目后期的校核环节发现,解析模型对转矩脉动指标的估算偏差在轻载时达到10%以上。这个问题的处理方式是:优化过程只针对额定工况进行,轻载特性在方案选定后单独用有限元验证,避免在模型不可靠的区域做决策。
建模仿真中还有个容易翻车的细节是几何参数没有做归一化。设计变量中气隙长度只有0.4到0.8mm,而轭厚在10到25mm区间,两个变量在遗传算法的交叉变异算子中数值量级差了两个数量级。算术交叉算子是按数值比例进行组合的,大数量级变量会主导遗传操作,小数量级变量几乎得不到有效变异。解决方法是所有变量在进入算法前统一归一化到0到1区间,遗传操作完成后反归一化再送入电机模型。
5.3 Matlab工具链相关的问题排查
Matlab环境在实际使用中的报错问题,也要单列一节好好捋一捋。运行过程中最烦人的一个问题出现在并行计算环节,parfor启动时偶尔报错,提示worker无法正常初始化。排查后发现是防病毒软件占用了一些临时文件句柄导致的偶发冲突,把防病毒扫描排除Matlab临时目录之后问题消失。
导出图片时也遇到过报错,版本在R2024a之后对print命令的某些参数处理方式有调整,如果导出eps文件用print命令,加-nosvg补丁参数可以解决。
还有一个容易忽略的问题:Matlab许可证偶发报错。我遇到过几次license error 8的错误,通常发生在换网络环境或者长时间休眠唤醒后。常规的解决方法是重启Matlab并重新激活许可证,如果还是不行,检查系统时间和许可证文件是否正常。注意不要在公网环境跟人分享你的激活码,合法授权渠道稳定得多。
5.4 优化结果可信度验证清单
优化算法跑完,不能直接拿去投入工程使用,必须经过可信度验证。我给自己定了一份验证清单,每一步都不省。
先看有限元校核。从帕累托前沿上均匀选取8到10个代表解,分别做二维瞬态有限元仿真,对比解析模型预测值与有限元计算值。效率偏差在3个百分点以内、转矩脉动偏差在8个百分点以内才算通过。
再看敏感度分析。对选定的方案做局部参数扰动,每个变量正负扰动5%,观察目标函数变化幅度。如果某个变量的扰动导致转矩脉动变化超过10个百分点,说明这个方案对该参数过于敏感,工艺公差可能无法保证性能稳定性,这种方案要果断降级。
最后是电机温升和结构强度校核。优化过程中没有直接包含热管理和结构应力约束,但最终方案需要带回热仿真和有限元结构分析中复验。我在项目里就有一次优化结果在电磁性能上非常漂亮,结果热载荷分析显示绕组温升超过绝缘等级上限,只能忍痛放弃,重新在约束条件中加入温升指标后再跑一轮。
最后的几句实在话
这个项目做完,我自己的体会是:多目标优化不是要给你一个标准答案,而是要帮你把设计空间里值得考虑的妥协方案全部梳理出来。NSGA-II加上Matlab这套组合,最大的优势是迭代速度快、可视化和调试顺手,特别适合电机设计这类靠直觉和经验反复打磨参数的领域。很多人刚接触这类问题总觉得必须找到那个"最优解",实际上工程里更常见的是在帕累托前沿上根据具体工况挑选最合身方案的过程。
后续我在这个方向上还打算做两件事。一是把有限元仿真结果作为反馈,在线更新代理模型,让解析模型在高饱和工况下也能保持精度。二是把优化和可视化封装成一个带界面的小工具,让我自己调参和团队内部评审时能省不少沟通成本。你在复用这套思路的时候,参数、模型、目标函数肯定都要按你自己的问题重写,但整体的框架和那些坑,应该都是通用的。