You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,6 +31,7 @@ For more information about this file see also [Keep a Changelog](http://keepacha
31
31
- PEcAn.SIPNET gains support for SIPNET v2, whose features includes management events, nitrogen cycle tracking, explicit N2O and methane fluxes, runtime setting of feature flags, and changes to the parameter set (now 73 parameters). SIPNET v1 is still fully supported, but workarounds for bugs in the legacy `sipnet.unk` version have been removed.
32
32
- Added `PEcAn.data.land::to_co2e()` for converting SOC change, CH4, and N2O to CO2-equivalent emissions using IPCC Global Warming Potential values.
33
33
- Added `PEcAn.data.land::event_parquet_to_json` for generating PEcAn `event.json` files from well-formatted event parquet files, with support for ensembles of events.
34
+
- Added statewide synthetic fertilization and compost amendment event workflows for CA ag parcels. Outputs share an ensemble naming so a downstream cleaner unions them into one fertilization event type for SIPNET.
34
35
35
36
### Fixed
36
37
- Docker GHA workflow no longer fails on pull requests opened from forks (#3618).
@@ -42,6 +43,7 @@ For more information about this file see also [Keep a Changelog](http://keepacha
42
43
-`segment_dataframe()` now returns an empty dataframe when date filtering removes all crop-cycle segments, instead of a single row with NA columns that caused downstream segment config errors (#4007).
43
44
44
45
### Changed
46
+
- Added `ensemble_downscale()`, a refactored version of `SDA_downscale()`.
45
47
-`PEcAn.uncertainty::get.parameter.samples()`: replaced the `save_to_disk` flag (from #3860) with an `outdir` argument (default `settings$outdir`) controlling whether `samples.Rdata` is written; `outdir = NULL` skips the save. Existing callers are unaffected (@omkarrr2533, #4016)
46
48
- Updated Docker architecture documentation to match current docker-compose.yml: removed portainer/minio/thredds, added rstudio/api sections, updated service lists and volumes (#3268).
47
49
- Improved PEcAn.SIPNET documentation including README, model description, and current installation instructions (@Eshaan-byte; #3703, #3705).
Copy file name to clipboardExpand all lines: documentation/tutorials/Demo_02_Uncertainty_Analysis/uncertainty.qmd
+14-3Lines changed: 14 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -121,13 +121,24 @@ See Demo 1 Section 6 for details on what these functions do. Briefly, they read
121
121
122
122
# Write Model Configuration Files {#sec-write-configs}
123
123
124
-
This step generates the model-specific configuration files that will be used to run the ecosystem model. The process involves:
124
+
This step decides which model runs to do, then writes the configuration files for them.
125
+
126
+
`generate_joint_ensemble_design()` builds the ensemble design: one row per run, holding indices that say which parameter draw each run uses. It returns those samples alongside the design, since the indices only mean anything together with the samples they point into. Because this demo also runs a sensitivity analysis, the SA design is generated internally as well; passing one in yourself isn't supported yet.
125
127
126
-
2. Generating SIPNET configuration files using the `runModule.run.write.configs()` function.
Generating the design yourself lets you inspect it before any runs happen: `design$design_matrix` is the table of runs, and `design$samples` holds the parameter draws behind it, which is what the sensitivity and variance decomposition steps later report on.
141
+
131
142
# Run Model Simulations
132
143
133
144
This section executes the SIPNET simulations and retrieves the results.
@@ -39,7 +39,7 @@ This notebook demonstrates how to:
39
39
40
40
We are modeling carbon and productivity dynamics at the Niwot Ridge Forest AmeriFlux site ([US-NR1](https://ameriflux.lbl.gov/sites/siteinfo/US-NR1), a high-elevation temperate coniferous forest in Colorado. The model configuration uses the SIPNET process-based ecosystem model, parameterized with a temperate coniferous plant functional type (PFT).
41
41
42
-
The simulation is run for the full year 2004 (January 1 – December 31) using AmeriFlux LBL meteorological drivers from the Niwot Ridge site. The ensemble setup specifies one model run focusing on net primary productivity (NPP) as the target output variable.
42
+
The simulation is run for the full year 2004 (January 1 – December 31) using AmeriFlux LBL meteorological drivers from the Niwot Ridge site. The ensemble setup specifies a small ten member ensemble focusing on net primary productivity (NPP) as the target output variable, so the plots later on show the spread across members rather than a single line.
43
43
44
44
This scenario is designed to be a minimal, reproducible example to demonstrate how to run SIPNET within the PEcAn workflow. In later steps, this same framework can be extended to include more ensemble members, additional PFTs, longer time periods, or alternative meteorological inputs.
45
45
@@ -192,12 +192,26 @@ Additional outputs include logs, a `STATUS` file that records the steps of the w
192
192
193
193
# Write Model Configuration Files
194
194
195
-
This step generates the model-specific configuration files and scripts that will be used to run the ecosystem model. The process involves generating SIPNET configuration files using the `runModule.run.write.configs()` function.
195
+
This step decides which model runs to do, then writes the configuration files for them.
196
+
197
+
`generate_joint_ensemble_design()` builds the design: one row per run, holding indices that say which parameter draw and which input file each run uses. It returns those samples alongside the design, since the indices only mean anything together with the samples they point into.
198
+
199
+
`runModule.run.write.configs()` then takes that whole object and writes the SIPNET configuration files.
You can call `runModule.run.write.configs()` without a design and it will build one for itself, but that path is deprecated and will warn. Generating the design yourself also lets you inspect it before any runs happen: `design$design_matrix` is the table of runs, and `design$samples` holds the parameter draws behind it.
214
+
201
215
# Run Model Simulations and Fetch Results
202
216
203
217
This section executes the actual model simulations and retrieves the results. The process is managed by PEcAn's workflow system, which handles the execution of your chosen ecosystem model.
@@ -215,27 +229,68 @@ This step generates raw model outputs in model-specific format (in this case, `s
215
229
216
230
After the model simulation completes, we need to extract the results and prepare them for analysis. This involves:
217
231
218
-
1. Reading the run ID
232
+
1. Reading the run IDs
219
233
2. Setting up output paths
220
234
3. Defining time period
221
235
4. Loading model output
222
236
5. Convert to a standard format
223
237
224
238
```{r get-plot-vars}
225
-
runid <- as.character(read.table(paste(settings$outdir, "/run/", "runs.txt", sep = ""))[1, 1]) # Note: if you are using an xml from a run with multiple ensembles this line will provide only the first run id
# empty plot drawn off the real time axis, so the x axis stays dates
278
+
plot(
279
+
data[[1]]$posix,
280
+
data[[1]][[vars[1]]],
281
+
type = "n",
282
+
ylim = yrange,
283
+
xlab = "Date",
284
+
ylab = ylab,
285
+
main = main
286
+
)
287
+
for (i in seq_along(vars)) {
288
+
for (member in data) {
289
+
lines(member$posix, member[[vars[i]]], col = adjustcolor(cols[i], alpha.f = 0.4))
290
+
}
291
+
}
292
+
legend("topright", legend = labels, col = cols, lty = 1)
293
+
}
239
294
```
240
295
241
296
Running this code will convert model specific output files into a standardized netCDF ([year].nc) that can be downloaded for visualization and analysis (R, Matlab, ncview, panoply, etc). This is a key step, because this standardization enables PEcAn to apply downstream analyses to outputs from different ecosystem models.
This section provides examples of how to create time series plots of different model variables. The examples cover various ecosystem processes including carbon fluxes, carbon pools, water variables, and structural variables like Leaf Area Index (LAI).
269
324
325
+
Each plot draws one line per ensemble member. The members differ only in their parameter draws, so the spread between the lines is the parameter uncertainty carried through the model.
326
+
270
327
## Plot Carbon Fluxes
271
328
329
+
Some members run negative NPP even in the growing season. That happens when the drawn respiration parameters outweigh photosynthesis, and it shows up here because this demo samples from priors rather than from a meta-analysis, so the spread is wide. Demo 3 shows what constraining these parameters with data does to that spread.
330
+
331
+
GPP and NPP are sub-daily fluxes, so ten overlaid members would just fill the panel. These are averaged to daily values first, which is enough to see the members apart.
332
+
272
333
```{r plot-carbon-fluxes}
273
-
# Plot Gross Primary Productivity (GPP) and Net Primary Productivity (NPP)
274
-
plot(model_output$posix, model_output$GPP,
275
-
type = "l",
276
-
col = "green",
277
-
xlab = "Date",
334
+
plot_ensemble(
335
+
vars = c("GPP", "NPP"),
336
+
cols = c("green", "blue"),
278
337
ylab = "Carbon Flux (kg C m-2 s-1)",
279
-
main = "Carbon Fluxes Over Time"
338
+
main = "Carbon Fluxes Over Time (daily average)",
339
+
data = daily_output
280
340
)
281
-
lines(model_output$posix, model_output$NPP, col = "blue")
labels = c("Total Live Biomass", "Total Soil Carbon"),
293
350
ylab = "Carbon Pool (kg C m-2)",
294
351
main = "Carbon Pools Over Time"
295
352
)
296
-
lines(model_output$posix, model_output$TotSoilCarb, col = "brown")
297
-
legend("topright", legend = c("Total Live Biomass", "Total Soil Carbon"), col = c("darkgreen", "brown"), lty = 1)
298
353
```
299
354
300
355
## Plot Water Variables
301
356
357
+
Soil moisture separates into ten lines once the growing season starts, but snow water equivalent stays a single line. That is expected: snow is driven by the met input, which is the same file for every member, while soil moisture responds to the sampled parameters.
358
+
302
359
```{r plot-water-variables}
303
-
# Plot Soil Moisture and Snow Water Equivalent
304
-
plot(model_output$posix, model_output$SoilMoist,
305
-
type = "l",
306
-
col = "blue",
307
-
xlab = "Date",
308
-
ylab = "Soil Moisture (kg m-2)",
309
-
main = "Soil Moisture Over Time"
360
+
plot_ensemble(
361
+
vars = c("SoilMoist", "SWE"),
362
+
cols = c("blue", "lightblue"),
363
+
labels = c("Soil Moisture", "Snow Water Equivalent"),
364
+
ylab = "Water (kg m-2)",
365
+
main = "Soil Moisture and Snow Water Equivalent Over Time"
310
366
)
311
-
lines(model_output$posix, model_output$SWE, col = "lightblue")
312
-
legend("topright", legend = c("Soil Moisture", "Snow Water Equivalent"), col = c("blue", "lightblue"), lty = 1)
313
367
```
314
368
315
-
## Plot LAI and Biomass
369
+
## Plot LAI and Above Ground Wood
316
370
317
371
```{r plot-lai-biomass}
318
-
# Plot Leaf Area Index (LAI) and Above Ground Wood
319
-
plot(model_output$posix, model_output$LAI,
320
-
type = "l",
321
-
col = "darkgreen",
322
-
xlab = "Date",
372
+
plot_ensemble(
373
+
vars = "LAI",
374
+
cols = "darkgreen",
323
375
ylab = "LAI (m2 m-2)",
324
376
main = "Leaf Area Index Over Time"
325
377
)
326
-
lines(model_output$posix, model_output$AbvGrndWood, col = "brown")
0 commit comments