Skip to content

Commit

Permalink
Merge pull request #534 from ImperialCollegeLondon/532-litter-model-s…
Browse files Browse the repository at this point in the history
…hould-average-abiotic-quantities-over-relevant-soil-layers

532 litter model should average abiotic quantities over relevant soil layers
  • Loading branch information
jacobcook1995 authored Aug 2, 2024
2 parents 3fcb8a7 + 7a17d21 commit 72ef3de
Show file tree
Hide file tree
Showing 7 changed files with 362 additions and 75 deletions.
4 changes: 3 additions & 1 deletion tests/models/litter/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@ def dummy_litter_data(fixture_core_components):

# Vertically structured variables
data["soil_temperature"] = lyr_strct.from_template()
data["soil_temperature"][lyr_strct.index_all_soil] = 20
data["soil_temperature"][lyr_strct.index_topsoil] = 20
data["soil_temperature"][lyr_strct.index_subsoil] = [19.5, 18.7, 18.7, 17.6]

# At present the soil model only uses the top soil layer, so this is the
# only one with real test values in
data["matric_potential"] = lyr_strct.from_template()
data["matric_potential"][lyr_strct.index_topsoil] = [-10.0, -25.0, -100.0, -100.0]
data["matric_potential"][lyr_strct.index_subsoil] = [-11.0, -29.5, -123.0, -154.1]

data["air_temperature"] = lyr_strct.from_template()
data["air_temperature"][lyr_strct.index_filled_atmosphere] = np.array(
Expand Down
141 changes: 136 additions & 5 deletions tests/models/litter/test_env_factors.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Test module for litter.env_factors.py."""

import numpy as np
import pytest

from virtual_ecosystem.models.litter.constants import LitterConsts

Expand All @@ -27,21 +28,151 @@ def test_calculate_temperature_effect_on_litter_decomp(
assert np.allclose(actual_factor, expected_factor)


def test_calculate_soil_water_effect_on_litter_decomp():
def test_calculate_soil_water_effect_on_litter_decomp(
dummy_litter_data, fixture_core_components
):
"""Test that soil moisture effects on decomposition are calculated correctly."""
from virtual_ecosystem.models.litter.env_factors import (
calculate_soil_water_effect_on_litter_decomp,
)

water_potentials = np.array([-10.0, -25.0, -100.0, -400.0])

expected_factor = [1.0, 0.88496823, 0.71093190, 0.53689556]
expected_factor = [1.0, 0.88496823, 0.71093190, 0.71093190]

actual_factor = calculate_soil_water_effect_on_litter_decomp(
water_potentials,
water_potential=dummy_litter_data["matric_potential"][
fixture_core_components.layer_structure.index_topsoil_scalar
],
water_potential_halt=LitterConsts.litter_decay_water_potential_halt,
water_potential_opt=LitterConsts.litter_decay_water_potential_optimum,
moisture_response_curvature=LitterConsts.moisture_response_curvature,
)

assert np.allclose(actual_factor, expected_factor)


@pytest.mark.parametrize(
"increased_depth,expected_av_temps",
[
pytest.param(
True,
[18.6319817, 18.498648, 18.498648, 18.315315],
id="increased depth",
),
pytest.param(
False,
[18.0729725, 18.0729725, 18.0729725, 18.0729725],
id="normal depth",
),
],
)
def test_average_temperature_over_microbially_active_layers(
dummy_litter_data, fixture_core_components, increased_depth, expected_av_temps
):
"""Check averaging of temperatures over soil layers works correctly."""
from virtual_ecosystem.models.litter.env_factors import (
average_temperature_over_microbially_active_layers,
)

if increased_depth:
fixture_core_components.layer_structure.soil_layer_active_thickness = np.array(
[0.5, 0.25]
)
fixture_core_components.layer_structure.max_depth_of_microbial_activity = 0.75

actual_av_temps = average_temperature_over_microbially_active_layers(
soil_temperatures=dummy_litter_data["soil_temperature"],
surface_temperature=dummy_litter_data["air_temperature"][
fixture_core_components.layer_structure.index_surface
].to_numpy(),
layer_structure=fixture_core_components.layer_structure,
)

assert np.allclose(actual_av_temps, expected_av_temps)


@pytest.mark.parametrize(
"increased_depth,expected_water_pots",
[
pytest.param(
True,
[-10.1667, -25.750, -103.8333, -109.0167],
id="increased depth",
),
pytest.param(
False,
[-10.0, -25.0, -100.0, -100.0],
id="normal depth",
),
],
)
def test_average_water_potential_over_microbially_active_layers(
dummy_litter_data, fixture_core_components, increased_depth, expected_water_pots
):
"""Check averaging of water potentials over soil layers works correctly."""
from virtual_ecosystem.models.litter.env_factors import (
average_water_potential_over_microbially_active_layers,
)

if increased_depth:
fixture_core_components.layer_structure.soil_layer_active_thickness = np.array(
[0.5, 0.25]
)
fixture_core_components.layer_structure.max_depth_of_microbial_activity = 0.75

actual_water_pots = average_water_potential_over_microbially_active_layers(
water_potentials=dummy_litter_data["matric_potential"],
layer_structure=fixture_core_components.layer_structure,
)

assert np.allclose(actual_water_pots, expected_water_pots)


@pytest.mark.parametrize(
"increased_depth,expected_factors",
[
pytest.param(
True,
{
"temp_above": [0.1878681, 0.1878681, 0.1878681, 0.1878681],
"temp_below": [0.2407699, 0.2377353, 0.2377353, 0.2335993],
"water": [0.9979245, 0.8812574, 0.7062095, 0.7000939],
},
id="increased depth",
),
pytest.param(
False,
{
"temp_above": [0.1878681, 0.1878681, 0.1878681, 0.1878681],
"temp_below": [0.2281971, 0.2281971, 0.2281971, 0.2281971],
"water": [1.0, 0.88496823, 0.71093190, 0.71093190],
},
id="normal depth",
),
],
)
def test_calculate_environmental_factors(
dummy_litter_data, fixture_core_components, increased_depth, expected_factors
):
"""Check that the calculation of the relevant environmental factors is correct."""
from virtual_ecosystem.models.litter.env_factors import (
calculate_environmental_factors,
)

if increased_depth:
fixture_core_components.layer_structure.soil_layer_active_thickness = np.array(
[0.5, 0.25]
)
fixture_core_components.layer_structure.max_depth_of_microbial_activity = 0.75

actual_factors = calculate_environmental_factors(
air_temperatures=dummy_litter_data["air_temperature"],
soil_temperatures=dummy_litter_data["soil_temperature"],
water_potentials=dummy_litter_data["matric_potential"],
layer_structure=fixture_core_components.layer_structure,
constants=LitterConsts,
)

assert set(expected_factors.keys()) == set(actual_factors.keys())

for key in actual_factors.keys():
assert np.allclose(actual_factors[key], expected_factors[key])
8 changes: 4 additions & 4 deletions tests/models/litter/test_litter_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,12 +311,12 @@ def test_update(fixture_litter_model, dummy_litter_data):
end_above_meta = [0.32072786, 0.15473132, 0.08523907, 0.08074153]
end_above_struct = [0.50470382, 0.25068224, 0.09843778, 0.11163532]
end_woody = [4.7745168, 11.89872931, 7.3614112, 7.3314112]
end_below_meta = [0.4090768, 0.37287148, 0.06883228, 0.08315412]
end_below_struct = [0.6066315, 0.31860251, 0.02010566, 0.03038382]
end_below_meta = [0.41087696, 0.37434507, 0.06905624, 0.08337808]
end_below_struct = [0.6066914, 0.31869812, 0.02010607, 0.03038423]
end_lignin_above_struct = [0.49790843, 0.10067782, 0.70495536, 0.71045831]
end_lignin_woody = [0.49580586, 0.79787834, 0.35224223, 0.35012603]
end_lignin_below_struct = [0.50313604, 0.2658639, 0.7499951, 0.82142894]
c_mineral = [0.02987233, 0.02316114, 0.00786517, 0.00786517]
end_lignin_below_struct = [0.50313573, 0.26585915, 0.7499951, 0.82142798]
c_mineral = [0.02652423, 0.02033658, 0.00746131, 0.00746131]

fixture_litter_model.update(time_index=0)

Expand Down
17 changes: 6 additions & 11 deletions tests/models/litter/test_litter_pools.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ def test_calculate_decay_rates(dummy_litter_data, fixture_core_components):
"metabolic_above": [0.00450883, 0.00225442, 0.00105206, 0.00105206],
"structural_above": [1.6742967e-4, 6.1857359e-4, 1.1086908e-5, 1.1086908e-5],
"woody": [0.0004832, 0.00027069, 0.0015888, 0.0015888],
"metabolic_below": [0.01092804, 0.00894564, 0.00135959, 0.00135959],
"structural_below": [3.6365995e-04, 5.803657e-04, 2.469074e-06, 2.469074e-06],
"metabolic_below": [0.00912788, 0.00747205, 0.00113563, 0.00113563],
"structural_below": [3.0375501e-4, 4.8476324e-4, 2.0623487e-6, 2.0623487e-6],
}

actual_decay = calculate_decay_rates(
Expand All @@ -109,15 +109,10 @@ def test_calculate_decay_rates(dummy_litter_data, fixture_core_components):
lignin_above_structural=dummy_litter_data["lignin_above_structural"].to_numpy(),
lignin_woody=dummy_litter_data["lignin_woody"].to_numpy(),
lignin_below_structural=dummy_litter_data["lignin_below_structural"].to_numpy(),
surface_temp=dummy_litter_data["air_temperature"][
fixture_core_components.layer_structure.index_surface_scalar
].to_numpy(),
topsoil_temp=dummy_litter_data["soil_temperature"][
fixture_core_components.layer_structure.index_topsoil_scalar
].to_numpy(),
water_potential=dummy_litter_data["matric_potential"][
fixture_core_components.layer_structure.index_topsoil_scalar
].to_numpy(),
air_temperatures=dummy_litter_data["air_temperature"],
soil_temperatures=dummy_litter_data["soil_temperature"],
water_potentials=dummy_litter_data["matric_potential"],
layer_structure=fixture_core_components.layer_structure,
constants=LitterConsts,
)

Expand Down
Loading

0 comments on commit 72ef3de

Please sign in to comment.