Model with mixotrophy
A mixotroph does not need a special component type. M is an ordinary Plankton that participates in both growth and grazing.
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, Growth, Light, ModelDefinition, NutrientResponse, Smith, Monod, PreferentialGrazing, participants
using Oceananigans.Units: day
components = (
N=Pool(:nitrogen),
P=Plankton(; states=:nitrogen, reference_state=:nitrogen, size_structure=[1.0]),
M=Plankton(; states=:nitrogen, reference_state=:nitrogen, size_structure=[4.0]),
)
processes = (
growth_M=Growth(;
plankton=:M,
reference_resource=:N,
bindings=(maximum_rate=:maximum_growth_rate,),
factors=(
light=Light(Smith(); driver=:PAR),
nutrients=NutrientResponse(
Monod(); resource=:N, bindings=(half_saturation=:nutrient_half_saturation,)
),
),
),
grazing_M=Consumption(
PreferentialGrazing();
consumers=:M,
resources=:P,
bindings=(
maximum_rate=:maximum_predation_rate,
half_saturation=:holling_half_saturation,
palatability=:palatability_matrix,
assimilation=:assimilation_matrix,
),
unassimilated_products=:N,
),
)(growth_M = Agate.Processes.Growth{@NamedTuple{light::Agate.Processes.Light{Agate.Processes.Smith}, nutrients::Agate.Processes.NutrientResponse{Agate.Processes.Monod}}, @NamedTuple{}, Nothing}((:M,), (light = Agate.Processes.Light{Agate.Processes.Smith}(Agate.Processes.Smith(), :PAR, NamedTuple()), nutrients = Agate.Processes.NutrientResponse{Agate.Processes.Monod}(Agate.Processes.Monod(), :N, (half_saturation = :nutrient_half_saturation,))), :N, NamedTuple(), nothing, (maximum_rate = :maximum_growth_rate,)), grazing_M = Agate.Processes.Consumption{Agate.Processes.PreferentialGrazing, @NamedTuple{}, Agate.Processes.Products{@NamedTuple{product::Symbol}, @NamedTuple{}, Nothing}}(Agate.Processes.PreferentialGrazing(), (:M,), (:P,), NamedTuple(), Agate.Processes.Products{@NamedTuple{product::Symbol}, @NamedTuple{}, Nothing}((product = :N,), NamedTuple(), nothing), (assimilation = :assimilation_matrix, half_saturation = :holling_half_saturation, maximum_rate = :maximum_predation_rate, palatability = :palatability_matrix)))Parameters
Each NamedTuple key is the stable model parameter name. Processes and factors bind their local scientific slots directly to these keys, and those slots determine runtime storage automatically. The interaction traits retain an explicit :plankton axis because they are dependency-only inputs to the derived interaction matrices.
parameters = (
maximum_growth_rate=Parameter(0.8 / day),
alpha=Parameter(0.08 / day),
nutrient_half_saturation=Parameter(0.2),
maximum_predation_rate=Parameter(0.4 / day),
holling_half_saturation=Parameter(0.15),
optimum_predator_prey_ratio=ConstructionParameter(4.0; axes=:plankton),
specificity=ConstructionParameter(0.5; axes=:plankton),
protection=ConstructionParameter(0.0; axes=:plankton),
assimilation_efficiency=ConstructionParameter(0.65; axes=:plankton),
palatability_matrix=Parameter(
DerivedDefault(
AllometricPalatability();
deps=(:optimum_predator_prey_ratio, :specificity, :protection),
)
),
assimilation_matrix=Parameter(
DerivedDefault(ConsumerAssimilation(); deps=(:assimilation_efficiency,))
),
)
definition = ModelDefinition(; components, processes, parameters)
bgc = construct(definition)
println("tracers: ", tracer_names(bgc))
println("drivers: ", auxiliary_field_names(bgc))
println("M grows as: ", participants(processes.growth_M).plankton)
println("M grazes as: ", participants(processes.grazing_M).consumer)
tracers: [:N, :P_1, :M_1]
drivers: [:PAR]
M grows as: (:M,)
M grazes as: (:M,)
This page was generated using Literate.jl.