-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #220 from OceanBioME/jsw/giant-kelp-growth
Make particles easier to use
- Loading branch information
Showing
29 changed files
with
1,147 additions
and
820 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,17 @@ | ||
name = "OceanBioME" | ||
uuid = "a49af516-9db8-4be4-be45-1dad61c5a376" | ||
authors = ["Jago Strong-Wright <[email protected]> and contributors"] | ||
version = "0.12.0" | ||
version = "0.13.0" | ||
|
||
[deps] | ||
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" | ||
Atomix = "a9b6321e-bd34-4604-b9c9-b65b8de01458" | ||
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" | ||
GibbsSeaWater = "9a22fb26-0b63-4589-b28e-8f9d0b5c3d05" | ||
JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" | ||
KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" | ||
Oceananigans = "9e8cae18-63c1-5223-a75c-80ca9d6e9a09" | ||
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" | ||
Roots = "f2b01f46-fcfa-551c-844a-d8ac1e96c665" | ||
SeawaterPolynomials = "d496a93d-167e-4197-9f49-d3af4ff8fe40" | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,92 +1,50 @@ | ||
# [Individuals](@id individuals) | ||
|
||
The effects of individuals can be modelled in OceanBioME. We have implemented this through custom dynamics in the [Lagrangian Particle tracking feature of Oceananigans](https://clima.github.io/OceananigansDocumentation/stable/model_setup/lagrangian_particles/). We have extended these functionalities to make it easier to implement "active" particles which interact with the tracers. We have then implemented a model of [sugar kelp](@ref SLatissima) which can be followed as an example of using this functionality. | ||
The effects of individuals can be modelled in OceanBioME. We have implemented this through custom dynamics in the [Lagrangian Particle tracking feature of Oceananigans](https://clima.github.io/OceananigansDocumentation/stable/model_setup/lagrangian_particles/). We have extended these functionalities to make it easier to implement "active" particles which interact with the tracers. We have then implemented a model of [sugar kelp](@ref sugar-kelp) which can be followed as an example of using this functionality. | ||
|
||
To setup particles first create a particle type with the desired properties, e.g.: | ||
To setup particles first create a particle biogeochemistry, e.g.: | ||
|
||
```@example particles | ||
using OceanBioME.Particles: BiogeochemicalParticles | ||
struct GrowingParticles{FT, VT} <: BiogeochemicalParticles | ||
struct GrowingParticles{FT} | ||
nutrients_half_saturation :: FT | ||
size :: VT | ||
nitrate_uptake :: VT | ||
x :: VT | ||
y :: VT | ||
z :: VT | ||
end | ||
``` | ||
|
||
You then need to overload particular functions to integrate the growth, so they need to first be `import`ed: | ||
|
||
```@example particles | ||
import Oceananigans.Biogeochemistry: update_tendencies! | ||
import Oceananigans.Models.LagrangianParticleTracking: update_lagrangian_particle_properties! | ||
``` | ||
|
||
First, to integrate the particles properties we overload `update_lagrangian_particle_properties!`; | ||
in this fictitious case we will have a Mondo-quota nutrient uptake and growth: | ||
We then need to add some methods to tell `OceanBioME` what properties this particle has, and what tracers it interacts with: | ||
|
||
```@example particles | ||
using Oceananigans.Fields: interpolate | ||
function update_lagrangian_particle_properties!(particles::GrowingParticles, model, bgc, Δt) | ||
@inbounds for p in 1:length(particles) | ||
nutrients = @inbounds interpolate(model.tracers.NO₃, particle.x[p], particle.y[p], particle.z[p]) | ||
uptake = nutrients / (particle.nutrients_half_saturation + nutrients) | ||
import OceanBioME.Particles: required_particle_fields, required_tracers, coupled_tracers | ||
particles.size[p] += uptake * Δt | ||
particles.nitrate_uptake[p] = uptake | ||
end | ||
return nothing | ||
end | ||
required_particle_fields(::GrowingParticles) = (:S, ) | ||
required_tracers(::GrowingParticles) = (:N, ) | ||
coupled_tracers(::GrowingParticles) = (:N, ) | ||
nothing #hide | ||
``` | ||
|
||
In this example the particles will not move around, and are only integrated on a single thread. For a more comprehensive example see the [Sugar Kelp](@ref SLatissima) implementation. We then need to update the tracer tendencies to match the nutrients' uptake: | ||
|
||
So our model is going to track the `S`ize of the particles and take up `N`utrients. | ||
Now we need to how this growth happens. | ||
The forcing functions should be of the form `(particles::ParticleBiogeochemistry)(::Val{:PROPERTY}, t, required_particle_fields..., required_tracers...)`, so in this example: | ||
```@example particles | ||
using OceanBioME.Particles: get_node | ||
function update_tendencies!(bgc, particles::GrowingParticles, model) | ||
@inbounds for p in 1:length(particles) | ||
i, j, k = fractional_indices((x, y, z), grid, Center(), Center(), Center()) | ||
# Convert fractional indices to unit cell coordinates 0 ≤ (ξ, η, ζ) ≤ 1 | ||
# and integer indices (with 0-based indexing). | ||
ξ, i = modf(i) | ||
η, j = modf(j) | ||
ζ, k = modf(k) | ||
(p::GrowingParticles)(::Val{:S}, t, S, N) = N / (N + p.nutrient_half_saturation) | ||
(p::GrowingParticles)(::Val{:N}, t, S, N) = - N / (N + p.nutrient_half_saturation) | ||
``` | ||
|
||
# Round to nearest node and enforce boundary conditions | ||
i, j, k = (get_node(TX(), Int(ifelse(ξ < 0.5, i + 1, i + 2)), grid.Nx), | ||
get_node(TY(), Int(ifelse(η < 0.5, j + 1, j + 2)), grid.Ny), | ||
get_node(TZ(), Int(ifelse(ζ < 0.5, k + 1, k + 2)), grid.Nz)) | ||
We can then create an instance of this particle model using `BiogeochemicalParticles`, and set their initial position and size: | ||
```@example particles | ||
using OceanBioME, Oceananigans | ||
node_volume = volume(i, j, k, grid, Center(), Center(), Center()) | ||
Lx, Ly, Lz = 100, 100, 100 | ||
grid = RectilinearGrid(; size = (8, 8, 8), extent = (Lx, Ly, Lz)) | ||
model.timestepper.Gⁿ.NO₃[i, j, k] += particles.nitrate_uptake[p] / (d * node_volume) | ||
end | ||
return nothing | ||
end | ||
particles = BiogeochemicalParticles(10; grid, biogeochemistry = GrowingParticles(0.5)) | ||
nothing #hide | ||
set!(particles, S = 0.1, x = rand(10) * Lx, y = rand(10) * Ly, z = rand(10) * Lz) | ||
``` | ||
|
||
Now we can just plug this into any biogeochemical model setup to have particles (currently [NPZD](@ref NPZD) and [LOBSTER](@ref LOBSTER)): | ||
|
||
We can then put these into a compatible biogeochemical model, for example: | ||
```@example particles | ||
using OceanBioME, Oceananigans | ||
Lx, Ly, Lz = 1000, 1000, 100 | ||
grid = RectilinearGrid(; size = (64, 64, 16), extent = (Lx, Ly, Lz)) | ||
# Start the particles randomly distributed, floating on the surface | ||
particles = GrowingParticles(0.5, zeros(3), zeros(3), rand(3) * Lx, rand(3) * Ly, zeros(3)) | ||
biogeochemistry = LOBSTER(; grid, particles) | ||
biogeochemistry = NPZD(; grid, particles) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
ba6b4ad
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JuliaRegistrator register
Release notes:
Breaking changes
BiogeochemicalParticles
ba6b4ad
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Registration pull request created: JuliaRegistries/General/117245
Tagging
After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.
This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via: