Wärmeflussmethoden mit fieldClim

Autor:in

Jörg Bendix & Chris Reudenbach

HinweisQuellcode

Der komplette R-Code dieser Lektion wird im gerenderten Dokument sichtbar angezeigt. Zusätzlich steht der extrahierte und ausführlich kommentierte R-Code als Datei bereit: L04_waermeflussmethoden_mit_fieldclim.R.

Ziel dieser Kurseinheit

Diese Einheit ist die eigentliche Anwendungseinheit. Die Studierenden haben Energiebilanz, Geländeklima und Mikroklima bereits behandelt. Jetzt wird mit fieldClim entschieden, welche Wärmeflussmethode zu welcher Messarchitektur passt und wie die Ergebnisse gelesen werden dürfen.

Die Methoden werden nicht als Rangliste behandelt. Sie beantworten unterschiedliche Fragen. Priestley–Taylor partitioniert verfügbare Energie in Richtung Verdunstung. Bulk–Residual schätzt fühlbare Wärme aus einem Temperaturprofil und definiert latente Wärme als Rest. Bowen nutzt Temperatur- und Feuchtegradienten. Penman ist latentwärmeorientiert. Monin/Profile bleibt eine Profil- und Stabilitätsdiagnose.

HinweisArbeitsprinzip in R

Der Code bleibt absichtlich einfach. Wir verwenden read.csv(), direkte Spaltenzugriffe mit $, kleine data.frame()-Tabellen und base-R-Plots. Das Ziel ist nicht ein eleganter R-Stil, sondern eine nachvollziehbare Übersetzung von Stationsdaten in fieldClim-Berechnungen. Pfade laufen über here::here(). Wenn die Kursdatei data/caldern_wiese_2017-06-30.csv nicht vorhanden ist, nutzt der Code als Fallback die mit dem Paket ausgelieferte Beispieldatei.

library(fieldClim)
library(here)

# Kursprojekt: bevorzugt lokale Datei unter data/.
caldern_file <- here::here("data", "caldern_wiese_2017-06-30.csv")

# Fallback: mit fieldClim ausgelieferter Beispieldatensatz.
if (!file.exists(caldern_file)) {
  caldern_file <- system.file(
    "extdata",
    "caldern_wiese_2017-06-30.csv",
    package = "fieldClim"
  )
}

stopifnot(file.exists(caldern_file))

caldern <- read.csv(
  caldern_file,
  na.strings = c("NULL", "NA", "")
)

caldern$datetime <- as.POSIXct(
  caldern$datetime,
  format = "%Y-%m-%d %H:%M:%S",
  tz = "Europe/Berlin"
)
caldern$Q_star <- caldern$rad_net
caldern$B <- caldern$heatflux_soil
caldern$Q_minus_B <- caldern$Q_star - caldern$B
ws <- build_weather_station(
  datetime = caldern$datetime,
  lon = 8.6832,
  lat = 50.8405,
  elev = 261,

  temp = caldern$Ta_2m,
  rh = caldern$Huma_2m,

  t1 = caldern$Ta_2m,
  t2 = caldern$Ta_10m,
  hum1 = caldern$Huma_2m,
  hum2 = caldern$Huma_10m,

  v1 = caldern$Windspeed_2m,
  v2 = caldern$Windspeed_10m,
  z1 = 2,
  z2 = 10,

  rad_bal = caldern$rad_net,
  soil_flux = caldern$heatflux_soil,

  slope = 0,
  exposition = 0,
  valley = FALSE,
  surface_type = "field",
  surface_temp = caldern$Ts,

  texture = "peat",
  moisture = caldern$water_vol_soil,
  soil_temp1 = caldern$Ts,
  soil_temp2 = caldern$Ta_2m,
  soil_depth1 = 0.25,
  soil_depth2 = 0,
  obs_height = 2
)

Messarchitektur zuerst

Die Methodenwahl beginnt nicht bei einem Funktionsnamen, sondern bei der Messarchitektur. Eine Station mit nur einer Messhöhe kann verfügbare Energie und latentwärmeorientierte Abschätzungen liefern. Eine Station mit zwei Messhöhen kann zusätzlich Gradientenmethoden stützen. Ein Bestand oder Turm verlangt vorher die Entscheidung, welche Schicht überhaupt interpretiert wird.

Für den Caldern-Datensatz liegt eine Zwei-Höhen-Situation vor: Temperatur, Feuchte und Wind sind in 2 m und 10 m vorhanden. Deshalb können neben Priestley–Taylor und Penman auch Bulk–Residual, Bowen und Monin/Profile als Vergleichswege gerechnet werden. Genau dieser Vergleich ist der Zweck der Einheit.

inspection <- inspect_weather_station_inputs(ws)
inspection$method_readiness[, c("method", "ready", "missing_fields", "partial_fields", "notes")]
#>                   method ready missing_fields partial_fields
#> 1       priestley_taylor  TRUE                              
#> 2          bulk_residual  TRUE                              
#> 3 bulk_residual_ri_guard  TRUE                              
#> 4                  bowen  TRUE                              
#> 5          monin_profile  TRUE                              
#> 6                 penman  TRUE                              
#>                                                                                                       notes
#> 1 Requires available measured input fields for temperature, net radiation, soil heat flux and surface type.
#> 2                                          Neutral bulk path can use v1 only; v2 is optional for mean wind.
#> 3                         Optional Richardson guard requires v2 and remains unavailable when v2 is missing.
#> 4                                                     Requires two-level temperature and humidity profiles.
#> 5                                           Requires profile inputs plus either surface_type or obs_height.
#> 6                  Uses hum1 when present, otherwise rh; both are interpreted as relative humidity percent.

Priestley–Taylor

Priestley–Taylor nutzt die verfügbare Energie und eine empirische Verdunstungsparametrisierung. Der Pfad ist hilfreich, wenn ein energiegebundener Vergleich benötigt wird, ohne sich sofort auf empfindliche Feuchte- oder Windgradienten zu stützen (Priestley und Taylor 1972).

\[ LE_\mathrm{PT} = \alpha_\mathrm{PT} \frac{s}{s + \gamma} (Q^* - B) \]

Das zugehörige H ist hier der Komplementärterm innerhalb der Partition. Es ist keine unabhängig aus einem Temperaturgradienten geschätzte fühlbare Wärme.

flux_pt <- turb_flux_calc(ws, pt_only = TRUE)

caldern$H_pt <- flux_pt$sensible_priestley_taylor
caldern$LE_pt <- flux_pt$latent_priestley_taylor
caldern$sum_pt <- caldern$H_pt + caldern$LE_pt

summary(caldern[, c("H_pt", "LE_pt", "sum_pt")])
#>       H_pt             LE_pt            sum_pt      
#>  Min.   :-16.951   Min.   :-40.12   Min.   :-56.84  
#>  1st Qu.: -5.597   1st Qu.:-12.14   1st Qu.:-17.75  
#>  Median : 13.043   Median : 33.77   Median : 47.75  
#>  Mean   : 25.121   Mean   : 83.57   Mean   :108.69  
#>  3rd Qu.: 49.373   3rd Qu.:163.40   3rd Qu.:210.15  
#>  Max.   :159.944   Max.   :541.61   Max.   :698.25
op <- par(mfrow = c(2, 1), mar = c(3.5, 4, 2, 1))

plot(caldern$datetime, caldern$H_pt, type = "l",
     xlab = "Zeit", ylab = "W m-2", main = "Priestley--Taylor: H")
abline(h = 0, lty = 2, col = "grey50")

plot(caldern$datetime, caldern$LE_pt, type = "l",
     xlab = "Zeit", ylab = "W m-2", main = "Priestley--Taylor: LE")
abline(h = 0, lty = 2, col = "grey50")


par(op)

Bulk–Residual mit Richardson-Guard

Bulk–Residual arbeitet anders. Zuerst wird fühlbare Wärme aus Temperaturgradient und Austauschannahme geschätzt. Danach wird latente Wärme als Rest der verfügbaren Energie definiert.

\[ H_\mathrm{bulk} = \rho c_p \frac{t_1 - t_2}{r_a} \]

\[ LE_\mathrm{res} = Q^* - B - H_\mathrm{bulk} \]

Diese Rechnung schließt formal, weil LE_res als Rest definiert ist. Die Schließung validiert aber nicht automatisch die Schätzung von H_bulk.

flux_bulk <- turb_flux_bulk_residual(
  ws,
  stability_method = "ri_guard"
)

caldern$H_bulk <- flux_bulk$sensible_bulk
caldern$LE_bulk <- flux_bulk$latent_bulk_residual
caldern$bulk_Ri <- attr(flux_bulk$sensible_bulk, "bulk_Ri_g")
caldern$bulk_stability <- attr(flux_bulk$sensible_bulk, "bulk_stability")

table(caldern$bulk_stability, useNA = "ifany")
#> 
#>     neutral      stable    unstable very_stable 
#>           1           5         107         175
summary(caldern[, c("H_bulk", "LE_bulk")])
#>      H_bulk          LE_bulk      
#>  Min.   :-26.05   Min.   :-45.32  
#>  1st Qu.: 29.62   1st Qu.:119.99  
#>  Median : 72.36   Median :157.74  
#>  Mean   : 90.89   Mean   :188.72  
#>  3rd Qu.:130.36   3rd Qu.:246.19  
#>  Max.   :405.80   Max.   :575.40  
#>  NAs    :175      NAs    :175
op <- par(mfrow = c(2, 1), mar = c(3.5, 4, 2, 1))

plot(caldern$datetime, caldern$H_bulk, type = "l",
     xlab = "Zeit", ylab = "W m-2", main = "Bulk--Residual: H mit ri_guard")
abline(h = 0, lty = 2, col = "grey50")

plot(caldern$datetime, caldern$LE_bulk, type = "l",
     xlab = "Zeit", ylab = "W m-2", main = "Bulk--Residual: LE als Rest")
abline(h = 0, lty = 2, col = "grey50")


par(op)

Der Guard ist keine Reparatur. Er verhindert, dass ein neutraler Bulk-Ansatz in sehr stabilen oder schwach konditionierten Situationen scheinbar robuste Werte liefert. Aus didaktischer Sicht ist genau das wichtig: Das Paket produziert nicht nur Zahlen, sondern markiert kritische Anwendungssituationen.

Voller Methodenvergleich

Im nächsten Schritt werden die Standardpfade gemeinsam berechnet. Der Code speichert die wichtigsten Ergebnisse in expliziten Spalten, damit sie mit einfachen base-R-Mitteln verglichen werden können.

flux_all <- turb_flux_calc(ws)

caldern$H_bowen <- flux_all$sensible_bowen
caldern$LE_bowen <- flux_all$latent_bowen
caldern$H_monin <- flux_all$sensible_monin
caldern$LE_monin <- flux_all$latent_monin
caldern$LE_penman <- flux_all$latent_penman

method_summary <- data.frame(
  method = c("Priestley--Taylor", "Bulk--Residual", "Bowen", "Monin/Profile", "Penman"),
  mean_H = c(
    mean(caldern$H_pt, na.rm = TRUE),
    mean(caldern$H_bulk, na.rm = TRUE),
    mean(caldern$H_bowen, na.rm = TRUE),
    mean(caldern$H_monin, na.rm = TRUE),
    NA_real_
  ),
  mean_LE = c(
    mean(caldern$LE_pt, na.rm = TRUE),
    mean(caldern$LE_bulk, na.rm = TRUE),
    mean(caldern$LE_bowen, na.rm = TRUE),
    mean(caldern$LE_monin, na.rm = TRUE),
    mean(caldern$LE_penman, na.rm = TRUE)
  )
)

method_summary[, -1] <- round(method_summary[, -1], 1)
method_summary
#>              method mean_H mean_LE
#> 1 Priestley--Taylor   25.1    83.6
#> 2    Bulk--Residual   90.9   188.7
#> 3             Bowen  -21.1   129.8
#> 4     Monin/Profile  104.2    52.7
#> 5            Penman     NA    13.2

Vergleichsplots

Ein guter Methodenplot zeigt nicht zu viel auf einmal. Zuerst wird H verglichen, dann LE. Penman steht nur im zweiten Plot, weil dieser Pfad keine gekoppelte sensible Wärme berechnet.

op <- par(mfrow = c(2, 1), mar = c(3.5, 4, 2, 1))

h_ylim <- range(caldern[, c("H_pt", "H_bulk", "H_bowen", "H_monin")], na.rm = TRUE)
plot(caldern$datetime, caldern$H_pt, type = "l", ylim = h_ylim,
     xlab = "Zeit", ylab = "W m-2", main = "Fühlbare Wärme H")
lines(caldern$datetime, caldern$H_bulk, lty = 2)
lines(caldern$datetime, caldern$H_bowen, lty = 3)
lines(caldern$datetime, caldern$H_monin, lty = 4)
abline(h = 0, lty = 2, col = "grey50")
legend("topright", legend = c("PT", "Bulk", "Bowen", "Monin"),
       lty = 1:4, bty = "n")

le_ylim <- range(caldern[, c("LE_pt", "LE_bulk", "LE_bowen", "LE_monin", "LE_penman")], na.rm = TRUE)
plot(caldern$datetime, caldern$LE_pt, type = "l", ylim = le_ylim,
     xlab = "Zeit", ylab = "W m-2", main = "Latente Wärme LE")
lines(caldern$datetime, caldern$LE_bulk, lty = 2)
lines(caldern$datetime, caldern$LE_bowen, lty = 3)
lines(caldern$datetime, caldern$LE_monin, lty = 4)
lines(caldern$datetime, caldern$LE_penman, lty = 5)
abline(h = 0, lty = 2, col = "grey50")
legend("topright", legend = c("PT", "Bulk", "Bowen", "Monin", "Penman"),
       lty = 1:5, bty = "n")


par(op)

Die Kurven sollen nicht als Wettrennen gelesen werden. Sie zeigen, wie unterschiedliche Annahmen dieselbe Messsituation in unterschiedliche Flussschätzungen übersetzen. Große Unterschiede sind nicht automatisch Fehler. Sie sind Hinweise darauf, dass Messdesign, Gradienten, Stabilität oder Residualdefinition eine starke Rolle spielen.

Schließung und Residualdiagnostik

Die Energiebilanzdiagnostik zeigt, wie die berechneten Flüsse zur verfügbaren Energie stehen. Formal geschlossene Methoden sind nicht automatisch physikalisch validiert. Das Schließungsverhalten beschreibt zunächst nur die interne Rechenlogik.

caldern$closure_pt <- caldern$Q_minus_B - caldern$H_pt - caldern$LE_pt
caldern$closure_bulk <- caldern$Q_minus_B - caldern$H_bulk - caldern$LE_bulk
caldern$closure_bowen <- caldern$Q_minus_B - caldern$H_bowen - caldern$LE_bowen
caldern$closure_monin <- caldern$Q_minus_B - caldern$H_monin - caldern$LE_monin
caldern$penman_open <- caldern$Q_minus_B - caldern$LE_penman

closure_summary <- data.frame(
  method = c("PT", "Bulk", "Bowen", "Monin/Profile", "Penman open term"),
  mean_term = c(
    mean(caldern$closure_pt, na.rm = TRUE),
    mean(caldern$closure_bulk, na.rm = TRUE),
    mean(caldern$closure_bowen, na.rm = TRUE),
    mean(caldern$closure_monin, na.rm = TRUE),
    mean(caldern$penman_open, na.rm = TRUE)
  )
)

closure_summary$mean_term <- round(closure_summary$mean_term, 1)
closure_summary
#>             method mean_term
#> 1               PT       0.0
#> 2             Bulk       0.0
#> 3            Bowen       0.0
#> 4    Monin/Profile     -48.2
#> 5 Penman open term      95.5
plot(caldern$datetime, caldern$closure_pt, type = "l",
     xlab = "Zeit", ylab = "W m-2", main = "Schließungs- und Offenheitsdiagnostik")
lines(caldern$datetime, caldern$closure_bulk, lty = 2)
lines(caldern$datetime, caldern$closure_bowen, lty = 3)
lines(caldern$datetime, caldern$closure_monin, lty = 4)
lines(caldern$datetime, caldern$penman_open, lty = 5)
abline(h = 0, lty = 2, col = "grey50")
legend("topright", legend = c("PT", "Bulk", "Bowen", "Monin", "Penman offen"),
       lty = 1:5, bty = "n")

Für Priestley–Taylor, Bulk–Residual und Bowen kann die Nähe zur Nulllinie methodisch erwartbar sein, weil diese Pfade verfügbare Energie partitionieren oder Residuen definieren. Für Monin/Profile bleibt der Residualterm sichtbar und ist ein Diagnoseergebnis. Für Penman ist der offene Term nicht automatisch H, sondern die nicht aufgelöste Restenergie nach der latentwärmeorientierten Schätzung.

Paketdiagnostik nutzen

Wenn die installierte Paketversion die Closure-Funktionen bereitstellt, können dieselben Aussagen mit den Paketdiagnosen geprüft werden. Dieser Block bleibt bewusst klein und ergänzt die manuelle Kontrolle.

if ("energy_balance_closure" %in% getNamespaceExports("fieldClim")) {
  closure_flux <- energy_balance_closure(flux_all)
  head(closure_flux)
}
#>              datetime           method      closure_type rad_bal soil_flux
#> 1 2017-06-30 00:00:00 priestley_taylor partition_closure -15.200  1.551533
#> 2 2017-06-30 00:05:00 priestley_taylor partition_closure  -8.920  1.492695
#> 3 2017-06-30 00:10:00 priestley_taylor partition_closure  -1.965  1.448708
#> 4 2017-06-30 00:15:00 priestley_taylor partition_closure  -1.790  1.390439
#> 5 2017-06-30 00:20:00 priestley_taylor partition_closure  -2.469  1.325316
#> 6 2017-06-30 00:25:00 priestley_taylor partition_closure  -3.857  1.268762
#>   available_energy  sensible     latent turbulent_sum closure_residual
#> 1       -16.751533 -5.301183 -11.450350    -16.751533    -3.552714e-15
#> 2       -10.412695 -3.308925  -7.103770    -10.412695    -1.776357e-15
#> 3        -3.413708 -1.084238  -2.329470     -3.413708     0.000000e+00
#> 4        -3.180439 -1.002820  -2.177619     -3.180439     0.000000e+00
#> 5        -3.794316 -1.189538  -2.604778     -3.794316     4.440892e-16
#> 6        -5.125762 -1.571959  -3.553803     -5.125762    -8.881784e-16
#>   closure_ratio unresolved_complement               status
#> 1            NA                    NA low_available_energy
#> 2            NA                    NA low_available_energy
#> 3            NA                    NA low_available_energy
#> 4            NA                    NA low_available_energy
#> 5            NA                    NA low_available_energy
#> 6            NA                    NA low_available_energy

Methodenauswahl als Ergebnis

Die Auswahlregel ist einfach, aber streng. Eine Methode wird nicht gewählt, weil ihre Kurve glatter aussieht. Sie wird gewählt, weil Messarchitektur und Zielaussage zusammenpassen.

Messarchitektur Plausible Paketpfade Vorsicht
eine Messhöhe mit Q_star und B Priestley–Taylor, Penman, verfügbare Energie keine direkte gradientenbasierte H-Schätzung
zwei Messhöhen mit Temperatur und Wind Bulk–Residual, Stabilitätsprüfung LE als Rest absorbiert Eingangs- und H-Fehler
zwei Messhöhen mit Temperatur und Feuchte Bowen schwache Feuchtegradienten können dominieren
zwei Messhöhen mit Temperatur, Feuchte und Wind Monin/Profile als Diagnose nicht force-closed, stark profil- und stabilitätssensitiv
Bestand oder Turm zuerst Austauschschicht definieren keine generische Flussdeutung ohne Schichtkontext
TippArbeitsauftrag

Wählen Sie für den Caldern-Datensatz zwei Methoden aus und begründen Sie die Auswahl über Messarchitektur und Zielaussage. Vergleichen Sie nicht nur die Mittelwerte, sondern auch die Schließungsdiagnostik und die kritischen Stabilitätsfälle. Formulieren Sie am Ende einen Satz, der die Aussage fachlich begrenzt.

Literatur

Priestley, C. H. B., und R. J. Taylor. 1972. „On the assessment of surface heat flux and evaporation using large-scale parameters“. Monthly Weather Review 100 (2): 81–92. https://doi.org/10.1175/1520-0493(1972)100<0081:OTAOSH>2.3.CO;2.