Skip to content

13 - Energy Balance and Leaf Temperature

Thermal infrared simulation requires surface temperature. You can prescribe a temperature directly, or let LESS calculate it from illumination, air temperature, humidity, and wind speed. This chapter introduces the second approach.

Mesh leaves, TurbidBoundary vegetation, and temperature-enabled terrain can participate in the same energy-balance calculation. Use stomatal_resistance (s/m) when stomatal resistance is prescribed. If a leaf also has a Farquhar property, LESS can solve leaf temperature together with net photosynthesis (An) and Ball--Berry stomatal conductance (gs).

What does the energy-balance calculation solve?

For each participating leaf or surface, LESS solves:

\[ R_n = H + LE + G \]

where:

  • \(R_n\) is net radiation, including absorbed shortwave radiation, absorbed longwave radiation, and the surface's own longwave emission;
  • \(H\) is sensible heat flux;
  • \(LE\) is latent heat flux;
  • \(G\) is ground or storage heat flux. It is normally zero for leaves.

The result contains temperatures and the corresponding R_n, H, LE, G, and energy-closure residuals for each mesh primitive or statistical vegetation component.

Required properties

Components included in the calculation need optical, thermal, and biophysical properties:

leaves.set_property(
    "leaf",
    less.Fluspect(
        N=1.5, cab=45, car=10, cw=0.012, cm=0.006,
        fqe=0.012,
    ),
)
leaves.set_property(
    "leaf",
    less.ThermalProperty(
        temperature="air",
        emissivity=0.98,
    ),
)
leaves.set_property(
    "leaf",
    less.BiophysicalProperty(
        leaf_width=0.05,
        stomata_side="bottom",
        stomatal_resistance=150.0,
    ),
)

There are two common ways to set ThermalProperty.temperature:

  • "air": use the current air temperature as the initial temperature;
  • a temperature in kelvin, such as 298.15: use that value as the initial temperature.

Before an energy-balance calculation is run, thermal imaging uses this value as the prescribed surface temperature. After a successful calculation, thermal imaging automatically uses the current solved temperature state.

Set the microclimate

microclimate = less.Microclimate(
    air_temperature=25.0,  # degrees Celsius
    humidity=60.0,         # relative humidity, percent
    wind_speed=2.0,        # m/s
    pressure=101325.0,     # Pa
    ca=400.0,              # CO2, ppm
)

air_temperature is in degrees Celsius, and humidity is a percentage from 0 to 100.

state = scene.solve(
    microclimate=microclimate,
    modules=["energy_balance"],
)

print(state.energy_balance.result.summary())

thermal = scene.simulate(
    less.ThermalImager(
        less.Orthographic(image_size=512),
        bands=[10600.0],
        quality=128,
    )
)
thermal.save("leaf_temperature.tif")

ThermalImager uses the scene's current energy-balance state by default. You do not need to pass state.energy_balance to the imager separately.

Check energy closure

eb = state.energy_balance.result
active = eb.active_mask

residual = eb.residual[active]
print("Maximum closure residual:", abs(residual).max(), "W/m2")
print("Mean closure residual:", abs(residual).mean(), "W/m2")
print("Iterations:", eb.n_iterations)
print("Converged:", eb.converged)

To assess a result, check converged, the resulting temperature range, and the R_n - H - LE - G residual. If the iteration does not converge, LESS raises less.ConvergenceError; review the microclimate, initial temperatures, and solver settings before running it again.

Mesh and TurbidBoundary results

Both geometry representations use the same user workflow:

  • Mesh results are reported by triangle primitive;
  • TurbidBoundary results are reported by placed component;
  • statistical vegetation reports separate conditional sunlit and shaded leaf temperatures and their leaf-area-weighted mean.
eb = state.energy_balance
print(eb.spatial_mode)  # "primitive" or "component"

When does a solved state become stale?

A solved state becomes stale after changing any of the following inputs:

  • illumination;
  • microclimate;
  • component properties;
  • scene geometry or instances.

Call scene.solve(...) again after changing one of these inputs. If an outdated result is supplied explicitly, LESS reports that it is stale instead of using it to produce an image.

Next step

  • less.EnergyBalanceProcess, less.RadiationFieldProcess
  • less.Microclimate, less.BiophysicalProperty
  • less.ThermalProperty, less.Farquhar
  • less.ThermalImager, less.EnergyBalanceProduct