跳转至

31 - 辐射场

辐射场描述场景中每个叶片或地面单元吸收了多少短波辐射。它是能量平衡、光合作用和荧光计算的输入,也可以单独用来研究冠层的光分布,例如吸收的光合有效辐射(APAR)、受光叶片比例和垂直廓线。

LESS 提供两种计算方式:

RadiationFieldProcess ForwardRadiationFieldSensor
方法 从每个场景元素向外追踪 从太阳和天空向场景追踪光子
结果 每个三角形或统计植被组件 每个三角形或三维体素
用途 后续的能量平衡、光合、荧光 垂直廓线、空间分布

每个元素的吸收

import numpy as np
import less

scene = less.Scene()
scene.size = 6.0
scene.terrain = less.Terrain(property=less.Lambertian(reflectance=0.15))
scene.illumination = less.Illumination(
    source=less.Sun(zenith=30, azimuth=150),
    atmosphere=less.SimpleSpectralAtmosphere(turbidity=2.0))

plant = less.Object("plant")
plant.add_component("leaves", less.Mesh(less.asset_path("tutorial_tree.obj"), group="leaves"))
plant.set_property("leaves", less.Prospect(cab=45))
scene.add(plant, positions=[(3, 3, 0)])

radiation = scene.simulate(less.RadiationFieldProcess(n_samples=64))
print(radiation.absorbed_top.shape)      # (元素数, 波段数)
print(radiation.wavelengths)
结果 含义
absorbed_top、absorbed_bot 正面和背面吸收的短波辐射(每单位面积,W m⁻²)
absorbed_direct 未被遮挡时吸收的太阳直射部分
sunlit_fraction 能直接看到太阳的叶面积比例
wavelengths、band_widths 波段中心和宽度(nm)
leaf_area 每个元素的面积

纯三角网格场景中,每个三角形是一个元素;含统计植被的场景中,每个放置后的统计植被组件是一个元素,结果是该组件内的叶面积加权平均。

在一个波长范围内积分:

par_absorbed = radiation.integrate((400, 700))           # 每个元素,W m⁻²
print(f"平均吸收的光合有效辐射: {par_absorbed.mean():.1f} W m⁻²")
print(radiation.summary())

波段设置

默认使用 24 个覆盖 415–2100 nm 的波段,其中 19 个在光合有效辐射范围内。spectral_profile 可以指定其他波段:

solar = less.SpectralProfile.solar_shortwave()         # 400–2400 nm,5 nm 间隔
par = less.SpectralProfile([less.SpectralBand(float(center), 10.0, "par")
                            for center in range(405, 700, 10)])

fine = scene.simulate(less.RadiationFieldProcess(spectral_profile=par, n_samples=64))

计算与色素有关的吸收(例如叶绿素吸收的光合有效辐射)时,光合有效辐射范围内宜使用较窄的波段。

采样参数

参数 含义
n_samples 每个三角形每一面的采样数
n_leaf_samples 每个统计植被组件的叶片样本数
max_depth 最多追踪的反射和透射次数

可以增大采样数比较结果,确认吸收已经稳定。

把辐射场交给其他过程

能量平衡、光合作用和荧光都可以直接使用已经算好的辐射场,避免重复计算:

plant.set_property("leaves", less.ThermalProperty(temperature="air", emissivity=0.98))
plant.set_property("leaves", less.BiophysicalProperty(leaf_width=0.05, stomata_side="bottom"))
scene.terrain.set_property(less.ThermalProperty(temperature="air", emissivity=0.95))
scene.terrain.set_property(less.BiophysicalProperty(two_sided=False, stomata_side="none",
                                                    ground_heat_fraction=0.3))

radiation = scene.simulate(less.RadiationFieldProcess(n_samples=64))
climate = less.Microclimate(air_temperature=25.0, humidity=60.0, wind_speed=2.0)
energy = scene.simulate(less.EnergyBalanceProcess(rad=radiation, quality="preview"),
                        microclimate=climate)

辐射场与计算它时的场景状态绑定:光照、属性或几何改变后(包括上面新设的热属性),需要重新计算辐射场。一个辐射场只交给一个过程使用。

三维体素中的吸收

ForwardRadiationFieldSensor 从光源出发追踪光子,按水平网格和高度分层统计吸收,可以得到冠层的垂直吸收廓线:

forest = less.Scene()
forest.size = 20.0
forest.terrain = less.Terrain(property=less.Lambertian(reflectance=0.15))
forest.illumination = less.Illumination(
    source=less.Sun(zenith=30, azimuth=150), atmosphere=less.NoAtmosphere())
tree = less.Object("ash", mesh=less.asset_path("FREX.obj"))
tree.set_property("leaves", less.Prospect(cab=40))
tree.set_property("stem_branch", less.Lambertian(reflectance=0.1))
forest.add(tree, positions=less.place.random(forest, n=8, min_dist=5.0, seed=1))

field = forest.simulate(less.ForwardRadiationFieldSensor(
    bands=[450, 550, 650], mode="grid", grid=(20, 20), layer_height=1.0,
    photons_per_m2=4000, integration_range=(400, 700)))
print(field.absorption_grid.shape)      # (层, 行, 列, 波段)
print(f"冠层吸收的光合有效辐射比例: {field.fpar:.3f}")
field.save("forest_radiation_field.npz")

mode="per_leaf"(默认)给出每个三角形的吸收,mode="grid" 给出(层, 行, 列, 波段)的体素吸收。layer_height 是每层的厚度,也可以用 layer_heights 直接给出各层的边界。

下一步