diff --git a/docs/source/using_the_ve/virtual_ecosystem_in_use.md b/docs/source/using_the_ve/virtual_ecosystem_in_use.md index ea9135183..f0d33ac10 100644 --- a/docs/source/using_the_ve/virtual_ecosystem_in_use.md +++ b/docs/source/using_the_ve/virtual_ecosystem_in_use.md @@ -9,6 +9,8 @@ language_info: nbconvert_exporter: python pygments_lexer: ipython3 version: 3.10.14 +execution: + timeout: 60 jupytext: formats: md:myst text_representation: diff --git a/tests/conftest.py b/tests/conftest.py index 01aea7601..cc5471cef 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -425,13 +425,16 @@ def dummy_carbon_data(fixture_core_components): lyr_str = fixture_core_components.layer_structure data["soil_moisture"] = lyr_str.from_template() - data["soil_moisture"][lyr_str.index_topsoil] = np.array( - [232.61550125, 196.88733175, 126.065797, 75.63195175] + data["soil_moisture"][lyr_str.index_all_soil] = np.array( + [ + [232.61550125, 196.88733175, 126.065797, 75.63195175], + [66.248474, 194.91137, 121.29988, 52.04422], + ] ) data["matric_potential"] = lyr_str.from_template() - data["matric_potential"][lyr_str.index_topsoil] = np.array( - [-3.0, -10.0, -250.0, -10000.0] + data["matric_potential"][lyr_str.index_all_soil] = np.array( + [[-3.0, -10.0, -250.0, -10000.0], [-2.8625, -8.978, -137.8, -8553.25]] ) data["soil_temperature"] = lyr_str.from_template() @@ -439,6 +442,11 @@ def dummy_carbon_data(fixture_core_components): [[35.0, 37.5, 40.0, 25.0], [22.5, 22.5, 22.5, 22.5]] ) + data["air_temperature"] = lyr_str.from_template() + data["air_temperature"][lyr_str.index_filled_atmosphere] = np.array( + [30.0, 29.844995, 28.87117, 27.206405, 16.145945] + )[:, None] + return data diff --git a/tests/models/soil/test_env_factors.py b/tests/models/soil/test_env_factors.py index 3c1bcbc3a..fdf1ac220 100644 --- a/tests/models/soil/test_env_factors.py +++ b/tests/models/soil/test_env_factors.py @@ -392,3 +392,40 @@ def test_calculate_leaching_rate(dummy_carbon_data, fixture_core_components): ) assert np.allclose(expected_rate, actual_rate) + + +@pytest.mark.parametrize( + "increased_depth,expected_soil_moisture", + [ + pytest.param( + True, + [265.73973825, 294.34301675, 186.715737, 101.65406175], + id="increased depth", + ), + pytest.param( + False, + [116.307750625, 98.443665875, 63.0328985, 37.815975875], + id="normal depth", + ), + ], +) +def test_find_total_soil_moisture_for_microbially_active_depth( + dummy_carbon_data, fixture_core_components, increased_depth, expected_soil_moisture +): + """Test that finding the total soil moisture works as expected.""" + from virtual_ecosystem.models.soil.env_factors import ( + find_total_soil_moisture_for_microbially_active_depth, + ) + + 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_soil_moisture = find_total_soil_moisture_for_microbially_active_depth( + soil_moistures=dummy_carbon_data["soil_moisture"], + layer_structure=fixture_core_components.layer_structure, + ) + + assert np.allclose(actual_soil_moisture, expected_soil_moisture) diff --git a/tests/models/soil/test_pools.py b/tests/models/soil/test_pools.py index 468a999a6..f161bc27f 100644 --- a/tests/models/soil/test_pools.py +++ b/tests/models/soil/test_pools.py @@ -46,29 +46,29 @@ def test_calculate_all_pool_updates( ) change_in_pools = { - "soil_c_pool_lmwc": [0.1178918, 0.06892161, 0.2489136, 0.03425211], - "soil_c_pool_maom": [0.03734787, 0.00340136, 0.05447554, 0.07275546], - "soil_c_pool_bacteria": [-0.0543618, -0.0226100, -0.1185237, -0.0071954], - "soil_c_pool_fungi": [-0.00832584, -0.08196413, -0.02280126, -0.03266732], - "soil_c_pool_pom": [0.00021589, -0.02918772, -0.0247599, 0.00520792], - "soil_c_pool_necromass": [0.01141213, 0.09537438, 0.05971513, -0.0566864], - "soil_enzyme_pom_bacteria": [-5.4395e-4, -2.2795e-4, -1.19323e-3, -7.2103e-5], - "soil_enzyme_maom_bacteria": [-8.5406e-4, -2.7893e-4, -5.9417e-4, -1.093e-4], - "soil_enzyme_pom_fungi": [-0.00062555, -0.00012062, -0.00015158, -0.00010522], - "soil_enzyme_maom_fungi": [-2.07924e-4, -1.46441e-4, -8.79093e-5, -5.1289e-5], - "soil_n_pool_don": [0.00180422, 0.00529461, 0.00549027, 0.00240583], - "soil_n_pool_particulate": [-1.005585e-4, 4.899227e-5, 7.96678e-5, 4.723906e-6], - "soil_n_pool_necromass": [0.00948372, 0.00118049, 0.00843786, -0.00381522], - "soil_n_pool_maom": [0.00099458, 0.01041398, 0.01326356, 0.00772835], - "soil_n_pool_ammonium": [0.00075125671, 0.02001151359, 0.00030892, 0.000172988], - "soil_n_pool_nitrate": [-0.003295899, -0.003990944, -0.00105915, -0.000642911], - "soil_p_pool_dop": [2.02317351e-4, 1.64662024e-4, 2.0799736e-4, 9.62312501e-5], - "soil_p_pool_particulate": [6.77587e-6, -7.228e-6, -1.29451192e-6, 1.898709e-7], - "soil_p_pool_necromass": [0.00297253, 0.00350535, 0.00755271, 0.0008742], - "soil_p_pool_maom": [5.44660113e-4, -6.28584725e-5, 4.528133e-4, 3.0913116e-4], + "soil_c_pool_lmwc": [0.117290490, 6.96565834e-2, 0.247627966, 3.42642831e-2], + "soil_c_pool_maom": [3.7894322e-2, 4.8705495e-3, 5.6793727e-2, 7.2757916e-2], + "soil_c_pool_bacteria": [-4.24905e-2, -1.71527e-2, -8.74104e-2, -6.36844e-3], + "soil_c_pool_fungi": [-6.507313e-3, -6.211968e-2, -1.680347e-2, -2.891271e-2], + "soil_c_pool_pom": [3.73447584e-4, -2.62977207e-2, -2.214249e-2, 5.219897e-3], + "soil_c_pool_necromass": [-2.296284e-3, 6.9255912e-2, 2.2051989e-2, -6.1268e-2], + "soil_enzyme_pom_bacteria": [-5.44018e-4, -2.2835e-4, -1.19517e-3, -7.21028e-5], + "soil_enzyme_maom_bacteria": [-8.54122e-4, -2.79326e-4, -5.9611e-4, -1.0930e-4], + "soil_enzyme_pom_fungi": [-6.25574e-4, -1.24304e-4, -1.52398e-4, -1.05217e-4], + "soil_enzyme_maom_fungi": [-2.07949e-4, -1.50128e-4, -8.87255e-5, -5.12891e-5], + "soil_n_pool_don": [1.60498e-3, 5.24092e-3, 5.31639e-3, 2.42007e-3], + "soil_n_pool_particulate": [-8.93041e-5, 5.105645e-5, 9.035108e-5, 5.212779e-6], + "soil_n_pool_necromass": [6.917627e-3, -3.050687e-3, 1.431913e-3, -4.551887e-3], + "soil_n_pool_maom": [1.183733e-3, 1.082948e-2, 1.343197e-2, 7.72882e-3], + "soil_n_pool_ammonium": [9.35035e-4, 2.72159e-2, 5.31626e-4, 1.83631e-4], + "soil_n_pool_nitrate": [-3.053041e-3, -3.922566e-3, -1.050268e-3, -9.197065e-4], + "soil_p_pool_dop": [1.99425697e-4, 1.39742546e-4, 1.99748943e-4, 9.68009312e-5], + "soil_p_pool_particulate": [6.820884e-6, -6.40228e-6, -8.6718e-7, 2.094258e-7], + "soil_p_pool_necromass": [2.184141e-3, 2.644765e-3, 5.429799e-3, 7.286432e-4], + "soil_p_pool_maom": [5.47518e-4, -3.2943e-5, 4.6272e-4, 3.0915e-4], "soil_p_pool_primary": [-4.473516e-10, -1.222973e-9, -6.33411e-10, -1.3674e-10], "soil_p_pool_secondary": [-5.050797e-7, -2.77311e-6, -7.40324e-7, -2.187697e-7], - "soil_p_pool_labile": [-1.643259e-5, -0.000295103, -1.212019e-4, -1.313285e-6], + "soil_p_pool_labile": [-1.54646e-5, -2.773006e-4, -9.46854e-5, -2.062198e-6], } # Make order of pools object @@ -78,7 +78,7 @@ def test_calculate_all_pool_updates( delta_pools = soil_pools.calculate_all_pool_updates( delta_pools_ordered=pool_order, - top_soil_layer_index=fixture_core_components.layer_structure.index_topsoil_scalar, + layer_structure=fixture_core_components.layer_structure, soil_moisture_capacity=CoreConsts.soil_moisture_capacity, top_soil_layer_thickness=fixture_core_components.layer_structure.soil_layer_thickness[ 0 diff --git a/tests/models/soil/test_soil_model.py b/tests/models/soil/test_soil_model.py index 965c97570..e0cb46979 100644 --- a/tests/models/soil/test_soil_model.py +++ b/tests/models/soil/test_soil_model.py @@ -85,12 +85,7 @@ def test_soil_model_initialization( ) -def test_soil_model_initialization_no_data( - caplog, - dummy_carbon_data, - fixture_core_components, - enzyme_classes, -): +def test_soil_model_initialization_no_data(caplog, fixture_core_components): """Test `SoilModel` initialization with no data.""" from virtual_ecosystem.core.constants import CoreConsts from virtual_ecosystem.core.data import Data @@ -350,67 +345,68 @@ def test_update(mocker, fixture_soil_model, dummy_carbon_data): Dataset( data_vars=dict( soil_c_pool_lmwc=DataArray( - [0.10867866, 0.0528613, 0.2235931, 0.02047065], dims="cell_id" + [0.10828621, 0.05492146, 0.22333439, 0.02039486], dims="cell_id" ), soil_c_pool_maom=DataArray( - [2.519536, 1.70883297, 4.53172237, 0.53214258], dims="cell_id" + [2.51878747, 1.70762064, 4.53007411, 0.53180235], dims="cell_id" ), soil_c_pool_bacteria=DataArray( - [5.77301795, 2.28884242, 11.24128134, 0.99642333], + [5.77888792, 2.29150361, 11.25660944, 0.996833], dims="cell_id", ), soil_c_pool_fungi=DataArray( - [0.88589868, 8.51022834, 2.1988625, 4.5237925], + [0.88678846, 8.51959122, 2.2017577, 4.52566274], dims="cell_id", ), soil_c_pool_pom=DataArray( - [0.1001131, 0.98559395, 0.68780336, 0.35260428], dims="cell_id" + [0.10019111, 0.98701374, 0.68908282, 0.35261025], dims="cell_id" ), soil_c_pool_necromass=DataArray( - [0.0625005, 0.05307367, 0.11674337, 0.08227162], dims="cell_id" + [0.05703629, 0.04266299, 0.10173659, 0.08044387], dims="cell_id" ), soil_enzyme_pom_bacteria=DataArray( - [0.02240932, 0.0094633, 0.04945988, 0.00297424], dims="cell_id" + [0.02240909, 0.00946283, 0.04945813, 0.00297422], dims="cell_id" ), soil_enzyme_maom_bacteria=DataArray( - [0.0351762, 0.01156196, 0.02479662, 0.00450575], dims="cell_id" + [0.03517596, 0.01156149, 0.02479487, 0.00450574], dims="cell_id" ), soil_enzyme_pom_fungi=DataArray( - [0.02575935, 0.00569559, 0.00638582, 0.00435819], dims="cell_id" + [0.02575926, 0.00569118, 0.00638497, 0.00435818], dims="cell_id" ), soil_enzyme_maom_fungi=DataArray( - [0.00856592, 0.00675875, 0.00376447, 0.00213799], dims="cell_id" + [0.00856583, 0.00675434, 0.00376362, 0.00213799], dims="cell_id" ), soil_n_pool_don=DataArray( - [0.00169773, 0.00382384, 0.00304483, 0.00395096], dims="cell_id" + [0.00153904, 0.00386884, 0.0028133, 0.0039439], dims="cell_id" ), soil_n_pool_particulate=DataArray( - [0.00709321, 0.00073862, 0.00289692, 0.01428811], dims="cell_id" + [0.00709876, 0.00073966, 0.00290222, 0.01428835], dims="cell_id" ), soil_n_pool_necromass=DataArray( - [0.00666897, 0.01833887, 0.02353984, 0.00962116], dims="cell_id" + [0.00564613, 0.01665236, 0.02074835, 0.00932728], dims="cell_id" ), soil_n_pool_maom=DataArray( - [0.86659183, 0.48606279, 0.33418043, 0.09973263], dims="cell_id" + [0.86649472, 0.4859555, 0.33374338, 0.09967796], dims="cell_id" ), soil_n_pool_ammonium=DataArray( - [0.00042733, 0.01509539, 0.00030326, 0.00524331], dims="cell_id" + [0.00052167, 0.01855596, 0.00043117, 0.0052487], dims="cell_id" ), soil_n_pool_nitrate=DataArray( - [0.0005624, 0.0020384, -0.0001656, 0.01271296], dims="cell_id" + [0.00069102, 0.00219584, -0.00016155, 0.01272167], + dims="cell_id", ), soil_p_pool_dop=DataArray( - [0.00018004, 0.00017463, 0.00034475, 0.00018331], dims="cell_id" + [0.00015938, 0.00015181, 0.00029053, 0.0001802], dims="cell_id" ), soil_p_pool_particulate=DataArray( - [3.19436203e-5, 2.82149510e-4, 1.13656052e-4, 5.71524688e-4], + [3.19672137e-5, 2.82555559e-4, 1.13866204e-4, 5.71534407e-4], dims="cell_id", ), soil_p_pool_necromass=DataArray( - [0.00199395, 0.0015151, 0.00373002, 0.00079515], dims="cell_id" + [0.0016797, 0.00117208, 0.00288416, 0.00073708], dims="cell_id" ), soil_p_pool_maom=DataArray( - [0.01357081, 0.03484564, 0.02002014, 0.00406592], dims="cell_id" + [0.01351353, 0.03479647, 0.01986707, 0.00405508], dims="cell_id" ), soil_p_pool_primary=DataArray( [0.0019594, 0.00535662, 0.00277434, 0.00059892], dims="cell_id" @@ -419,7 +415,7 @@ def test_update(mocker, fixture_soil_model, dummy_carbon_data): [0.00705642, 0.03816755, 0.0115255, 0.00733096], dims="cell_id" ), soil_p_pool_labile=DataArray( - [-6.7324868e-6, -1.331584e-4, -1.860591e-5, 1.9133659e-4], + [-3.64956738e-6, -1.18679784e-4, 4.19911975e-6, 1.90983100e-4], dims="cell_id", ), ) @@ -499,6 +495,7 @@ def test_order_independance( "matric_potential", "vertical_flow", "soil_temperature", + "air_temperature", "clay_fraction", "litter_C_mineralisation_rate", "litter_N_mineralisation_rate", @@ -591,86 +588,86 @@ def test_construct_full_soil_model( ) delta_pools = [ - 0.1178918, - 0.06892161, - 0.2489136, - 0.03425211, - 0.03734787, - 0.00340136, - 0.05447554, - 0.07275546, - -0.0543618, - -0.0226100, - -0.1185237, - -0.0071954, - -0.00832584, - -0.08196413, - -0.02280126, - -0.03266732, - 0.00021589, - -0.02918772, - -0.0247599, - 0.00520792, - 0.01141213, - 0.09537438, - 0.05971513, - -0.0566864, - -5.4395e-4, - -2.2795e-4, - -1.19323e-3, - -7.2103e-5, - -8.5406e-4, - -2.7893e-4, - -5.9417e-4, - -1.093e-4, - -0.00062555, - -0.00012062, - -0.00015158, - -0.00010522, - -2.07924e-4, - -1.46441e-4, - -8.79093e-5, - -5.1289e-5, - 0.00180422, - 0.00529461, - 0.00549027, - 0.00240583, - -1.005585e-4, - 4.899227e-5, - 7.96678e-5, - 4.723906e-6, - 0.00948372, - 0.00118049, - 0.00843786, - -0.00381522, - 0.00099458, - 0.01041398, - 0.01326356, - 0.00772835, - 0.00075125671, - 0.02001151359, - 0.00030892, - 0.000172988, - -0.003295899, - -0.003990944, - -0.00105915, - -0.000642911, - 2.02317351e-4, - 1.64662024e-4, - 2.0799736e-4, - 9.62312501e-5, - 6.77587e-6, - -7.228e-6, - -1.29451192e-6, - 1.898709e-7, - 0.00297253, - 0.00350535, - 0.00755271, - 0.0008742, - 5.44660113e-4, - -6.28584725e-5, - 4.528133e-4, - 3.0913116e-4, + 0.117290490, + 6.96565834e-2, + 0.247627966, + 3.42642831e-2, + 3.7894322e-2, + 4.8705495e-3, + 5.6793727e-2, + 7.2757916e-2, + -4.24905e-2, + -1.71527e-2, + -8.74104e-2, + -6.36844e-3, + -6.507313e-3, + -6.211968e-2, + -1.680347e-2, + -2.891271e-2, + 3.73447584e-4, + -2.62977207e-2, + -2.214249e-2, + 5.219897e-3, + -2.296284e-3, + 6.9255912e-2, + 2.2051989e-2, + -6.1268e-2, + -5.44018e-4, + -2.2835e-4, + -1.19517e-3, + -7.21028e-5, + -8.54122e-4, + -2.79326e-4, + -5.9611e-4, + -1.0930e-4, + -6.25574e-4, + -1.24304e-4, + -1.52398e-4, + -1.05217e-4, + -2.07949e-4, + -1.50128e-4, + -8.87255e-5, + -5.12891e-5, + 1.60498e-3, + 5.24092e-3, + 5.31639e-3, + 2.42007e-3, + -8.93041e-5, + 5.105645e-5, + 9.035108e-5, + 5.212779e-6, + 6.917627e-3, + -3.050687e-3, + 1.431913e-3, + -4.551887e-3, + 1.183733e-3, + 1.082948e-2, + 1.343197e-2, + 7.72882e-3, + 9.35035e-4, + 2.72159e-2, + 5.31626e-4, + 1.83631e-4, + -3.053041e-3, + -3.922566e-3, + -1.050268e-3, + -9.197065e-4, + 1.99425697e-4, + 1.39742546e-4, + 1.99748943e-4, + 9.68009312e-5, + 6.820884e-6, + -6.40228e-6, + -8.6718e-7, + 2.094258e-7, + 2.184141e-3, + 2.644765e-3, + 5.429799e-3, + 7.286432e-4, + 5.47518e-4, + -3.2943e-5, + 4.6272e-4, + 3.0915e-4, -4.473516e-10, -1.222973e-9, -6.33411e-10, @@ -679,10 +676,10 @@ def test_construct_full_soil_model( -2.77311e-6, -7.40324e-7, -2.187697e-7, - -1.643259e-5, - -0.000295103, - -1.212019e-4, - -1.313285e-6, + -1.54646e-5, + -2.773006e-4, + -9.46854e-5, + -2.062198e-6, ] # make pools @@ -706,7 +703,7 @@ def test_construct_full_soil_model( pools=pools, data=dummy_carbon_data, no_cells=4, - top_soil_layer_index=fixture_core_components.layer_structure.index_topsoil_scalar, + layer_structure=fixture_core_components.layer_structure, delta_pools_ordered=delta_pools_ordered, model_constants=SoilConsts, functional_groups=functional_groups, diff --git a/virtual_ecosystem/models/soil/env_factors.py b/virtual_ecosystem/models/soil/env_factors.py index 70a12824c..35422ace0 100644 --- a/virtual_ecosystem/models/soil/env_factors.py +++ b/virtual_ecosystem/models/soil/env_factors.py @@ -8,7 +8,9 @@ import numpy as np from numpy.typing import NDArray from scipy.constants import convert_temperature, gas_constant +from xarray import DataArray +from virtual_ecosystem.core.core_components import LayerStructure from virtual_ecosystem.core.logger import LOGGER from virtual_ecosystem.models.soil.constants import SoilConsts @@ -405,3 +407,32 @@ def calculate_leaching_rate( """ return solubility_coefficient * solute_density * vertical_flow_rate / soil_moisture + + +def find_total_soil_moisture_for_microbially_active_depth( + soil_moistures: DataArray, + layer_structure: LayerStructure, +) -> NDArray[np.float32]: + """Find total soil moisture for the microbially active depth. + + The proportion of each soil layer that lies within the microbially active zone is + first found. The soil moisture for each layer is then multiplied by this proportion + and summed, to find the total soil moisture in the microbially active zone. + + Args: + soil_moistures: Soil moistures across all soil layers [mm] + layer_structure: The LayerStructure instance for the simulation. From this we + use the thickness of each layer, as well as `soil_layer_active_thickness` + which is how much of each layer lies within the microbially active zone + + Returns: + The total soil moisture in the microbially active depth [mm] + """ + + # Find the fraction of each layer that lies within the microbially active zone + layer_weights = ( + layer_structure.soil_layer_active_thickness + / layer_structure.soil_layer_thickness + ) + + return np.dot(layer_weights, soil_moistures[layer_structure.index_all_soil]) diff --git a/virtual_ecosystem/models/soil/pools.py b/virtual_ecosystem/models/soil/pools.py index f525fa55c..a6dd95c6d 100644 --- a/virtual_ecosystem/models/soil/pools.py +++ b/virtual_ecosystem/models/soil/pools.py @@ -12,7 +12,12 @@ from numpy.typing import NDArray from scipy.constants import convert_temperature +from virtual_ecosystem.core.core_components import LayerStructure from virtual_ecosystem.core.data import Data +from virtual_ecosystem.models.litter.env_factors import ( + average_temperature_over_microbially_active_layers, + average_water_potential_over_microbially_active_layers, +) from virtual_ecosystem.models.soil.constants import SoilConsts from virtual_ecosystem.models.soil.env_factors import ( EnvironmentalEffectFactors, @@ -23,6 +28,7 @@ calculate_nitrification_temperature_factor, calculate_symbiotic_nitrogen_fixation_carbon_cost, calculate_temperature_effect_on_microbes, + find_total_soil_moisture_for_microbially_active_depth, ) from virtual_ecosystem.models.soil.microbial_groups import ( EnzymeConstants, @@ -382,7 +388,7 @@ def __init__( def calculate_all_pool_updates( self, delta_pools_ordered: dict[str, NDArray[np.float32]], - top_soil_layer_index: int, + layer_structure: LayerStructure, soil_moisture_capacity: float, top_soil_layer_thickness: float, ) -> NDArray[np.float32]: @@ -405,8 +411,8 @@ def calculate_all_pool_updates( Args: delta_pools_ordered: Dictionary to store pool changes in the order that pools are stored in the initial condition vector. - top_soil_layer_index: Index for layer in data object representing top soil - layer + layer_structure: The details of the layer structure used across the Virtual + Ecosystem. soil_moisture_capacity: Soil moisture capacity, i.e. the maximum (volumetric) moisture the soil can hold [unitless]. top_soil_layer_thickness: Thickness of the topsoil layer [mm]. @@ -415,20 +421,28 @@ def calculate_all_pool_updates( A vector containing net changes to each pool. Order [lmwc, maom]. """ - # Find temperature and soil moisture values for the topsoil layer - soil_water_potential = self.data["matric_potential"][ - top_soil_layer_index - ].to_numpy() - soil_temperature = self.data["soil_temperature"][ - top_soil_layer_index - ].to_numpy() - soil_moisture = self.data["soil_moisture"][top_soil_layer_index].to_numpy() + # Find temperature, soil water potential and soil moisture values for the + # microbially active depth + soil_water_potential = average_water_potential_over_microbially_active_layers( + water_potentials=self.data["matric_potential"], + layer_structure=layer_structure, + ) + soil_temperature = average_temperature_over_microbially_active_layers( + soil_temperatures=self.data["soil_temperature"], + surface_temperature=self.data["air_temperature"][ + layer_structure.index_surface_scalar + ].to_numpy(), + layer_structure=layer_structure, + ) + soil_moisture = find_total_soil_moisture_for_microbially_active_depth( + soil_moistures=self.data["soil_moisture"], layer_structure=layer_structure + ) # Calculate the effective saturation of the soil (soil layer thickness needs to # be converted from m to mm here to be consistent with soil moisture units) # TODO - This needs to be reviewed as part of the soil abiotic links review - effective_saturation = self.data["soil_moisture"][ - top_soil_layer_index - ].to_numpy() / (soil_moisture_capacity * top_soil_layer_thickness * 1e3) + effective_saturation = soil_moisture / ( + soil_moisture_capacity * top_soil_layer_thickness * 1e3 + ) # Find environmental factors which impact biogeochemical soil processes env_factors = calculate_environmental_effect_factors( diff --git a/virtual_ecosystem/models/soil/soil_model.py b/virtual_ecosystem/models/soil/soil_model.py index edc5e207c..a95b78b83 100644 --- a/virtual_ecosystem/models/soil/soil_model.py +++ b/virtual_ecosystem/models/soil/soil_model.py @@ -27,7 +27,7 @@ from virtual_ecosystem.core.base_model import BaseModel from virtual_ecosystem.core.config import Config from virtual_ecosystem.core.constants_loader import load_constants -from virtual_ecosystem.core.core_components import CoreComponents +from virtual_ecosystem.core.core_components import CoreComponents, LayerStructure from virtual_ecosystem.core.data import Data from virtual_ecosystem.core.exceptions import InitialisationError from virtual_ecosystem.core.logger import LOGGER @@ -334,7 +334,7 @@ def integrate(self) -> dict[str, DataArray]: args=( self.data, no_cells, - self.layer_structure.index_topsoil_scalar, + self.layer_structure, delta_pools_ordered, self.model_constants, self.microbial_groups, @@ -406,7 +406,7 @@ def construct_full_soil_model( pools: NDArray[np.float32], data: Data, no_cells: int, - top_soil_layer_index: int, + layer_structure: LayerStructure, delta_pools_ordered: dict[str, NDArray[np.float32]], model_constants: SoilConsts, functional_groups: dict[str, MicrobialGroupConstants], @@ -424,7 +424,8 @@ def construct_full_soil_model( pools: An array containing all soil pools in a single vector data: The data object, used to populate the arguments i.e. pH and bulk density no_cells: Number of grid cells the integration is being performed over - top_soil_layer_index: Index for layer in data object representing top soil layer + layer_structure: The details of the layer structure used across the Virtual + Ecosystem. delta_pools_ordered: Dictionary to store pool changes in the order that pools are stored in the initial condition vector. model_constants: Set of constants for the soil model. @@ -459,7 +460,7 @@ def construct_full_soil_model( return soil_pools.calculate_all_pool_updates( delta_pools_ordered=delta_pools_ordered, - top_soil_layer_index=top_soil_layer_index, + layer_structure=layer_structure, # TODO - This needs to be reconsidered as part of the soil-abiotic links review soil_moisture_capacity=soil_moisture_capacity, top_soil_layer_thickness=top_soil_layer_thickness,