API documentation for the soil_model module#

The soil_model module creates a SoilModel class as a child of the BaseModel class. At present a lot of the abstract methods of the parent class (e.g. spinup()) are overwritten using placeholder functions that don’t do anything. This will change as the Virtual Ecosystem model develops. The factory method from_config() exists in a more complete state, and unpacks a small number of parameters from our currently pretty minimal configuration dictionary. These parameters are then used to generate a class instance. If errors crop here when converting the information from the config dictionary to the required types (e.g. timedelta64) they are caught and then logged, and at the end of the unpacking an error is thrown. This error should be caught and handled by downstream functions so that all model configuration failures can be reported as one.

Exceptions:

IntegrationError

Custom exception class for cases when model integration cannot be completed.

Classes:

SoilModel(data, core_components, ...[, ...])

A class defining the soil model.

Functions:

construct_full_soil_model(t, pools, data, ...)

Function that constructs the full soil model in a solve_ivp friendly form.

estimate_past_mycorrhizal_supply(...)

Estimate nutrient supply by mycorrhizal fungi for the previous time step.

make_slices(no_cells, no_pools)

Constructs a list of slices based on the number of grid cells and pools.

exception virtual_ecosystem.models.soil.soil_model.IntegrationError[source]#

Custom exception class for cases when model integration cannot be completed.

Methods:

add_note(object, /)

Exception.add_note(note) -- add a note to the exception

with_traceback(object, /)

Exception.with_traceback(tb) -- set self.__traceback__ to tb and return self.

add_note(object, /)#

Exception.add_note(note) – add a note to the exception

with_traceback(object, /)#

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class virtual_ecosystem.models.soil.soil_model.SoilModel(data: Data, core_components: CoreComponents, microbial_groups: dict[str, MicrobialGroupConstants], enzyme_classes: dict[str, SoilEnzymeClass], soil_moisture_saturation: float, soil_moisture_residual: float, model_constants: SoilConstants = SoilConstants(), static: bool = False)[source]#

A class defining the soil model.

This model can be configured based on the data object and a config dictionary. It can be updated by numerical integration. At present the underlying model this class wraps is quite simple (i.e. four soil carbon pools), but this will get more complex as the Virtual Ecosystem develops.

Parameters:
  • data – The data object to be used in the model.

  • core_components – The core components used across models.

  • microbial_groups – A dictionary of soil microbial group constant classes.

  • enzyme_classes – A dictionary of soil enzyme classes.

  • soil_moisture_saturation – An initial value for soil moisture saturation

  • soil_moisture_residual – An initial value for soil moisture residual

  • model_constants – Set of constants for the soil model.

  • static – Boolean flag indicating if the model should run in static mode.

Methods:

calculate_dissolved_nutrient_concentrations()

Calculate the amount of each inorganic nutrient that is in dissolved form.

calculate_initial_symbiotic_supply()

Estimate symbiotic supply from zeroth time step.

check_for_invalid_input_values(var)

Check if there are any invalid values in the data for a specific variable.

check_init_data()

Check the init data contains the required variables.

cleanup()

Placeholder function for soil model cleanup.

convert_fruiting_body_production_to_rate(...)

Convert total fungal fruiting body production into a rate are being produced.

convert_mycorrhizal_supplies_to_mass(...)

Convert mycorrhizal nutrient supplies from mass per volume to mass units.

from_config(data, configuration, core_components)

Factory function to initialise the soil model from configuration.

integrate()

Integrate the soil model.

spinup()

Placeholder function to spin up the soil model.

to_total_mass(output_rate)

Method to convert soil model rates from per volume to total mass units.

update(time_index, **kwargs)

Function to update the model.

Attributes:

core_constants

The core constants used in the model.

data

A Data instance providing access to the shared simulation data.

grid

The Grid details used in the model.

layer_structure

The LayerStructure details used in the model.

model_constants

Set of constants for the soil model.

model_timing

The ModelTiming details used in the model.

model_update_bounds

Bounds on model update frequencies.

refreshed_variables

List of variables that the model resets for each new integration step.

vars_populated_by_first_update

Variables that are initialised by the model during the first update.

vars_populated_by_init

Variables that are initialised by the model during the setup.

vars_required_for_init

Required variables for model initialisation.

vars_required_for_update

Variables that are required by the update method of the model.

vars_updated

Variables that are updated by the model.

calculate_dissolved_nutrient_concentrations() dict[str, DataArray][source]#

Calculate the amount of each inorganic nutrient that is in dissolved form.

This calculates the nutrient concentration of the water in the topsoil layer. Negative values are explicitly handled by this function to prevent them from passing from the soil model (where they are unavoidable) into the plants model (where they could break things). When soil nutrient concentrations are negative it is assumed dissolved nutrient concentrations are taken to be zero.

Returns:

A data array containing the size of each dissolved nutrient pool [kg{nutrient} m^-3].

calculate_initial_symbiotic_supply() dict[str, DataArray][source]#

Estimate symbiotic supply from zeroth time step.

In order to do the first update pf the plant model an estimate of the amount of nutrients supplied in the previous (zeroth) time step needs to be provided. As the plant model runs first this has to be an estimate. We make this estimate by assuming that mycorrhizal fungi uptake nutrients at the maximum achievable rate. Maximum uptake is only observed in our model if microbes are equally limited by all nutrients, if this isn’t the case then the initial prediction will be an overestimate.

Returns:

The amount of each nutrient (nitrogen and phosphorus) that plants receive from each mycorrhizal partner (arbuscular mycorrhizal and ectomycorrhizal fungi) for the initial time step [kg]

check_for_invalid_input_values(var: str) bool[source]#

Check if there are any invalid values in the data for a specific variable.

This function checks for NaN and infinite values.

For variables with a layer structure, only the layers relevant to the soil model are checked. For the air_temperature variable this is just the soil surface layer, but for the other layer-structured variable all soil layers are checked.

Parameters:

var – The name of the variable being checked

Returns:

Whether the data for the variable has any invalid values.

check_init_data() None#

Check the init data contains the required variables.

This method is used to check that the set of variables defined in the vars_required_for_init class attribute are present in the Data instance used to create a new instance of the class.

Raises:

ValueError – If the Data instance does not contain all the required variables or if those variables do not map onto the required axes.

cleanup() None[source]#

Placeholder function for soil model cleanup.

convert_fruiting_body_production_to_rate(total_production: DataArray) dict[str, DataArray][source]#

Convert total fungal fruiting body production into a rate are being produced.

The soil model integration provides a total mass produced (per soil volume) over the integration time period. This method converts this into a rate, and into per area rather than soil volume terms.

Parameters:

total_production – The total production of fungal fruiting bodies over the integration time period, per volume of soil [kg{C} m^-3]

Returns:

A data array containing the rate at which fungal fruiting bodies are produced per unit area [kg{C} m^-2 day^-1].

convert_mycorrhizal_supplies_to_mass(updated_soil_pools: dict[str, DataArray]) dict[str, DataArray][source]#

Convert mycorrhizal nutrient supplies from mass per volume to mass units.

Parameters:

updated_soil_pools – A dictionary of data arrays containing soil pool values at the end of the model integration.

Returns:

A dictionary of data arrays containing the total supply of each nutrient (per grid cell) [kg nutrient].

core_constants: CoreConstants#

The core constants used in the model.

data: Data#

A Data instance providing access to the shared simulation data.

classmethod from_config(data: Data, configuration: CompiledConfiguration, core_components: CoreComponents) SoilModel[source]#

Factory function to initialise the soil model from configuration.

This function unpacks the relevant information from the configuration file, and then uses it to initialise the model. If any information from the config is invalid rather than returning an initialised model instance an error is raised.

Parameters:
  • data – A Data instance.

  • configuration – A validated Virtual Ecosystem model configuration object.

  • core_components – The core components used across models.

  • config – A validated Virtual Ecosystem model configuration object.

grid: Grid#

The Grid details used in the model.

integrate() dict[str, DataArray][source]#

Integrate the soil model.

For now a single integration will be used to advance the entire soil module. However, this might get split into several separate integrations in future (if that is feasible).

This function unpacks the variables that are to be integrated into a single numpy array suitable for integration.

Returns:

A data array containing the new pool values (i.e. the values at the final time point)

Raises:
  • IntegrationError – When the integration cannot be successfully completed.

  • ValueError – If any of the variables used by the soil model have NaN values.

layer_structure: LayerStructure#

The LayerStructure details used in the model.

model_constants: SoilConstants#

Set of constants for the soil model.

model_timing: ModelTiming#

The ModelTiming details used in the model.

model_update_bounds: tuple[Quantity, Quantity] = (<Quantity(30, 'minute')>, <Quantity(3, 'month')>)#

Bounds on model update frequencies.

This class attribute defines two time intervals that define a lower and upper bound on the update frequency that can reasonably be used with a model. Models updated more often than the lower bound may fail to capture transient dynamics and models updated more slowly than the upper bound may fail to capture important temporal patterns.

refreshed_variables#

List of variables that the model resets for each new integration step.

These variables are intermediate values that it does not make sense to store in the data object.

spinup() None[source]#

Placeholder function to spin up the soil model.

to_total_mass(output_rate: float | ndarray[tuple[Any, ...], dtype[floating]]) ndarray[tuple[Any, ...], dtype[floating]][source]#

Method to convert soil model rates from per volume to total mass units.

Total mass (across a grid cell over a time step) units are used by the plant model, so quantities returned to the plant model need to have their units converted to this.

Parameters:

output_rate – Rate of output to convert [kg m^-3 day^-1].

Returns:

Output rate converted to per area units [kg].

update(time_index: int, **kwargs: Any) None#

Function to update the model.

If the model is static, the inner update method, self._update will only run once, at most.

Parameters:
  • time_index – The index representing the current time step in the data object.

  • **kwargs – Further arguments to the update method.

vars_populated_by_first_update: tuple[str, ...] = ()#

Variables that are initialised by the model during the first update.

These are the variables that are initialised by the model and stored in the data object when running the update method for the first time. They will be available for other models to use in their update methods but not in the setup methods.

vars_populated_by_init: tuple[str, ...] = ('dissolved_nitrate', 'dissolved_ammonium', 'dissolved_phosphorus', 'arbuscular_mycorrhizal_n_supply', 'arbuscular_mycorrhizal_p_supply', 'ectomycorrhizal_n_supply', 'ectomycorrhizal_p_supply', 'production_of_fungal_fruiting_bodies')#

Variables that are initialised by the model during the setup.

These are the variables that are initialised by the model and stored in the data object when running the setup method and that will be available for other models to use in their own setup or update methods.

vars_required_for_init: tuple[str, ...] = ('soil_cnp_pool_maom', 'soil_cnp_pool_lmwc', 'soil_cnp_pool_pom', 'soil_cnp_pool_necromass', 'soil_c_pool_bacteria', 'soil_c_pool_saprotrophic_fungi', 'soil_c_pool_arbuscular_mycorrhiza', 'soil_c_pool_ectomycorrhiza', 'soil_enzyme_pom_bacteria', 'soil_enzyme_maom_bacteria', 'soil_enzyme_pom_fungi', 'soil_enzyme_maom_fungi', 'soil_n_pool_ammonium', 'soil_n_pool_nitrate', 'soil_p_pool_primary', 'soil_p_pool_secondary', 'soil_p_pool_labile', 'pH', 'clay_fraction', 'matric_potential', 'soil_temperature', 'air_temperature')#

Required variables for model initialisation.

This class property defines a set of variable names that must be present in the Data instance used to initialise an instance of this class. It is a tuple containing zero or more tuples, each providing a variable name and then a tuple of zero or more core axes that the variable must map onto.

For example: (('temperature', ('spatial', 'temporal')),)

vars_required_for_update: tuple[str, ...] = ('soil_cnp_pool_maom', 'soil_cnp_pool_lmwc', 'soil_cnp_pool_pom', 'soil_cnp_pool_necromass', 'soil_c_pool_bacteria', 'soil_c_pool_saprotrophic_fungi', 'soil_c_pool_arbuscular_mycorrhiza', 'soil_c_pool_ectomycorrhiza', 'soil_enzyme_pom_bacteria', 'soil_enzyme_maom_bacteria', 'soil_enzyme_pom_fungi', 'soil_enzyme_maom_fungi', 'soil_n_pool_ammonium', 'soil_n_pool_nitrate', 'soil_p_pool_primary', 'soil_p_pool_secondary', 'soil_p_pool_labile', 'pH', 'clay_fraction', 'matric_potential', 'vertical_flow', 'soil_temperature', 'air_temperature', 'soil_moisture', 'litter_mineralisation_rate_cnp', 'plant_symbiote_carbon_supply', 'root_carbohydrate_exudation', 'plant_ammonium_uptake', 'plant_nitrate_uptake', 'plant_phosphorus_uptake', 'subcanopy_ammonium_uptake', 'subcanopy_nitrate_uptake', 'subcanopy_phosphorus_uptake', 'animal_pom_consumption_cnp', 'animal_bacteria_consumption', 'animal_saprotrophic_fungi_consumption', 'animal_ectomycorrhiza_consumption', 'animal_arbuscular_mycorrhiza_consumption', 'decay_of_fungal_fruiting_bodies', 'decomposed_excrement_cnp', 'decomposed_carcasses_cnp')#

Variables that are required by the update method of the model.

These variables should have been initialised by another model or loaded from external sources, but in either case they will be available in the data object.

vars_updated: tuple[str, ...] = ('soil_cnp_pool_maom', 'soil_cnp_pool_lmwc', 'soil_cnp_pool_pom', 'soil_cnp_pool_necromass', 'soil_c_pool_bacteria', 'soil_c_pool_saprotrophic_fungi', 'soil_c_pool_arbuscular_mycorrhiza', 'soil_c_pool_ectomycorrhiza', 'soil_enzyme_pom_bacteria', 'soil_enzyme_maom_bacteria', 'soil_enzyme_pom_fungi', 'soil_enzyme_maom_fungi', 'soil_n_pool_ammonium', 'soil_n_pool_nitrate', 'soil_p_pool_primary', 'soil_p_pool_secondary', 'soil_p_pool_labile', 'dissolved_nitrate', 'dissolved_ammonium', 'dissolved_phosphorus', 'arbuscular_mycorrhizal_n_supply', 'arbuscular_mycorrhizal_p_supply', 'ectomycorrhizal_n_supply', 'ectomycorrhizal_p_supply', 'production_of_fungal_fruiting_bodies')#

Variables that are updated by the model.

At the moment, this tuple is used to decide which variables to output from the Data object, i.e. every variable updated by a model used in the specific simulation. It is also be used warn if multiple models will be updating the same variable and to verify that these variables are indeed initialised by another model, and therefore will be available.

virtual_ecosystem.models.soil.soil_model.construct_full_soil_model(t: float, pools: ndarray[tuple[Any, ...], dtype[floating]], data: Data, no_cells: int, layer_structure: LayerStructure, delta_pools_ordered: dict[str, ndarray[tuple[Any, ...], dtype[floating]]], model_constants: SoilConstants, functional_groups: dict[str, MicrobialGroupConstants], enzyme_classes: dict[str, SoilEnzymeClass], core_constants: CoreConstants, soil_moisture_saturation: float, soil_moisture_residual: float, top_soil_layer_thickness: float) ndarray[tuple[Any, ...], dtype[floating]][source]#

Function that constructs the full soil model in a solve_ivp friendly form.

Parameters:
  • t – Current time [days]. At present the model has no explicit time dependence, but the function must still be accept a time value to allow it to be integrated.

  • 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

  • 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.

  • functional_groups – Set of microbial functional groups used by the soil model.

  • enzyme_classes – Set of enzyme classes used by the soil model.

  • core_constants – Set of constants shared across all models.

  • soil_moisture_saturationsoil moisture saturation, i.e. the maximum (volumetric) moisture the soil can hold [unitless].

  • soil_moisture_residualsoil moisture residual, i.e. the minimum (volumetric) moisture the soil can hold [unitless].

  • top_soil_layer_thickness – Thickness of the topsoil layer [m].

Returns:

The rate of change for each soil pool

virtual_ecosystem.models.soil.soil_model.estimate_past_mycorrhizal_supply(soil_c_pool_lmwc: ndarray[tuple[Any, ...], dtype[floating]], soil_n_pool_don: ndarray[tuple[Any, ...], dtype[floating]], soil_n_pool_ammonium: ndarray[tuple[Any, ...], dtype[floating]], soil_n_pool_nitrate: ndarray[tuple[Any, ...], dtype[floating]], soil_p_pool_dop: ndarray[tuple[Any, ...], dtype[floating]], soil_p_pool_labile: ndarray[tuple[Any, ...], dtype[floating]], microbe_pool_size: ndarray[tuple[Any, ...], dtype[floating]], soil_temp: ndarray[tuple[Any, ...], dtype[floating]], microbial_group: MicrobialGroupConstants, env_factors: EnvironmentalEffectFactors) tuple[ndarray[tuple[Any, ...], dtype[floating]], ndarray[tuple[Any, ...], dtype[floating]]][source]#

Estimate nutrient supply by mycorrhizal fungi for the previous time step.

This function estimates the rates at which mycorrhizal fungi were supplying nutrients (nitrogen and phosphorus) to their plant partners prior to the start of the simulation. This estimate is calculated based the initial soil conditions, and involves assuming that mycorrhizal fungi take up nutrients at the maximum possible rate, and then pass on a fixed fraction of this to their plant partners.

Parameters:
  • soil_c_pool_lmwc – The amount of carbon in the labile mineral associated organic matter pool [kg{C} m^-3]

  • soil_n_pool_don – The amount of nitrogen in the dissolved organic nitrogen pool [kg{N} m^-3]

  • soil_n_pool_ammonium – Size of the soil ammonium pool [kg{N} m^-3]

  • soil_n_pool_nitrate – Size of the soil nitrate pool [kg{N} m^-3]

  • soil_p_pool_dop – The amount of phosphorus in the dissolved organic phosphorus pool [kg{P} m^-3]

  • soil_p_pool_labile – Size of the labile phosphorus pool [kg{P} m^-3]

  • microbe_pool_size – Size of the microbial pool of interest [kg{C} m^-3]

  • soil_temp – Soil temperature [Celsius]

  • microbial_group – Constants associated with the microbial group of interest.

  • env_factors – Data class containing the various factors through which the environment effects soil cycling rates.

Returns:

A tuple containing estimates of the rate at which each mycorrhizal fungal group supplied nitrogen and phosphorus to their plant partners in the time step before the simulation started [kg m^-3 day^-1].

virtual_ecosystem.models.soil.soil_model.make_slices(no_cells: int, no_pools: int) list[slice][source]#

Constructs a list of slices based on the number of grid cells and pools.

Parameters:
  • no_cells – Number of grid cells the pools are defined for

  • no_pools – Number of soil pools being integrated

Returns:

A list of containing the correct number of correctly spaced slices