Skip to content

Commit

Permalink
Merge branch 'develop' into feature/multi_grid_no_community
Browse files Browse the repository at this point in the history
  • Loading branch information
TaranRallings committed Dec 3, 2024
2 parents d343841 + 655073f commit 5c0c3e5
Show file tree
Hide file tree
Showing 19 changed files with 689 additions and 417 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
matrix.python-version == '3.10'
)
}}
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
Expand Down
4 changes: 2 additions & 2 deletions docs/source/_toc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ subtrees:
- file: api/models/soil
title: The soil model
entries:
- file: api/models/soil/carbon
title: The carbon submodule
- file: api/models/soil/pools
title: The pools submodule
- file: api/models/soil/constants
title: The constants submodule
- file: api/models/soil/env_factors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ language_info:
version: 3.11.9
---

# API documentation for the {mod}`~virtual_ecosystem.models.soil.carbon` module
# API documentation for the {mod}`~virtual_ecosystem.models.soil.pools` module

```{eval-rst}
.. automodule:: virtual_ecosystem.models.soil.carbon
.. automodule:: virtual_ecosystem.models.soil.pools
:autosummary:
:members:
```
367 changes: 201 additions & 166 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ types-tqdm = "^4.66.0.20240106"
[tool.poetry.group.test.dependencies]
hypothesis = "^6.54.2"
pytest = ">=7.1.2,<9.0.0"
pytest-cov = ">=3,<6"
pytest-cov = ">=3,<7"
pytest-datadir = "^1.4.1"
pytest-mock = "^3.8.1"

Expand Down
3 changes: 3 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,13 @@ def dummy_carbon_data(fixture_core_components):
"soil_c_pool_necromass": [0.058, 0.015, 0.093, 0.105],
"soil_enzyme_pom": [0.022679, 0.009576, 0.050051, 0.003010],
"soil_enzyme_maom": [0.0356, 0.0117, 0.02509, 0.00456],
"soil_n_pool_don": [0.000571428, 0.00142857, 0.00014285, 0.002857142],
"soil_n_pool_particulate": [0.00714285, 0.00071425, 0.00285714, 0.01428571],
"pH": [3.0, 7.5, 9.0, 5.7],
"bulk_density": [1350.0, 1800.0, 1000.0, 1500.0],
"clay_fraction": [0.8, 0.3, 0.1, 0.9],
"litter_C_mineralisation_rate": [0.00212106, 0.00106053, 0.00049000, 0.0055],
"litter_N_mineralisation_rate": [3.5351e-5, 7.0702e-5, 0.000183, 1.63333e-5],
"vertical_flow": [0.1, 0.5, 2.5, 1.59],
}

Expand Down
2 changes: 2 additions & 0 deletions tests/core/test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,8 @@ def test_output_current_state(mocker, dummy_carbon_data, time_index):
"soil_c_pool_necromass",
"soil_enzyme_pom",
"soil_enzyme_maom",
"soil_n_pool_don",
"soil_n_pool_particulate",
],
time_index,
)
Expand Down
21 changes: 21 additions & 0 deletions tests/models/soil/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,24 @@ def environmental_factors(dummy_carbon_data, fixture_core_components):
return EnvironmentalEffectFactors(
water=water_factors, pH=pH_factors, clay_saturation=clay_saturation_factors
)


@pytest.fixture
def enzyme_mediated_rates(
dummy_carbon_data, fixture_core_components, environmental_factors
):
"""Enzyme mediated rates based on dummy carbon data."""
from virtual_ecosystem.models.soil.constants import SoilConsts
from virtual_ecosystem.models.soil.pools import calculate_enzyme_mediated_rates

return calculate_enzyme_mediated_rates(
soil_enzyme_pom=dummy_carbon_data["soil_enzyme_pom"],
soil_enzyme_maom=dummy_carbon_data["soil_enzyme_maom"],
soil_c_pool_pom=dummy_carbon_data["soil_c_pool_pom"],
soil_c_pool_maom=dummy_carbon_data["soil_c_pool_maom"],
soil_temp=dummy_carbon_data["soil_temperature"][
fixture_core_components.layer_structure.index_topsoil_scalar
],
env_factors=environmental_factors,
constants=SoilConsts,
)
126 changes: 85 additions & 41 deletions tests/models/soil/test_carbon.py → tests/models/soil/test_pools.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Test module for soil.carbon.py.
"""Test module for soil.pools.py.
This module tests the functionality of the soil carbon module
"""
Expand All @@ -9,51 +9,52 @@
from virtual_ecosystem.models.soil.constants import SoilConsts


def test_calculate_soil_carbon_updates(dummy_carbon_data, fixture_core_components):
def test_calculate_all_pool_updates(dummy_carbon_data, fixture_core_components):
"""Test that the two pool update functions work correctly."""
from virtual_ecosystem.core.constants import CoreConsts
from virtual_ecosystem.models.soil.carbon import calculate_soil_carbon_updates
from virtual_ecosystem.models.soil.pools import SoilPools
from virtual_ecosystem.models.soil.soil_model import SoilModel, make_slices

# Find and store order of pools (this requires loads of steps because it needs to
# work with the integrator)
y0 = np.concatenate(
[
dummy_carbon_data[name].to_numpy()
for name in map(str, dummy_carbon_data.data.keys())
if name in SoilModel.vars_updated
]
)
delta_pools_ordered = {
name: np.array([])
for name in map(str, dummy_carbon_data.data.keys())
if name in SoilModel.vars_updated
}
no_cells = 4
slices = make_slices(no_cells, len(delta_pools_ordered))
pools = {
str(pool): y0[slc] for slc, pool in zip(slices, delta_pools_ordered.keys())
}
soil_pools = SoilPools(data=dummy_carbon_data, pools=pools, constants=SoilConsts)

change_in_pools = {
"soil_c_pool_lmwc": [0.0022585928, 0.0060483065, -0.019175058, 0.024247214],
"soil_c_pool_lmwc": [0.00226177439, 0.006049897295, -0.019174323, 0.024255464],
"soil_c_pool_maom": [0.038767651, 0.00829848, 0.05982197, 0.07277182],
"soil_c_pool_microbe": [-0.04978105, -0.02020101, -0.10280967, -0.00719517],
"soil_c_pool_pom": [0.00178122, -0.00785937, -0.01201551, 0.00545857],
"soil_c_pool_pom": [0.00177803841, -0.007860960795, -0.012016245, 0.00545032],
"soil_c_pool_necromass": [0.001137474, 0.009172067, 0.033573266, -0.08978050],
"soil_enzyme_pom": [1.18e-8, 1.67e-8, 1.8e-9, -1.12e-8],
"soil_enzyme_maom": [-0.00031009, -5.09593e-5, 0.0005990658, -3.72112e-5],
"soil_n_pool_don": [2.4081961e-5, 2.84920682e-6, 4.84845086e-5, -5.83499913e-5],
"soil_n_pool_particulate": [1.102338e-5, 6.422491e-5, 0.000131687, 1.461799e-5],
}

# Make order of pools object
pool_order = {}
for pool in change_in_pools.keys():
pool_order[pool] = np.array([])

delta_pools = calculate_soil_carbon_updates(
soil_c_pool_lmwc=dummy_carbon_data["soil_c_pool_lmwc"].to_numpy(),
soil_c_pool_maom=dummy_carbon_data["soil_c_pool_maom"].to_numpy(),
soil_c_pool_microbe=dummy_carbon_data["soil_c_pool_microbe"].to_numpy(),
soil_c_pool_pom=dummy_carbon_data["soil_c_pool_pom"].to_numpy(),
soil_c_pool_necromass=dummy_carbon_data["soil_c_pool_necromass"].to_numpy(),
soil_enzyme_pom=dummy_carbon_data["soil_enzyme_pom"].to_numpy(),
soil_enzyme_maom=dummy_carbon_data["soil_enzyme_maom"].to_numpy(),
pH=dummy_carbon_data["pH"],
bulk_density=dummy_carbon_data["bulk_density"],
soil_moisture=dummy_carbon_data["soil_moisture"][
fixture_core_components.layer_structure.index_topsoil_scalar
].to_numpy(),
soil_water_potential=dummy_carbon_data["matric_potential"][
fixture_core_components.layer_structure.index_topsoil_scalar
].to_numpy(),
vertical_flow_rate=dummy_carbon_data["vertical_flow"],
soil_temp=dummy_carbon_data["soil_temperature"][
fixture_core_components.layer_structure.index_topsoil_scalar
],
clay_fraction=dummy_carbon_data["clay_fraction"],
mineralisation_rate=dummy_carbon_data["litter_C_mineralisation_rate"],
delta_pools = soil_pools.calculate_all_pool_updates(
delta_pools_ordered=pool_order,
model_constants=SoilConsts,
core_constants=CoreConsts,
top_soil_layer_index=fixture_core_components.layer_structure.index_topsoil_scalar,
)

# Check that the updates are correctly calculated. Using a loop here implicitly
Expand All @@ -67,7 +68,7 @@ def test_calculate_microbial_changes(
):
"""Check that calculation of microbe related changes works correctly."""

from virtual_ecosystem.models.soil.carbon import calculate_microbial_changes
from virtual_ecosystem.models.soil.pools import calculate_microbial_changes

expected_lmwc_uptake = [1.29159055e-2, 8.43352433e-3, 5.77096991e-2, 5.77363558e-5]
expected_microbe = [-0.04978105, -0.02020101, -0.10280967, -0.00719517]
Expand Down Expand Up @@ -100,7 +101,7 @@ def test_calculate_enzyme_mediated_rates(
):
"""Check that calculation of enzyme mediated rates works as expected."""

from virtual_ecosystem.models.soil.carbon import calculate_enzyme_mediated_rates
from virtual_ecosystem.models.soil.pools import calculate_enzyme_mediated_rates

expected_pom_to_lmwc = [3.39844565e-4, 8.91990315e-3, 1.25055119e-2, 4.14247999e-5]
expected_maom_to_lmwc = [1.45988485e-3, 2.10172756e-3, 4.69571604e-3, 8.62951373e-6]
Expand All @@ -124,7 +125,7 @@ def test_calculate_enzyme_mediated_rates(
def test_calculate_enzyme_changes(dummy_carbon_data):
"""Check that the determination of enzyme pool changes works correctly."""

from virtual_ecosystem.models.soil.carbon import calculate_enzyme_changes
from virtual_ecosystem.models.soil.pools import calculate_enzyme_changes

biomass_loss = np.array([0.05443078, 0.02298407, 0.12012258, 0.00722288])

Expand All @@ -148,7 +149,7 @@ def test_calculate_maintenance_biomass_synthesis(
dummy_carbon_data, fixture_core_components
):
"""Check maintenance respiration cost calculates correctly."""
from virtual_ecosystem.models.soil.carbon import (
from virtual_ecosystem.models.soil.pools import (
calculate_maintenance_biomass_synthesis,
)

Expand All @@ -167,7 +168,7 @@ def test_calculate_maintenance_biomass_synthesis(

def test_calculate_carbon_use_efficiency(dummy_carbon_data, fixture_core_components):
"""Check carbon use efficiency calculates correctly."""
from virtual_ecosystem.models.soil.carbon import calculate_carbon_use_efficiency
from virtual_ecosystem.models.soil.pools import calculate_carbon_use_efficiency

expected_cues = [0.36, 0.33, 0.3, 0.48]

Expand Down Expand Up @@ -202,7 +203,7 @@ def test_calculate_carbon_use_efficiency(dummy_carbon_data, fixture_core_compone
)
def test_calculate_enzyme_turnover(dummy_carbon_data, turnover, expected_decay):
"""Check that enzyme turnover rates are calculated correctly."""
from virtual_ecosystem.models.soil.carbon import calculate_enzyme_turnover
from virtual_ecosystem.models.soil.pools import calculate_enzyme_turnover

actual_decay = calculate_enzyme_turnover(
enzyme_pool=dummy_carbon_data["soil_enzyme_pom"], turnover_rate=turnover
Expand All @@ -215,7 +216,9 @@ def test_calculate_microbial_carbon_uptake(
dummy_carbon_data, fixture_core_components, environmental_factors
):
"""Check microbial carbon uptake calculates correctly."""
from virtual_ecosystem.models.soil.carbon import calculate_microbial_carbon_uptake
from virtual_ecosystem.models.soil.pools import (
calculate_microbial_carbon_uptake,
)

expected_uptake = [1.29159055e-2, 8.43352433e-3, 5.77096991e-2, 5.77363558e-5]
expected_assimilation = [4.64972597e-3, 2.78306303e-3, 1.73129097e-2, 2.77134508e-5]
Expand All @@ -239,7 +242,7 @@ def test_calculate_enzyme_mediated_decomposition(
dummy_carbon_data, fixture_core_components, environmental_factors
):
"""Check that particulate organic matter decomposition is calculated correctly."""
from virtual_ecosystem.models.soil.carbon import (
from virtual_ecosystem.models.soil.pools import (
calculate_enzyme_mediated_decomposition,
)

Expand All @@ -265,7 +268,7 @@ def test_calculate_enzyme_mediated_decomposition(
def test_calculate_maom_desorption(dummy_carbon_data):
"""Check that mineral associated matter desorption is calculated correctly."""

from virtual_ecosystem.models.soil.carbon import calculate_maom_desorption
from virtual_ecosystem.models.soil.pools import calculate_maom_desorption

expected_desorption = [2.5e-5, 1.7e-5, 4.5e-5, 5.0e-6]

Expand Down Expand Up @@ -297,7 +300,7 @@ def test_calculate_sorption_to_maom(
):
"""Check that sorption to mineral associated matter is calculated correctly."""

from virtual_ecosystem.models.soil.carbon import calculate_sorption_to_maom
from virtual_ecosystem.models.soil.pools import calculate_sorption_to_maom

actual_sorption = calculate_sorption_to_maom(
soil_c_pool=dummy_carbon_data[pool_name],
Expand All @@ -310,7 +313,7 @@ def test_calculate_sorption_to_maom(
def test_calculate_necromass_breakdown(dummy_carbon_data):
"""Check that necromass breakdown to lmwc is calculated correctly."""

from virtual_ecosystem.models.soil.carbon import calculate_necromass_breakdown
from virtual_ecosystem.models.soil.pools import calculate_necromass_breakdown

expected_breakdown = [0.0134008455, 0.0034657359, 0.0214875626, 0.0242601513]

Expand All @@ -320,3 +323,44 @@ def test_calculate_necromass_breakdown(dummy_carbon_data):
)

assert np.allclose(actual_breakdown, expected_breakdown)


def test_calculate_litter_mineralisation_split(dummy_carbon_data):
"""Test that the calculation of the mineralisation split works as expected."""
from virtual_ecosystem.models.soil.pools import (
calculate_litter_mineralisation_split,
)

expected_split = {
"dissolved": [3.18159e-6, 1.590795e-6, 7.35e-7, 8.25e-6],
"particulate": [0.00211787841, 0.001058939205, 0.000489265, 0.00549175],
}

actual_split = calculate_litter_mineralisation_split(
mineralisation_rate=dummy_carbon_data["litter_C_mineralisation_rate"],
litter_leaching_coefficient=SoilConsts.litter_leaching_fraction_carbon,
)

assert set(expected_split.keys()) == set(actual_split.keys())

for key in actual_split.keys():
assert np.allclose(actual_split[key], expected_split[key])


def test_calculate_soil_nutrient_mineralisation(
dummy_carbon_data, enzyme_mediated_rates
):
"""Test that function to calculate soil nutrient mineralisation works properly."""
from virtual_ecosystem.models.soil.pools import (
calculate_soil_nutrient_mineralisation,
)

expected_rate = [2.42745875e-5, 6.371041e-6, 5.104285e-5, 1.690808e-6]

actual_rate = calculate_soil_nutrient_mineralisation(
pool_carbon=dummy_carbon_data["soil_c_pool_pom"],
pool_nutrient=dummy_carbon_data["soil_n_pool_particulate"],
breakdown_rate=enzyme_mediated_rates.pom_to_lmwc,
)

assert np.allclose(actual_rate, expected_rate)
Loading

0 comments on commit 5c0c3e5

Please sign in to comment.