Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
5599e09
Replace manual unit conversions with ud_convert()
ayushman1210 Dec 14, 2025
2fc0106
Update models/stics/R/met2model.STICS.R
ayushman1210 Dec 15, 2025
c425ca7
Update models/sipnet/R/write_restart.SIPNET.R
ayushman1210 Dec 15, 2025
747277a
Merge branch 'develop' into fix
ayushman1210 Dec 19, 2025
c29e56f
fixes done as per maintainer suggestion
ayushman1210 Dec 19, 2025
a2d79d5
Merge branch 'fix' of https://github.com/ayushman1210/pecan into fix
ayushman1210 Dec 19, 2025
8e2b0a4
Merge branch 'develop' into fix
ayushman1210 Dec 24, 2025
aa8f2d4
Update models/dalec/R/model2netcdf.DALEC.R
ayushman1210 Dec 26, 2025
e6ad156
Update models/dalec/R/model2netcdf.DALEC.R
ayushman1210 Dec 26, 2025
0c2bb74
Update models/gday/R/model2netcdf.GDAY.R
ayushman1210 Dec 26, 2025
1aeddf7
Update tests/testthat/test_model_conversions.R
ayushman1210 Dec 26, 2025
570b899
Update tests/testthat/test_model_conversions.R
ayushman1210 Dec 26, 2025
9970af2
Update tests/testthat/test_model_conversions.R
ayushman1210 Dec 26, 2025
476de3d
Update tests/testthat/test_model_conversions.R
ayushman1210 Dec 26, 2025
2fdc5d9
Merge branch 'develop' into fix
infotroph Jan 7, 2026
46773d1
Merge branch 'develop' into fix
ayushman1210 Jan 12, 2026
20bd418
changes as suggested by the maintainer
ayushman1210 Jan 12, 2026
adecf54
suggested changes
ayushman1210 Jan 12, 2026
6ecf394
Merge branch 'develop' into fix
ayushman1210 Jan 13, 2026
10950c9
Merge branch 'develop' into fix
ayushman1210 Jan 13, 2026
a21b66f
Merge branch 'develop' into fix
ayushman1210 Jan 14, 2026
a7d584a
Merge branch 'develop' into fix
ayushman1210 Jan 16, 2026
f78452c
Merge branch 'develop' into fix
ayushman1210 Jan 16, 2026
c7786e6
Merge branch 'develop' into fix
ayushman1210 Jan 19, 2026
c84dc76
Merge branch 'develop' into fix
ayushman1210 Jan 21, 2026
3b1d45d
Merge branch 'develop' into fix
infotroph Jan 23, 2026
ae48649
Update models/fates/R/write.configs.FATES.R
ayushman1210 Jan 24, 2026
4d9ca18
Update models/fates/R/write.configs.FATES.R
ayushman1210 Jan 24, 2026
b63051f
Update models/sipnet/R/model2netcdf.SIPNET.R
ayushman1210 Jan 24, 2026
014e58f
Update models/fates/R/write.configs.FATES.R
ayushman1210 Jan 24, 2026
d0f49ee
Update models/fates/R/write.configs.FATES.R
ayushman1210 Jan 24, 2026
73db407
Merge branch 'develop' into fix
ayushman1210 Jan 27, 2026
785d156
removed testthat.R updated model2netcdf.SIPNET.R updated model2netcdf…
ayushman1210 Jan 28, 2026
de366f6
Fix: Skip Docker push on forks to avoid ghcr.io authentication errors
ayushman1210 Jan 28, 2026
ec3c96c
Add GDAY unit conversion tests and clean up redundant test files
ayushman1210 Jan 28, 2026
6ac287a
Add unit tests for SIPNET model2netcdf unit conversion changes
ayushman1210 Jan 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/docker-build-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,13 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}

# build the docker images
# Only push to registry on the main repository, not on forks
- name: Build and push ${{ steps.name.outputs.image_name }}
uses: docker/build-push-action@v6
with:
context: ${{ inputs.build-context }}
file: ${{ inputs.dockerfile }}
push: true
push: ${{ github.repository == 'pecanproject/pecan' }}
platforms: ${{ inputs.platforms }}
cache-from: type=gha
cache-to: type=gha,mode=max
Expand Down
17 changes: 17 additions & 0 deletions base/utils/tests/testthat/test-ud_convert.R
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,21 @@ test_that("ud_convert() warns with wrong input units for difftime", {
expect_warning(ud_convert(as.difftime("12:00:00"), u1 = "years", u2 = "minutes"))
#should still error if units are not convertible
expect_error(ud_convert(as.difftime("12:00:00"), u1 = "kilograms", u2 = "minutes"))
})

test_that("model-specific pool conversions", {
# DALEC/SIPNET C pools
expect_equal(ud_convert(100, "g/m2", "kg/m2"), 0.1)
# GDAY pools
expect_equal(ud_convert(10, "Mg/ha", "kg/m2"), 1)
})

test_that("model-specific flux conversions", {
# DALEC/SIPNET C fluxes
expect_equal(ud_convert(86400, "g/m2/d", "kg/m2/s"), 0.001, tolerance = 1e-10)
})

test_that("photosynthesis parameters", {
# Photosynthesis energy parameters
expect_equal(ud_convert(1000, "J/mol", "kJ/mol"), 1)
})
30 changes: 15 additions & 15 deletions models/dalec/R/model2netcdf.DALEC.R
Original file line number Diff line number Diff line change
Expand Up @@ -83,22 +83,22 @@ model2netcdf.DALEC <- function(outdir, sitelat, sitelon, start_date, end_date) {

## Setup outputs for netCDF file in appropriate units
output <- list()
## Fluxes
output[[1]] <- (sub.DALEC.output[, 1] * 0.001)/timestep.s # Autotrophic Respiration in kgC/m2/s
output[[2]] <- (sub.DALEC.output[, 21] + sub.DALEC.output[, 23]) * 0.001 / timestep.s # Heterotrophic Resp kgC/m2/s
output[[3]] <- (sub.DALEC.output[, 31] * 0.001)/timestep.s # GPP in kgC/m2/s
output[[4]] <- (sub.DALEC.output[, 33] * 0.001)/timestep.s # NEE in kgC/m2/s
output[[5]] <- (sub.DALEC.output[, 3] + sub.DALEC.output[, 5] + sub.DALEC.output[, 7]) * 0.001/timestep.s # NPP kgC/m2/s
output[[6]] <- (sub.DALEC.output[, 9] * 0.001) / timestep.s # Leaf Litter Flux, kgC/m2/s
output[[7]] <- (sub.DALEC.output[, 11] * 0.001) / timestep.s # Woody Litter Flux, kgC/m2/s
output[[8]] <- (sub.DALEC.output[, 13] * 0.001) / timestep.s # Root Litter Flux, kgC/m2/s
## Fluxes (convert g/m2/day to kg/m2/s)
output[[1]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 1], "g/m2/d", "kg/m2/s") # Autotrophic Respiration
output[[2]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 21] + sub.DALEC.output[, 23], "g/m2/d", "kg/m2/s") # Heterotrophic Resp
output[[3]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 31], "g/m2/d", "kg/m2/s") # GPP
output[[4]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 33], "g/m2/d", "kg/m2/s") # NEE
output[[5]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 3] + sub.DALEC.output[, 5] + sub.DALEC.output[, 7], "g/m2/d", "kg/m2/s") # NPP
output[[6]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 9], "g/m2/d", "kg/m2/s") # Leaf Litter Flux
output[[7]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 11], "g/m2/d", "kg/m2/s") # Woody Litter Flux
output[[8]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 13], "g/m2/d", "kg/m2/s") # Root Litter Flux

## Pools
output[[9]] <- (sub.DALEC.output[, 15] * 0.001) # Leaf Carbon, kgC/m2
output[[10]] <- (sub.DALEC.output[, 17] * 0.001) # Wood Carbon, kgC/m2
output[[11]] <- (sub.DALEC.output[, 19] * 0.001) # Root Carbon, kgC/m2
output[[12]] <- (sub.DALEC.output[, 27] * 0.001) # Litter Carbon, kgC/m2
output[[13]] <- (sub.DALEC.output[, 29] * 0.001) # Soil Carbon, kgC/m2
## Pools (convert g/m2 to kg/m2)
output[[9]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 15], "g/m2", "kg/m2") # Leaf Carbon
output[[10]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 17], "g/m2", "kg/m2") # Wood Carbon
output[[11]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 19], "g/m2", "kg/m2") # Root Carbon
output[[12]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 27], "g/m2", "kg/m2") # Litter Carbon
output[[13]] <- PEcAn.utils::ud_convert(sub.DALEC.output[, 29], "g/m2", "kg/m2") # Soil Carbon

## standard composites
output[[14]] <- output[[1]] + output[[2]] # Total Respiration
Expand Down
8 changes: 4 additions & 4 deletions models/fates/R/write.configs.FATES.R
Original file line number Diff line number Diff line change
Expand Up @@ -307,25 +307,25 @@ write.config.FATES <- function(defaults, trait.values, settings, run.id){
# Ha activation energy for vcmax - FATES units: J/mol
if(var == "Ha_Modified_Arrhenius_Vcmax"){
ncdf4::ncvar_put(nc=fates.param.nc, varid='fates_vcmaxha', start = ipft, count = 1,
vals=pft[v]*1000) ## convert from kj/mol to J/mol (FATES units)
vals=PEcAn.utils::ud_convert(pft[v], "kJ/mol", "J/mol"))
}

# Hd deactivation energy for vcmax - FATES units: J/mol
if(var == "Hd_Modified_Arrhenius_Vcmax"){
ncdf4::ncvar_put(nc=fates.param.nc, varid='fates_vcmaxhd', start = ipft, count = 1,
vals=pft[v]*1000) ## convert from kj/mol to J/mol (FATES units)
vals = PEcAn.utils::ud_convert(pft[v], "kJ/mol", "J/mol"))
}

# Ha activation energy for Jmax - FATES units: J/mol
if(var == "Ha_Modified_Arrhenius_Jmax"){
ncdf4::ncvar_put(nc=fates.param.nc, varid='fates_jmaxha', start = ipft, count = 1,
vals=pft[v]*1000) ## convert from kj/mol to J/mol (FATES units)
vals = PEcAn.utils::ud_convert(pft[v], "kJ/mol", "J/mol"))
}

# Hd deactivation energy for Jmax - FATES units: J/mol
if(var == "Hd_Modified_Arrhenius_Jmax"){
ncdf4::ncvar_put(nc=fates.param.nc, varid='fates_jmaxhd', start = ipft, count = 1,
vals=pft[v]*1000) ## convert from kj/mol to J/mol (FATES units)
vals = PEcAn.utils::ud_convert(pft[v], "kJ/mol", "J/mol"))
}

# deltaS Vcmax - BETY units:J/mol/K; FATES units: J/mol/K
Expand Down
23 changes: 10 additions & 13 deletions models/gday/R/model2netcdf.GDAY.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
model2netcdf.GDAY <- function(outdir, sitelat, sitelon, start_date, end_date) {


G_2_KG <- 0.001
TONNES_PER_HA_TO_G_M2 <- 100
THA_2_KG_M2 <- TONNES_PER_HA_TO_G_M2 * 0.001

### Read in model output in GDAY format
GDAY.output <- utils::read.csv(file.path(outdir, "gday_out.csv"), header = TRUE, sep = ",", skip = 1)
Expand All @@ -44,17 +41,17 @@ model2netcdf.GDAY <- function(outdir, sitelat, sitelon, start_date, end_date) {
output <- list()

## standard variables: C-Fluxes
output[[1]] <- (sub.GDAY.output[, "auto_resp"] * THA_2_KG_M2) / timestep.s
output[[2]] <- (sub.GDAY.output[, "hetero_resp"] * THA_2_KG_M2) / timestep.s
output[[3]] <- (sub.GDAY.output[, "auto_resp"] + sub.GDAY.output[, "hetero_resp"] *
THA_2_KG_M2) / timestep.s
output[[4]] <- (sub.GDAY.output[, "gpp"] * THA_2_KG_M2) / timestep.s
output[[5]] <- (sub.GDAY.output[, "nep"] * -1 * THA_2_KG_M2) / timestep.s
output[[6]] <- (sub.GDAY.output[, "npp"] * THA_2_KG_M2) / timestep.s
# GDAY outputs in Mg/ha/day, convert directly to kgC/m2/s (ud_convert returns per-second)
output[[1]] <- PEcAn.utils::ud_convert(sub.GDAY.output[, "auto_resp"], "Mg/ha/day", "kg/m2/s")
output[[2]] <- PEcAn.utils::ud_convert(sub.GDAY.output[, "hetero_resp"], "Mg/ha/day", "kg/m2/s")
output[[3]] <- PEcAn.utils::ud_convert(sub.GDAY.output[, "auto_resp"] + sub.GDAY.output[, "hetero_resp"], "Mg/ha/day", "kg/m2/s")
output[[4]] <- PEcAn.utils::ud_convert(sub.GDAY.output[, "gpp"], "Mg/ha/day", "kg/m2/s")
output[[5]] <- PEcAn.utils::ud_convert(sub.GDAY.output[, "nep"] * -1, "Mg/ha/day", "kg/m2/s")
output[[6]] <- PEcAn.utils::ud_convert(sub.GDAY.output[, "npp"], "Mg/ha/day", "kg/m2/s")

## standard variables: C-State
output[[7]] <- (sub.GDAY.output[, "stem"] + sub.GDAY.output[, "branch"] * THA_2_KG_M2) / timestep.s
output[[8]] <- (sub.GDAY.output[, "soilc"] * THA_2_KG_M2) / timestep.s
## standard variables: C-State (pools) - divide by timestep as in original code
output[[7]] <- (PEcAn.utils::ud_convert(sub.GDAY.output[, "stem"], "Mg/ha", "kg/m2") + sub.GDAY.output[, "branch"] * THA_2_KG_M2) / timestep.s
output[[8]] <- PEcAn.utils::ud_convert(sub.GDAY.output[, "soilc"], "Mg/ha", "kg/m2") / timestep.s
output[[9]] <- (sub.GDAY.output[, "lai"])

## standard variables: water fluxes
Expand Down
98 changes: 98 additions & 0 deletions models/gday/tests/testthat/test.model2netcdf.GDAY.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
##' Test for GDAY model2netcdf unit conversions
##'
##' This test verifies that the unit conversions in model2netcdf.GDAY are correct.
##'
##' Reference: https://github.com/PecanProject/pecan/pull/XXXX
##' GDAY outputs daily values in Mg/ha/day, which should be converted to kg/m2/s
##'
##' Conversion factors:
##' 1 Mg/ha = 0.1 kg/m2 (area conversion)
##' 1 day = 86400 seconds
##' Therefore: 1 Mg/ha/day = 0.1 / 86400 kg/m2/s = 1.157e-6 kg/m2/s

context("GDAY model2netcdf unit conversions")

test_that("GDAY Mg/ha/day to kg/m2/s conversion is correct", {
# Test data - using simple round numbers for verification
# GDAY example output: https://github.com/mdekauwe/GDAY/blob/master/example/outputs/D1GDAYDUKEAMB.csv

# Manual conversion test
# 1 Mg/ha/day -> kg/m2/s conversion factor
conversion_factor <- 0.1 / 86400 # ~1.157e-6

# Test value from GDAY output (example: 0.05 Mg/ha/day)
gday_value_mgha_day <- 0.05
expected_value_kgm2s <- gday_value_mgha_day * conversion_factor

# Verify using ud_convert (if available)
if (requireNamespace("PEcAn.utils", quietly = TRUE)) {
converted_value <- PEcAn.utils::ud_convert(gday_value_mgha_day, "Mg/ha/day", "kg/m2/s")
expect_equal(converted_value, expected_value_kgm2s, tolerance = 1e-10,
label = "GDAY daily output conversion")
}

# More realistic test values based on GDAY Duke Ambient output
# From D1GDAYDUKEAMB.csv: GPP ~= 3.5 Mg/ha/day for summer months
gday_gpp <- 3.5
converted_gpp <- gday_gpp * conversion_factor

# This should be approximately 4.05e-6 kg/m2/s
expect_true(converted_gpp > 0, "Conversion should result in positive value")
expect_true(converted_gpp < 1e-5, "Converted value should be small (< 1e-5 kg/m2/s)")
})

test_that("GDAY timestep is correctly set to daily (86400 seconds)", {
# The timestep.s in model2netcdf.GDAY should be 86400 seconds (1 day)
# This is different from SIPNET which uses 86400/out_day for more flexible timesteps
timestep_s <- 86400

expect_equal(timestep_s, 86400,
label = "GDAY timestep should be 86400 seconds (daily data)")

# Verify that this matches the conversion (since ud_convert assumes per-second)
seconds_per_day <- 86400
expect_equal(timestep_s, seconds_per_day)
})

test_that("GDAY flux variables are converted from Mg/ha/day not Mg/ha/yr", {
# GDAY outputs are daily accumulations, not annual
# The conversion should use "Mg/ha/day" not "Mg/ha/yr"

# Test with a realistic GDAY value
# Example: auto_resp (autotrophic respiration) ~ 0.02-0.05 Mg/ha/day
auto_resp_daily <- 0.035

# Correct conversion: Mg/ha/day -> kg/m2/s
if (requireNamespace("PEcAn.utils", quietly = TRUE)) {
correct_result <- PEcAn.utils::ud_convert(auto_resp_daily, "Mg/ha/day", "kg/m2/s")

# Incorrect conversion (old code): Mg/ha/yr -> kg/m2/s
# This would give a much larger value (365 times larger!)
incorrect_result <- PEcAn.utils::ud_convert(auto_resp_daily, "Mg/ha/yr", "kg/m2/s")

# The incorrect result should be ~365x larger
ratio <- incorrect_result / correct_result
expect_true(ratio > 300 & ratio < 400,
label = "Incorrect Mg/ha/yr conversion would be ~365x larger")
}
})

test_that("GDAY respiration outputs consistency check", {
# Test that total respiration = auto_resp + hetero_resp (within floating point precision)
if (requireNamespace("PEcAn.utils", quietly = TRUE)) {
# Test values
auto_resp <- 0.03
hetero_resp <- 0.02
total_resp <- auto_resp + hetero_resp

# All should convert to same scale (kg/m2/s)
auto_resp_kgm2s <- PEcAn.utils::ud_convert(auto_resp, "Mg/ha/day", "kg/m2/s")
hetero_resp_kgm2s <- PEcAn.utils::ud_convert(hetero_resp, "Mg/ha/day", "kg/m2/s")
total_resp_kgm2s <- PEcAn.utils::ud_convert(total_resp, "Mg/ha/day", "kg/m2/s")

# Total should equal sum of components
expect_equal(total_resp_kgm2s, auto_resp_kgm2s + hetero_resp_kgm2s,
tolerance = 1e-15,
label = "Total respiration should equal sum of components")
}
})
40 changes: 19 additions & 21 deletions models/sipnet/R/model2netcdf.SIPNET.R
Original file line number Diff line number Diff line change
Expand Up @@ -134,21 +134,19 @@ model2netcdf.SIPNET <- function(outdir, sitelat, sitelon, start_date, end_date,
bounds <- round(bounds,4)

## Setup outputs for netCDF file in appropriate units
output <- list(
"GPP" = (sub.sipnet.output$gpp * 0.001) / timestep.s, # GPP in kgC/m2/s
"NPP" = (sub.sipnet.output$gpp * 0.001) / timestep.s - ((sub.sipnet.output$rAboveground *
0.001) / timestep.s + (sub.sipnet.output$rRoot * 0.001) / timestep.s), # NPP in kgC/m2/s. Post SIPNET calculation
"TotalResp" = (sub.sipnet.output$rtot * 0.001) / timestep.s, # Total Respiration in kgC/m2/s
"AutoResp" = (sub.sipnet.output$rAboveground * 0.001) / timestep.s + (sub.sipnet.output$rRoot *
0.001) / timestep.s, # Autotrophic Respiration in kgC/m2/s
"HeteroResp" = ((sub.sipnet.output$rSoil - sub.sipnet.output$rRoot) * 0.001) / timestep.s, # Heterotrophic Respiration in kgC/m2/s
"SoilResp" = (sub.sipnet.output$rSoil * 0.001) / timestep.s, # Soil Respiration in kgC/m2/s
"NEE" = (sub.sipnet.output$nee * 0.001) / timestep.s, # NEE in kgC/m2/s
"AbvGrndWood" = (sub.sipnet.output$plantWoodC * 0.001), # Above ground wood kgC/m2
"leaf_carbon_content" = (sub.sipnet.output$plantLeafC * 0.001), # Leaf C kgC/m2
"TotLivBiom" = (sub.sipnet.output$plantWoodC * 0.001) + (sub.sipnet.output$plantLeafC * 0.001) +
(sub.sipnet.output$coarseRootC + sub.sipnet.output$fineRootC) * 0.001, # Total living C kgC/m2
"TotSoilCarb" = (sub.sipnet.output$soil * 0.001) + (sub.sipnet.output$litter * 0.001) # Total soil C kgC/m2
output <- list(
"GPP" = PEcAn.utils::ud_convert(sub.sipnet.output$gpp, "g/m2", "kg/m2") / timestep.s,
"NPP" = PEcAn.utils::ud_convert(sub.sipnet.output$gpp - (sub.sipnet.output$rAboveground + sub.sipnet.output$rRoot), "g/m2", "kg/m2") / timestep.s,
"TotalResp" = PEcAn.utils::ud_convert(sub.sipnet.output$rtot, "g/m2", "kg/m2") / timestep.s,
"AutoResp" = (PEcAn.utils::ud_convert(sub.sipnet.output$rAboveground + sub.sipnet.output$rRoot, "g/m2", "kg/m2")) / timestep.s,
"HeteroResp" = PEcAn.utils::ud_convert(sub.sipnet.output$rSoil - sub.sipnet.output$rRoot, "g/m2", "kg/m2") / timestep.s,
"SoilResp" = PEcAn.utils::ud_convert(sub.sipnet.output$rSoil, "g/m2", "kg/m2") / timestep.s,
"NEE" = PEcAn.utils::ud_convert(sub.sipnet.output$nee, "g/m2", "kg/m2") / timestep.s,
"AbvGrndWood" = PEcAn.utils::ud_convert(sub.sipnet.output$plantWoodC, "g/m2", "kg/m2"),
"leaf_carbon_content" = PEcAn.utils::ud_convert(sub.sipnet.output$plantLeafC, "g/m2", "kg/m2"),
"TotLivBiom" = (PEcAn.utils::ud_convert(sub.sipnet.output$plantWoodC + sub.sipnet.output$plantLeafC +
sub.sipnet.output$coarseRootC + sub.sipnet.output$fineRootC, "g/m2", "kg/m2")),
"TotSoilCarb" = PEcAn.utils::ud_convert(sub.sipnet.output$soil + sub.sipnet.output$litter, "g/m2", "kg/m2")
)
if (revision == "unk") {
## *** NOTE : npp in the sipnet output file is actually evapotranspiration, this is due to a bug in sipnet.c : ***
Expand All @@ -164,8 +162,8 @@ model2netcdf.SIPNET <- function(outdir, sitelat, sitelon, start_date, end_date,
output[["SoilMoist"]] <- (sub.sipnet.output$soilWater * 10) # Soil moisture kgW/m2
output[["SoilMoistFrac"]] <- (sub.sipnet.output$soilWetnessFrac) # Fractional soil wetness
output[["SWE"]] <- (sub.sipnet.output$snow * 10) # SWE
output[["litter_carbon_content"]] <- sub.sipnet.output$litter * 0.001 ## litter kgC/m2
output[["litter_mass_content_of_water"]] <- (sub.sipnet.output$litterWater * 10) # Litter water kgW/m2
output[["litter_carbon_content"]] <- PEcAn.utils::ud_convert(sub.sipnet.output$litter, "g/m2", "kg/m2")
output[["litter_mass_content_of_water"]] <- PEcAn.utils::ud_convert(sub.sipnet.output$litterWater, "cm", "mm") # labeled elsewhere as kg water m-2 (which is equivalent but ud_convert doesn't know that)
#calculate LAI for standard output
param <- utils::read.table(file.path(gsub(pattern = "/out/",
replacement = "/run/", x = outdir),
Expand All @@ -174,10 +172,10 @@ model2netcdf.SIPNET <- function(outdir, sitelat, sitelon, start_date, end_date,
leafC <- 0.48
SLA <- 1000 / param[id, 2] #SLA, m2/kgC
output[["LAI"]] <- output[["leaf_carbon_content"]] * SLA # LAI
output[["fine_root_carbon_content"]] <- sub.sipnet.output$fineRootC * 0.001 ## fine_root_carbon_content kgC/m2
output[["coarse_root_carbon_content"]] <- sub.sipnet.output$coarseRootC * 0.001 ## coarse_root_carbon_content kgC/m2
output[["GWBI"]] <- (sub.sipnet.output$woodCreation * 0.001) / 86400 ## kgC/m2/s - this is daily in SIPNET
output[["AGB"]] <- (sub.sipnet.output$plantWoodC + sub.sipnet.output$plantLeafC) * 0.001 # Total aboveground biomass kgC/m2
output[["fine_root_carbon_content"]] <- PEcAn.utils::ud_convert(sub.sipnet.output$fineRootC, "g/m2", "kg/m2")
output[["coarse_root_carbon_content"]] <- PEcAn.utils::ud_convert(sub.sipnet.output$coarseRootC, "g/m2", "kg/m2")
output[["GWBI"]] <- PEcAn.utils::ud_convert(sub.sipnet.output$woodCreation, "g/m2/d", "kg/m2/s")
output[["AGB"]] <- PEcAn.utils::ud_convert(sub.sipnet.output$plantWoodC + sub.sipnet.output$plantLeafC, "g/m2", "kg/m2")
output[["time_bounds"]] <- c(rbind(bounds[,1], bounds[,2]))

# ******************** Declare netCDF variables ********************#
Expand Down
3 changes: 1 addition & 2 deletions models/sipnet/R/write_restart.SIPNET.R
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,11 @@ write_restart.SIPNET <- function(outdir, runid, start.time, stop.time, settings,

## Converting to sipnet units
prior.sla <- new.params[[which(!names(new.params) %in% c("soil", "soil_SDA", "restart"))[1]]]$SLA
unit.conv <- 2 * (10000 / 1) * (1 / 1000) * (3.154 * 10^7) # kgC/m2/s -> Mg/ha/yr

analysis.save <- list()

if ("NPP" %in% variables) {
analysis.save[[length(analysis.save) + 1]] <- PEcAn.utils::ud_convert(new.state$NPP, "kg/m^2/s", "Mg/ha/yr") #*unit.conv -> Mg/ha/yr
analysis.save[[length(analysis.save) + 1]] <- PEcAn.utils::ud_convert(new.state$NPP, "kg/m^2/s", "Mg/ha/yr")
names(analysis.save[[length(analysis.save)]]) <- c("NPP")
}

Expand Down
5 changes: 0 additions & 5 deletions models/sipnet/tests/testthat.R

This file was deleted.

Loading
Loading