GithubHelp home page GithubHelp logo

oceanbiome / oceanbiome.jl Goto Github PK

View Code? Open in Web Editor NEW
37.0 10.0 20.0 235.45 MB

🌊 🦠 🌿 A fast and flexible modelling environment written in Julia for modelling the coupled interactions between ocean biogeochemistry, carbonate chemistry, and physics

Home Page: https://oceanbiome.github.io/OceanBioME.jl/

License: MIT License

Julia 96.52% TeX 3.48%
biogeochemical-models biogeochemistry julia ocean-modelling ocean-sciences oceanography climate ocean

oceanbiome.jl's Introduction

DOI DOI MIT license ColPrac: Contributor's Guide on Collaborative Practices for Community Packages

Documentation Documentation Testing build status codecov

Ocean Biogeochemical Modelling Environment

Description

OceanBioME was developed with generous support from the Cambridge Centre for Climate Repair CCRC and the Gordon and Betty Moore Foundation as a tool to study the effectiveness and impacts of ocean carbon dioxide removal (CDR) strategies.

OceanBioME is a flexible modelling environment written in Julia for modelling the coupled interactions between ocean biogeochemistry, carbonate chemistry, and physics. OceanBioME can be run as a stand-alone box model, or coupled with Oceananigans.jl to run as a 1D column model or with 2 and 3D physics.

Installation:

First, download and install Julia

From the Julia prompt (REPL), type:

julia> using Pkg
julia> Pkg.add("OceanBioME")

Running your first model

As a simple example lets run a Nutrient-Phytoplankton-Zooplankton-Detritus (NPZD) model in a two-dimensional simulation of a buoyancy front. This example requires Oceananigans, so we install that first:

using Pkg; Pkg.add("Oceananigans")

using OceanBioME, Oceananigans
using Oceananigans.Units

grid = RectilinearGrid(CPU(), size = (160, 32), extent = (10000meters, 500meters), topology = (Bounded, Flat, Bounded))

biogeochemistry = NutrientPhytoplanktonZooplanktonDetritus(; grid) 

model = NonhydrostaticModel(; grid, biogeochemistry,
                              advection = WENO(; grid),
			                  closure = AnisotropicMinimumDissipation(),
			                  buoyancy = SeawaterBuoyancy(constant_salinity = true))

@inline front(x, z, μ, δ) = μ + δ * tanh((x - 7000 + 4 * z) / 500)

Pᵢ(x, z) = ifelse(z > -50, 0.03, 0.01)
Nᵢ(x, z) = front(x, z, 2.5, -2)
Tᵢ(x, z) = front(x, z, 9, 0.05)

set!(model, N = Nᵢ, P = Pᵢ, Z = Pᵢ, T = Tᵢ)

simulation = Simulation(model; Δt = 50, stop_time = 4days)

simulation.output_writers[:tracers] = JLD2OutputWriter(model, model.tracers,
                                                       filename = "buoyancy_front.jld2",
                                                       schedule = TimeInterval(24minute),
                                                       overwrite_existing = true)

run!(simulation)
We can then visualise this:
T = FieldTimeSeries("buoyancy_front.jld2", "T")
N = FieldTimeSeries("buoyancy_front.jld2", "N")
P = FieldTimeSeries("buoyancy_front.jld2", "P")

xc, yc, zc = nodes(T)

times = T.times

using CairoMakie

n = Observable(1)

T_lims = (8.94, 9.06)
N_lims = (0, 4.5)
P_lims = (0.007, 0.02)

Tₙ = @lift interior(T[$n], :, 1, :)
Nₙ = @lift interior(N[$n], :, 1, :)
Pₙ = @lift interior(P[$n], :, 1, :)

fig = Figure(size = (1000, 520), fontsize = 20)

title = @lift "t = $(prettytime(times[$n]))"
Label(fig[0, :], title)

axis_kwargs = (xlabel = "x (m)", ylabel = "z (m)", width = 770, yticks = [-400, -200, 0])
ax1 = Axis(fig[1, 1]; title = "Temperature (°C)", axis_kwargs...)
ax2 = Axis(fig[2, 1]; title = "Nutrients concentration (mmol N / m³)",axis_kwargs...)
ax3 = Axis(fig[3, 1]; title = "Phytoplankton concentration (mmol N / m³)", axis_kwargs...)

hm1 = heatmap!(ax1, xc, zc, Tₙ, colorrange = T_lims, colormap = Reverse(:lajolla), interpolate = true)
hm2 = heatmap!(ax2, xc, zc, Nₙ, colorrange = N_lims, colormap = Reverse(:bamako), interpolate = true)
hm3 = heatmap!(ax3, xc, zc, Pₙ, colorrange = P_lims, colormap = Reverse(:bamako), interpolate = true)

Colorbar(fig[1, 2], hm1, ticks = [8.95, 9.0, 9.05])
Colorbar(fig[2, 2], hm2, ticks = [0, 2, 4])
Colorbar(fig[3, 2], hm3, ticks = [0.01, 0.02, 0.03])

rowgap!(fig.layout, 0)

record(fig, "buoyancy_front.gif", 1:length(times)) do i
    n[] = i
end
buoyancy_front.mp4

In this example OceanBioME is providing the biogeochemistry and the remainder is taken care of by Oceananigans. For comprehensive documentation of the physics modelling see Oceananigans' Documentation, and for biogeochemistry and other features we provide read below.

Using GPU

To run the same example on a GPU we just need to construct the grid on the GPU; the rest is taken care of!

Just replace CPU() with GPU() in the grid construction with everything else left unchanged:

grid = RectilinearGrid(GPU(), size = (256, 32), extent = (500meters, 100meters), topology = (Bounded, Flat, Bounded))

Documentation

See the documentation for full description of the software package and more examples.

Contributing

If you're interested in contributing to the development of OceanBioME we would appreciate your help!

If you'd like to work on a new feature, or if you're new to open source and want to crowd-source projects that fit your interests, please start a discussion.

For more information check out our contributor's guide.

Citing

If you use OceanBioME as part of your research, teaching, or other activities, we would be grateful if you could cite our work below and mention the package by name.

@article{OceanBioMEJOSS,
  doi = {10.21105/joss.05669},
  url = {https://doi.org/10.21105/joss.05669},
  year = {2023},
  publisher = {The Open Journal},
  volume = {8},
  number = {90},
  pages = {5669},
  author = {Jago Strong-Wright and Si Chen and Navid C. Constantinou and Simone Silvestri and Gregory LeClaire Wagner and John R. Taylor},
  title = {{OceanBioME.jl: A flexible environment for modelling the coupled interactions between ocean biogeochemistry and physics}},
  journal = {Journal of Open Source Software}
}

If on top of citing the JOSS paper above, you need to cite a specific version of the package then please cite its corresponding version from the Zenodo archive.

oceanbiome.jl's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oceanbiome.jl's Issues

LOBSTER documentation issues

Hi both,

From what I gather this paper is the most advanced version of LOBSTER? And in table A2 I'm fairly sure that the equations don't add up.

In the DOM and NH4 equations they each have two terms where organic waste is getting converted into inorganics, but in the NH4 equation they are sometimes using (1-\alpha_X) and other times \alpha_X (which is correct). They also have a ratio of redfield ratios term, but this doesn't make sense since all of these things are in units of nitrogen anyway (if they weren't then this ratio would need to also appear in other places where DOM was mineralized or aggregated into detritus).

Are you both therefore happy for me to get rid of the Rd_phy/Rd_dom term (we currently have these both the same so it has made no results difference and only results in extra computation)?

example names

@syou83syou83: Can we change the names of the LOBSTER example files which aren't very intuitive at the moment? I would suggest changing idealized_LOBSTER.jl to column.jl. I don't understand the difference between simple_LOBSTER.jl and complex_LOBSTER.jl - they sound very similar from the descriptions in the readme.md file in the examples folder. We probably don't need two examples that are forced with the Mercator model output anyway. Maybe you can pick one and call it data_forced.jl or something like that. In the description in readme.md (and in the script itself) you can say that it uses the LOBSTER model, but I think the main thing that we're trying to illustrate with these is how to run a simple column model and how to force a model with external data.

`scale_negative_tracers` fails on GPU

Everything else seems to work okay on GPU now except the utilities for stopping tracers going negative. When a GPU node becomes available I'll try and get this working.

Why does `CenterField` contain no data for `BoxModelGrid`?

I noticed that CenterField is defined as nothing on BoxModelGrid:

CenterField(::BoxModelGrid, args...; kwargs...) = nothing

But if I understand this correctly, a box model grid is effectively 0-dimensional. That means that any field would actually have 1 point (not 0 points). Otherwise, what is the prognostic state of a BoxModel?

I'm asking because I think the concept of a 0D grid could be possibly useful in Oceananigans (but right now we use a triply-Flat grid for the same purpose when we need it).

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

Box model definition

When I update to use the new Oceananigans API I think we should change the box model construction to be nicer and more similar.

Light attenuation model does not work on lat/lon grids

Light attenuation model does not work on lat/lon grids because xnode is defined differently for each. I imagine this may have been fixed recently in Oceananigans so will just be a case of updating the use of the xnode function.

`column_diffusion_timescale` does not work on GPU

As noted in #138, column_diffusion_timescale does not work on GPU.

This function seems unlikely to ever be needed on GPU since column models would probably never need the performance.

We could rethink how it works so please let us know if you need it!

Regression tests to check models are still running without having to check example plots

I've been trying to work out how to check we don't break models between commits because sometimes it becomes apparent that something has changed only when you look at the example plots and noticing they look wrong.

For example, when I recently changed the PAR API I only noticed that it wasn't working properly by looking at one of the box model example outputs.

I guess a solution to this is to improve unit testing, but that requires us to foresea the problems. Another idea I had was to run regression tests so if model outputs change we know, and can hunt down the cause.

I started writing this here: https://github.com/OceanBioME/OceanBioME.jl/tree/jsw/regression-tests/test/regression_tests but was wondering if anyone else thought it was worthwhile?

I'm dubious about calling them regression tests like Oceananigans does because we're not checking the models fit some physical/analytical result but just that they don't change each time.

error in `box.jl` example

I am keen to learn how to use this library and I decided to start by running the example.

Below you can see that I have only the barebones installed for testing purposes.

Unfortunately, I seem to get an error with Clock. Any idea what might have gone wrong here?

(@v1.10) pkg> status
Status `~/.julia/environments/v1.10/Project.toml`
  [a49af516] OceanBioME v0.10.2
⌅ [9e8cae18] Oceananigans v0.90.14
Info Packages marked with ⌅ have new versions available but compatibility constraints restrict them from upgrading. To see why use `status --outdated`

julia> include("box.jl")
ERROR: LoadError: MethodError: no method matching Clock(::Float64, ::Int64, ::Int64)

Closest candidates are:
  Clock(::TT, ::DT, ::Int64, ::Int64) where {TT, DT}
   @ Oceananigans ~/.julia/packages/Oceananigans/aI5AQ/src/TimeSteppers/clock.jl:16

Stacktrace:
 [1] top-level scope
   @ ~/Software/OceanBioME.jl/examples/box.jl:28
 [2] include(fname::String)
   @ Base.MainInclude ./client.jl:489
 [3] top-level scope
   @ REPL[18]:1
 [4] top-level scope
   @ ~/.julia/packages/CUDA/jdJ7Z/src/initialization.jl:206
in expression starting at /home/fpoulin/Software/OceanBioME.jl/examples/box.jl:28

Docstrings are outdated for NPZD model

It looks like I didn't update the docstrings last time I changed the API for the NPZD model (and probably others):

"""
NutrientPhytoplanktonZooplanktonDetritus(; grid,
initial_photosynthetic_slope::FT = 0.1953 / day, # 1/(W/m²)/s
base_maximum_growth::FT = 0.6989 / day, # 1/s
nutrient_half_saturation::FT = 2.3868, # mmol N/m³
base_respiration_rate::FT = 0.066 / day, # 1/s/(mmol N / m³)
phyto_base_mortality_rate::FT = 0.0101 / day, # 1/s/(mmol N / m³)
maximum_grazing_rate::FT = 2.1522 / day, # 1/s
grazing_half_saturation::FT = 0.5573, # mmol N/m³
assimulation_efficiency::FT = 0.9116,
base_excretion_rate::FT = 0.0102 / day, # 1/s/(mmol N / m³)
zoo_base_mortality_rate::FT = 0.3395 / day, # 1/s/(mmol N / m³)²
remineralization_rate::FT = 0.1213 / day, # 1/s
surface_phytosynthetically_active_radiation = (x, y, t) -> 100 * max(0.0, cos(t * π / 12hours)),
light_attenuation_model::LA =
TwoBandPhotosyntheticallyActiveRadiation(; grid,
surface_PAR = surface_phytosynthetically_active_radiation),
sediment_model::S = nothing,
sinking_speeds = (P = 0.2551/day, D = 2.7489/day),
open_bottom::Bool = true,
particles::P = nothing)
Construct a Nutrient-Phytoplankton-Zooplankton-Detritus ([NPZD](@ref NPZD)) biogeochemical model.
Keyword Arguments
=================
- `grid`: (required) the geometry to build the model on, required to calculate sinking
- `initial_photosynthetic_slope`, ..., `remineralization_rate`: NPZD parameter values
- `surface_phytosynthetically_active_radiation`: funciton (or array in the future) for the photosynthetically available radiation at the surface, should be shape `f(x, y, t)`
- `light_attenuation_model`: light attenuation model which integrated the attenuation of available light
- `sediment_model`: slot for `AbstractSediment`
- `sinking_speed`: named tuple of constant sinking, of fields (i.e. `ZFaceField(...)`) for any tracers which sink (convention is that a sinking speed is positive, but a field will need to follow the usual down being negative)
- `open_bottom`: should the sinking velocity be smoothly brought to zero at the bottom to prevent the tracers leaving the domain
- `particles`: slot for `BiogeochemicalParticles`
Example
=======
```jldoctest
julia> using OceanBioME
julia> using Oceananigans
julia> grid = RectilinearGrid(size=(20, 30), extent=(200, 200), topology=(Bounded, Flat, Bounded));
julia> model = NutrientPhytoplanktonZooplanktonDetritus(; grid)
Nutrient Phytoplankton Zooplankton Detritus model (Float64)
Sinking Velocities:
├── P: 0.0 to -2.9525462962962963e-6 m/s
└── D: 0.0 to -3.181597222222222e-5 m/s
Light attenuation: Two-band light attenuation model (Float64)
Sediment: Nothing
Particles: Nothing
```
"""
function NutrientPhytoplanktonZooplanktonDetritus(; grid,
initial_photosynthetic_slope::FT = 0.1953 / day, # 1/(W/m²)/s
base_maximum_growth::FT = 0.6989 / day, # 1/s
nutrient_half_saturation::FT = 2.3868, # mmol N/m³
base_respiration_rate::FT = 0.066 / day, # 1/s/(mmol N / m³)
phyto_base_mortality_rate::FT = 0.0101 / day, # 1/s/(mmol N / m³)
maximum_grazing_rate::FT = 2.1522 / day, # 1/s
grazing_half_saturation::FT = 0.5573, # mmol N/m³
assimulation_efficiency::FT = 0.9116,
base_excretion_rate::FT = 0.0102 / day, # 1/s/(mmol N / m³)
zoo_base_mortality_rate::FT = 0.3395 / day, # 1/s/(mmol N / m³)²
remineralization_rate::FT = 0.1213 / day, # 1/s
surface_phytosynthetically_active_radiation = (x, y, t) -> 100 * max(0.0, cos(t * π / 12hours)),
light_attenuation_model::LA =
TwoBandPhotosyntheticallyActiveRadiation(; grid,
surface_PAR = surface_phytosynthetically_active_radiation),
sediment_model::S = nothing,
sinking_speeds = (P = 0.2551/day, D = 2.7489/day),
open_bottom::Bool = true,
scale_negatives = false,
particles::P = nothing,
modifiers::M = nothing) where {FT, LA, S, P, M}

Will update when I get round to it, making this issue as a reminder

Model directory names

I was thinking about the names of the directories inside /src/Models. I think that we can make it more generic if we call them TracerBasedModels (TBMs) and IndividualBasedModels (IBMs) instead of Biogeochemistry and Macroalgae. That way Macroalgae models could be a subset of the IBMs, but others could use IBMs for other things, e.g. fish or zooplankton. What do you think?

PAR units

Hi all,

I think we need to clarify the units for PAR. LOBSTER (and other BGC models) seem to use W/m $^2$ while e.g. the kelp model use einsteim/m $^2$ /day.

Since PAR is defined as an integral between 400 and 700nm (by MODIS at least) then we can take the very rough approximaiton at the central wavelength for putting it into the BGC models, but I don't know if this is the best solution.

At the moment we're implicitly assuming W/m $^2$ and converting for the kelp model:

PAR = _interpolate(auxiliary_fields.PAR, ξ, η, ζ, Int(i+1), Int(j+1), Int(k+1)) * day / (3.99e-10 * 545e12) # W / m² / s to einstein / m² / day

(This is, as far as I can tell, also being done wrong). I'm not exactly sure when this got added in but we need to a) agree on units for the defaults, and b) agree how to convert for the different models.

I think the above should read:

...* day / (3.99e-10 * (299792458 / 550e-9))

(the second factor is ~545e12 so we've lost a factor somewhere in the past)

All tracers go to NaN using a non-regular grid

I've just tried running the subpolar example with the grid defined like:

stretching = 5
refinement = 2.5
h(k) = (k-1)/ Nz
ζ₀(k) = 1 + (h(k) - 1) / refinement
Σ(k) = (1 - exp(-stretching * h(k))) / (1 - exp(-stretching))
z_faces(k) = Lz * (ζ₀(k) * Σ(k) - 1)

grd = RectilinearGrid(
                size=(Nx, Ny, Nz), 
                x=(0,Lx),
                y=(0,Ly),
                z=z_faces)

and (having battled with it for ages thinking it was something else) I realized this is causing all of the tracers to go to NaN after the first iteration. I've tried making a minimal example of this but it runs fine with a tracer and simple forcing/boundary conditions, with the PAR updating, buoyancy, and with the turbulent closure.

So I can't work out what it is yet but it seems to only occur when the full model is used.

(Note: if you set the grid as above in the subpolar example the issue presents its self as the root finder failing in the air/sea flux boundary condition as that is the first place that the newly NaNed tracers get used. I thought the issue was the boundary condition its self for a while before I realized it was happening before it got there.)

error from twoband.jl with high vertical resolution

I am getting an error from twoband.jl which seems to occur when I run with high (<1m) vertical resolution. When I run eady.jl and use 128 gridpoints in the vertical, I get the error message below. I am using Julia 1.9.2 on my macbook pro. I also get a very similar error message in a high resolution version of a column model (where I first encountered this error).

[ Info: Initializing simulation...
i: 0, sim time: 0 seconds, wall time: 0 seconds, Δt: 16.500 minutes, CFL: 1.84e-01
[ Info: ... simulation initialization complete (9.006 seconds)
[ Info: Executing initial time step...
[ Info: ... initial time step complete (54.796 seconds).
ERROR: DomainError with -2.618155629978065e21:
Exponentiation yielding a complex result requires a complex argument.
Replace x^y with (x+0im)^y, Complex(x)^y, or similar.
Stacktrace:
[1] throw_exp_domainerror(x::Float64)
@ Base.Math ./math.jl:37
[2] ^(x::Float64, y::Float64)
@ Base.Math ./math.jl:1123
[3] macro expansion
@ ~/.julia/packages/OceanBioME/mii75/src/Light/2band.jl:30 [inlined]
[4] macro expansion
@ ~/.julia/packages/KernelAbstractions/cWlFz/src/extras/loopinfo.jl:26 [inlined]
[5] macro expansion
@ ~/.julia/packages/OceanBioME/mii75/src/Light/2band.jl:28 [inlined]
[6] cpu_update_TwoBandPhotosyntheticallyActiveRadiation!
@ ~/.julia/packages/KernelAbstractions/cWlFz/src/macros.jl:276 [inlined]
[7] cpu_update_TwoBandPhotosyntheticallyActiveRadiation!(ctx::Ker

error with LOBSTER.defaults

I am now getting the following error when I try to run box.jl. The problem is coming from line 36 which references LOBSTER.default

include("box.jl")
ERROR: UndefVarError: default not defined
Stacktrace:
[1] getproperty(x::Module, f::Symbol)
@ Base ./Base.jl:35
[2] top-level scope
@ ~/Work/OceanBioME.jl/examples/box.jl:36

Hiding output for `run!(simulation)` in Docs (Warnings)

Hi,

Very cool that this package is being released! Great work!
I am definitely planning to use this package and maybe even contribute at some point.

I was checking the documentation and noticed a lot of warnings in the pattern of
Warning: type parameters for ... do not match type NamedTuple in workspace

e.g.:
https://oceanbiome.github.io/OceanBioME.jl/dev/generated/kelp/

I am not sure if this is because of the way the data is being saved or if we should just ignore it, but I was wondering if it would be a good idea to hide those warnings for the examples on docs.

GPU memory leak (?) when running with particles

As described in #73, I have a problem when I try to run a model with particles that the RAM usage increases until slurm kills the process (requesting more memory just makes it take longer to be killed) and never manages to complelte a timestep. I have also experianced this with normal Oceananigans particles so will investigate.

Oceananigans version compatability

Hi @johnryantaylor and @syou83syou83,

Just a quick note that I'm going to change Project.toml to specify that Oceananigans needs to be v0.77.1 or greater because otherwise the Lagrangian Particles don't work correctly (@johnryantaylor this is why the kelp results I sent the other day start a bit below 2m deep because I accidentally used an older version). I fixed the issue which was released in v0.77.1.

I have also removed the dependency on SugarKelp.jl since it has a dependency conflict with Oceananigans. Since it is only used to import a few equations it seems similar from a maintenance perspective to just remove the dependency and copy the equations over.

This will possibly cause some issues, especially if you have Oceananigans dependencies that are different versions from those compatible with Oceananigans v0.77.1 (I had this problem). I resolved this by manually deleting all of the dependencies, restoring Project.toml and then ]resolve and ]instantiate again. If you don't change any packages perhaps nothing will happen but if you intend to use the particles its worth making sure they're all updated.

Roots.ConvergenceFailed-kelp.jl

Hi @jagoosw

While I ran the latest kelp.jl example, I still got the following error. Have you run it and met the same issue?

`ERROR: LoadError: TaskFailedException

nested task error: Roots.ConvergenceFailed("Algorithm failed to converge")`

Plus, there is a small bug in line 45, which should be
t_function(x, y, z, t) = temp_itp(mod(t, 364days))

Thanks,
Si

Error when loading OceanBioME

After the most recent update, I am now getting an error when I run "using OceanBioME". Strangely it seems to be coming from KernelAbstractions, but I'm using the same version of Julia that I was before. Is anyone else getting this error? Here is the message:

using OceanBioME
[ Info: Precompiling OceanBioME [a49af516-9db8-4be4-be45-1dad61c5a376]
ERROR: LoadError: ArgumentError: Package KernelAbstractions does not have Cassette in its dependencies:

  • If you have KernelAbstractions checked out for development and have
    added Cassette as a dependency but haven't updated your primary
    environment's manifest file, try Pkg.resolve().
  • Otherwise you may need to report an issue with KernelAbstractions
    Stacktrace:
    [1] require(into::Module, mod::Symbol)
    @ Base ./loading.jl:906
    [2] include
    @ ./Base.jl:384 [inlined]
    [3] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt64}}, source::String)
    @ Base ./loading.jl:1235
    [4] top-level scope
    @ none:1
    [5] eval
    @ ./boot.jl:360 [inlined]
    [6] eval(x::Expr)
    @ Base.MainInclude ./client.jl:446
    [7] top-level scope
    @ none:1
    in expression starting at /Users/john/.julia/packages/KernelAbstractions/3ZHln/src/KernelAbstractions.jl:1
    ERROR: LoadError: LoadError: Failed to precompile KernelAbstractions [63c18a36-062a-441e-b654-da1e3ab1ce7c] to /Users/john/.julia/compiled/v1.6/KernelAbstractions/jl_VWfwqR.
    Stacktrace:
    [1] error(s::String)
    @ Base ./error.jl:33
    [2] compilecache(pkg::Base.PkgId, path::String, internal_stderr::Base.TTY, internal_stdout::Base.TTY, ignore_loaded_modules::Bool)
    @ Base ./loading.jl:1385
    [3] compilecache(pkg::Base.PkgId, path::String)
    @ Base ./loading.jl:1329
    [4] _require(pkg::Base.PkgId)
    @ Base ./loading.jl:1043
    [5] require(uuidkey::Base.PkgId)
    @ Base ./loading.jl:936
    [6] require(into::Module, mod::Symbol)
    @ Base ./loading.jl:923
    [7] include(mod::Module, _path::String)
    @ Base ./Base.jl:384
    [8] include(x::String)
    @ Oceananigans ~/.julia/packages/Oceananigans/lwYJk/src/Oceananigans.jl:5
    [9] top-level scope
    @ ~/.julia/packages/Oceananigans/lwYJk/src/Oceananigans.jl:181
    [10] include
    @ ./Base.jl:384 [inlined]
    [11] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt64}}, source::String)
    @ Base ./loading.jl:1235
    [12] top-level scope
    @ none:1
    [13] eval
    @ ./boot.jl:360 [inlined]
    [14] eval(x::Expr)
    @ Base.MainInclude ./client.jl:446
    [15] top-level scope
    @ none:1
    in expression starting at /Users/john/.julia/packages/Oceananigans/lwYJk/src/Architectures.jl:1
    in expression starting at /Users/john/.julia/packages/Oceananigans/lwYJk/src/Oceananigans.jl:1
    ERROR: LoadError: LoadError: Failed to precompile Oceananigans [9e8cae18-63c1-5223-a75c-80ca9d6e9a09] to /Users/john/.julia/compiled/v1.6/Oceananigans/jl_IaSQAO.
    Stacktrace:
    [1] error(s::String)
    @ Base ./error.jl:33
    [2] compilecache(pkg::Base.PkgId, path::String, internal_stderr::Base.TTY, internal_stdout::Base.TTY, ignore_loaded_modules::Bool)
    @ Base ./loading.jl:1385
    [3] compilecache(pkg::Base.PkgId, path::String)
    @ Base ./loading.jl:1329
    [4] _require(pkg::Base.PkgId)
    @ Base ./loading.jl:1043
    [5] require(uuidkey::Base.PkgId)
    @ Base ./loading.jl:936
    [6] require(into::Module, mod::Symbol)
    @ Base ./loading.jl:923
    [7] include(mod::Module, _path::String)
    @ Base ./Base.jl:384
    [8] include(x::String)
    @ OceanBioME ~/Downloads/OceanBioME.jl-main/src/OceanBioME.jl:1
    [9] top-level scope
    @ ~/Downloads/OceanBioME.jl-main/src/OceanBioME.jl:5
    [10] include
    @ ./Base.jl:384 [inlined]
    [11] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt64}}, source::Nothing)
    @ Base ./loading.jl:1235
    [12] top-level scope
    @ none:1
    [13] eval
    @ ./boot.jl:360 [inlined]
    [14] eval(x::Expr)
    @ Base.MainInclude ./client.jl:446
    [15] top-level scope
    @ none:1
    in expression starting at /Users/john/Downloads/OceanBioME.jl-main/src/Boundaries/Boundaries.jl:1
    in expression starting at /Users/john/Downloads/OceanBioME.jl-main/src/OceanBioME.jl:1
    ERROR: Failed to precompile OceanBioME [a49af516-9db8-4be4-be45-1dad61c5a376] to /Users/john/.julia/compiled/v1.6/OceanBioME/jl_RiRV9e.
    Stacktrace:
    [1] error(s::String)
    @ Base ./error.jl:33
    [2] compilecache(pkg::Base.PkgId, path::String, internal_stderr::Base.TTY, internal_stdout::Base.TTY, ignore_loaded_modules::Bool)
    @ Base ./loading.jl:1385
    [3] compilecache(pkg::Base.PkgId, path::String)
    @ Base ./loading.jl:1329
    [4] _require(pkg::Base.PkgId)
    @ Base ./loading.jl:1043
    [5] require(uuidkey::Base.PkgId)
    @ Base ./loading.jl:936
    [6] require(into::Module, mod::Symbol)
    @ Base ./loading.jl:923
    [7] eval
    @ ./boot.jl:360 [inlined]
    [8] eval
    @ ./Base.jl:39 [inlined]
    [9] repleval(m::Module, code::Expr, #unused#::String)
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.31/scripts/packages/VSCodeServer/src/repl.jl:222
    [10] (::VSCodeServer.var"#105#107"{Module, Expr, REPL.LineEditREPL, REPL.LineEdit.Prompt})()
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.31/scripts/packages/VSCodeServer/src/repl.jl:186
    [11] with_logstate(f::Function, logstate::Any)
    @ Base.CoreLogging ./logging.jl:491
    [12] with_logger
    @ ./logging.jl:603 [inlined]
    [13] (::VSCodeServer.var"#104#106"{Module, Expr, REPL.LineEditREPL, REPL.LineEdit.Prompt})()
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.31/scripts/packages/VSCodeServer/src/repl.jl:187
    [14] #invokelatest#2
    @ ./essentials.jl:708 [inlined]
    [15] invokelatest(::Any)
    @ Base ./essentials.jl:706
    [16] macro expansion
    @ ~/.vscode/extensions/julialang.language-julia-1.6.31/scripts/packages/VSCodeServer/src/eval.jl:34 [inlined]
    [17] (::VSCodeServer.var"#59#60")()
    @ VSCodeServer ./task.jl:411

Sediment tendency calculations

As discussed in #143, sediment model tendency calculations are quite confusing and all packed together. At some point, we should restructure the code to e.g. calculate each field's tendencies separately.

No `adapt_structure` method for NPZD model

Discussed in https://github.com/orgs/OceanBioME/discussions/86

Originally posted by zwei961120 May 2, 2023
Hi @jagoosw, thanks for your beautiful work which helps me do some interesting numerical experiments. I have coupled the NPZD model in physical models implemented by Oceananigans.jl on the CPU, and everything went well, but when I tried to run it on the GPU, some errors threw up, so I want to know have you tested the NPZD model on the GPU yet? Thanks!

Negative tracer scaling raises a very confusing error message when it fails on GPU

Due to error not being inlined (see JuliaGPU/KernelAbstractions.jl#383) when raised on GPU it leads to a very long an unhelpful error message e.g.

ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
ERROR: a exception was thrown during kernel execution.
       Run Julia on debug level 2 for device stack traces.
KernelException: exception thrown during kernel execution on device NVIDIA A100 80GB PCIe
 >   (stacktrace)
      (user)
       CUDA
   +    check_exceptions ~/.julia/packages/CUDA/35NC6/src/compiler/exceptions.jl:34
   +    #synchronize#836 ~/.julia/packages/CUDA/35NC6/lib/cudadrv/stream.jl:136
   +   [inlined]
       Oceananigans.Models.NonhydrostaticModels
   +    calculate_tendencies! ~/.julia/packages/Oceananigans/mwXt0/src/Models/NonhydrostaticModels/calculate_nonhydrostatic_tendencies.jl:42
       Oceananigans.TimeSteppers
v  +    #time_step!#8 ~/.julia/packages/Oceananigans/mwXt0/src/TimeSteppers/runge_kutta_3.jl:102

When a better error messaging is available in GPU kernels we should update to fix this.

Using `znode` instead of `znodes` inside kernels

zᶜ = znodes(grid, Center(), Center(), Center())
zᶠ = znodes(grid, Center(), Center(), Face())
∫chlʳ = @inbounds (zᶠ[grid.Nz + 1] - zᶜ[grid.Nz]) * (P[i, j, grid.Nz] * Rᶜₚ / r) ^
∫chlᵇ = @inbounds (zᶠ[grid.Nz + 1] - zᶜ[grid.Nz]) * (P[i, j, grid.Nz] * Rᶜₚ / r) ^ eᵇ
# first point below surface
@inbounds PAR[i, j, grid.Nz] = PAR⁰ * (exp(kʳ * zᶜ[grid.Nz] - χʳ * ∫chlʳ) + exp(kᵇ * zᶜ[grid.Nz] - χᵇ * ∫chlᵇ)) / 2
@inbounds for k in grid.Nz-1:-1:1
∫chlʳ += (zᶜ[k + 1] - zᶠ[k + 1]) * (P[i, j, k+1] * Rᶜₚ / r) ^+ (zᶠ[k + 1] - zᶜ[k]) * (P[i, j, k] * Rᶜₚ / r) ^
∫chlᵇ += (zᶜ[k + 1] - zᶠ[k + 1]) * (P[i, j, k+1] * Rᶜₚ / r) ^ eᵇ + (zᶠ[k + 1] - zᶜ[k]) * (P[i, j, k] * Rᶜₚ / r) ^ eᵇ
PAR[i, j, k] = PAR⁰ * (exp(kʳ * zᶜ[k] - χʳ * ∫chlʳ) + exp(kᵇ * zᶜ[k] - χᵇ * ∫chlᵇ)) / 2
end

Here, I think it'd be much more efficient if instead of, e.g.,

zᶜ = znodes(grid, Center(), Center(), Center()) 
zᶜ[k + 1]
using Oceananigans.Grids: znode
znode(i, j, k+1, grid, Center(), Center(), Center())

The former create a whole array and selects a value from it. The latter just gets the value needed from the grid.

Negative kelp nitrogen

@jagoosw @syou83syou83: I ran Si's kelp100 code that is blowing up after about 3 years with a large scale factor. It looks like in this case the kelp nitrogen becomes negative. Perhaps this is coming from the fallback that is called when the kelp attempts to take the water nutrient levels below zero.

kelp example

For some reason, the kelp growth model doesn't seem to be doing anything in this example. The area, carbon, and nitrogen are constant on the kelp particles throughout the simulation.

Repository size

The repository is very large. Does it include large output files? If even something was committed in main, even if then deleted it still exists in the repo's history. Or it could be thegh-pages branch with the docs...

PAR interpolation incorrect above top grid point

@syou83syou83 has noticed that interpolating the PAR field at a point above the top center point gives a value lower than that at the top point. This is probably because we've not been filling the halo region so its interpolating between [top value] and 0, the default for the halo region.

This should be easily fixed by filling the top halo points with the surface value, or surface ^ 2 / top point so that interpoalting to the surface will give the correct value. I will do this tomorrow.

`SimpleMultiG` sediment models will not run on GPU

While the kernel for SimpleMultiG sediments will compile on GPU they will not run due to their complexity leading to a PTX error about parameter size being thrown. This may be fixed in the future if LLVM updates its CUDA version support (JuliaGPU/CUDA.jl#2080). We may also be able to rework the model to use less parameter space so please do get in contact if you would like to use the model on GPU.

An error similar to the following will be raised:

Failed to compile PTX code (ptxas exited with code 255)
Invocation arguments: --generate-line-info --verbose --gpu-name sm_75 --output-file /tmp/jl_bELIheLkzO.cubin /tmp/jl_VczMJifKRu.ptx
ptxas /tmp/jl_VczMJifKRu.ptx, line 3215; error   : Entry function '_Z26gpu__calculate_tendencies_16CompilerMetadataI10StaticSizeI6_3__3_E12DynamicCheckvv7NDRangeILi2ES0_I6_1__1_ES0_I8_16__16_EvvEE12SimpleMultiGI7Float6410NamedTupleI24__A___B___C___D___E___F_5TupleIS4_S4_S4_S4_S4_S4_EES5_I24__A___B___C___D___E___F_S6_IS4_S4_S4_S4_S4_S4_EES5_I24__A___B___C___D___E___F_S6_IS4_S4_S4_S4_S4_S4_EES5_I24__A___B___C___D___depth_S6_IS4_S4_5Int64S4_S4_EES5_I52__C_slow___C_fast___N_slow___N_fast___C_ref___N_ref_S6_I11OffsetArrayIS4_Li3E13CuDeviceArrayIS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEEEES5_I10__G____G__S6_IS5_I52__C_slow___C_fast___N_slow___N_fast___C_ref___N_ref_S6_IS8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEEEES5_I52__C_slow___C_fast___N_slow___N_fast___C_ref___N_ref_S6_IS8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEES8_IS4_Li3ES9_IS4_Li3ELi1EEEEEEES9_IS7_Li2ELi1EEE7LOBSTERIS4_3ValI18_true__true__true_ES5_I14__sPOM___bPOM_S6_IS5_I12__u___v___w_S6_I13ConstantFieldIS7_Li3EES12_IS7_Li3EES8_IS4_Li3ES9_IS4_Li3ELi1EEEEES5_I12__u___v___w_S6_IS12_IS7_Li3EES12_IS7_Li3EES8_IS4_Li3ES9_IS4_Li3ELi1EEEEEEEE15RectilinearGridIS4_8PeriodicS14_7BoundedS4_S4_S4_S8_IS4_Li1...
ptxas /tmp/jl_VczMJifKRu.ptx, line 3215; error   : Feature 'Kernel parameter size larger than 4352 bytes' requires PTX ISA .version 8.1 or later
ptxas fatal   : Ptx assembly aborted due to errors
If you think this is a bug, please file an issue and attach /tmp/jl_VczMJifKRu.ptx

Also, note that InstantRemineralisation sediment does work on GPU.

Discussed in #138.

Ratiation or Radiation

I saw this a lot in the code and I thought it was a typo... but then I see it even here:

@kernel function update_TwoBandPhotosyntheticallyActiveRatiation!(PAR, grid, P, surface_PAR, t, PAR_model)

Is it a typo or a term I am not aware of?

If it's actually legit then note I may have replaced some with radiation in the docs...

NPZ model does not work

Haven't looked into it properly yet but there is something wrong with the NPZ model. When I run in a simple configuration P goes negative quite quickly and it doesn't conserve nitrogen. I will look into it if I have time in the next few days but am going to exclude from the testing for now.

Update gas transfer coefficients

I'm interested in implementing updated gas transfer velocity (k) parameterisations (at the very least, Wanninkhof 1992 is outdated and could be replaced by Wanninkhof 2014). It would be great to add other gas transfer velocities e.g. Ho et al. 2006, as is mentioned in the code comments. I'm guessing the best way to implement this would be to add all of these parameterisations (and more?) and include a kwarg when calling GasExchange?

k(T, uₐᵥ, Sc_params) = 0.39 * (0.01 / 3600) * uₐᵥ ^ 2 * (Sc(T, Sc_params) / 660) ^ (-0.5)# m/s, may want to add variable wind speed instead of average wind here at some point

State of the field

Following one of the points on the checklist
openjournals/joss-reviews#5669 (comment)

State of the field: Do the authors describe how this software compares to other commonly-used packages?

I think that it should be added to the manuscript a description on how biogeochemical models are currently performed using Oceananigans.jl and how this package is improving the current state of the field.

Even myself have already used Oceananigans.jl coupled with a simple NP model, which led to a published paper,
https://www.frontiersin.org/articles/10.3389/fmars.2022.825027/full
https://github.com/iuryt/NorthAtlanticBloom
and I developed a very simple package that can be used for estimating the mixed-layer depth and light-limiting growth.
https://github.com/iuryt/Bioceananigans.jl

While those were a contribution to the field, I clearly see a huge improvement that your package is making to the state of the field, which I don't think you are making it clear in the manuscript.

Advantages:

This is a long list, but in summary, this package is clearly well integrated with Oceananigans.jl and have many options for different models both using tracers and particles. It has a documentation and description of the different variables.

Disadvantages (if any):

This is kind of hard to find a disadvantage for this package in relation to the current state of the field, but I will try to list something here.
The first one is that there is no way to change the equations or define my own set of equations for my biogeochemical model. This is important for theoretical process modelling approches.
I also could not find any way to define the mixed layer from the fields (there is a discussion to add that to Oceanostics.jl) and there are actually different ways to deal with the effect of the mixed layer on the biogeochemical modelling in the literature. The main point is that there are mismatches between the time scales of the mixing and cell division. Although light-averaging within the mixed layer has been previously employed and compared to observations (Mahadevan et al., 2012), other studies approach this issue differently (e.g., Sarmiento et al., 1993). Fasham et al., (1990), for example, average the light-limiting growth in the mixed layer. I could not see an implementation for that in this package.

While I don't think this is something you need to implement for the publication, it is important to, at least, mention that in the manuscript. If needed, I can add another issue for this improvement for tracking purposes.

References

Mahadevan A., D’asaro E., Lee C., Perry M. J. (2012). Eddy-driven stratification initiates north atlantic spring phytoplankton blooms. Science 337, 54–58. doi: 10.1126/science.1218740

Sarmiento J.L., Slater R.D., Fasham M.J.R., Ducklow H.W., Toggweiler J.R., Evans G.T. (1993) A seasonal three‐dimensional ecosystem model of nitrogen cycling in the North Atlantic euphotic zone. Global biogeochemical cycles, 7 (2), 417–450. doi: 10.1029/93GB00375

Fasham M. J., Ducklow H. W., McKelvie S. M. (1990). A nitrogen-based model of plankton dynamics in the oceanic mixed layer. J. Mar. Res. 48, 591–639. doi: 10.1357/002224090784984678

Use `Oceananigans.OutputReaders.FieldTimeSeries` instead of manually reading output from `.jld2` files

Using FieldTimeSeries would cleanup this bit a lot. (And similarly for other examples.)

# Open the file with our data
file = jldopen(simulation.output_writers[:fields].filepath)
iterations = parse.(Int, keys(file["timeseries/t"]))
times = zeros(length(iterations))
w, P, N, DIC = ntuple(n -> zeros(grid.Nx, grid.Ny, grid.Nz, length(iterations)), 5);
for (idx, it) in enumerate(iterations)
w[:, :, :, idx] = file["timeseries/w/$it"][1:grid.Nx, 1:grid.Ny, 1:grid.Nz]
P[:, :, :, idx] = file["timeseries/P/$it"][1:grid.Nx, 1:grid.Ny, 1:grid.Nz]
N[:, :, :, idx] = file["timeseries/NO₃/$it"][1:grid.Nx, 1:grid.Ny, 1:grid.Nz] .+ file["timeseries/NH₄/$it"][1:grid.Nx, 1:grid.Ny, 1:grid.Nz]
DIC[:, :, :, idx] = file["timeseries/DIC/$it"][1:grid.Nx, 1:grid.Ny, 1:grid.Nz]
times[idx] = file["timeseries/t/$it"]
end

PISCES

Having been worrying about what dynamic elements we're missing with such a simple model as LOBSTER I've started coding up PISCESv2. It is very complicated with a lot of tracers so may take me a while.

Even if we don't use it much it will be helpful to compare LOBSTER to and is helping me to understand the more complex elements of biogeochemistry. It will also be good to have the gold standard biogeochemical model available for other people to use/improve in the future.

Figure 1 from JOSS paper

This should be an easy fix.

As mentioned in openjournals/joss-reviews#5669 (comment)

The axis tick labels in this figure is unnecessarily small. If you cannot find a way to make it larger, you can remove it and mention the dimensions of the domain in the caption.

All other fonts from the images are also small, but not as small as these tick labels.
I usually try to use fonts around the same size as the main text.

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.