ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

美赛问题E建模指南:被动式太阳能遮阳的仿真与多目标优化

美赛问题E建模指南:被动式太阳能遮阳的仿真与多目标优化

每年美赛出题方向都不太一样,但问题E这类偏环境与可持续发展的题一直很稳——重点不在你用了多高级的算法,而在于能不能把一个现实问题抽象成一套逻辑自洽的模型,并且用数据和代码让模型真正跑起来。2026年问题E落到“被动式太阳能遮阳”上,说实话,这个选题比很多纯算法题好处理,因为它有明确的物理背景和可计算的量化指标,但同时它也特别容易让人一开始就陷进建筑物理的细节里出不来。这篇内容是我带队伍备赛问题E时整理的完整思路,覆盖从题目拆解、太阳位置计算、遮阳系数建模、蒙特卡洛模拟到多目标优化和论文写作的完整链路,代码部分也直接给了可复用的Python实现。不管你是第一次参加美赛的建模小白,还是已经拿过奖想冲更高名次的老手,按这条线往下走基本不会空。

1. 题目真正在问什么:被动式遮阳背后的三个隐性问题

很多人拿到问题E的第一反应是查“被动式太阳能遮阳”的定义,然后开始找各种建筑节能规范。方向没错,但如果只是停留在“挑一个遮阳装置算遮阳系数”的层面,论文基本只能拿到完成分。拆题的时候一定要看到赛题背后真正想让你回答的三种问题:物理机理、不确定性、决策权衡。

1.1 被动式遮阳的物理本质:先挡掉不该进来的太阳辐射

所谓“被动式”,是相对于主动式遮阳(比如依赖电机、传感器控制的智能百叶)而言的。被动式遮阳依靠固定的建筑构件来完成遮挡,比如屋檐、遮阳板、竖向鳍片、格栅、固定百叶,甚至树木和相邻建筑。它不消耗额外能源,但一旦安装就很难根据天气和季节动态调整。

这一点决定了建模的第一层目标:在给定地理位置、朝向和建筑形态的条件下,计算不同遮阳构件对透过窗户的太阳辐射量的削减效果。太阳辐射不是恒定的,一天内太阳高度角和方位角都在变,一年内太阳赤纬角也在南北回归线之间来回摆动。所以遮阳不是“挡”这么简单,而是要在夏季尽量挡、在冬季尽量放,在早晨和傍晚兼顾采光。这句话本质上就是在说:你的模型必须包含足够的时间分辨率,至少要能按小时步长跑一整年。

1.2 题目不会明说的三个隐藏问题

赛题一般不会直接告诉你“请建立太阳辐射模型”,它会用场景化语言描述一个村镇、一栋建筑或一种工况。但透过描述,你至少能挖出这三个隐藏问题:

第一,动态热平衡问题。遮阳板不是越宽越好。挡住了夏季得热,也可能同时挡掉了冬季的免费采暖,还有可能让室内照度骤降、增加人工照明能耗。所以你需要一个包含透光、传热、室内得热和照明需求的逐时热平衡模型,而不是只算一个静态的“遮阳系数”。

第二,不确定性传播问题。真实的太阳辐射受云量影响极大,不同年份的天气数据也不一样,用户开关窗帘、调节空调的习惯也会改变总能耗。赛题如果给的是平均气候数据,你就得考虑用蒙特卡洛方法把随机性显式地加进去,否则评委很容易用“数据波动大”这一点质疑你的结论。

第三,多目标决策问题。一个遮阳方案好不好,不能只看能耗。遮阳构件有建造成本,有维护难度,还可能影响建筑外观和室内视觉舒适度。赛题往往要求你在能源、经济、舒适之间做权衡,这就把题目从物理计算推到了数学优化。

想清楚这三层目标后,后面的模型选型才有方向。我见过不少队伍一上来就写神经网络,其实是误把题目的“分析”当成了“预测”,反而丢了物理内核。

2. 太阳位置计算:整个模型的第一块地基

不管你后面用解析模型还是模拟仿真,太阳几何都是绕不开的地基。太阳的高度角、方位角决定了直射阳光能照到哪个窗面、能穿过多深的房间,也决定了遮阳板该突出多少。

2.1 核心公式:赤纬角、时角、高度角与方位角

对北半球某纬度φ来说,一年中第N天(N从1到365)的太阳赤纬角δ可以近似为:

δ = 23.45 * sin(360 * (284 + N) / 365) # 单位:度

这个公式是经典Cooper近似,精度对建模竞赛足够。用弧度制还是角度制自己是容易出bug的地方,建议全代码统一转成弧度。

时角H由地方太阳时决定:

H = 15 * (local_solar_time - 12) # 单位:度

注意这里用的是地方太阳时,不是北京时间、也不是手表上的标准时间。它跟经度、时区中心经线、均时差都有关系。很多队伍在这里翻车:直接用北京时间算,算出来的太阳方位偏了好几度,导致遮阳板长度明显失真。备赛时建议写一个小函数处理时区经度修正:

longitude_correction = 4 * (standard_meridian - longitude) # 单位:分钟 solar_time = standard_time + longitude_correction + equation_of_time

有了δ和H,太阳高度角α和太阳方位角γ就可以用球面三角公式算:

sin(α) = sin(φ)*sin(δ) + cos(φ)*cos(δ)*cos(H) cos(γ) = (sin(δ) - sin(α)*sin(φ)) / (cos(α)*cos(φ))

高度角就是太阳离地平线的角度,方位角用来判断阳光相对建筑朝向的偏转方向。如果建筑朝向不是正南而是偏东或偏西,还需要把法线方向换算成相对太阳的入射角,这个角度才是窗户真正接受到的直射辐射量。

光有直射还不够,实际到达窗户的太阳辐射里还有一部分是散射辐射。太阳被云层或被大气散射后,即使没有直射阳光,天空光仍然会通过窗户进到室内。所以在逐时热平衡里,通常把总水平辐射拆成直射和散射两个分量,再分别投影到窗户法线方向上。

2.2 Python实现与常见的三个易错点

下面这段代码是我反复用过的基础函数,可以直接抄到建模脚本里:

import math def solar_position(lat, lon, year_day, solar_time_std, standard_meridian=120): """ 计算太阳高度角和方位角 lat: 纬度(度) lon: 经度(度) year_day: 年积日(1-365) solar_time_std: 标准时间(小时, 可带小数) standard_meridian: 时区中心经度(度) """ # 均时差近似 B = 2 * math.pi * (year_day - 81) / 364 eot = 9.87 * math.sin(2*B) - 7.53 * math.cos(B) - 1.5 * math.sin(B) # 分钟 # 地方太阳时 solar_time = solar_time_std + (standard_meridian - lon) * 4 / 60 + eot / 60 hour_angle = 15 * (solar_time - 12) # 赤纬角 declination = 23.45 * math.sin(math.radians(360 * (284 + year_day) / 365)) lat_r = math.radians(lat) dec_r = math.radians(declination) ha_r = math.radians(hour_angle) sin_alt = math.sin(lat_r)*math.sin(dec_r) + math.cos(lat_r)*math.cos(dec_r)*math.cos(ha_r) alt = math.degrees(math.asin(sin_alt)) cos_az = (math.sin(dec_r) - math.sin(lat_r)*sin_alt) / (math.cos(lat_r)*math.cos(math.asin(sin_alt))) az = math.degrees(math.acos(max(-1, min(1, cos_az)))) if solar_time < 12: az = az - 180 return alt, az

实际跑起来之后,我会额外盯三个点:

一是负高度角处理。日出前和日落后,sin_alt是负值,这时候太阳还没升起来,直射辐射应该置零,不能把负高度角直接代入辐射公式算出一个负值得热。该裁剪的地方一定要裁剪。

二是方位角象限修正。上面用acos算出的方位角在上午和下午的符号需要单独处理,否则中午到下午的过渡段会出现方位角跳变。这个点最容易排查的办法是画一张整天的太阳轨迹图,看曲线是否连续。

三是经纬度和时区中心经线保持一致。如果赛题给出的是某地的标准经度数据,要确认它用的是哪个时区基准。之前有队伍把东八区的中心经度直接套到西半球某地,结果整个朝向反了180度,能耗结论全反,最后只能重跑。

3. 遮阳系数与建筑热平衡:把物理名词翻译成可计算的数学量

太阳位置算对之后,下一步就是把“遮阳”这个动作量化。很多参赛队把这一步想得太简单,以为查一个玻璃遮阳系数表格就完事。实际上,被动式遮阳的建模核心在于:不同太阳高度角、方位角下,遮阳构件对窗户的有效遮挡比例是动态变化的。

3.1 SC、SHGC与有效遮阳系数的区别

玻璃本身的遮阳性能常用太阳得热系数SHGC表示,它描述的是透过玻璃进入室内的太阳辐射占室外总辐射的比例,范围通常在0到1之间。SC是同等条件下的相对值,通常以3mm透明玻璃为基准折算。这两个参数是玻璃自身的属性,跟遮阳板无关。

但赛题里的“遮阳系数”一旦进入被动式构件的语境,指的就是遮阳构件和玻璃的综合效果。同一个南向窗户,底部水平遮阳板在夏季中午几乎能把直射光全部挡住,但在冬季中午太阳高度角本来就低,遮阳板反而可能把宝贵的采暖阳光挡在室外。这个“动态综合系数”不能只查表,必须由几何关系推出来。

简便做法是把室外遮阳构件简化为二维投影问题:从窗户中心看出去,遮阳板在太阳方向上的投影角度决定了它遮住的那部分天空/辐射区域。实际计算中可以先求太阳相对于窗面的入射角θ,再计算遮阳板外伸长度相对于窗高的遮挡比例。更严谨的队伍会用光线追踪的思路,把窗面离散成网格,逐网格判断直射光是否被构件遮挡,最后统计被照亮面积占比作为有效透过率。

3.2 逐时热平衡模型:一个能跑通全文的Skeleton

有了动态遮阳系数,就可以搭建整栋建筑或单个房间的逐时热平衡模型。核心方程可以写成:

Q_total(t) = Q_solar(t) + Q_cond(t) + Q_vent(t) + Q_internal(t) - Q_hvac(t)

其中:

  • Q_solar(t)是经过遮阳后的太阳得热;
  • Q_cond(t)是墙体和窗户的传热,跟室内外温差成正比;
  • Q_vent(t)是通风换气带来的热量;
  • Q_internal(t)是人员、设备、照明的内部产热;
  • Q_hvac(t)是暖通系统需要移除或补充的热量,这是我们最终关心的响应变量。

在被动式遮阳题目里,Q_hvac的正负和大小就是衡量遮阳效果的关键指标。为了让模型不至于复杂到没法调参,我会建议用一阶热容模型(集总参数模型),把房间等效成单一热容加等效热阻:

Q_hvac = U_wall * A_wall * (T_out - T_in) + U_win * A_win * (T_out - T_in) + SHGC_eff * A_win * I_solar

T_in可以设置成恒温区间(比如22到26摄氏度),低于下限开启采暖,高于上限开启制冷。这样代码结构非常简单,但物理逻辑仍然是完整的。如果赛题明确要求考虑温度波动,再把T_in作为状态变量,加入一阶常微分方程做数值积分。

表1是我用过的变量清单,建议写论文时直接照这个组织符号表:

符号含义单位
φ纬度度
δ太阳赤纬角度
α太阳高度角度
SHGC_eff综合有效太阳得热系数无量纲
I_solar窗面太阳总辐射强度W/m²
U_wall墙体传热系数W/(m²·K)
Q_hvac暖通负荷W

这一步做完,你手里就有一套能逐时输出全年8760小时能耗的仿真器。这个仿真器是后面蒙特卡洛和优化共用的公分母,值得花时间写稳。

4. 蒙特卡洛模拟:不要只在单一气候场景下拍板

模型能跑8760小时不等于结论可靠,因为任何一年的天气数据都只是一次随机实现。赛题如果能找到多年的气象观测,或者提供的是典型气象年数据,我会强烈建议做蒙特卡洛模拟,把所有结论从“一个案例”升级成“一个分布”。

4.1 为什么非要用随机模拟

典型气象年(TMY)数据是把多年的天气数据“平滑”后选出来的代表性月份拼接而成,它代表的是平均水平,不是真实某一年。真实年份里可能出现连续高温热浪,也可能出现多雨阴天。如果只用TMY数据优化遮阳板尺寸,得到的最优解只能在“平均年”最优,在极端天气下可能非常差。

蒙特卡洛的思路很简单:把关键不确定因素当作随机变量,重复跑足够多次仿真,观察结果的统计特征。需要随机化处理的主要有三类:

  • 水平太阳辐射与云量的随机扰动,可以按天气类型分组抽样;
  • 室内人员作息和照明用能的随机性,比如上下班时间、是否拉窗帘;
  • 空调设定温度的随机波动,体感偏热的人会把温度调低半度。

4.2 随机抽样与仿真的代码骨架

我习惯先用天气数据本身的波动幅度构造正态分布扰动,再做情景分层抽样。下面这段代码演示了最核心的循环结构:

import numpy as np def run_simulation(solar_data, shading_length, T_set_min=22, T_set_max=26, n_samples=500): results = [] for _ in range(n_samples): # 对逐时太阳辐射施加随机扰动,波动幅度由数据统计量决定 noise = np.random.normal(1.0, 0.15, size=len(solar_data)) hourly_radiation = solar_data * np.clip(noise, 0.3, 1.8) total_hvac = 0.0 for t in range(len(hourly_radiation)): eff_shgc = compute_effective_shgc(t, shading_length) heat_gain = eff_shgc * window_area * hourly_radiation[t] # 简化的恒温区间控制 if T_interior < T_set_min: total_hvac += heating_need(heat_gain, T_out[t]) elif T_interior > T_set_max: total_hvac += cooling_need(heat_gain, T_out[t]) results.append(total_hvac) return np.percentile(results, [5, 50, 95])

代码里隐藏了一个重要细节:扰动系数要加上下限裁剪。如果你放任随机噪声无限增大,模拟结果会包含大量在现实中不可能出现的极端辐射水平,导致5%分位数异常偏离。我通常会把扰动系数限制在0.3到1.8倍之间,这个范围基本能覆盖常见气候波动,又不至于产生非物理样本。

跑完500次之后,不要只报期望值,一定要把5%、50%、95%分位数一起放进结果表。评委看到“最优遮阳长度使年能耗中位数下降18%,最差年份也能保证下降12%以上”这种表达,一眼就能看出你考虑了不确定性,比分裸报一个平均值有说服力得多。

5. 遮阳方案优化:多目标权衡才是问题E的分水岭

单看能耗,最优方案往往是“遮阳板越长越好”——把全年直射光全挡住,制冷和采暖需求都降到最低。但现实中没有人会装一根伸出好几米的遮阳板,因为成本、自重、风荷载、视觉压抑和冬季采光都会让你无法接受。所以问题E真正拉开差距的地方在于多目标优化。

5.1 目标函数与约束的设定思路

我的做法是把评价体系拆成四个维度,每个维度都缩放到同一量纲,再通过权重或帕累托前沿来处理:

  1. 年综合能耗:直接取蒙特卡洛模拟的年暖通负荷中位数,单位换算成kW·h;
  2. 初装成本:遮阳构件面积乘以单位造价,再加固定安装费;
  3. 视觉舒适度:用“全年超额眩光小时数”或“自然采光不足小时数”来近似;
  4. 维护与耐久:可以用遮阳板的暴露面积和年均更换周期的倒数来量化,复杂度不够的话也可以并入成本项。

如果赛题没有明确给出权衡权重,建议不要急着拍脑袋定权重。先跑一次帕累托分析,用带约束的遗传算法或粒子群得到非支配解集,再在解集前沿上点出几个典型方案,比如“最节能方案”“最低成本方案”“综合均衡方案”。这样论文结论的层次感立刻就不一样了。

决策变量的选择也要跟物理模型对齐。常见变量包括:

  • 水平遮阳板的外伸长度(cm)
  • 遮阳板距窗顶的垂直间距(cm)
  • 竖向鳍片的间距
  • 窗面与遮阳板之间的角度

每个变量都可以做范围约束,比如外伸长度不超过窗高的1.5倍,否则结构上不可行。

5.2 一个能直接跑的粒子群优化轮廓

粒子群算法(PSO)实现简单,收敛也快,特别适合连续型决策变量。直接给一个非常朴素的版本:

def pso_optimize(objective, bounds, n_particles=30, n_iter=50): dim = len(bounds) particles = np.random.rand(n_particles, dim) velocities = np.zeros((n_particles, dim)) bounds_arr = np.array(bounds) span = bounds_arr[:, 1] - bounds_arr[:, 0] x = particles * span + bounds_arr[:, 0] pbest = x.copy() pbest_score = np.array([objective(x[i]) for i in range(n_particles)]) gbest = x[pbest_score.argmin()] gbest_score = pbest_score.min() for _ in range(n_iter): w, c1, c2 = 0.6, 1.2, 1.2 velocities = (w * velocities + c1 * np.random.rand(dim) * (pbest - x) + c2 * np.random.rand(dim) * (gbest - x)) x = np.clip(x + velocities, bounds_arr[:, 0], bounds_arr[:, 1]) scores = np.array([objective(x[i]) for i in range(n_particles)]) improved = scores < pbest_score pbest[improved] = x[improved] pbest_score[improved] = scores[improved] if scores.min() < gbest_score: gbest = x[scores.argmin()] gbest_score = scores.min() return gbest, gbest_score

要注意的是,每评估一次目标函数就要调用一整年的8760小时模拟,如果你的仿真函数写得慢,粒子群迭代几十次会非常耗时。备赛时建议先把仿真函数用NumPy向量化,或者把太阳位置、辐射数据全部预计算成数组,优化循环里只做查表和乘法。实测下来,优化性能的瓶颈基本都出现在“反复计算太阳位置”而不是优化算法本身。

5.3 帕累托前沿怎么看

跑完优化后,把每个粒子的能耗和成本画成散点图,左下角就是帕累托前沿。不要只画最优解的点,把粒子群所有迭代过程中出现的可行解都画出来,形成一条“云带”,论文里视觉冲击力会强很多。

如果赛题要求给出最终推荐方案,我的习惯是从帕累托前沿里选“成本增加不超过10%、能耗下降最明显”的点作为主推方案,再把“最省能方案”作为备选。这样既表明你会权衡,又不显得只会调权重。

6. 论文写作:把建模过程讲成一个完整的故事

代码跑通了不代表论文就能写明白。美赛评委会花大量时间看摘要和图表,很多队伍模型做得不错,但因为论文没有主线,最终只拿到不错的奖而不是更好的奖。这一章我挑最关键的四个环节讲:摘要、问题分析、图表和模型检验。

6.1 摘要要像“一个人的项目汇报”

摘要不是把每个模型名字念一遍,而是让评委一眼看到:你做了什么、用了什么数据、得到什么结论、结论有多稳。

我用过比较顺手的三段式结构是:

  • 第一段:一句话交代问题和你的总体思路;
  • 第二段:按步骤列代码实现的三四个关键模块,每个模块配一个核心方法名和对应结论,尽量带数字;
  • 第三段:写敏感性分析和不确定性结论,点出最优方案的量化优势。

摘要里一定要出现的关键词包括:被动式遮阳、太阳高度角、综合遮阳系数、8760小时逐时仿真、蒙特卡洛、多目标优化、帕累托前沿。如果评委三秒内看不到这些词,基本可以判断这篇论文的核心内容是什么。

6.2 图表:让评委少读一千字

美赛图表的规划思路跟普通论文不太一样。普通论文图表是证据,美赛图表同时是“叙事主干”。我总结出三张必备图:

第一张,太阳轨迹与遮阳关系示意。画某典型日(夏至和冬至)的太阳高度角变化曲线,同时在图上标出遮阳板遮挡范围,让人一眼看懂“为什么这个遮阳长度在特定时间能挡住阳光”。

第二张,逐时热平衡图。挑一个典型夏季日和冬季日,画出24小时的Q_solar、Q_cond和Q_hvac三条曲线,直观展示模型的动态特性和遮阳构件的影响。如果手头没有仿真软件,直接用Python的matplotlib堆叠面积图即可。

第三张,帕累托前沿散点图。把多目标优化的结果可视化,在图上标出推荐方案。这张图基本能让评委确定你真正做了权衡分析。

图表还有个容易被忽略的细节:单位要统一。常见问题是前面用的是W,后面又冒出来kW·h;或者逐时数据画图时忘记除以1000,结果曲线横跨好几个数量级。每次出图之前,建议用断言检查数据范围。

6.3 敏感性分析与模型检验:不要只写“模型合理”

敏感性分析是美赛论文的硬性加分项,也是很多队伍最不喜欢写的部分。最简单的做法是:把遮阳板长度、墙体传热系数、窗户面积三个变量分别上下浮动10%到20%,看年综合能耗的变化幅度。如果变化幅度小,说明模型稳定;如果某个参数影响特别大,要在结论部分说明“该参数需要精确测量”。

模型检验方面,可以去查赛题是否提供了简化案例的参考数据。如果提供,直接用你的模型跑一遍案例并与参考值对比,算相对误差。如果没提供,就把你的仿真器跟另一个简化模型(比如只用固定遮阳系数)对比,证明引入动态几何计算后结果更合理。这种“对比式验证”在美赛论文里比自说自话可靠得多。

7. 现场避坑:三天半时间里最容易翻车的五个环节

最后这部分是我带队几年踩下来的坑,也是我每次赛前一定会给队伍强调的五个环节。问题E的命题看似温和,实际陷阱不少,任何一个坑都可能让前面的代码白跑。

7.1 数据源和单位不统一

逐时气象数据的格式五花八门。有些数据库给的是总水平辐射,有些给的是法向直射和水平散射,单位还有W/m²和MJ/m²的差别。建议第一天上午先做数据清洗:统一单位、统一时间基准(UTC还是当地标准时间)、统一时间分辨率。如果时间基准搞错,后面所有太阳位置计算都会偏移,且很难通过肉眼排查。

7.2 太阳时和标准时的混淆

前面已经提过一次,这里再强调一遍:赛题数据通常按当地标准时间记录,而太阳位置公式需要地方太阳时。两队人合作时最容易出现的分歧就在这里——负责数据处理的队员和负责建模的队员各用各的时间定义,结果太阳高度角在凌晨出现正值。建议在代码里定义统一的时间转换函数,并在模型假设里写清楚时区修正和均时差修正。

7.3 边界条件写得太粗糙

恒温区间、遮阳板反射率、墙体热惰性这些边界条件要尽量按物理常识设置,不要拍脑袋。反射率取值0.5和0.8的遮阳板,夏季得热差距可能超过20%,这一点在敏感性分析里会暴露。宁可少做几个情景,也要把边界条件写清楚。

7.4 优化结果脱离物理可行性

粒子群跑出来的最优遮阳板长度可能特别夸张,比如3米外伸。这种结果放到现实里基本不可能施工。交卷前一定要加一道“人工审查”,用现实中的结构限制和经验范围把不合理的最优解打回去,或者直接给决策变量加上可行域约束。

7.5 论文写作拖到最后一天

很多队伍把仿真和优化一直调到最后一天下午,留给论文的时间只剩四五个小时,摘要写得非常仓促。更稳的节奏是:第一天晚上就把摘要的整体框架搭好,先写每个模型模块对应的段落标题;第二天边跑代码边填结果;第三天晚上专门做图表与摘要定稿。宁可少跑一次额外情景,也不能让论文在表达上掉链子。

如果你正在备赛2026年问题E,我的建议是先把太阳位置和遮阳系数两个基础模块吃透,再逐步扩展仿真、优化和论文部分。被动式遮阳这个题最迷人的地方在于,每一步都可以用现实中的物理现象去验证——你在某一天某一时刻算出来的遮挡效果,跟真实看到的光影是一致的。这种可验证性,是建模过程最大的信心来源。希望这篇思路整理能帮你少走一些弯路,也期待你的队伍在赛场上交出漂亮的作品。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进