Skip to content

Commit af5f3b8

Browse files
mswilburnmswilburndlebauerAlomir
authored
SIP287 Add C Saturation (#301)
* Adding C saturation flag * Fix flag numbering error * Soil carbon pool calculation and fluxes * Updating flag count * Updating flux state variable calculation * Create unit test * clang-format * Updating unit testing and config files * Update to unit test * Updating documentation and changelog * Updating more documentation * Revised documentation * Capping satFrac and limiting org N * Update model inputs restrictions (#346) Add restriction for 'carbon-saturation' requiring 'litter-pool'. * Updating documentation * Updating documentation * Add testCarbontSaturation * Add unitClip function * Update to use unitClip * Extern fix for unitClip --------- Co-authored-by: mswilburn <mwilburn@co2.aos.wisc.edu> Co-authored-by: David LeBauer <dlebauer@gmail.com> Co-authored-by: Mike Longfritz <Mike.Longfritz@gmail.com>
1 parent 7b2a515 commit af5f3b8

28 files changed

Lines changed: 300 additions & 29 deletions

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ add_library(tests
5656
tests/sipnet/test_events_types/testEventPlanting.c
5757
tests/sipnet/test_events_types/testEventTillage.c
5858
tests/sipnet/test_modeling/testBalance.c
59+
tests/sipnet/test_modeling/testCarbonSaturation.c
5960
tests/sipnet/test_modeling/testDependencyFunctions.c
6061
tests/sipnet/test_modeling/testMethane.c
6162
tests/sipnet/test_modeling/testNitrogenCycle.c

docs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ sections to include in release notes:
3030
- `leafon` and `leafoff` events for tracking phenological transitions (#326)
3131
- `leafon` limited by available carbon and nitrogen; N storage pool; N resorption on `leafoff` (#337)
3232
- New required parameter `leafOnReallocFrac` to control how much of wood and coarse root carbon is reallocated to leaves on `leafon` (#337)
33+
- `carbonSaturation` cli option and calculation of soil and litter carbon pools that observes soil carbon saturating behavior (#301)
3334

3435
### Fixed
3536

docs/model-structure.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,15 @@ F^C_\text{fert,org}
309309
Where $K_{\text{plant},i}$ is the turnover rate of plant pool $i$ that controls the rate at which plant biomass is
310310
transferred to litter.
311311

312+
When soil carbon saturation is enabled, a fraction of soil carbon inputs may be redirected to the litter pool as fast-turnover carbon. This functionality is described in more detail below in the Soil Carbon section \eqref{eq:soil_carbon_saturation}.
313+
314+
\begin{equation}
315+
\frac{dC_\text{litter}}{dt} = F^C_\text{litter} + F^C_{\text{soil}} \cdot \frac{C_{\text{soil}}}{C_{\text{soil,saturation}}} - F^C_{\text{decomp}} - F^C_{\text{CH}_4\text{,litter}}
316+
\label{eq:soil_carbon_to_litter}
317+
\end{equation}
318+
319+
Where $\frac{C_{\text{soil}}}{C_{\text{soil,saturation}}}$ is bound from 0 to 1.
320+
312321
$F^C_{\text{decomp}}$ represents the rate at which litter carbon is processed by microbial activity. Litter
313322
decomposition
314323
is modeled as a first-order process proportional to litter carbon content and modified by temperature and moisture:
@@ -370,6 +379,15 @@ F^C_{\text{soil}} = F^C_{\text{soil,litter}} + F^C_{\text{soil,roots}}
370379
\label{eq:soil_carbon_flux}
371380
\end{equation}
372381

382+
When soil carbon saturation is enabled, only a saturation-dependent fraction of gross soil C inputs is added to the soil pool. This fraction declines as $C_{\text{soil}}$ approaches the specified soil C saturation limit. The remaining input C is redirected to the litter pool \eqref{eq:soil_carbon_to_litter} as fast-turnover carbon rather than being added to the soil pool.
383+
384+
\begin{equation}
385+
\frac{dC_\text{soil}}{dt} = F^C_{\text{soil}} \cdot (1 - \frac{C_{\text{soil}}}{C_{\text{soil,saturation}}}) - R_{\text{soil}} - F^C_{\text{CH}_4\text{,soil}}
386+
\label{eq:soil_carbon_saturation}
387+
\end{equation}
388+
389+
where $C_{\text{soil,saturation}}$ is the soil carbon saturation limit entered as an input parameter. This is based on equation (3) from Stewart et al. (2007). $\frac{C_{\text{soil}}}{C_{\text{soil,saturation}}}$ is bound from 0 to 1.
390+
373391
Soil heterotrophic respiration is modeled as a first-order process proportional
374392
to soil organic carbon content and modified by environmental and management factors:
375393

docs/parameters.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ Run-time parameters can change from one run to the next, or when the model is st
197197
| $Q_{10s}$ | soilRespQ10 | Soil respiration Q10 | unitless | scalar determining effect of temp on soil respiration |
198198
| $D_{\text{moisture}}$ | soilRespMoistEffect | scalar determining effect of moisture on soil resp. | unitless | |
199199
| $f_{\text{till}}$ | tillageEff | Effect of tillage on decomposition that exponentially decays over time | fraction | Documented in model structure; event-level term in `events.in` |
200+
| $C_{\text{soil,saturation}}$ | soilCSaturation | Maximum amount of carbon that can be stabilized in the soil, used when carbon-saturation is enabled. | $\text{g C} \cdot \text{m}^{-2} \text{ ground area}$ | |
200201

201202
### Nitrogen Cycle Parameters
202203

docs/user-guide/model-inputs.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,13 @@ Thus, command-line arguments override settings in the configuration file, and co
242242
| `snow` | on | Keep track of snowpack, rather than assuming all precipitation is liquid |
243243
| `soil-phenol` | off | Use soil temperature to determine leaf growth |
244244
| `water-hresp` | on | Whether soil moisture affects heterotrophic respiration |
245+
| `carbon-saturation`| off | Enable soil carbon saturation behavior to constrain carbon stored in soil |
245246

246247
Note the following restrictions on these options:
247248
- `soil-phenol` and `gdd` may not both be turned on
248249
- `anaerobic` requires `water-hresp`
249250
- 'nitrogen-cycle' requires both 'litter-pool' and 'anaerobic'
251+
- `carbon-saturation` requires `litter-pool`
250252

251253
### Command Line Arguments
252254

docs/user-guide/running-sipnet.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ These flags enable or disable optional model processes. Prepend `no-` to the fla
4848
| `--snow` | ON (1) | Track snowpack separately; if disabled, all precipitation is treated as liquid |
4949
| `--soil-phenol` | OFF (0) | Use soil temperature (instead of growing degree days) to determine leaf growth |
5050
| `--water-hresp` | ON (1) | Allow soil moisture to affect heterotrophic respiration rates |
51+
| `--carbon-saturation`| OFF (0) | Enable soil carbon saturation behavior to constrain carbon stored in soil |
5152

5253
#### Model Flag Restrictions
5354

@@ -56,6 +57,7 @@ The following flag constraints are enforced:
5657
- `--soil-phenol` and `--gdd` cannot both be enabled
5758
- `--anaerobic` requires `--water-hresp`
5859
- `--nitrogen-cycle` requires both `--litter-pool` and `--anaerobic`
60+
- `--carbon-saturation` requires `--litter-pool`
5961

6062
### Output Flags
6163

@@ -118,13 +120,14 @@ Keys are case-insensitive and can use hyphens or underscores (e.g., `EVENTS`, `e
118120

119121
| Key | Value (1/0) | Description |
120122
| ---------------- | ----------- | ----------------------------------------- |
123+
| `ANAEROBIC` | 0 or 1 | Enable methane/anaerobic Rh moisture behavior |
124+
| `CARBON_SATURATION` | 0 or 1 | Enable soil carbon saturating behavior |
121125
| `EVENTS` | 0 or 1 | Enable/disable event handling |
122126
| `GDD` | 0 or 1 | Use growing degree days for leaf growth |
123127
| `GROWTH_RESP` | 0 or 1 | Explicitly model growth respiration |
124128
| `LEAF_WATER` | 0 or 1 | Track separate leaf water pool |
125129
| `LITTER_POOL` | 0 or 1 | Enable separate litter pool |
126130
| `NITROGEN_CYCLE` | 0 or 1 | Enable nitrogen cycle modeling |
127-
| `ANAEROBIC` | 0 or 1 | Enable methane/anaerobic Rh moisture behavior |
128131
| `SNOW` | 0 or 1 | Track snowpack |
129132
| `SOIL_PHENOL` | 0 or 1 | Use soil temperature for phenology |
130133
| `WATER_HRESP` | 0 or 1 | Allow soil moisture to affect respiration |

src/common/context.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ void initContext(void) {
4343
CREATE_INT_CONTEXT(nitrogenCycle, "NITROGEN_CYCLE", ARG_OFF, FLAG_YES);
4444
CREATE_INT_CONTEXT(anaerobic, "ANAEROBIC", ARG_OFF, FLAG_YES);
4545
CREATE_INT_CONTEXT(flooding, "FLOODING", ARG_OFF, FLAG_YES);
46+
CREATE_INT_CONTEXT(carbonSaturation,"CARBON_SATURATION",ARG_OFF, FLAG_YES);
4647

4748
// Flags, I/O
4849
CREATE_INT_CONTEXT(doMainOutput, "DO_MAIN_OUTPUT", ARG_ON, FLAG_YES);
@@ -209,6 +210,12 @@ void validateContext(void) {
209210
hasError = 1;
210211
}
211212

213+
if (ctx.carbonSaturation && !ctx.litterPool) {
214+
logError("carbon-saturation requires litter-pool to be "
215+
"turned on\n");
216+
hasError = 1;
217+
}
218+
212219
if (hasError) {
213220
exit(EXIT_CODE_BAD_PARAMETER_VALUE);
214221
}

src/common/context.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ struct context_metadata {
3636
UT_hash_handle hh; // makes this structure hashable
3737
};
3838

39-
#define NUM_CONTEXT_MODEL_FLAGS 11
39+
#define NUM_CONTEXT_MODEL_FLAGS 12
4040
// See docs/developer-guide/cli-options.md for details on how to add a new
4141
// Context entry
4242
struct Context {
@@ -53,7 +53,7 @@ struct Context {
5353
int nitrogenCycle;
5454
int anaerobic;
5555
int flooding;
56-
56+
int carbonSaturation;
5757
// IF ADDING A NEW MODEL FLAG, update NUM_CONTEXT_MODEL_FLAGS above and
5858
// relevant code in restart.c
5959

src/common/util.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,6 @@ double calcRatio(const double num, const double den) {
7373
const double effectiveDen = den < TINY ? TINY : den;
7474
return num / effectiveDen;
7575
}
76+
77+
// For global linkage
78+
extern inline double unitClip(double preClip);

src/common/util.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#ifndef UTIL_H
99
#define UTIL_H
1010

11+
#include <math.h>
1112
#include <stdio.h>
1213

1314
#define TINY 0.000001 // to avoid those nasty divide-by-zero errors
@@ -28,4 +29,12 @@ int countFields(const char *line, const char *sep);
2829
*/
2930
double calcRatio(double num, double den);
3031

32+
/**
33+
* Clips input double to [0,1]
34+
*
35+
* @param preClip Pre-clipped value
36+
* @return Clipped value
37+
*/
38+
inline double unitClip(double preClip) { return fmin(fmax(preClip, 0.0), 1.0); }
39+
3140
#endif

0 commit comments

Comments
 (0)