如何在pvlib的clear_sky函数中实现云量对太阳辐照度的影响?
你提的这个问题太实用了——毕竟实际场景里,云量对太阳辐照度的影响可不能忽略!pvlib的clear_sky函数确实只针对完全晴朗的天空,不过我们完全可以手动结合云量数据来调整辐照度,下面给你几种靠谱的实现方式:
一、快速线性衰减法(适合初步估算)
这是最直接的方式,完全贴合你拿到的0-100范围的云量数据。核心逻辑就是:云量越高,辐照度的衰减比例越大。
假设你已经获取了和times时间序列一一对应的云量数据(比如从气象数据源拿到的pandas.Series,值范围0到100),可以这样实现:
import pvlib import pandas as pd import numpy as np # 你的原有代码 location = pvlib.location.Location(latitude=54, longitude=16) times = pd.date_range('2024-01-01', periods=24*365, freq='H', tz='Europe/Warsaw') solpos = location.get_solarposition(times) clearsky = location.get_clearsky(times, model='ineichen') # 模拟云量数据(实际中替换为你的真实数据) cloud_cover = pd.Series(np.random.randint(0, 101, size=len(times)), index=times) # 把云量转换成0-1的衰减系数:0(晴)对应系数1,100(全阴)对应系数0 attenuation_factor = 1 - (cloud_cover / 100) # 对晴天辐照度的三个分量分别应用衰减 irradiance_with_clouds = clearsky * attenuation_factor # 可以查看结果 irradiance_with_clouds.plot(subplots=True)
这种方法的优点是简单易实现,缺点是比较粗略——实际中云对直射辐照度(DNI)和漫射辐照度(DHI)的影响并非完全线性,但如果是快速估算已经足够用了。
二、更精准的经验模型(贴近实际场景)
如果你想要更符合真实气象情况的结果,可以针对不同辐照度分量做差异化处理:比如云量增加时,DNI的衰减会比GHI更显著,而部分多云时DHI甚至可能比晴天更高。
举个参考实现的例子:
# 处理DNI:用指数衰减,模拟云对直射光的强遮挡 dni_attenuation = 1 - (cloud_cover / 100) ** 1.2 # 指数可根据当地情况调整 dni_with_clouds = clearsky['dni'] * dni_attenuation # 处理GHI:用稍弱的线性衰减 ghi_attenuation = 1 - (cloud_cover / 100) * 0.9 ghi_with_clouds = clearsky['ghi'] * ghi_attenuation # 从GHI和DNI反推DHI(利用辐照度分量的关系) dhi_with_clouds = ghi_with_clouds - dni_with_clouds * np.cos(np.radians(solpos['zenith'])) # 组合成结果DataFrame irradiance_with_clouds = pd.DataFrame({ 'ghi': ghi_with_clouds, 'dni': dni_with_clouds, 'dhi': dhi_with_clouds })
这种方法需要你根据当地的气候特点调整衰减参数,比如多雨地区和干旱地区的云对辐照度的影响会有差异,你可以结合实测数据来优化这些系数。
三、pvlib内置的云量转换函数
你提到旧版本pvlib有支持云量的函数,其实现在有个更合适的替代:pvlib.irradiance.cloud_cover_to_ghi,它可以基于晴天GHI和云量直接估算受云影响的GHI,内部采用了经过验证的经验公式,比手动线性衰减更靠谱。
用法如下:
from pvlib import irradiance # 用内置函数计算带云量影响的GHI ghi_with_clouds = irradiance.cloud_cover_to_ghi(clearsky['ghi'], cloud_cover) # 用Erbs模型从GHI和太阳位置拆分出DNI和DHI split_result = irradiance.erbs(ghi_with_clouds, solpos['zenith'], solpos['azimuth']) dni_with_clouds = split_result['dni'] dhi_with_clouds = split_result['dhi'] # 组合结果 irradiance_with_clouds = pd.DataFrame({ 'ghi': ghi_with_clouds, 'dni': dni_with_clouds, 'dhi': dhi_with_clouds })
这个函数的优势是无需自己手动调参,已经封装了行业内常用的经验逻辑,推荐优先试试这种方式。
最后提醒一下:不管用哪种方法,云量数据的时间分辨率要和你的辐照度数据保持一致(比如都是小时级),如果用日均值云量来估算小时级辐照度,结果会有较大误差。
内容来源于stack exchange

