Skip to content
Snippets Groups Projects
Select Git revision
  • 0366f2005c28163b74c496f24de64b44b4fd29df
  • master default protected
  • development
  • precompile-statements
  • precompile-tools
  • tmp-faster-loading
  • skylark
  • testsuite
  • code-review
  • v0.7.0
  • v0.6.1
  • v0.6.0
  • v0.5.5
  • v0.5.4
  • v0.5.3
  • v0.5.2
  • v0.2
  • v0.3.0
  • v0.4.1
  • v0.5
20 results

energy.jl

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    energy.jl 8.56 KiB
    ### Persefone.jl - a model of agricultural landscapes and ecosystems in Europe.
    ###
    ### This file contains structs and functions for implementing Dynamic Energy Budgets.
    ###
    
    ## XXX THE CODE IN THIS FILE IS CURRENTLY NOT USED AND LIKELY WON'T BE IN FUTURE.
    ## HOWEVER, I PREFER TO KEEP IT FOR NOW IN CASE WE EVER DO. (DV, 29th July 2024)
    
    #TODO add units
    
    ## STRUCTS
    
    """
        DEBparameters
    
    An immutable struct to save the parameter list for a species' Dynamic Energy Budget
    model. (See Sousa et al., 2010.)
    """
    struct DEBparameters
        maxsearchrate::Float64 # maximum amount of food handled per day (F_m)
        assimilation::Float64 # percentage of food biomass assimilated (y_EX)
        growthefficiency::Float64 # yield of structure on reserve (y_VE)
        v::Float64 # energy conductance
        surfacesomaticmaintenance::Float64 # surface-specific somatic maintenance (J_ET)
        volumesomaticmaintenance::Float64 # volume-specific somatic maintenance (J_EM)
        #maturitymaintenance::Float64 # specific maturity maintenance (k_J)
        kappa::Float64 # percentage allocated to somatic maintenance and growth (k)
        reproductionefficiency::Float64 # overhead cost of reproduction (k_R)
        eggsize::Float64 # weight of an egg/embryo, = initial amount of reserve (M_E0)
        juvenilesize::Float64 # structure size at which an embryo becomes a juvenile (M_Hb)
        adultsize::Float64 # structure size at which a juvenile becomes an adult (M_Hp)
    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
    - *compare with:* 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    # M_E
        structure::Float64  # M_V
        #maturity::Float64  # M_H
        offspring::Float64  # M_ER
    end
    
    
    ## INTERNAL CALCULATIONS
    
    """
        volumetriclength(energybudget)
    
    Calculate the structural length in cm based on an individual's weight
    (assuming a density of 1 g/cm³ to calculate volume, see Kooijman 2009).
    """
    function volumetriclength(deb::EnergyBudget)
        #TODO is cm the right unit?
        weight = deb.reserve + deb.structure + deb.offspring
        vlength = weight ^ (1/3)
        vlength
    end
    
    """
        maturitymaintenance(energybudget)
    
    Calculate the specific maturity maintenance k_J.
    (Internal function.)
    """
    function maturitymaintenance(deb::EnergyBudget)
        y_VE = deb.params.growthefficiency
        J_EM = deb.params.volumesomaticmaintenance
        M_V = deb.structure
        k_J = (y_VE * J_EM) / M_V
        k_J
    end
    
    """
        scaledreservedensity(energybudget)
    
    Calculate the scaled reserve density e.
    (Internal function.)
    """
    function scaledreservedensity(deb::EnergyBudget)
        J_EAm = deb.params.assimilation * deb.params.maxsearchrate
        m_E = deb.reserve / deb.structure
        m_Em = J_EAm / (deb.params.v * deb.structure)
        e = m_E / m_Em
        e
    end
    
    """
        investmentratio(energybudget)
    
    Calculate the investment ratio g.
    (Internal function.)
    """
    function investmentratio(deb::EnergyBudget)
        J_EAm = deb.params.assimilation * deb.params.maxsearchrate
        y_VE = deb.params.growthefficiency
        k = deb.params.kappa
        v = deb.params.v
        M_V = deb.structure
        g = (v * M_V) / (k * J_EAm * y_VE)
        g
    end
    
    """
        growthrate(energybudget)
    
    Calculate the specific growth rate r.
    (Internal function.)
    """
    function growthrate(deb::EnergyBudget)
        J_EAm = deb.params.assimilation * deb.params.maxsearchrate
        J_ET = deb.params.surfacesomaticmaintenance
        J_EM = deb.params.volumesomaticmaintenance
        k = deb.params.kappa
        v = deb.params.v
        e = scaledreservedensity(deb)
        g = investmentratio(deb)
        L = volumetriclength(deb)
        L_m = k * (J_EAm / J_EM) # max length
        L_T = J_ET / J_EM # heating length
        r = v * (e/L - (1+L_T/L)/L_m) / (e+g)
        r
    end
    
    """
        mobilisation(energybudget)
    
    Calculate the mobilisation rate J_EC.
    (Internal function.)
    """
    function mobilisation(deb::EnergyBudget)
        M_E = deb.reserve
        r = growthrate(deb)
        v = deb.params.v
        L = volumetriclength(deb)
        J_EC = M_E * (v/L - r)
        J_EC
    end
    
    
    ## PUBLIC INTERFACE
    
    """
        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)
        J_ET = deb.params.surfacesomaticmaintenance
        J_EM = deb.params.volumesomaticmaintenance
        k_R = deb.params.reproductionefficiency
        y_VE = deb.params.growthefficiency
        #k_J = deb.params.maturitymaintenance
        k_J = maturitymaintenance(deb)
        L = volumetriclength(deb)
        k = deb.params.kappa
        M_V = deb.structure
        #M_H = deb.maturity
        M_E = deb.reserve
    
        J_EC = mobilisation(deb)
    
        ## Somatic maintenance and growth
        J_ES = J_EM * (L^3) + J_ET * (L^2) # somatic maintenance
        J_EG = J_EC * k - J_ES # energy devoted to growth
        J_VG = J_EG * y_VE # actual growth
        #J_VG = growthrate(deb) * deb.structure # r*M_V
        #XXX check if J_VG == J_EG * y_VE == r * M_V
        deb.structure += J_VG
    
        # juveniles grow until they reach adult size
        #XXX growth should stop automatically at M_V == M_Hp
        if deb.structure < adultsize
            growth = (mobilisation*deb.params.kappa) - somaticmaintenance
            deb.structure += growth
        end
    
        # juveniles increase in maturity, adults invest into reproduction
        J_EJ = k_J * M_H # maturity maintenance
        J_ER = J_EC*(1-k) - J_EJ # resources for reproduction
        if M_V >= deb.params.adultsize
            deb.offspring += J_ER * k_R
        else
            #deb.maturity += J_ER #XXX I'm ignoring the maturity buffer for now
        end
    
        #XXX Check that J_EC == J_ES + J_EG + J_EJ + J_ER
        deb.reserve -= J_EC
        return deb.reserve > 0
    end
    
    """
        feed!(quantity, energybudget)
    
    Consume a given quantity of food. Expands the energy reserve by an
    amount determined by the assimilation rate. Returns `true` if successful,
    `false` if the reserve is already full.
    """
    function feed!(quantity::Float64, deb::EnergyBudget)
        F_m = deb.params.maxsearchrate
        y_EX = deb.params.assimilation
        M_V = deb.structure
        M_E = deb.reserve
        v = deb.params.v
    
        J_EAm = y_EX * F_m # max assimilation rate
        m_E = M_E / M_V # reserve density
        m_Em = J_EAm / (v * M_V) # max reserve density
    
        # only feed if the reserve is not yet at maximum capacity
        if m_E < m_Em
            deb.reserve += quantity * y_EX
            return true
        else
            return false
        end
    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)
        M_V = deb.structure
        M_ER = deb.offspring
        M_Hp = deb.params.adultsize
        M_E0 = deb.params.eggsize
        
        if M_V >= M_Hp && M_ER >= M_E0
            deb.offspring -= M_E0
            return EnergyBudget(deb.params, M_E0, 0.0, 0.0)
        else
            return nothing
        end
    end