Energy balance
The energy balance module computes the surface energy budget at the land surface and calculates the potential evapotranspiration (PET) before the soil-water balance calculations. Surface (\(T_s\)) and deep-soil (\(T_d\)) temperatures are calculated as additional state variables.
Overview
The currently available scheme is the 1-layer (1L) analytical formulation. It solves a linearised Fourier decomposition of the surface energy budget, with the diurnal cycle of incoming shortwave radiation represented as a sinusoid plus a constant term. Each model timestep is split at the sunrise and sunset boundaries so that day and night sub-periods are integrated separately (radiation forcing is only present in the day sub-period).
The energy budget includes:
- Net shortwave radiation (corrected by surface albedo \(\alpha\))
- Net longwave radiation (Stefan-Boltzmann linearised around mean air temperature)
- Sensible heat flux (turbulent exchange coefficient \(C_H\) times wind speed)
- Latent heat flux (Magnus formula for saturation specific humidity)
- Ground heat flux (1-D conduction with deep-temperature boundary \(T_{const}\))
Two-step calculation
For each timestep the energy balance is solved in two steps:
- Initial (soil saturation assumption): calculates the energy balance assuming no water limitation. The ratio \(\eta = \text{ET} / \text{PET}\) is set to 1.
- Second step (after the soil water balance): re-computes \(T_s\) and \(T_d\) using the actual ratio \(\eta\) obtained from the soil module.
The deep-temperature value evaluated at sunrise is preserved across timesteps and is used as the starting point for the day sub-period in the second step calculation.
Diurnal radiation cycle
Daily incoming shortwave radiation \(R_s\) is decomposed into:
with \(\omega = 2\pi / 86400\) rad/s. Two modes are supported:
- average: \(R_s\) is the day-average value; the amplitude \(A\) and constant \(C\) are fitted so that the integral between sunrise and sunset returns the daily mean.
- instant: \(R_s\) is interpreted as an instantaneous value at sunrise time.
Sunrise and sunset hours are obtained by bisection on the solar elevation, computed from the basin baricenter latitude/longitude and the Julian day.
Land-cover adjustment via Kc
When a Corine Land Cover raster (raster_files.CLC) is provided, the turbulent exchange coefficient \(C_H\) is scaled by the monthly FAO crop coefficient \(K_c\) before the energy balance solver is called:
\(C_H^{\text{adj}}\) is then used in the calculation of both sensible heat flux \(H\) and the latent heat flux \(LE\). See Crop coefficients (Kc) for the full description and configuration options.
Configuration
The energy balance is enabled under simulation.energy_balance and is configured through parameters.energy, the optional CH / Alb rasters, and the basin.baricenter coordinates required to compute solar hours.
basin:
baricenter:
lon: 11.10 # Longitude of basin baricenter [deg. East]
lat: 43.77 # Latitude of basin baricenter [deg. North]
simulation:
# Energy balance scheme [None | 1L]
energy_balance: 1L
raster_files:
# OPTIONAL: Grid of turbulent exchange coefficient for heat, non dimensional
CH: example/raster/CH.tif
# OPTIONAL: Grid of surface albedo, non dimensional
Alb: example/raster/Alb.tif
parameters:
energy:
Tconst: 290.0 # Deep ground temperature [K] (default: 290.0)
kaps: 2.5 # Soil thermal conductivity [W/m/K] (default: 2.5)
nis: 0.8e-6 # Soil thermal diffusivity [m^2/s] (default: 0.8e-6)
CH: 1.0e-3 # Default turbulent exchange coefficient (used if CH raster missing)
Alb: 0.2 # Default surface albedo (used if Alb raster missing)
multipliers:
CH_factor: 1.0 # Calibration multiplier applied to CH raster/scalar
output_states:
surface_temperature: true # Save Ts grid to state file
ground_temperature: true # Save Td grid to state file
output_forcing_data:
meteo_data: true # Saves precipitation, temperature_min/max, humidity,
# wind_speed, radiation, and pet_c (Kc-adjusted PET) to meteo_forcing.nc
Required meteorological forcing. When simulation.energy_balance == "1L", the simulation needs the following variables in addition to precipitation:
temperature_min,temperature_max— daily air temperature extremes [°C]humidity— relative humidity [%]wind_speed— wind speed [m/s]radiation— incoming shortwave radiation [W/m²]
Both station-based (MeteoData) and raster-based (MeteoRaster) inputs are supported.
Integration with the simulation loop
When simulation.energy_balance == "1L":
- The simulation initialises \(T_s = T_d = T_{air,lin}\) on the first step (when no warm start is used) or restores them from the loaded state file.
td_riseis initialised from \(T_d\). - Each timestep, the initial step is run with \(\eta = 1\) to obtain PET and a tentative \((T_s, T_d)\).
- PET values are fed into the soil water balance, which produces the actual evapotranspiration ET.
- The second step is run with \(\eta = \text{ET} / \text{PET}\), restarting the day sub-period from the initial
td_rise. The result overwrites \((T_s, T_d)\) only on water-limited cells. - \(T_s\) and \(T_d\) are written to the state file when the corresponding
output_statesflags are enabled.
ET/PET when using raster forcing, to speed up simulations
When the input MeteoRaster contains either pet or pet_c variable, the simulation skips the energy balance entirely regardless of the simulation.energy_balance setting, and reads the evapotranspiration values directly from the raster. In this case, the simulation speeds up significantly. In this mode, the temperature/humidity/wind/radiation variables are not required in the input file. See Crop coefficients (Kc) for details.
Model status
- None — energy balance disabled, constant 1 mm/day PET is used
- 1L — single-layer analytical Fourier scheme (this module)
- 5L — multi-layer soil temperature profile (not yet implemented)
- Snow — snow accumulation and melt (not yet implemented)
Functions
mobidic.core.energy_balance.compute_energy_balance_1l(ts, td, td_rise, rs, u, tair_max, tair_min, qair, ch, alb, kaps, nis, tcost, pair, ctim_s, ftim_s, hrise_s, hset_s, etrsuetp, dt, reentry=False)
Run the 1L surface energy balance for a single model timestep.
Day and night sub-periods are solved separately (day uses radiation forcing, night does not).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ts
|
NDArray[float64]
|
Surface temperature [K] at the beginning of the step (per cell). |
required |
td
|
NDArray[float64]
|
Deep-soil temperature [K] at the beginning of the step (per cell). |
required |
td_rise
|
NDArray[float64]
|
|
required |
rs
|
NDArray[float64]
|
Incoming shortwave radiation [W/m²] (per cell). |
required |
u
|
NDArray[float64]
|
Wind speed [m/s] (per cell). |
required |
tair_max
|
NDArray[float64]
|
Maximum air temperature [K] (per cell). |
required |
tair_min
|
NDArray[float64]
|
Minimum air temperature [K] (per cell). |
required |
qair
|
NDArray[float64]
|
Relative humidity [0-1] (per cell). |
required |
ch
|
NDArray[float64]
|
Turbulent exchange coefficient [-] (per cell). |
required |
alb
|
NDArray[float64]
|
Surface albedo [-] (per cell). |
required |
kaps
|
float
|
Soil thermal conductivity [W/m/K]. |
required |
nis
|
float
|
Soil thermal diffusivity [m²/s]. |
required |
tcost
|
float
|
Deep-soil constant temperature [K]. |
required |
pair
|
float
|
Air pressure [mb]. |
required |
ctim_s
|
float
|
Current-time seconds of day [s] (start of step). |
required |
ftim_s
|
float
|
Future-time seconds of day [s] (end of step = ctim_s + dt). |
required |
hrise_s
|
float
|
Sunrise time [s of day]. |
required |
hset_s
|
float
|
Sunset time [s of day]. |
required |
etrsuetp
|
float | NDArray[float64]
|
Water-to-energy ET ratio [-]. |
required |
dt
|
float
|
Model timestep [s]. |
required |
reentry
|
bool
|
If True, skip the pre-sunrise night sub-period (physics is
independent of |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
ts_new |
NDArray[float64]
|
Updated surface temperature [K]. |
td_new |
NDArray[float64]
|
Updated deep temperature [K]. |
etp |
NDArray[float64]
|
Potential evapotranspiration over the timestep [m]. |
td_rise_new |
NDArray[float64]
|
Updated |
Source code in mobidic/core/energy_balance.py
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 | |
mobidic.core.energy_balance.energy_balance_1l(ff, a_tem, a_rad, p_tem, p_rad, c_tem, c_rad, td_ini, tm, u, pair, hair, t_end, step, ch, alb, kaps, nis, tcost, etrsuetp)
Analytical Fourier 1-layer surface energy balance over a sub-period.
Solves the constant + sinusoidal parts of the linearised surface energy
balance analytically and integrates the evaporation flux via trapezoidal
integration inside [0, t_end] with step step. Numba-accelerated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ff
|
float
|
Diurnal angular frequency [rad/s] (typically |
required |
a_tem
|
NDArray[float64]
|
Air-temperature amplitude [K] (per cell). |
required |
a_rad
|
NDArray[float64] | float
|
Radiation amplitude [W/m²] (per cell or scalar 0 for night). |
required |
p_tem
|
float
|
Air-temperature phase [rad] (scalar, already time-shifted). |
required |
p_rad
|
float
|
Radiation phase [rad] (scalar, already time-shifted). |
required |
c_tem
|
NDArray[float64]
|
Constant part of air temperature [K] (per cell). |
required |
c_rad
|
NDArray[float64] | float
|
Constant part of radiation [W/m²] (per cell or 0 for night). |
required |
td_ini
|
NDArray[float64]
|
Initial deep-soil temperature [K] (per cell). |
required |
tm
|
NDArray[float64]
|
Mean air temperature used for linearisation [K] (per cell). |
required |
u
|
NDArray[float64] | float
|
Wind speed [m/s] (per cell, or 0 for night). |
required |
pair
|
float
|
Air pressure [mb] (scalar). |
required |
hair
|
NDArray[float64]
|
Relative humidity [0-1] (per cell). |
required |
t_end
|
float
|
Integration length of this sub-period [s]. |
required |
step
|
float
|
Integration step for evaporation [s]. |
required |
ch
|
NDArray[float64]
|
Turbulent exchange coefficient for heat [-] (per cell). |
required |
alb
|
NDArray[float64]
|
Surface albedo [-] (per cell). |
required |
kaps
|
float
|
Soil thermal conductivity [W/m/K] (scalar). |
required |
nis
|
float
|
Soil thermal diffusivity [m²/s] (scalar). |
required |
tcost
|
float
|
Deep ground (constant) temperature [K] (scalar). |
required |
etrsuetp
|
float | NDArray[float64]
|
Water-limited to energy-limited ET ratio [-] (scalar or per cell). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
ts |
NDArray[float64]
|
Surface temperature at the end of the sub-period [K]. |
td |
NDArray[float64]
|
Deep-soil temperature at the end of the sub-period [K]. |
evp |
NDArray[float64]
|
Evaporation over the sub-period [m]. |
Source code in mobidic/core/energy_balance.py
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 | |
mobidic.core.energy_balance.diurnal_radiation_cycle(rs_avg, t_sunrise, t_sunset, mode='average')
Decompose daily radiation into sinusoidal amplitude and constant.
The diurnal radiation cycle is represented as A * sin(omega * t + phi) + C
where omega = 2*pi/86400 and the phase phi = -pi/2. This function
returns (A, C).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rs_avg
|
float | NDArray[float64]
|
Incoming shortwave radiation [W/m²]. Scalar or per-cell array. |
required |
t_sunrise
|
float
|
Sunrise time [s] (seconds of day). |
required |
t_sunset
|
float
|
Sunset time [s] (seconds of day). |
required |
mode
|
str
|
“average” if |
'average'
|
Returns:
| Type | Description |
|---|---|
tuple[NDArray[float64], NDArray[float64]]
|
tuple[NDArray[np.float64], NDArray[np.float64]]: (amplitude, constant) arrays with the same shape as |
Source code in mobidic/core/energy_balance.py
mobidic.core.energy_balance.solar_hours(lat, lon, jday)
Compute sunrise and sunset hours via bisection on solar elevation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lat
|
float
|
Latitude [deg North]. |
required |
lon
|
float
|
Longitude [deg East]. |
required |
jday
|
int
|
Day of year (1-365). |
required |
Returns:
| Type | Description |
|---|---|
tuple[float, float]
|
tuple[float, float]: Sunrise (hrise) and sunset (hset) in decimal hours. |
Source code in mobidic/core/energy_balance.py
mobidic.core.energy_balance.solar_position(hour, day, lat, lon)
Compute solar azimuth and elevation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hour
|
float
|
Local time in decimal hours (0-24). |
required |
day
|
int
|
Day of year (Julian day, 1-365). |
required |
lat
|
float
|
Latitude [deg North]. |
required |
lon
|
float
|
Longitude [deg East]. |
required |
Returns:
| Type | Description |
|---|---|
tuple[float, float]
|
tuple[float, float]: Solar (azimuth, elevation) [deg]. |
Source code in mobidic/core/energy_balance.py
mobidic.core.energy_balance.saturation_specific_humidity(T, P, dT=0.0)
Saturation specific humidity (Magnus formula).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
T
|
NDArray[float64]
|
Temperature [K]. |
required |
P
|
float
|
Pressure [mb] (scalar). |
required |
dT
|
float | NDArray[float64]
|
Dew-point depression [K] (default 0). |
0.0
|
Returns:
| Type | Description |
|---|---|
NDArray[float64]
|
NDArray[np.float64]: Specific humidity [kg/kg]. |