基于comsol的非均匀热源流热拓扑优化,使用归一化方法以最大换热量以及最小化压降进行双目标函...
基于comsol的非均匀热源流热拓扑优化使用归一化方法以最大换热量以及最小化压降进行双目标函数、以流体体积分数为约束进行液冷散热冷板测拓扑优化设计最近折腾了一阵液冷冷板的拓扑优化本来以为就是套个Comsol模板调调参数的活结果踩了一堆坑尤其是碰到非均匀热源的情况跟之前做的均匀热源完全不是一回事今天就把整个过程唠唠。现在服务器、大功率功率模块的散热传统冷板都是手动开几道槽但手动开槽完全是凭经验热流大的地方流道密一点也全靠猜而且同时兼顾「换热量最大」和「压降最小」两个目标的时候很容易顾此失彼。这次我用Comsol的优化模块加MATLAB联动做了双目标的拓扑优化约束流体体积分数不超过30%还用上了归一化方法把两个量纲完全不一样的目标拉到同一个尺度里避免权重失衡。首先得先搭一个基础的冷板模板我画了100mm100mm10mm的铝制冷板流体域走纯水进出口在侧边网格用的自由四面体网格特意把质量调到0.5以上不然求解容易崩。之前第一次没弄模板改个热源分布就重新画网格花了俩小时才发现网格质量直接掉到0.1了差点砸键盘后来就学乖了先搭好模板存起来每次直接调用就行。先贴一段启动Comsol服务器加载模板的代码省得每次手动开软件% 启动Comsol服务器不开图形界面省内存端口随便选只要不被占用就行 model mphstartserver(serverport, 2035); % 加载提前搭好的冷板模板不用每次从头搭几何网格 mphload(model, cooling_plate_template.mph);这里特意用了服务器模式而不是直接打开Comsol GUI主要是省资源还能批量处理迭代不用每次手动点鼠标。基于comsol的非均匀热源流热拓扑优化使用归一化方法以最大换热量以及最小化压降进行双目标函数、以流体体积分数为约束进行液冷散热冷板测拓扑优化设计接下来是重点的非均匀热源设置这次模拟的是服务器的三个模块CPU、内存、SSD热流密度分别是100W/cm²、50W/cm²、20W/cm²也就是1e6、5e5、2e5 W/m²。这里踩过巨坑一开始误把热源选成了固体域结果Comsol直接报错说「所选域不支持热流边界条件」尬住了半天翻帮助文档才反应过来热流是要加在固体和流体的交界面上的% 选对热源边界别像我一开始选成域了报错到怀疑人生 % 假设boundary 1-5是CPU的热源面boundary6是内存boundary7-8是SSD cpu_heat mphsel(model, boundary, [1:5]); mphset(model, ht.T1.q0, 1000000[W/m^2], selection, cpu_heat); mem_heat mphsel(model, boundary, 6); mphset(model, ht.T1.q0, 500000[W/m^2], selection, mem_heat); ssd_heat mphsel(model, boundary, [7:8]); mphset(model, ht.T1.q0, 200000[W/m^2], selection, ssd_heat);然后就是最头疼的双目标优化问题了。一开始没考虑归一化直接把换热量和压降加起来当目标函数结果优化出来压降小了一半但换热量直接掉了30%完全不符合需求。毕竟换热量的单位是W压降是Pa差了好几个数量级直接相加的话压降的权重会被完全忽略优化器只会优先往压降小的方向跑完全不管换热效果。所以后来翻了资料用上了归一化方法用初始设计的换热量和压降当参考值把两个目标都拉到0到1之间的尺度。再加上MATLAB的gamultiobj多目标优化工具箱和Comsol联动代码大概是这样的% 定义基础目标函数输入是拓扑优化的密度场变量输出两个目标值 function [f1, f2] cooling_obj(x) % 把设计变量密度场导入Comsol模型 mphset(model, topo.density, x); % 一定要同时求解流体流动和热传导分开算的话结果完全不对 mphsolve(model, {spf, ht}); % 计算换热量质量流量*定压比热容*温差要取负因为gamultiobj默认最小化目标 mass_flow mphget(model, spf.U0); % 进口质量流量 cp_water mphget(model, spf.Cp); T_in mphget(model, ht.T, selection, mphsel(model, boundary, inlet)); T_out mphget(model, ht.T, selection, mphsel(model, boundary, outlet)); heat_transfer mass_flow * cp_water * (T_out - T_in); f1 -heat_transfer; % 计算压降进口总压减出口总压直接最小化 P_in mphget(model, spf.p, selection, mphsel(model, boundary, inlet)); P_out mphget(model, spf.p, selection, mphsel(model, boundary, outlet)); pressure_drop P_in - P_out; f2 pressure_drop; end % 先跑一次初始设计得到参考值用来归一化 x_initial mphget(model, topo.density); [f1_init, f2_init] cooling_obj(x_initial); % 归一化后的目标函数把两个目标都拉到0-1之间 function [f1_norm, f2_norm] cooling_obj_norm(x) [f1, f2] cooling_obj(x); f1_norm (-f1) / (-f1_init); f2_norm f2 / f2_init; end % 加流体体积分数约束gamultiobj不好加积分型约束直接用惩罚项搞定 function [f1_norm, f2_norm] cooling_obj_norm_constraint(x) [f1, f2] cooling_obj(x); fluid_vol mphget(model, topo.volume_fraction, fluid); % 如果流体体积超过30%给目标加巨额惩罚强制优化器避开 if fluid_vol 0.3 f1 f1 1e6; f2 f2 1e6; end f1_norm (-f1) / (-f1_init); f2_norm f2 / f2_init; end % 设置优化参数种群大小50迭代30次够了不然太费时间 options optimoptions(gamultiobj, ... PopulationSize, 50, ... MaxGenerations, 30, ... Display, iter); % 运行多目标优化 [x_pareto, fval_pareto] gamultiobj(cooling_obj_norm_constraint, numel(x_initial), [], [], [], [], [], [], [], options);这段代码踩的坑最多一开始没加惩罚项优化出来的流体体积直接超了30%一开始没取负优化器反而往换热量最小的方向跑差点以为优化器坏了还有第一次分开求解流体和热传导结果温度分布完全不对后来才知道这俩是强耦合的流速影响温度温度又反过来影响流体密度。最后跑出来的帕累托前沿有一堆备选方案我选了一个折中方案换热量比初始设计提升了32%压降降低了21%流体体积分数刚好卡在29.8%完全符合约束。看后处理的结构CPU对应的位置流道特别密因为那里热流最大需要更多换热面积内存那边稍稀疏SSD那边就更稀疏完全符合预期比手动开槽的设计合理太多了。最后吐槽几个小细节导出后处理动画的时候Comsol默认会把网格也导出来导致动画文件有好几G后来才知道要在导出设置里关掉「导出网格」拓扑优化默认会加棋盘格过滤得到的结构都是光滑的适合加工不用特意调整还有如果想要更粗犷的结构可以把过滤半径调小一点。这次折腾下来感觉拓扑优化真的不是套个模板就能出结果的活尤其是双目标和非均匀热源的情况一定要先理清楚目标的量纲问题还有边界选择这种小细节错了就全白搭。不过最后出结果的时候还是挺有成就感的毕竟比手动开槽的效率高太多了。有没有大佬用过Comsol拓扑优化做过其他散热设计的欢迎评论区交流啊