Skip to content
Snippets Groups Projects
Commit c5c8f603 authored by xo30xoqa's avatar xo30xoqa
Browse files

Started working on energy budgets

parent 26ee5084
No related branches found
No related tags found
No related merge requests found
......@@ -82,8 +82,9 @@ include("world/weather.jl")
include("farm/farm.jl")
include("crop/crops.jl")
include("nature/nature.jl")
include("nature/insects.jl")
include("nature/energy.jl")
include("nature/nature.jl")
include("nature/populations.jl")
include("nature/ecologicaldata.jl")
#TODO loop over files in nature/species directory
......
### Persefone - a socio-economic-ecological model of European agricultural landscapes.
###
### This file contains structs and functions for implementing Dynamic Energy Budgets.
###
"""
DEBparameters
An immutable struct to save the parameter list for a species' Dynamic Energy Budget
model. (See Sousa et al., 2010.)
"""
struct DEBparameters
assimilation::Float64 # percentage of food biomass assimilated (y_EX)
kappa::Float64 # percentage allocated to somatic maintenance and growth (k)
juvenilesize::Float64 # structure size at which an embryo becomes a juvenile (MHb)
adultsize::Float64 # structure size at which a juvenile becomes an adult (MHp)
maintenance::Float64 # daily percentage of body size needed per update for somatic and maturity maintenance
reproduction::Float64 # energy needed to produce an egg (= initial amount of reserve)
v::Float64 # energy conductance (XXX ???)
end
"""
EnergyBudget
This struct represents an individual's energy balance, as conceptualised by the
Dynamic Energy Budget theory. Upon assimilation, energy is first stored as biomass
in a reserve buffer, before being used for maintenance, growth, and reproduction.
(Note that this is a simplified model form which ignores maturity as a separate buffer.)
**Sources:**
- Malishev & Kramer-Schadt (2021). Movement, models, and metabolism:
Individual-based energy budget models as next-generation extensions
for predicting animal movement outcomes across scales. Ecological
Modelling, 441, 109413. https://doi.org/10.1016/j.ecolmodel.2020.109413
- Marques et al. (2018). The AmP project: Comparing species on the basis
of dynamic energy budget parameters. PLOS Computational Biology,
14(5), e1006100. https://doi.org/10.1371/journal.pcbi.1006100
- Sibly et al. (2013). Representing the acquisition and use of energy
by individuals in agent-based models of animal populations. Methods in
Ecology and Evolution, 4(2), 151–161. https://doi.org/10.1111/2041-210x.12002
- Sousa et al. (2010). Dynamic energy budget theory restores coherence
in biology. Philosophical Transactions of the Royal Society B: Biological
Sciences, 365(1557), 3413–3428. https://doi.org/10.1098/rstb.2010.0166
- Kooijman, S. A. L. M. (2009). Dynamic energy and mass budgets
in biological systems (3rd ed). Cambridge University Press.
https://www.researchgate.net/profile/Edgar-Meza-3/post/Is_there_a_toxicokinetic_model_for_daphnia_magna_or_other_zooplankton/attachment/59d62cf579197b807798b396/AS%3A348547653357569%401460111644286/download/Dynamic+Energy+Budget+theory+-+Kooijman.pdf
- *see also:* Brown et al. (2004). Toward a metabolic theory of ecology.
Ecology, 85(7), 1771–1789. https://doi.org/10.1890/03-9000
"""
mutable struct EnergyBudget
params::DEBparameters
reserve::Float64
structure::Float64
offspring::Float64
end
"""
biomass(energybudget)
Calculate the total biomass of an individual based on its energy budget.
(Sum of the reserve, structure, and offspring buffers; Sibly et al. 2013.)
"""
function biomass(deb::EnergyBudget)
deb.reserve + deb.structure + deb.offspring
end
"""
feed!(biomass, energybudget)
Consume a given quantity of food. Expands the energy reserve by an
amount determined by the assimilation rate.
"""
function feed!(biomass::Float64, deb::EnergyBudget)
deb.reserve += biomass * deb.params.assimilation
#TODO reserve doesn't grow infinitely
end
"""
update!(energybudget)
Carry out a daily update of the energy budget. Mobilises reserves and allocates
these to maintenance (prioritised), growth, and reproduction.
Return `true` if the individual has enough energy to survive, or `false` if the
reserve is empty and it starves.
"""
function update!(deb::EnergyBudget)
#TODO
mobilisation = 0
somaticmaintenance = deb.params.maintenance # J_ES
maturitymaintenance = deb.params.maintenance # J_EJ
# juveniles grow until they reach adult size
if deb.structure < adultsize
growth = (mobilisation*deb.params.kappa) - somaticmaintenance
deb.structure += growth
end
# juveniles increase in maturity, adults invest into reproduction
maturityreproduction = (mobilisation*(1-deb.params.kappa)) - maturitymaintenance
if deb.structure >= adultsize
deb.offspring += maturityreproduction
end
deb.reserve -= mobilisation
return deb.reserve > 0
end
"""
reproduce!(energybudget)
If there is sufficient energy in the `offspring` buffer of an adult, produce an
embryo/egg, reducing the parent energy in the process. Returns the embryo's energy
budget, or `nothing` if the conditions are not met.
"""
function reproduce!(deb::EnergyBudget)
if deb.structure >= deb.params.adultsize && deb.offspring >= deb.params.reproduction
deb.offspring -= deb.params.reproduction
return EnergyBudget(deb.params, deb.params.reproduction, 0.0, 0.0)
else
return nothing
end
end
### Persefone - a socio-economic-ecological model of European agricultural landscapes.
###
### This file contains submodel that calculates insect biomass
### This file contains the submodel that calculates insect biomass
###
##TODO write tests for this
"""
insectbiomass(pixel, model)
Calculate the insect biomass in this location, using the factors configured
in the `nature.insectmodel` settings (any of: "season", "habitat", "weather",
"pesticides"). Returns a float value in mg/m².
in the `nature.insectmodel` settings (any combination of: "season", "habitat",
"weather", "pesticides"). Returns a float value in g/m².
**Biological note:** this is a very approximate calculation! Insect biomass
varies wildly in time and space and is hard to measure. This calculation is
based on the idea of a parabolic seasonal development of insect abundance,
modified habitat suitability, weather, and pesticide application. Although it
modified by habitat suitability, weather, and pesticide application. Although it
is based on empirical studies, it can only deliver a rough, order-of-magnitude
estimation of likely insect biomass in a given location.
......@@ -35,9 +33,9 @@ farmland. Ecology and Evolution, 12(1), e8461. https://doi.org/10.1002/ece3.8461
"""
function insectbiomass(pixel::Pixel, model::AgentBasedModel)::Float64
## if no factors are configure, insect abundance defaults to 300 mg/m²,
## if no factors are configured, insect abundance defaults to 300 mg/m²,
## a value in the upper range of insect biomass density in agricultural landscapes
baseline = 300.0
baseline = 300
seasonfactor = 0.0
habitatfactor = 1.0
weatherfactor = 1.0
......@@ -68,6 +66,7 @@ function insectbiomass(pixel::Pixel, model::AgentBasedModel)::Float64
## based on fig. 3b in Paquette et al. (2013)
##XXX (and possibly table 3 in Grübler et al. (2008))
if "weather" in @param(nature.insectmodel)
@warn "Weather effects on insect biomass are not yet implemented."
#TODO add this once we have a working weather module
end
......@@ -81,5 +80,5 @@ function insectbiomass(pixel::Pixel, model::AgentBasedModel)::Float64
## calculate biomass using a parabolic equation in the vertex form
biomass = seasonfactor+baseline*habitatfactor*pesticidefactor*weatherfactor
biomass > 0 ? biomass : 0.0
biomass > 0 ? biomass/1000 : 0.0 # convert mg to g
end
......@@ -24,10 +24,15 @@ i.e. the trait `phase` can be accessed and modified with `animal.phase`.)
# to deepcopy the speciesdict.
#XXX add `phase` and `species` (rather than `name`) directly to the struct?
traits::Dict{String,Any}
energy::Union{EnergyBudget,Nothing} # DEB is optional
sex::Sex
age::Int
end
# DEB is optional
Animal(id::Int64, pos::Tuple{Int64,Int64}, traits::Dict{String,Any},
sex::Sex, age::Int) = Animal(id, pos, traits, nothing, sex, age)
# Overloading the `getproperty` and `setproperty!` methods for `Animal` allows
# us to write `animal.property` instead of `animal.traits["property"]`.
# (This is inspired by Agents.jl in `model.jl`.)
......
......@@ -151,24 +151,24 @@ end
p6 = Pixel(Ps.water, 1, [])
# check whether the model calculates the same numbers I did by hand
model.date = date1
@test Ps.insectbiomass(p1, model) 4.11 atol=0.01
@test Ps.insectbiomass(p1, model) 0.00411 atol=0.0001
@test Ps.insectbiomass(p2, model) == 0.0
@test Ps.insectbiomass(p3, model) 154.11 atol=0.01
@test Ps.insectbiomass(p4, model) 4.11 atol=0.01
@test Ps.insectbiomass(p5, model) 304.11 atol=0.01
@test Ps.insectbiomass(p3, model) 0.15411 atol=0.0001
@test Ps.insectbiomass(p4, model) 0.00411 atol=0.0001
@test Ps.insectbiomass(p5, model) 0.30411 atol=0.0001
@test Ps.insectbiomass(p6, model) == 0.0
model.date = date2
@test Ps.insectbiomass(p1, model) == 300.0
@test Ps.insectbiomass(p2, model) == 150.0
@test Ps.insectbiomass(p3, model) == 450.0
@test Ps.insectbiomass(p4, model) == 300.0
@test Ps.insectbiomass(p5, model) == 600.0
@test Ps.insectbiomass(p1, model) == 0.3
@test Ps.insectbiomass(p2, model) == 0.15
@test Ps.insectbiomass(p3, model) == 0.45
@test Ps.insectbiomass(p4, model) == 0.3
@test Ps.insectbiomass(p5, model) == 0.6
@test Ps.insectbiomass(p6, model) == 0.0
model.date = date3
@test Ps.insectbiomass(p1, model) == 0.0
@test Ps.insectbiomass(p2, model) == 0.0
@test Ps.insectbiomass(p3, model) == 0.0
@test Ps.insectbiomass(p4, model) == 0.0
@test Ps.insectbiomass(p5, model) 14.43 atol=0.01
@test Ps.insectbiomass(p5, model) 0.01443 atol=0.0001
@test Ps.insectbiomass(p6, model) == 0.0
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment