From 48c6f9be70a520b3792b344b892b63556892d434 Mon Sep 17 00:00:00 2001 From: Mike Longfritz Date: Fri, 25 Sep 2026 13:56:47 -0400 Subject: [PATCH 1/4] Convert negative stock warning to error --- src/sipnet/sipnet.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sipnet/sipnet.c b/src/sipnet/sipnet.c index 5153c552..19389df2 100644 --- a/src/sipnet/sipnet.c +++ b/src/sipnet/sipnet.c @@ -1349,10 +1349,10 @@ void calculateFluxes(void) { void ensureNonNegative(double *var, double minVal, const char *label) { if (*var < minVal) { if (fabs(*var) > EPS) { // Don't print the zeros - logWarning( - "Non-negative stock constraint applied for %s (value %8.5f set " - "to zero) year %d day %d time %6.3f\n", - label, *var, climate->year, climate->day, climate->time); + logError("Non-negative stock constraint applied for %s (value %8.5f set " + "to zero) year %d day %d time %6.3f\n", + label, *var, climate->year, climate->day, climate->time); + exit(EXIT_CODE_INTERNAL_ERROR); } *var = 0.; } From 078cec725ac376fd4e10261776948f8a959e7b09 Mon Sep 17 00:00:00 2001 From: Mike Longfritz Date: Fri, 25 Sep 2026 14:00:10 -0400 Subject: [PATCH 2/4] PR 398 --- docs/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index cdc5b4a6..189884ee 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -28,6 +28,7 @@ sections to include in release notes: ### Fixed ### Changed +- SIPNET will now error instead of warning when a environment pool goes negative. This is a change from previous behavior where SIPNET would log a warning and continue running. (#398) ### Removed From eb56ac0bf295cad4f4fc82721501640859db5f9f Mon Sep 17 00:00:00 2001 From: Mike Longfritz Date: Tue, 29 Sep 2026 12:30:58 -0400 Subject: [PATCH 3/4] Fix typo Updated changelog to reflect error behavior change for negative environment pools. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- docs/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 189884ee..5fe7e618 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -28,7 +28,7 @@ sections to include in release notes: ### Fixed ### Changed -- SIPNET will now error instead of warning when a environment pool goes negative. This is a change from previous behavior where SIPNET would log a warning and continue running. (#398) +- SIPNET will now error instead of warning when an environment pool goes negative. This is a change from previous behavior where SIPNET would log a warning and continue running. (#398) ### Removed From a1d45a9e55170297826c24ac5ac9be977c8695ba Mon Sep 17 00:00:00 2001 From: Mike Longfritz Date: Wed, 30 Sep 2026 11:59:22 -0400 Subject: [PATCH 4/4] Updates from feedback in #398 --- docs/developer-guide/code-structure.md | 2 +- src/sipnet/sipnet.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/developer-guide/code-structure.md b/docs/developer-guide/code-structure.md index b2d7b844..26730a76 100644 --- a/docs/developer-guide/code-structure.md +++ b/docs/developer-guide/code-structure.md @@ -65,7 +65,7 @@ Name fluxes by direction and target, e.g., `fluxes.NPP`, `fluxes.soilRespiration - Apply all additions/removals in a consistent order if constraints require it (e.g., water first if it bounds biochemical rates next step). - Enforce invariants: - - No negative pools; clamp with tracked deficits and warnings if needed. + - No negative pools; enforce with additional `ensureNonNegative()` call(s) in `ensureNonNegativeStocks()`. - Mass conservation across linked pools (e.g., C/N stoichiometry) with balanced cross-pool transfers. - Centralize any event-specific application here (e.g., harvest removing biomass, adding residues). diff --git a/src/sipnet/sipnet.c b/src/sipnet/sipnet.c index 19389df2..5b3a86b7 100644 --- a/src/sipnet/sipnet.c +++ b/src/sipnet/sipnet.c @@ -1348,9 +1348,9 @@ void calculateFluxes(void) { // which var is treated as 0 void ensureNonNegative(double *var, double minVal, const char *label) { if (*var < minVal) { - if (fabs(*var) > EPS) { // Don't print the zeros - logError("Non-negative stock constraint applied for %s (value %8.5f set " - "to zero) year %d day %d time %6.3f\n", + if (*var < -EPS) { // Don't print the zeros + logError("Non-negative stock constraint violated for %s year %d day %d " + "time %6.3f\n", label, *var, climate->year, climate->day, climate->time); exit(EXIT_CODE_INTERNAL_ERROR); }