Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
06e1b98
Implements mineral N pool, nitrogen-cycle command line option
Alomir Oct 17, 2025
cf04cbc
Updates for more edge cases
Alomir Oct 17, 2025
b5be765
Converts russell_2 to nitrogen cycle test
Alomir Oct 17, 2025
bb3edf7
Updates for addition of mineral N pool
Alomir Oct 17, 2025
e0ef4b7
Remove strcpy error
Alomir Oct 17, 2025
550f226
Remove inadvertent breakpoint()
Alomir Oct 17, 2025
6154598
Tweaks min N comments
Alomir Oct 17, 2025
a943703
Adds init nitrogen cycle doc
Alomir Oct 17, 2025
5c15922
Restores accidental soilWater deletion from outputs list
Alomir Oct 20, 2025
0177d59
Merge branch 'master' into SIP86-Add-soil-mineral-nitrogen-state-vari…
Alomir Oct 21, 2025
5989d7e
Adds logAppend
Alomir Oct 21, 2025
a820894
Fixes opt param warning
Alomir Oct 21, 2025
db62654
Implement fert min N
Alomir Oct 21, 2025
f4c38fc
Adds fert event
Alomir Oct 21, 2025
b6b9c59
Implements N volatilization
Alomir Oct 22, 2025
52aa179
Adds test for N cycle modeling
Alomir Oct 22, 2025
5b1e1b4
Updates for N cycle modeling
Alomir Oct 22, 2025
dea95ea
Updates results for fixed N vol
Alomir Oct 22, 2025
0b5c857
Changes from PR Feedback
Alomir Oct 27, 2025
2f27618
Merge branch 'master' into SIP86-Add-soil-mineral-nitrogen-state-vari…
Alomir Oct 27, 2025
f406eef
Merge branch 'SIP86-Add-soil-mineral-nitrogen-state-variable' into SI…
Alomir Oct 29, 2025
68e1fc6
Merge branch 'master' into SIP87-Implement-fertilizer-nitrogen
Alomir Oct 29, 2025
d8a8a84
Remove reference to MAGIC project
Alomir Oct 29, 2025
ef03f6e
Fix reference typo in comment
Alomir Oct 29, 2025
63d3548
Merge branch 'SIP87-Implement-fertilizer-nitrogen' into SIP89-Add-N-l…
Alomir Oct 29, 2025
60ec12c
Adding N loss to leaching
Oct 30, 2025
003abdc
Updating N leaching note and flux
Oct 30, 2025
940bea9
Merged from SIP89
Oct 30, 2025
67276a0
Adding N Leaching output column
Oct 30, 2025
fd35fb1
Updating test run output
Oct 30, 2025
c941a40
Format fix
Oct 30, 2025
c700671
Testing N leaching function
Oct 31, 2025
45168a2
Reorder find arguments for Linux
Oct 31, 2025
090a1d8
Adding .vscode to gitignore
Oct 31, 2025
06047d5
Merge from master
Alomir Nov 7, 2025
251aab4
Added tests dir
Alomir Nov 7, 2025
b383411
Added test_modeling
Alomir Nov 7, 2025
eb1fcbb
Tweaked k_vol description
Alomir Nov 7, 2025
90f3f55
PR feedback, tweaks to N vol
Alomir Nov 7, 2025
2f168c0
Updates for fixed N vol
Alomir Nov 7, 2025
60a5274
Updates for fixe N vol
Alomir Nov 7, 2025
98e3f71
tests/ try two
Alomir Nov 7, 2025
18ba9dc
Fixed comments
Alomir Nov 7, 2025
33fdb9f
Updating N leach flux calculation
Nov 11, 2025
816418b
Update N leaching equation and test output
Nov 11, 2025
f4b4612
Renamed param nVolatilization to nVolatilizationFrac
Alomir Nov 12, 2025
b6c3d92
Tweaked nVolatilizationFrac comment
Alomir Nov 12, 2025
1e94893
Updated param name nVolatilizationFrac
Alomir Nov 12, 2025
9dc8149
Resolving conflicts with parent branch
Nov 12, 2025
68d86a7
Resolving final parent branch conflicts
Nov 12, 2025
f9ded2b
Resolving conflict errors with original parent branch
Nov 13, 2025
f4a6e65
Resolving conflicts with master
Nov 13, 2025
3ba6f57
Remove unit test events.out file
Alomir Nov 13, 2025
8bd64c4
Merge branch 'master' into SIP90-Add-N-loss-to-leaching
dlebauer Nov 15, 2025
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ tests/sipnet/*/*
.DS_Store
.Rproj.user
.Rhistory
src/sipnet/.vscode/*

# Temporary and backup files
*.bak
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ clean:
rm -f .doxygen.stamp .mkdocs.stamp

# UNIT TESTS
SIPNET_TEST_DIRS:=$(shell find tests/sipnet -type d -mindepth 1 -maxdepth 1)
SIPNET_TEST_DIRS:=$(shell find tests/sipnet -mindepth 1 -maxdepth 1 -type d)
SIPNET_TEST_DIRS_RUN:= $(addsuffix .run, $(SIPNET_TEST_DIRS))
SIPNET_TEST_DIRS_CLEAN:= $(addsuffix .clean, $(SIPNET_TEST_DIRS))

Expand Down
35 changes: 28 additions & 7 deletions src/sipnet/sipnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,9 @@ void readParamData(ModelParams **modelParamsPtr, const char *paramFile) {
initializeOneModelParam(modelParams, "microbePulseEff", &(params.microbePulseEff), ctx.microbes);

// Nitrogen cycle params from [5] LeBauer et al. (unpublished)
initializeOneModelParam(modelParams, "mineralNInit", &(params.minNInit), ctx.nitrogenCycle);
initializeOneModelParam(modelParams, "nVolatilizationFrac", &(params.nVolatilizationFrac), ctx.nitrogenCycle);
initializeOneModelParam(modelParams, "mineralNInit", &(params.minNInit), ctx.nitrogenCycle);
initializeOneModelParam(modelParams, "nVolatilizationFrac", &(params.nVolatilizationFrac), ctx.nitrogenCycle);
initializeOneModelParam(modelParams, "nLeachingFrac", &(params.nLeachingFrac), ctx.nitrogenCycle);

// NOLINTEND
// clang-format on
Expand All @@ -409,8 +410,9 @@ void outputHeader(FILE *out) {
fprintf(out, "year day time plantWoodC plantLeafC woodCreation ");
fprintf(out, "soil microbeC coarseRootC fineRootC ");
fprintf(out, "litter soilWater soilWetnessFrac snow ");
fprintf(out, "npp nee cumNEE gpp rAboveground rSoil rRoot ra rh rtot "
"evapotranspiration fluxestranspiration minN n2oFlux\n");
fprintf(out,
"npp nee cumNEE gpp rAboveground rSoil rRoot ra rh rtot "
"evapotranspiration fluxestranspiration minN n2oFlux nLeachFlux\n");
}

/*!
Expand All @@ -431,11 +433,12 @@ void outputState(FILE *out, int year, int day, double time) {
trackers.soilWetnessFrac, envi.snow);
fprintf(out,
"%8.2f %8.2f %8.2f %8.2f %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f %8.8f "
"%8.4f %8.3f %8.6f\n",
"%8.4f %8.3f %8.6f %8.4f\n",
trackers.npp, trackers.nee, trackers.totNee, trackers.gpp,
trackers.rAboveground, trackers.rSoil, trackers.rRoot, trackers.ra,
trackers.rh, trackers.rtot, trackers.evapotranspiration,
fluxes.transpiration, envi.minN, fluxes.nVolatilization);
fluxes.transpiration, envi.minN, fluxes.nVolatilization,
fluxes.nLeaching);
}

// de-allocate space used for climate linked list
Expand Down Expand Up @@ -1223,6 +1226,21 @@ void calcNVolatilizationFlux() {
params.nVolatilizationFrac * envi.minN * d_temp * d_water;
}

/*!
* Calculate mineral N leaching flux
*/
void calcNLeachingFlux() {
double phi;
// phi is (drainage / soilWHC) between 0 and 1
if ((fluxes.drainage / params.soilWHC) < 1) {
phi = fluxes.drainage / params.soilWHC;
} else {
phi = 1;
}
// flux = nMin * phi * leaching fraction, g N * m^-2 * day^-1
fluxes.nLeaching = envi.minN * phi * params.nLeachingFrac;
}

/*!
* Calculate flux terms for sipnet as part of main model flow
*
Expand Down Expand Up @@ -1289,6 +1307,9 @@ void calculateFluxes(void) {
// Nitrogen cycle
if (ctx.nitrogenCycle) {
calcNVolatilizationFlux();
// Leaching depends on drainage flux so makes sure calcNLeachingFlux
// occurs after calcSoilWaterFluxes
calcNLeachingFlux();
}
}

Expand Down Expand Up @@ -1577,7 +1598,7 @@ void updatePoolsForSoil(void) {
climate->length;

// Nitrogen Cycle
envi.minN -= fluxes.nVolatilization * climate->length;
envi.minN -= (fluxes.nVolatilization + fluxes.nLeaching) * climate->length;
}

// !!! main runner function !!!
Expand Down
7 changes: 6 additions & 1 deletion src/sipnet/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,12 +358,15 @@ typedef struct Parameters {
// ****************************************
// Nitrogen Cycle

// Initial soil mineral nitrogen pool amount, g C * m^-2 ground area
// Initial soil mineral nitrogen pool amount, g N * m^-2 ground area
double minNInit;

// Fraction of mineral N available to be volatilized per day, d^-1
double nVolatilizationFrac;

// Fraction of mineral N lost to leaching per day
double nLeachingFrac;

} Params;

#define NUM_PARAMS (sizeof(Params) / sizeof(double))
Expand Down Expand Up @@ -530,6 +533,8 @@ typedef struct FluxVars {

// Mineral N lost to volatilization
double nVolatilization;
// Mineral N lost to leaching
double nLeaching;

// ****************************************
// Fluxes for event handling
Expand Down
69 changes: 65 additions & 4 deletions tests/sipnet/test_modeling/testNitrogenCycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ void setupTests(void) {
ctx.nitrogenCycle = 1;
}

void initState(double initN, double nVol) {
void initState(double initN, double nVol, double nLeachFrac) {
// per test
envi.minN = initN;
params.nVolatilizationFrac = nVol;
params.nLeachingFrac = nLeachFrac;

// static
envi.soilWater = 5.0;
Expand All @@ -32,6 +33,7 @@ void initState(double initN, double nVol) {
params.soilWHC = 10.0;

fluxes.nVolatilization = 0;
fluxes.nLeaching = 0;

// Values from russell_2 smoke test
params.soilRespMoistEffect = 1.0;
Expand All @@ -50,6 +52,63 @@ int checkVolatilizationFlux(double expNVolFlux) {
return status;
}

int checkNLeachingFlux(double expNLeachingFlux) {
int status = 0;
if (!compareDoubles(fluxes.nLeaching, expNLeachingFlux)) {
status = 1;
logTest("N leaching flux is %f, expected %f\n", fluxes.nLeaching,
expNLeachingFlux);
}

return status;
}

int testNLeaching(void) {
int status = 0;
double minN;
double nLeachFrac;
double expNLeaching;
double phi;

minN = 1;
nLeachFrac = 0.5;
fluxes.drainage = 5;
initState(minN, 0, nLeachFrac);
if ((fluxes.drainage / params.soilWHC) < 1) {
phi = fluxes.drainage / params.soilWHC;
} else {
phi = 1;
}
expNLeaching = minN * phi * nLeachFrac;
calcNLeachingFlux();
status |= checkNLeachingFlux(expNLeaching);

minN = 1;
nLeachFrac = 0.5;
fluxes.drainage = 20;
initState(minN, 0, nLeachFrac);
if ((fluxes.drainage / params.soilWHC) < 1) {
phi = fluxes.drainage / params.soilWHC;
} else {
phi = 1;
}
expNLeaching = minN * phi * nLeachFrac;
calcNLeachingFlux();
status |= checkNLeachingFlux(expNLeaching);

// Check minN for the last
updatePoolsForSoil();
double expMinN = minN - (expNLeaching * climate->length);
int minStatus = 0;
if (!compareDoubles(envi.minN, expMinN)) {
minStatus = 1;
logTest("minN pool is %8.3f, expected %8.3f\n", envi.minN, expMinN);
}
status |= minStatus;

return status;
}

int testNVolatilization(void) {
int status = 0;
double minN;
Expand All @@ -58,7 +117,7 @@ int testNVolatilization(void) {

minN = 2;
nVolFrac = 0.1;
initState(minN, nVolFrac);
initState(minN, nVolFrac, 0);
double tEffect = calcTempEffect(climate->tsoil);
double mEffect = calcMoistEffect(envi.soilWater, params.soilWHC);
expNVolFlux = nVolFrac * minN * tEffect * mEffect;
Expand All @@ -68,7 +127,7 @@ int testNVolatilization(void) {
// easy proportionality test - doubling params should double output
minN *= 2;
expNVolFlux *= 2;
initState(minN, nVolFrac);
initState(minN, nVolFrac, 0);
calcNVolatilizationFlux();
status |= checkVolatilizationFlux(expNVolFlux);

Expand All @@ -92,7 +151,7 @@ int testFertilization(void) {
double expMinN, expEventMinNFlux, expNVolFlux;

// init minN 2, nVol 0.1
initState(initN, nVolFrac);
initState(initN, nVolFrac, 0);

// fert event: 15 5 10
double fertMinN = 10;
Expand Down Expand Up @@ -140,6 +199,8 @@ int run(void) {

status |= testNVolatilization();

status |= testNLeaching();

return status;
}

Expand Down
Loading