Production

TimeIntegration TimeIntegration Input Facies State time step WaterDepth WaterDepth Input Facies State sea_level sediment_height initial_topography subsidence_rate TimeIntegration->WaterDepth Production Production Input Facies State insolation maximum_growth_rate extinction_coefficient saturation_intensity WaterDepth->Production Boxes Boxes Input Facies State box Boxes->WaterDepth FaciesBase FaciesBase Input Facies State facies FaciesBase->Production

The Production module specifies the production rate following the model by Bosscher & Schlager 1992 [1]. The growth rate is given as

\[g(w) = g_m \tanh\left({{I_0 e^{-kw}} \over {I_k}}\right).\]

This can be understood as a smooth transition between the maximum growth rate under saturated conditions, and exponential decay due to light intensity dropping with greater water depth.

⪡component-production-rate⪢≣
function production_rate(insolation, facies, water_depth)
    gₘ = facies.maximum_growth_rate
    I = insolation / facies.saturation_intensity
    x = water_depth * facies.extinction_coefficient
    return water_depth > 0.0u"m" ? gₘ * tanh(I * exp(-x)) : 0.0u"m/Myr"
end

From just this equation we can define a uniform production process. This requires that we have a Facies that defines the maximum_growth_rate, extinction_coefficient and saturation_intensity.

file:test/Components/ProductionSpec.jl
module ProductionSpec
    using Test
    using CarboKitten.Components.Common
    using CarboKitten.Components.Production: Facies, Input, uniform_production
    using CarboKitten.Components.WaterDepth: initial_state

    @testset "Components/Production" begin
        let facies = Facies(
                maximum_growth_rate = 500u"m/Myr",
                extinction_coefficient = 0.8u"m^-1",
                saturation_intensity = 60u"W/m^2"),
            input = Input(
                box = Box{Periodic{2}}(grid_size=(10, 1), phys_scale=1.0u"m"),
                time = TimeProperties(Δt=1.0u"kyr", steps=10),
                sea_level = t -> 0.0u"m",
		        initial_topography = (x, y) -> -10u"m",
		        subsidence_rate = 0.0u"m/Myr",
                facies = [facies],
                insolation = 400.0u"W/m^2")

            state = initial_state(input)
            prod = uniform_production(input)(state)
            @test all(prod[1:end-1,:] .>= prod[2:end,:])
        end
    end
end
file:src/Components/Production.jl
@compose module Production
@mixin WaterDepth, FaciesBase
using ..Common
using ..WaterDepth: water_depth
using HDF5

export production_rate, uniform_production

@kwdef struct Facies <: AbstractFacies
    maximum_growth_rate::Rate
    extinction_coefficient::typeof(1.0u"m^-1")
    saturation_intensity::Intensity
end

@kwdef struct Input <: AbstractInput
    insolation::Intensity
end

function write_header(fid, input::AbstractInput)
    attributes(fid["input"])["insolation"] = input.insolation |> in_units_of(u"W/m^2")
    for (i, f) in enumerate(input.facies)
        attr = attributes(fid["input/facies$(i)"])
        attr["maximum_growth_rate"] = f.maximum_growth_rate |> in_units_of(u"m/Myr")
        attr["extinction_coefficient"] = f.extinction_coefficient |> in_units_of(u"m^-1")
        attr["saturation_intensity"] = f.saturation_intensity |> in_units_of(u"W/m^2")
    end
end

<<component-production-rate>>

function uniform_production(input::AbstractInput)
    w = water_depth(input)
    na = [CartesianIndex()]

    return function (state::AbstractState)
        return production_rate.(
            input.insolation,
            input.facies[:, na, na],
            w(state)[na, :, :])
    end
end
end

CA Production

TimeIntegration TimeIntegration Input Facies State time step WaterDepth WaterDepth Input Facies State sea_level sediment_height initial_topography subsidence_rate TimeIntegration->WaterDepth Boxes Boxes Input Facies State box Boxes->WaterDepth CellularAutomaton CellularAutomaton Input Facies State ca_interval viability_range ca ca_random_seed activation_range ca_priority Boxes->CellularAutomaton Production Production Input Facies State insolation maximum_growth_rate extinction_coefficient saturation_intensity WaterDepth->Production FaciesBase FaciesBase Input Facies State facies FaciesBase->Production FaciesBase->CellularAutomaton CAProduction CAProduction Production->CAProduction CellularAutomaton->CAProduction

The CAProduction component gives production that depends on the provided CA.

file:src/Components/CAProduction.jl
@compose module CAProduction
    @mixin TimeIntegration, CellularAutomaton, Production
    using ..Common
    using ..Production: production_rate
    using ..WaterDepth: water_depth

    function production(input::AbstractInput)
        w = water_depth(input)
        na = [CartesianIndex()]
        output = Array{Amount, 3}(undef, n_facies(input), input.box.grid_size...)

        w = water_depth(input)
        p(f, w) = production_rate(input.insolation, input.facies[f], w) .* input.time.Δt

        return function(state::AbstractState)
            for f = 1:n_facies(input)
                output[f, :, :] = ifelse.(state.ca .== f, p.(f, w(state)), 0.0u"m")
            end
            return output
        end
    end
end