Skip to content

Commit 0e81fe2

Browse files
authored
Merge pull request #4090 from infotroph/fix-4089
read LAI from sipnet.out if present
2 parents 886cd83 + db579fe commit 0e81fe2

3 files changed

Lines changed: 38 additions & 11 deletions

File tree

models/sipnet/NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# PEcAn.SIPNET 1.10.0.9000
22

3+
* `model2netcdf.SIPNET` takes `LAI` from sipnet.out if present (which requires
4+
Sipnet > v2.2). If it is not present, LAI is calculated as
5+
`plantLeafC / leafCSpWt` as previously.
36
* `split_inputs.SIPNET` now avoids internal time format conversions, giving a
47
substantial speedup and reduced memory use when processing multi-year files.
58
* `model2netcdf.SIPNET` now detects the number of timesteps per day by taking the maximum count across all days in the first simulation year, rather than reading only from day 1. This prevents a factor-of-N error in flux unit conversions when the first day of output is partial (fewer timesteps than a complete day) (#3624, #3989).

models/sipnet/R/model2netcdf.SIPNET.R

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -150,16 +150,21 @@ model2netcdf.SIPNET <- function(outdir, sitelat, sitelon, start_date, end_date,
150150
)
151151

152152

153-
# calculate LAI for standard output
154-
# LAI = plantLeafC / leafCSpWt
155-
# both operands are in carbon units (gC/m2 and gC/m2_leaf),
156-
# so no carbon fraction conversion (e.g. cFracLeaf) is needed.
157-
param <- utils::read.table(file.path(gsub(pattern = "/out/",
158-
replacement = "/run/", x = outdir),
159-
"sipnet.param"), stringsAsFactors = FALSE)
160-
leafCSpWt <- param[param[, 1] == "leafCSpWt", 2]
161-
SLA <- 1000 / leafCSpWt # m2 leaf / kg C
162-
153+
if (!("LAI" %in% colnames(sipnet_output))) {
154+
# When LAI not reported, calculate it from leaf C and leaf specific weight,
155+
# with the latter read from the parameter file.
156+
# Note the hardcoded + undocumented assumption that ../run/sipnet.param
157+
# exists and contains the values that were used to generate this output.
158+
# LAI = plantLeafC [gC/m2] / leafCSpWt [gC/m2 leaf] = m2 leaf / m2
159+
# both operands are in carbon units (gC/m2 and gC/m2_leaf),
160+
# so no carbon fraction conversion (e.g. cFracLeaf) is needed.
161+
param <- utils::read.table(file.path(gsub(pattern = "/out/",
162+
replacement = "/run/", x = outdir),
163+
"sipnet.param"), stringsAsFactors = FALSE)
164+
leafCSpWt <- param[param[, 1] == "leafCSpWt", 2]
165+
SLA <- 1000 / leafCSpWt # m2 leaf / kg C
166+
sipnet_output$LAI = sipnet_output$plantLeafC * SLA
167+
}
163168

164169
### Loop over years in SIPNET output to create separate netCDF outputs
165170
for (y in year_seq) {
@@ -208,7 +213,7 @@ model2netcdf.SIPNET <- function(outdir, sitelat, sitelon, start_date, end_date,
208213
"litter_carbon_content" = sub.sipnet.output$litter,
209214
"fine_root_carbon_content" = sub.sipnet.output$fineRootC,
210215
"coarse_root_carbon_content" = sub.sipnet.output$coarseRootC,
211-
"LAI" = sub.sipnet.output$plantLeafC * SLA,
216+
"LAI" = sub.sipnet.output$LAI,
212217
"TotLivBiom" = sub.sipnet.output$plantWoodC + sub.sipnet.output$plantLeafC +
213218
sub.sipnet.output$coarseRootC + sub.sipnet.output$fineRootC,
214219
"TotSoilCarb" = sub.sipnet.output$soil + sub.sipnet.output$litter,

models/sipnet/tests/testthat/test-model2netcdf.SIPNET.R

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,22 @@ test_that("out_day is correct when the first day of output is partial", {
291291
ts_correct <- 86400 / 2
292292
expect_equal(gpp, rep(base_row$gpp * 1e-3 / ts_correct, 5), tolerance = 1e-10)
293293
})
294+
295+
test_that("LAI taken from leafCSpWt if not present in output", {
296+
dat <- make_v2_sipnet(2)
297+
# setup_sipnet_test sets leafCSpWt = 32 => expect LAI of 1 and 10
298+
dat$plantLeafC = c(32, 320)
299+
300+
# First without LAI in dat => looks for sipnet.param in run dir
301+
paths <- setup_sipnet_test(dat, notes_line = NULL)
302+
nc1 <- ncdf4::nc_open(file.path(paths$outdir, "2002.nc"))
303+
on.exit(ncdf4::nc_close(nc1), add = TRUE)
304+
expect_equal(as.vector(ncdf4::ncvar_get(nc1, "LAI")), c(1, 10))
305+
306+
# Now with LAI specified => uses it as-is
307+
dat$LAI = c(2, 3)
308+
paths <- setup_sipnet_test(dat, notes_line = NULL)
309+
nc2 <- ncdf4::nc_open(file.path(paths$outdir, "2002.nc"))
310+
on.exit(ncdf4::nc_close(nc2), add = TRUE)
311+
expect_equal(as.vector(ncdf4::ncvar_get(nc2, "LAI")), c(2, 3))
312+
})

0 commit comments

Comments
 (0)