ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

数学建模竞赛A题:定日镜场优化设计与光学效率计算详解

数学建模竞赛A题:定日镜场优化设计与光学效率计算详解 简介一份针对2023年高教社杯全国大学生数学建模竞赛A题的定日镜场优化设计模型资料包面向准备数学建模竞赛的高校学生与需要完成类似光热发电优化问题的研究者。内容围绕定日镜场的镜面布局、太阳轨迹模拟、聚光效率与成本效益分析展开配套Matlab代码可辅助完成多目标参数优化与仿真计算帮助读者理解从物理建模到算法实现的全过程。压缩包共23个文件由word文档、xml配置、png图片、rels关联文件及jpg图像组成word文档承载完整建模思路与求解步骤图片展示镜场排布、运行结果等可视化内容xml/rels主要用于保障文档兼容性与结构完整性整体仅844KB下载和打开都非常轻量。已有40人学习该资源适合希望快速获取赛题参考实现并动手复现的建模团队。1. 赛题背景与核心需求拆解1.1 这道题到底在解决什么工程问题2023年高教社杯全国大学生数学建模竞赛A题定日镜场优化设计模型表面上是一道几何计算题骨子里其实是一道典型的工程优化题。塔式太阳能光热电站利用成千上万面定日镜把阳光反射到集热塔顶端的吸热器上通过高温熔盐储存热量再发电。这里面的关键问题非常现实镜场里面的每一面镜子位置怎么摆、镜面尺寸做多大、塔高怎么定直接决定了整个电站的年发电量和单位面积发电成本。很多参赛队伍第一眼看到题目时觉得无从下手原因在于题目给的数据量不小——镜面尺寸、安装高度、镜场形状、塔高、坐标范围再加上光学效率要分成四段来算。但拆开看这个赛题的核心就是在给定约束下通过调整设计变量让某个经济效益指标最大化。它是典型的物理仿真数值优化复合问题跟实际工程项目里做参数寻优的套路完全一致。1.2 题目要点回顾与建模目标分层以我对这届赛题的理解A题一共有三问层层递进第一问是给定一个确定的镜场布局让你算这个镜场的年平均光学效率、年平均输出热功率以及单位镜面面积年平均输出热功率。这一问的核心是建模与仿真把光学效率算准结果必须能复现。第二问是在第一问模型基础上允许调整定日镜尺寸、安装高度、位置同时给定吸收塔位置和高度范围要求你重新设计镜场让单位镜面面积年平均输出热功率尽量大。这一问的核心是优化目标函数明确约束条件相对宽松。第三问更进一步把塔高和吸热器位置也放开作为设计变量并且给了一个具体的镜场面积约束依然要优化单位镜面面积输出功率。这一问的难点在于优化维度变高、计算量明显加大很多队伍在这里被卡住。从建模目标上我习惯把问题拆成三层来看物理层坐标变换、太阳位置计算、光线反射路径效率层余弦效率、大气透射率、阴影遮挡效率、截断效率优化层设计变量、目标函数、约束条件、寻优算法这三层必须层层咬合任何一个环节出错后面的优化结果都会失真。下面我把每一层的关键细节展开说。2. 核心物理模型光学效率的计算链2.1 四条效率链路的物理含义定日镜场的光学效率不是一个大锅烩而是四个独立环节的乘积。这四段效率分别刻画了光从太阳到镜面、光在空气中传播、光绕开邻居、光落进吸热器四个物理过程余弦效率太阳光斜射到镜面上时有效接收面积要打折扣。镜面法线方向与入射光线方向的夹角余弦值直接决定了反射光线的方向和强度损耗。大气透射率光线在镜面到吸热塔之间几公里的大气路径中传播会因吸收和散射损失一部分能量距离越远损失越大。阴影遮挡效率前排镜子会挡住后排镜子的入射光阴影相邻镜子也可能挡住反射光遮挡这一项在密集布局时下降非常明显。截断效率反射光斑落到吸热器窗口之外的那部分能量白白浪费掉了只有落进窗口里的才算有效。有人把四段效率笼统乘在一起不分误差来源一股脑计算这种思路在初赛中偶尔能蒙对但一旦涉及优化就会出问题。正确做法是每一段效率都独立建模、独立计算最后再乘成总光学效率。这样才能在优化迭代中看清到底是哪一段效率拖了后腿。2.2 余弦效率与太阳位置计算余弦效率是四段效率里最基础也最容易出错的一项。它的定义看起来很简单η_cos cos(θ)其中θ是太阳入射光线与镜面法线的夹角。但要算出这个夹角你需要完成三步坐标变换从大地坐标系转到镜面坐标系、从镜面坐标系转到光线坐标系中间还涉及太阳高度角和方位角的实时计算。太阳位置的计算公式在《太阳能利用技术》这类教材里有标准算法核心是计算太阳赤纬角和时角再换算成高度角和方位角。在Matlab里我建议写成独立函数传入日期和时刻返回太阳高度角和方位角function [alt, az] sun_position(day, hour) % day: 年积日 (1-365) % hour: 真太阳时 (小时) decl 23.45 * sind(360 * (284 day) / 365); hour_angle 15 * (hour - 12); alt asind(sind(decl) * sind(30) cosd(decl) * cosd(30) * cosd(hour_angle)); az acosd((sind(decl) - sind(alt) * sind(30)) / (cosd(alt) * cosd(30))); if hour_angle 0 az 360 - az; end end注意这里把维度固定为了30度实际题目给了具体位置不要把纬度写死。我见过有队伍把纬度当变量输进去结果太阳位置全套错后面的余弦效率全废。余弦效率在早晚时刻会掉得非常厉害。太阳高度角低的时候光线几乎贴着地面斜射每面镜子的有效接收面积只有正午的百分之二三十。因此优化时千万不要只看正午效率必须以全年逐时效率的加权平均值来评价。2.3 阴影遮挡与截断效率的处理技巧阴影遮挡效率是这道题里最费时间的部分也是拉开队伍差距的地方。很多参赛队用逐面镜子做光线追踪判断代码写了几百行跑一次要半小时优化根本没法迭代。这里我分享一个非常实用的技巧把阴影遮挡判断化简为平面投影包围盒过滤。具体做法是对所有定日镜建立投影平面把所有镜面投影到垂直于太阳入射方向的平面上然后做二维重叠检测。这样做的好处是把三维空间相交判断降维成二维多边形重叠问题计算量可以减小一个数量级。Matlab里可以用polyshape对象来做交集判断代码非常简洁poly1 polyshape(x1, y1); poly2 polyshape(x2, y2); inter_area area(intersect(poly1, poly2));不过polyshape在大规模镜场上千面镜子下会有点慢。如果追求性能可以先做一步粗略筛选计算两个镜面中心投影的距离如果距离大于两镜面的最大半径之和直接跳过重叠检测。这个粗筛能去掉90%以上的无效判断。截断效率这块我的经验是用光斑高斯分布近似吸热器窗口积分来算。理论上可以做详细光线追踪但题目给的吸热器是圆柱形或平面形光斑在窗口上的分布近似为高斯斑点直接用积分就能算出一个相当可靠的截断因子。这样做既能保证精度又能避免蒙特卡洛光线追踪带来的随机波动优化迭代时稳定性更好。3. 优化变量与约束条件的数学化3.1 设计变量怎么选这类赛题的设计变量看着很多但真正影响优化结果的主变量就几个定日镜的镜面高度和宽度、安装高度镜面中心离地高度、相邻镜面的径向间距和周向间距以及镜场整体布局的半径范围。第三问再加一个吸收塔高度。选变量的核心原则是尽量用连续变量少用离散变量。镜面宽度和高度、安装高度、塔高都是连续变量直接扔给优化器就行。径向间距和周向间距虽然实际设计时会有标准尺寸但在建模阶段可以先视为连续变量来优化得到最优值后再就近圆整到标准规格。这个先松后紧的思路可以避免离散优化带来的组合爆炸。3.2 约束条件的取舍与线性化处理题目里的约束条件大致分三类最小间距约束任意两面定日镜的中心距离不能小于某个阈值防止机械碰撞和互相遮挡过重位置范围约束所有镜面必须落在给定的圆形或方形区域内塔高和吸热器尺寸约束第三问里塔高有上下限吸热器尺寸和安装位置也有范围最小间距约束是非线性的直接写进优化器会让求解变慢。我的做法是先按同心圆径向排布的布局模式来参数化镜场径向间距和周向间距直接决定相邻镜面的位置只要这两个参数本身就满足最小值要求所有镜面之间的间距约束就自动满足了。这种参数化设计的好处是约束天然满足优化器只需要在二维参数空间里搜索效率高很多。3.3 目标函数的选择直接优化还是分层优化第二问和第三问的目标函数都是单位镜面面积年平均输出热功率可以写成f (Σ_t η_total(t) · DNI(t) · A_total) / (A_total · N_hours) (Σ_t η_total(t) · DNI(t)) / N_hours注意单位镜面面积的年平均输出热功率实际上是只跟总光学效率的时间加权平均值以及DNI的时间序列有关的量。镜面总面积A_total在分子分母里被约掉了所以这个目标函数不会直接惩罚镜场面积过大而是惩罚平均效率低下。直接把这个目标函数交给优化器会遇到一个问题整个镜场效率的计算需要遍历全年8760小时或代表日逐时每次目标函数评估都很贵。我的策略是先用代表日法简化挑春分、夏至、秋分、冬至四个典型日每天取6:00到18:00逐时计算加权平均得到年平均效率。这样一次目标函数评估只需要计算约48个时刻比8760小时快了近两个数量级优化迭代十几轮毫无压力。等优化收敛后再用全年逐时数据做一次精确验算。4. Matlab实现从公式到可运行的代码4.1 整体程序架构我给的Matlab代码采用了主脚本函数库的结构主脚本负责参数定义和优化调用函数库负责计算效率和目标函数。目录结构大致是这样的heliostat_opt/ ├── main_optimize.m % 主脚本设置参数、调用优化 ├── compute_efficiency.m % 计算某时刻四段效率和总效率 ├── annual_objective.m % 目标函数返回年平均输出功率 ├── sun_position.m % 太阳位置计算 ├── layout_generate.m % 根据设计变量生成镜场坐标 ├── shadow_check.m % 阴影遮挡计算 └── plot_field.m % 可视化镜场布局这种架构最大的好处是模块之间解耦想改太阳位置算法只动sun_position.m不用担心影响别的模块。很多参赛队把所有代码堆在一个脚本里最后改一个参数要找半天非常浪费时间。4.2 布局生成与坐标变换的向量化布局生成是重中之重。给定径向间距和周向间距我采用径向圈层方式生成镜场坐标镜场由若干个同心圆组成每个圆上均匀分布若干面镜子镜子的径向距离按径向间距递增同圈的镜子按周向间距均匀分布。function [x, y] layout_generate(R_ring, d_radial, d_circ, N_ring) x []; y []; for k 1:N_ring radius k * d_radial; N_mirror floor(2 * pi * radius / d_circ); theta linspace(0, 2*pi, N_mirror1); theta(end) []; x [x, radius * cos(theta)]; y [y, radius * sin(theta)]; end x x(:); y y(:); end这里有个小坑每圈镜子数量不能直接用2πr/d_circ取整否则会出现同一镜子的位置重叠或相邻圈间距不协调。我通常会在生成后跑一遍最小间距检查把所有镜面两两距离求出来确认不小于最小间距阈值。坐标变换方面我强烈建议把所有镜面的法向量、入射光方向、反射光方向统一用三维向量表示不要用角度硬算。向量化写法的好处是Matlab矩阵运算可以直接批量处理上万面镜子速度快很多% 假设镜面中心在 (cx, cy, cz)塔在 (tx, ty, tz) incident sun_vec; % 1x3 单位向量指向太阳 to_tower [tx - cx, ty - cy, tz - cz]; to_tower to_tower ./ vecnorm(to_tower, 2, 2); normal (incident to_tower) ./ vecnorm(incident to_tower, 2, 2); cos_eff abs(sum(incident .* normal, 2));4.3 优化求解器怎么选这道题的目标函数有很强的非线性而且我算过它并不是一个光滑的单峰函数。直接用fmincon容易陷入局部最优尤其是镜场布局这种周期性很强的设计空间。我的方案是全局搜索局部精修两步走第一步用遗传算法ga或粒子群particleswarm在参数范围内做全局搜索。这一步不求精度高只求找到好的区域。种群大小设50到100迭代代数60到100代通常能收敛到一个不错的区域。第二步把全局搜索得到的最优解作为初值交给fmincon做局部精修。因为初值已经在比较好的区域fmincon能快速收敛到高精度解。options_ga optimoptions(ga, PopulationSize, 80, ... MaxGenerations, 80, Display, iter, ... FunctionTolerance, 1e-4); [x_ga, fval_ga] ga(annual_objective, nvars, [], [], ... A, b, lb, ub, nonlcon, options_ga); options_fmin optimoptions(fmincon, Display, iter, ... Algorithm, sqp, MaxFunctionEvaluations, 3000); [x_opt, fval_opt] fmincon(annual_objective, x_ga, ... [], [], A, b, lb, ub, nonlcon, options_fmin);这里有个经验遗传算法的收敛判据不要设得太严格不然最后一个小时全耗在原地踏步。我一般用FunctionTolerance默认值配合MaxGenerations来控制。4.4 并行计算与性能优化镜场规模大时逐时刻计算效率非常耗时。我的做法是先用parfor把不同时刻的效率计算并行化。但如果电脑核心数少parfor反而会因为通信开销变慢。更稳妥的性能优化方法是时间采样预计算预计算所有镜面中心到塔的距离这段距离固定不变不需要在每个时刻重复计算预计算所有镜面两两之间的相对位置阴影遮挡判断时的投影变换可以复用时间采样只取典型日整点时刻不做分钟级采样这些优化加起来整个目标函数的评估时间可以从几秒降到零点几秒。对于优化算法来说这个差距直接决定了能否在比赛时间内跑完足够的迭代。5. 调试中的常见坑与排查实录5.1 余弦效率大于1是怎么回事我见过好几个队伍被这个bug坑了整整一天。余弦效率的定义是cos(θ)取值范围应该在0到1之间。但有人算出来会大于1原因几乎都是向量方向搞反了入射光线方向向量没有反号导致法线方向夹角的余弦算成了钝角的余弦绝对值超过1。或者直接用点乘结果而没归一化两个向量长度不为1点乘结果自然不在[-1,1]区间。排查方法很简单随机挑几面镜子手算一遍余弦效率跟程序输出对比。对不上就检查向量定义的方向特别要注意指向太阳和来自太阳是两种完全不同的方向。5.2 阴影遮挡把内存吃爆了用polyshape做重叠检测上千面镜子逐对判断内存会直接爆炸。我的解法前面提过先做中心距离粗筛。距离大于两镜最大半径之和的直接判断为无阴影遮挡只有距离小于阈值的少数镜对才做精确多边形求交。实测下来粗筛能过滤掉95%的镜对内存占用降了一个数量级。如果再不够快还有一个更暴力的方案把每一面镜子的投影区域离散成像素格点用矩阵逻辑运算做重叠计数。精度稍差但速度极快适合做优化初期的粗筛。5.3 优化结果不稳定、每次跑都不一样遗传算法和粒子群算法都有随机性每次运行结果不同是正常的。但如果在同一代种群规模下结果差异非常大说明目标函数存在大量局部极值或者约束处理有问题。我的建议是先把约束条件放到最松看优化器能不能找到合理区域然后把约束逐步收紧观察到目标函数变化趋势是否平滑。如果目标函数在某个参数附近剧烈跳变多半是代码里某个离散取整操作导致的比如每圈镜子数量取整的边界效应。5.4 赛题结果检验的几条硬标准写完代码、跑完优化最后必须做三道检验数值检验把第一问的布局参数代入计算得到的年平均光学效率和题目参考值对比误差要在合理范围内物理检验检查镜场最大半径内所有镜面是否都在给定区域内检查任意镜面中心间距是否大于最小间距检查塔高和吸热器尺寸是否满足题目范围时间检验用全年8760小时数据重新计算最优布局的年平均输出功率看是否和代表日法的结果一致这三道检验都过了才能保证论文里的数字经得起评委推敲。6. 个人实操体会与扩展建议这道题我前前后后调试了一周最大的体会是定日镜场优化最重要的不是某个单点技术而是物理模型精度与优化计算效率之间的平衡。效率算得太细优化迭代一步要半小时比赛时间根本不够效率算得太粗优化结果跟真实值差太远论文站不住脚。我的折中方案是粗模型做搜索、精模型做验证——优化阶段用代表日采样法验证阶段用全年逐时法。后面如果你们想继续深挖这个方向有几个扩展点值得琢磨一是把DNI的实际气象数据替换进去看镜场布局在不同气候条件下怎么变化二是加入吸热器熔盐流量和热传递模型把光学效率优化升级成热电联产系统优化三是试试用贝叶斯优化替代遗传算法在镜面数量很大时能明显减少目标函数评估次数。最后再分享一个小技巧所有涉及角度和向量的运算尽量在Matlab里写成向量化形式既避免for循环的龟速也减少角标错位带来的低级错误。希望这篇拆解能帮你们少走弯路。本文还有配套的精品资源点击获取
返回列表