Model with bacterioplankton

Material pools and living prey are separate concepts. Here a POM pool is consumed by heterotrophic bacterioplankton B, while zooplankton Z graze the living bacterial plankton. A Q10 factor modifies POM consumption.

using Agate.Components: Plankton, Pool
using Agate.Parameters: AllometricPalatability, ConsumerAssimilation, ConstructionParameter, DerivedDefault, Parameter
using Agate.Construction: construct
using Agate.Introspection: auxiliary_field_names, tracer_names
using Agate.Processes:
    Consumption, ModelDefinition, Temperature, Q10,
    HeterotrophicConsumption, PreferentialGrazing, participants
using Oceananigans.Units: day

Components

POM is one material inventory. B and Z are ordinary living plankton; their ecological roles are supplied by the processes below.

components = (
    N=Pool(:nitrogen),
    POM=Pool(:nitrogen),
    B=Plankton(; states=:nitrogen, reference_state=:nitrogen, size_structure=[0.8]),
    Z=Plankton(; states=:nitrogen, reference_state=:nitrogen, size_structure=[10.0]),
)

processes = (
    consume_POM=Consumption(
        HeterotrophicConsumption();
        consumers=:B,
        resources=:POM,
        bindings=(
            maximum_rate=:maximum_consumption_rate,
            half_saturation=:pom_half_saturation,
            assimilation=:bacterial_assimilation,
        ),
        factors=(
            temperature=Temperature(
                Q10();
                bindings=(
                    q10=:temperature_q10,
                    reference_temperature=:reference_temperature,
                ),
            ),
        ),
        unassimilated_products=:N,
    ),
    graze_bacteria=Consumption(
        PreferentialGrazing();
        consumers=:Z,
        resources=:B,
        bindings=(
            maximum_rate=:maximum_predation_rate,
            half_saturation=:holling_half_saturation,
            palatability=:living_palatability,
            assimilation=:living_assimilation,
        ),
        unassimilated_products=:N,
    ),
)
(consume_POM = Agate.Processes.Consumption{Agate.Processes.HeterotrophicConsumption, @NamedTuple{temperature::Agate.Processes.Temperature{Agate.Processes.Q10}}, Agate.Processes.Products{@NamedTuple{product::Symbol}, @NamedTuple{}, Nothing}}(Agate.Processes.HeterotrophicConsumption(), (:B,), (:POM,), (temperature = Agate.Processes.Temperature{Agate.Processes.Q10}(Agate.Processes.Q10(), :temperature, (q10 = :temperature_q10, reference_temperature = :reference_temperature)),), Agate.Processes.Products{@NamedTuple{product::Symbol}, @NamedTuple{}, Nothing}((product = :N,), NamedTuple(), nothing), (assimilation = :bacterial_assimilation, half_saturation = :pom_half_saturation, maximum_rate = :maximum_consumption_rate)), graze_bacteria = Agate.Processes.Consumption{Agate.Processes.PreferentialGrazing, @NamedTuple{}, Agate.Processes.Products{@NamedTuple{product::Symbol}, @NamedTuple{}, Nothing}}(Agate.Processes.PreferentialGrazing(), (:Z,), (:B,), NamedTuple(), Agate.Processes.Products{@NamedTuple{product::Symbol}, @NamedTuple{}, Nothing}((product = :N,), NamedTuple(), nothing), (assimilation = :living_assimilation, half_saturation = :holling_half_saturation, maximum_rate = :maximum_predation_rate, palatability = :living_palatability)))

Parameters

Each NamedTuple key is the stable model parameter name. Slot-bound parameters derive their storage from the process roles and realized entities, so process parameters need no axis declarations. The four interaction traits are dependency-only setup parameters, so they retain an explicit :plankton axis for the derived matrices.

parameters = (
    maximum_consumption_rate=Parameter(0.8 / day),
    pom_half_saturation=Parameter(0.2),
    bacterial_assimilation=Parameter(0.65),
    temperature_q10=Parameter(2.0),
    reference_temperature=Parameter(20.0),
    maximum_predation_rate=Parameter(0.6 / day),
    holling_half_saturation=Parameter(0.1),
    optimum_predator_prey_ratio=ConstructionParameter(12.5; axes=:plankton),
    specificity=ConstructionParameter(0.4; axes=:plankton),
    protection=ConstructionParameter(0.0; axes=:plankton),
    assimilation_efficiency=ConstructionParameter(0.7; axes=:plankton),
    living_palatability=Parameter(
        DerivedDefault(
            AllometricPalatability();
            deps=(:optimum_predator_prey_ratio, :specificity, :protection),
        )
    ),
    living_assimilation=Parameter(
        DerivedDefault(ConsumerAssimilation(); deps=(:assimilation_efficiency,))
    ),
)
(maximum_consumption_rate = Agate.Parameters.Parameter{Agate.Parameters.ConstantDefault{Float64}}(Agate.Parameters.ConstantDefault{Float64}(9.259259259259259e-6)), pom_half_saturation = Agate.Parameters.Parameter{Agate.Parameters.ConstantDefault{Float64}}(Agate.Parameters.ConstantDefault{Float64}(0.2)), bacterial_assimilation = Agate.Parameters.Parameter{Agate.Parameters.ConstantDefault{Float64}}(Agate.Parameters.ConstantDefault{Float64}(0.65)), temperature_q10 = Agate.Parameters.Parameter{Agate.Parameters.ConstantDefault{Float64}}(Agate.Parameters.ConstantDefault{Float64}(2.0)), reference_temperature = Agate.Parameters.Parameter{Agate.Parameters.ConstantDefault{Float64}}(Agate.Parameters.ConstantDefault{Float64}(20.0)), maximum_predation_rate = Agate.Parameters.Parameter{Agate.Parameters.ConstantDefault{Float64}}(Agate.Parameters.ConstantDefault{Float64}(6.944444444444444e-6)), holling_half_saturation = Agate.Parameters.Parameter{Agate.Parameters.ConstantDefault{Float64}}(Agate.Parameters.ConstantDefault{Float64}(0.1)), optimum_predator_prey_ratio = Agate.Parameters.ConstructionParameter{Agate.Parameters.ConstantDefault{Float64}, Symbol}(Agate.Parameters.ConstantDefault{Float64}(12.5), :plankton), specificity = Agate.Parameters.ConstructionParameter{Agate.Parameters.ConstantDefault{Float64}, Symbol}(Agate.Parameters.ConstantDefault{Float64}(0.4), :plankton), protection = Agate.Parameters.ConstructionParameter{Agate.Parameters.ConstantDefault{Float64}, Symbol}(Agate.Parameters.ConstantDefault{Float64}(0.0), :plankton), assimilation_efficiency = Agate.Parameters.ConstructionParameter{Agate.Parameters.ConstantDefault{Float64}, Symbol}(Agate.Parameters.ConstantDefault{Float64}(0.7), :plankton), living_palatability = Agate.Parameters.Parameter{Agate.Parameters.DerivedDefault{Agate.Parameters.AllometricPalatability, Tuple{Symbol, Symbol, Symbol}}}(Agate.Parameters.DerivedDefault{Agate.Parameters.AllometricPalatability, Tuple{Symbol, Symbol, Symbol}}(Agate.Parameters.AllometricPalatability(), (:optimum_predator_prey_ratio, :specificity, :protection))), living_assimilation = Agate.Parameters.Parameter{Agate.Parameters.DerivedDefault{Agate.Parameters.ConsumerAssimilation, Tuple{Symbol}}}(Agate.Parameters.DerivedDefault{Agate.Parameters.ConsumerAssimilation, Tuple{Symbol}}(Agate.Parameters.ConsumerAssimilation(), (:assimilation_efficiency,))))

Construct and inspect

definition = ModelDefinition(; components, processes, parameters)
bgc = construct(definition)

println("tracers: ", tracer_names(bgc))
println("drivers: ", auxiliary_field_names(bgc))
println("POM consumer: ", participants(processes.consume_POM).consumer)
println("living grazing prey: ", participants(processes.graze_bacteria).resource)
tracers: [:N, :POM, :B_1, :Z_1]
drivers: [:temperature]
POM consumer: (:B,)
living grazing prey: (:B,)

This page was generated using Literate.jl.