Skip to content

Commit da427c9

Browse files
authored
SIP208, SIP209 Add carbon balance check (#248)
* Add balance.c|h * Improve do-single-output help * Carbon and nitrogen balance checks * Add event fluxes to track system inputs and outputs; add nppStorage pool to envi * Add external writeEvent function, refactor original * Add event for leaf on/off; split woodC into two pools; add balance checks * Updates for balance checks and leaf on/off events * Add ability to compare to base * Remove tolerance from balance tracker * Update col list for niwot * Avoid negative zero * Remove negative zeros * Add test for balance check * PR feedback * Turn off microbes, as it is now broken * Test updates after balance check updates * Split leaf-on carbon creation into own flux * Fix leafOn flux * Updates for leafOn split * Force skipping russell_4 * Update for new event fluxes
1 parent fbe9222 commit da427c9

File tree

28 files changed

+29384
-28736
lines changed

28 files changed

+29384
-28736
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ add_library(sipnetlib
3737
src/sipnet/runmean.c
3838
src/sipnet/sipnet.c
3939
src/sipnet/state.c
40+
src/sipnet/balance.c
4041
)
4142

4243
add_library(tests
@@ -52,4 +53,6 @@ add_library(tests
5253
tests/sipnet/test_events_types/testEventTillage.c
5354
tests/sipnet/test_bugfixes/testEventFileOrderChecks.c
5455
tests/sipnet/test_modeling/testNitrogenCycle.c
56+
tests/sipnet/test_modeling/testDependencyFunctions.c
57+
tests/sipnet/test_modeling/testBalance.c
5558
)

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ COMMON_CFILES:=context.c logging.c modelParams.c util.c
1111
COMMON_CFILES:=$(addprefix src/common/, $(COMMON_CFILES))
1212
COMMON_OFILES=$(COMMON_CFILES:.c=.o)
1313

14-
SIPNET_CFILES:=sipnet.c cli.c events.c frontend.c outputItems.c runmean.c state.c
14+
SIPNET_CFILES:=sipnet.c cli.c events.c frontend.c outputItems.c runmean.c state.c balance.c
1515
SIPNET_CFILES:=$(addprefix src/sipnet/, $(SIPNET_CFILES))
1616
SIPNET_OFILES=$(SIPNET_CFILES:.c=.o)
1717
SIPNET_LIBS=-lsipnet_common

src/sipnet/balance.c

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#include "balance.h"
2+
3+
#include <math.h>
4+
5+
#include "common/context.h"
6+
#include "common/exitCodes.h"
7+
#include "common/logging.h"
8+
#include "state.h"
9+
10+
// Definition of global balance tracker struct
11+
BalanceTracker balanceTracker;
12+
13+
void getMassTotals(double *carbon, double *nitrogen) {
14+
*carbon = (envi.plantWoodC + envi.plantWoodCStorageDelta) + envi.plantLeafC +
15+
envi.fineRootC + envi.coarseRootC + envi.soilC;
16+
if (ctx.litterPool) {
17+
*carbon += envi.litterC;
18+
}
19+
20+
if (ctx.nitrogenCycle) {
21+
// Note: this is the one place where we ust plantWoodC by itself; it's the
22+
// reason plantNSCWoodCDelta was created, so that we can ignore it here.
23+
*nitrogen =
24+
envi.plantWoodC / params.woodCN + envi.plantLeafC / params.leafCN +
25+
envi.fineRootC / params.fineRootCN + envi.coarseRootC / params.woodCN +
26+
envi.soilOrgN + envi.litterN + envi.minN;
27+
} else {
28+
*nitrogen = 0.0;
29+
}
30+
}
31+
32+
void updateBalanceTrackerPreUpdate(void) {
33+
// Set the pre-update pool totals
34+
getMassTotals(&balanceTracker.preTotalC, &balanceTracker.preTotalN);
35+
}
36+
37+
void updateBalanceTrackerPostUpdate(void) {
38+
// Set the post-update pool totals
39+
getMassTotals(&balanceTracker.postTotalC, &balanceTracker.postTotalN);
40+
41+
// Calculate the system inputs and outputs
42+
// CARBON
43+
balanceTracker.inputsC = fluxes.photosynthesis + // GPP
44+
fluxes.eventInputC; // agro event additions
45+
balanceTracker.outputsC = fluxes.rVeg + fluxes.rFineRoot +
46+
fluxes.rCoarseRoot + // R_a
47+
fluxes.rSoil + // R_h
48+
fluxes.eventOutputC; // agro event removals
49+
if (ctx.litterPool) {
50+
balanceTracker.outputsC += fluxes.rLitter;
51+
}
52+
// Account for climate length
53+
balanceTracker.inputsC *= climate->length;
54+
balanceTracker.outputsC *= climate->length;
55+
56+
// NITROGEN
57+
if (ctx.nitrogenCycle) {
58+
balanceTracker.inputsN =
59+
// TODO: fluxes.fixation +
60+
fluxes.eventInputN;
61+
balanceTracker.outputsN =
62+
fluxes.nLeaching + fluxes.nVolatilization + fluxes.eventOutputN;
63+
64+
// Account for climate length
65+
balanceTracker.inputsN *= climate->length;
66+
balanceTracker.outputsN *= climate->length;
67+
}
68+
}
69+
70+
void initBalanceTracker(void) {
71+
// Initialize all to zero
72+
balanceTracker.preTotalC = 0.0;
73+
balanceTracker.postTotalC = 0.0;
74+
balanceTracker.inputsC = 0.0;
75+
balanceTracker.outputsC = 0.0;
76+
balanceTracker.preTotalN = 0.0;
77+
balanceTracker.postTotalN = 0.0;
78+
balanceTracker.inputsN = 0.0;
79+
balanceTracker.outputsN = 0.0;
80+
balanceTracker.deltaC = 0.0;
81+
balanceTracker.deltaN = 0.0;
82+
}
83+
84+
void checkBalance(void) {
85+
// CARBON
86+
// Pool delta
87+
double poolCDelta = balanceTracker.postTotalC - balanceTracker.preTotalC;
88+
// System delta
89+
double systemCDelta = balanceTracker.inputsC - balanceTracker.outputsC;
90+
balanceTracker.deltaC = poolCDelta - systemCDelta;
91+
92+
// NITROGEN
93+
// Pool delta
94+
double poolNDelta = balanceTracker.postTotalN - balanceTracker.preTotalN;
95+
// System delta
96+
double systemNDelta = balanceTracker.inputsN - balanceTracker.outputsN;
97+
balanceTracker.deltaN = poolNDelta - systemNDelta;
98+
99+
// To avoid weird negative-zero issues...
100+
if (fabs(balanceTracker.deltaC) < 1e-8) {
101+
balanceTracker.deltaC = 0.0;
102+
}
103+
if (fabs(balanceTracker.deltaN) < 1e-8) {
104+
balanceTracker.deltaN = 0.0;
105+
}
106+
107+
int err = 0;
108+
if (fabs(balanceTracker.deltaC) > 0.0) {
109+
err = 1;
110+
logInternalError(
111+
"Carbon balance check failed (delta=%8.4f, Y: %d D: %d T: %4.2f)\n",
112+
balanceTracker.deltaC, climate->year, climate->day, climate->time);
113+
}
114+
// RE-ENABLE WHEN N IS FIXED
115+
// if (fabs(balanceTracker.deltaN) > 0.0) {
116+
// err = 1;
117+
// logInternalError("Nitrogen balance check failed (delta=%8.4f)\n",
118+
// balanceTracker.deltaN);
119+
//}
120+
if (err) {
121+
logInternalError("Exiting\n");
122+
// exit(EXIT_CODE_INTERNAL_ERROR);
123+
}
124+
}

src/sipnet/balance.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#ifndef BALANCE_H
2+
#define BALANCE_H
3+
4+
typedef struct BalanceTrackerStruct {
5+
// Mass balance checks:
6+
// X_t - X_(t-1) = inputs - outputs + tolerance
7+
// or, we check that
8+
// (pool delta) + (system delta) < tolerance
9+
// where
10+
// pool delta = X_t - X_(t-1)
11+
// system delta = outputs - inputs
12+
13+
// Carbon balance
14+
double preTotalC;
15+
double postTotalC;
16+
double inputsC;
17+
double outputsC;
18+
19+
// Nitrogen balance
20+
double preTotalN;
21+
double postTotalN;
22+
double inputsN;
23+
double outputsN;
24+
25+
// Checks
26+
double deltaC;
27+
double deltaN;
28+
} BalanceTracker;
29+
30+
// Global var
31+
extern BalanceTracker balanceTracker;
32+
33+
void updateBalanceTrackerPreUpdate(void);
34+
35+
void updateBalanceTrackerPostUpdate(void);
36+
37+
void initBalanceTracker(void);
38+
39+
void checkBalance(void);
40+
41+
#endif // BALANCE_H

src/sipnet/cli.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void usage(char *progName) {
8989
printf("\n");
9090
printf("Output flags: (prepend flag with 'no-' to force off, eg '--no-print-header')\n");
9191
printf(" --do-main-output Print time series of all output variables to <file-name>.out (1)\n");
92-
printf(" --do-single-outputs Print outputs one variable per file (e.g. <file-name>.NEE)\n");
92+
printf(" --do-single-outputs Print selection* of outputs one variable per file (e.g. <file-name>.NEE)\n");
9393
printf(" --dump-config Print final config to <file-name>.config (0)\n");
9494
printf(" --print-header Whether to print header row in output files (1)\n");
9595
printf(" --quiet Suppress info and warning message (0)\n");
@@ -98,6 +98,8 @@ void usage(char *progName) {
9898
printf(" -h, --help Print this message and exit\n");
9999
printf(" -v, --version Print version information and exit\n");
100100
printf("\n");
101+
printf("*do-single-outputs option outputs are: NEE, NEE_cum, GPP, GPP_cum\n");
102+
printf("\n");
101103
printf("Configuration options are read from <input_file>. Other options specified on the command\n");
102104
printf("line override settings from that file.\n");
103105
printf("\n");

0 commit comments

Comments
 (0)