Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .JuliaFormatter.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
style="blue"
indent=4
margin=92
trailing_comma=true
for_in_replacement="∈"
whitespace_typedefs=true
normalize_line_endings="unix"
align_assignment=true
align_struct_field=true
align_conditional=true
align_pair_arrow=true
align_matrix=true
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# CoralBlox.jl
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.13251118.svg)](https://doi.org/10.5281/zenodo.13251118)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.13251118.svg)](https://doi.org/10.5281/zenodo.13251118) [![Code Style: Blue](https://img.shields.io/badge/code%20style-blue-4495d1.svg)](https://github.com/JuliaDiff/BlueStyle)


-----

Expand All @@ -19,7 +20,7 @@ same `SizeClass` and `FunctionalGroup` have the same growth rate, we can visuali
growth as groups of corals moving on the diameter space in blocks. Further details about
how this growth and mortality are implemented can be found below.

## Quick Start
# Quick Start

This plot was generated using the following script as an example of how CoralBlox can be used:

Expand Down Expand Up @@ -157,7 +158,7 @@ Consideration of external factors that may influence coral growth and mortality
could be included outside of each `timestep!` call, potentially informed by a broader
ecosystem model.

## Model details
# Model details

Consider the area of each colony approximated by the area of a circumference with diameter
$x$:
Expand Down Expand Up @@ -195,7 +196,7 @@ $$

The following sections explain in more detail how growth and mortality are represented.

### How does mortality work?
## How does mortality work?

At each timestep $t$, before the growth event, we apply a survival rate to each
`CoralBlock`. That is done by multiplying each `FunctionalGroup` and `SizeClass` survival
Expand All @@ -208,7 +209,7 @@ $$
\end{equation}
$$

### How does growth work?
## How does growth work?

For each `FunctionalGroup`, we can think of a horizontal axis representing the diameter
space with its `CoralBlock`s lined up. Then, a growth event is conceived as the displacement
Expand All @@ -234,7 +235,7 @@ The paper will have a section with more details about this movement in the front

TODO -->

### How does the linear extension scale factor work?
## How does the linear extension scale factor work?

Each coral colony has a base growth $l_{\tau\sigma}$, which is an increase in diameter.
This is referred to as the *linear extension* and depends on the colony's `FunctionalGroup`
Expand Down Expand Up @@ -280,3 +281,7 @@ $$
\omega_{\tau\sigma;t} = l_{\tau\sigma} \gamma_t
\end{equation}
$$

# Contributing

This project uses [BlueStyle](https://domluna.github.io/JuliaFormatter.jl/dev/blue_style/) style guide with some extra configuration. If you use VSCode, you don't need to install any extensions, the `.JuliaFormatter.toml` will be used automatically to format the files.
3 changes: 1 addition & 2 deletions ext/CoralBloxPlotExt/CoralBloxPlotExt.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
module CoralBloxPlotExt
end
module CoralBloxPlotExt end
#using CoralBlox
#import CoralBlox.blocks_model: CoverBlock
#import CoralBlox.blocks_model: SizeClass
Expand Down
131 changes: 63 additions & 68 deletions src/linear_extension.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,24 @@ size class all combinations are tested.
- `habitable_areas` : Habitable area
"""
function max_projected_cover(
linear_extensions::Matrix{Float64},
bin_edges::Matrix{Float64},
habitable_area::Float64
linear_extensions::Matrix{Float64}, bin_edges::Matrix{Float64}, habitable_area::Float64
)::Float64
return _diameter_coef(linear_extensions, bin_edges) * habitable_area
end
function max_projected_cover(
linear_extensions::Matrix{Float64},
bin_edges::Matrix{Float64},
habitable_areas::Vector{Float64}
habitable_areas::Vector{Float64},
)::Vector{Float64}
return [_diameter_coef(linear_extensions, bin_edges)] .* habitable_areas
end

function _diameter_coef(
linear_extensions::Matrix{Float64}, bin_edges::Matrix{Float64}
)::Float64
size_class_coefs = ((bin_edges[:, 2:end-1] .+ linear_extensions[:, 1:end-1]) .^ 2) ./
(bin_edges[:, 2:end-1] .^ 2)
size_class_coefs =
((bin_edges[:, 2:(end - 1)] .+ linear_extensions[:, 1:(end - 1)]) .^ 2) ./
(bin_edges[:, 2:(end - 1)] .^ 2)
return findmax(size_class_coefs)[1]
end

Expand All @@ -57,19 +56,21 @@ function linear_extension_scale_factors(
habitable_area::Float64,
linear_extensions::AbstractMatrix{Float64},
bin_edges::AbstractMatrix{Float64},
max_projected_cover::Float64
max_projected_cover::Float64,
)::Float64
# Target here refers to all size classes except the last one of each functional group
# since these don't grow
target_linear_extensions = @view linear_extensions[:, 1:end-1]
target_bin_edges = @view bin_edges[:, 1:end-1]
target_C_cover_t = @view C_cover_t[:, 1:end-1]
target_linear_extensions = @view linear_extensions[:, 1:(end - 1)]
target_bin_edges = @view bin_edges[:, 1:(end - 1)]
target_C_cover_t = @view C_cover_t[:, 1:(end - 1)]

total_cover::Float64 = sum(target_C_cover_t)
non_target_total_cover = sum(C_cover_t[:, end])

# Average density for each functional group and size class
size_class_densities::Matrix{Float64} = _size_class_densities(target_C_cover_t, target_bin_edges)
size_class_densities::Matrix{Float64} = _size_class_densities(
target_C_cover_t, target_bin_edges
)

# Projected coral cover at t+1
projected_cover::Float64 = _projected_cover(
Expand All @@ -80,144 +81,140 @@ function linear_extension_scale_factors(
total_cover,
projected_cover,
max_projected_cover - non_target_total_cover,
habitable_area - non_target_total_cover
habitable_area - non_target_total_cover,
)

# Solve quadratic equation
a::Float64 = _quadratic_coeff(size_class_densities, target_linear_extensions, Δd(target_bin_edges, 1))
b::Float64 = _linear_coeff(size_class_densities, target_linear_extensions, Δd(target_bin_edges, 2))
a::Float64 = _quadratic_coeff(
size_class_densities, target_linear_extensions, Δd(target_bin_edges, 1)
)
b::Float64 = _linear_coeff(
size_class_densities, target_linear_extensions, Δd(target_bin_edges, 2)
)
c::Float64 = _constant_coeff(
size_class_densities, adjusted_projected_cover, Δd(target_bin_edges, 3)
)

return (sqrt((b^2) - (4 * a * c)) - (b)) / (2 * a)
end
function linear_extension_scale_factors(
C_cover_t::AbstractArray{Float64,3},
C_cover_t::AbstractArray{Float64, 3},
loc_habitable_areas::AbstractVector{Float64},
linear_extensions::AbstractMatrix{Float64},
bin_edges::AbstractMatrix{Float64},
max_projected_cover::AbstractVector{Float64}
max_projected_cover::AbstractVector{Float64},
)::AbstractVector{Float64}
n = size(C_cover_t, 3)
result = Vector{Float64}(undef, n)
@views for i in 1:n
@views for i 1:n
result[i] = linear_extension_scale_factors(
C_cover_t[:, :, i],
loc_habitable_areas[i],
linear_extensions,
bin_edges,
max_projected_cover[i]
max_projected_cover[i],
)
end
return result
end

Δd(
bin_edges::AbstractMatrix{Float64},
n::Int64
)::Matrix{Float64} = ((bin_edges[:, 2:end] .^ n) .- (bin_edges[:, 1:end-1] .^ n))
Δd(bin_edges::AbstractMatrix{Float64}, n::Int64)::Matrix{Float64} =
((bin_edges[:, 2:end] .^ n) .- (bin_edges[:, 1:(end - 1)] .^ n))

_size_class_densities(
C_cover_t::AbstractMatrix{Float64},
bin_edges::AbstractMatrix{Float64}
C_cover_t::AbstractMatrix{Float64}, bin_edges::AbstractMatrix{Float64}
)::Matrix{Float64} = (12 / π) .* (C_cover_t ./ Δd(bin_edges, 3))
_size_class_densities(
C_cover_t::AbstractArray{Float64,3},
bin_edges::AbstractMatrix{Float64}
)::Array{Float64,3} = (12 / π) .* (C_cover_t ./ Δd(bin_edges, 3))
C_cover_t::AbstractArray{Float64, 3}, bin_edges::AbstractMatrix{Float64}
)::Array{Float64, 3} = (12 / π) .* (C_cover_t ./ Δd(bin_edges, 3))

function _projected_cover(
size_class_densities::AbstractMatrix{Float64},
linear_extensions::AbstractMatrix{Float64},
bin_edges::AbstractMatrix{Float64}
bin_edges::AbstractMatrix{Float64},
)::Float64
return sum(
(π / 12) .*
size_class_densities .* (
(π / 12) .* size_class_densities .* (
(3 .* (linear_extensions .^ 2) .* Δd(bin_edges, 1)) .+
(3 .* linear_extensions .* Δd(bin_edges, 2)) .+
Δd(bin_edges, 3)
)
(3 .* linear_extensions .* Δd(bin_edges, 2)) .+ Δd(bin_edges, 3)
),
)
end
function _projected_cover(
size_class_densities::AbstractArray{Float64,3},
size_class_densities::AbstractArray{Float64, 3},
linear_extensions::AbstractMatrix{Float64},
bin_edges::AbstractMatrix{Float64}
bin_edges::AbstractMatrix{Float64},
)::Vector{Float64}
return dropdims(sum(
((π / 12) .*
size_class_densities .* (
(3 .* (linear_extensions .^ 2) .* Δd(bin_edges, 1)) .+
(3 .* linear_extensions .* Δd(bin_edges, 2)) .+
Δd(bin_edges, 3)
)
),
dims=(2, 1)
); dims=(2, 1))
return dropdims(
sum(
(
(π / 12) .* size_class_densities .* (
(3 .* (linear_extensions .^ 2) .* Δd(bin_edges, 1)) .+
(3 .* linear_extensions .* Δd(bin_edges, 2)) .+ Δd(bin_edges, 3)
)
);
dims=(2, 1),
);
dims=(2, 1),
)
end

function _adjusted_projected_cover(
total_cover::Float64,
projected_cover::Float64,
max_projected_cover::Float64,
habitable_area::Float64
habitable_area::Float64,
)::Float64
return total_cover + (
(projected_cover - total_cover) *
(
(habitable_area - total_cover) / (max_projected_cover - total_cover)
)
((habitable_area - total_cover) / (max_projected_cover - total_cover))
)
end
function _adjusted_projected_cover(
loc_cover::AbstractVector{Float64},
projected_cover::AbstractVector{Float64},
max_projected_cover::AbstractVector{Float64},
loc_habitable_areas::AbstractVector{Float64}
loc_habitable_areas::AbstractVector{Float64},
)::Vector{Float64}
return loc_cover .+ (
(projected_cover .- loc_cover) .*
(
(loc_habitable_areas .- loc_cover) ./ (max_projected_cover .- loc_cover)
)
((loc_habitable_areas .- loc_cover) ./ (max_projected_cover .- loc_cover))
)
end

function _quadratic_coeff(
size_class_densities::AbstractMatrix{Float64},
linear_extensions::AbstractMatrix{Float64},
Δ¹d::AbstractMatrix{Float64}
Δ¹d::AbstractMatrix{Float64},
)::Float64
return sum(3 .* (size_class_densities .* (linear_extensions .^ 2) .* Δ¹d))
end
function _quadratic_coeff(
size_class_densities::Array{Float64,3},
size_class_densities::Array{Float64, 3},
linear_extensions::AbstractMatrix{Float64},
Δ¹d::AbstractMatrix{Float64}
Δ¹d::AbstractMatrix{Float64},
)::Vector{Float64}
return dropdims(
sum((3 .* (size_class_densities .* (linear_extensions .^ 2) .* Δ¹d)), dims=(1, 2)),
dims=(1, 2)
sum((3 .* (size_class_densities .* (linear_extensions .^ 2) .* Δ¹d)); dims=(1, 2));
dims=(1, 2),
)
end

function _linear_coeff(
size_class_densities::AbstractMatrix{Float64},
linear_extensions::AbstractMatrix{Float64},
Δ²d::AbstractMatrix{Float64}
Δ²d::AbstractMatrix{Float64},
)::Float64
return sum(3 .* (size_class_densities .* linear_extensions .* Δ²d))
end
function _linear_coeff(
size_class_densities::Array{Float64,3},
size_class_densities::Array{Float64, 3},
linear_extensions::AbstractMatrix{Float64},
Δ²d::AbstractMatrix{Float64}
Δ²d::AbstractMatrix{Float64},
)::Vector{Float64}
return dropdims(
sum((3 .* (size_class_densities .* linear_extensions .* Δ²d)), dims=(1, 2)),
dims=(1, 2)
sum((3 .* (size_class_densities .* linear_extensions .* Δ²d)); dims=(1, 2));
dims=(1, 2),
)
end

Expand All @@ -229,12 +226,10 @@ function _constant_coeff(
return sum((size_class_densities .* Δ³d)) - ((12 / π) * adjusted_projected_cover)
end
function _constant_coeff(
size_class_densities::Array{Float64,3},
size_class_densities::Array{Float64, 3},
adjusted_projected_cover::Vector{Float64},
Δ³d::AbstractMatrix{Float64},
)::Vector{Float64}
return dropdims(
sum(((size_class_densities .* Δ³d)), dims=(1, 2)),
dims=(1, 2)
) .- ((12 / π) .* adjusted_projected_cover)
return dropdims(sum(((size_class_densities .* Δ³d)); dims=(1, 2)); dims=(1, 2)) .-
((12 / π) .* adjusted_projected_cover)
end
Loading