{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "scrolled": true, "slideshow": { "slide_type": "slide" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", " Unable to load WebIO. Please make sure WebIO works for your Jupyter client.\n", " For troubleshooting, please see \n", " the WebIO/IJulia documentation.\n", " \n", "

\n" ], "text/plain": [ "HTML{String}(\"\\n\\n Unable to load WebIO. Please make sure WebIO works for your Jupyter client.\\n For troubleshooting, please see \\n the WebIO/IJulia documentation.\\n \\n

\\n\")" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "using AIBECS\n", "using PyPlot, PyCall\n", "using LinearAlgebra\n", "using GR, Interact" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "\n", "\n", "

AIBECS.jl

\n", "\n", "*The ideal tool for exploring global marine biogeochemical cycles*\n", "\n", "**A**lgebraic **I**mplicit **B**iogeochemical **E**lemental **C**ycling **S**ystem\n", "\n", "Check it on GitHub (look for [AIBECS.jl](https://github.com/briochemc/AIBECS.jl))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "\n", "\n", "\n", "
A Julia package developed by Benoît Pasquier at the Department of Earth System Sciences, UCI
with François Primeau and J. Keith Moore
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Outline\n", "\n", "1. Motivation and concept\n", "1. Example 1: Radiocarbon\n", " 1. Toy model circulation\n", " 1. OCIM1\n", "1. Example 2: Phosphorus cycle\n", "1. AIBECS ecosystem" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Motivation: Starting from the AWESOME OCIM\n", "\n", "\n", "\n", "The AWESOME OCIM (for A Working Environment for Simulating Ocean Movement and Elemental cycling in an Ocean Circulation Inverse Model framework) by **Seth John** (USC)\n", "\n", "Features: **GUI**, **simple to use**, **fast**, and **good circulation**
(thanks to the OCIM1 by **Tim DeVries** (UCSB))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Motivation: comes the AIBECS\n", "\n", "\n", "\n", "Features (at present)\n", "\n", "\\- **simple to use**
\n", "\\- **fast**
\n", "\\- **Julia** instead of MATLAB (free, open-source, better performance, and better syntax)
\n", "\\- **nonlinear** systems
\n", "\\- **multiple tracers**
\n", "\\- **Other circulations** (not just the OCIM)
\n", "\\- **Parameter estimation/optimization** and **Sensitivity analysis** (shameless plug: F-1 algorithm seminar tomorrow at the School of Mathematics)
\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "\n", "\n", "# AIBECS Concept: a simple interface\n", "\n", "To build a BGC model with the AIBECS, you just need to\n", "\n", "**1.** Specify the **local sources and sinks**\n", "\n", "**2.** Chose the **ocean circulation**
\n", "\n", "(**3.** Specify the **particle transport**, if any)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "\n", "\n", "# AIBECS concept: Vectorization\n", "\n", "The **3D ocean grid** is rearranged
into a **1D column vector**.\n", "\n", "And **linear operators** are represented by **matrices**." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "

Example 1: Radiocarbon, a tracer for water age

\n", "\n", "
\n", "\n", "\n", "\n", "*Image credit: Luke Skinner, University of Cambridge*\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "

Tracer equation: transport + sources and sinks

\n", "\n", "The **Tracer equation**\n", " ($x=$ Radiocarbon concentration)\n", "\n", "$$\\frac{\\partial x}{\\partial t} + \\color{RoyalBlue}{\\nabla \\cdot \\left[ \\boldsymbol{u} - \\mathbf{K} \\cdot \\nabla \\right]} x = \\color{ForestGreen}{\\underbrace{\\Lambda(x)}_{\\textrm{air–sea exchange}} - \\underbrace{x / \\tau}_{\\textrm{radioactive decay}}}$$\n", "\n", "becomes \n", "\n", "$$\\frac{\\partial \\boldsymbol{x}}{\\partial t} + \\color{RoyalBlue}{\\mathbf{T}} \\, \\boldsymbol{x} = \\color{ForestGreen}{\\mathbf{\\Lambda}(\\boldsymbol{x}) - \\boldsymbol{x} / \\tau}.$$\n", "\n", "with the **transport matrix**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Translating to AIBECS Code is easy\n", "\n", "To use AIBECS, we must recast each tracer equation,\n", "\n", "$$\\frac{\\partial \\boldsymbol{x}}{\\partial t} + \\color{RoyalBlue}{\\mathbf{T}} \\, \\boldsymbol{x} = \\color{ForestGreen}{\\mathbf{\\Lambda}(\\boldsymbol{x}) - \\boldsymbol{x} / \\tau}$$\n", "\n", "here, into the generic form:\n", "\n", "$$\\frac{\\partial \\boldsymbol{x}}{\\partial t} + \\color{RoyalBlue}{\\mathbf{T}(\\boldsymbol{p})} \\, \\boldsymbol{x} = \\color{ForestGreen}{\\boldsymbol{G}(\\boldsymbol{x}, \\boldsymbol{p})}$$\n", "\n", "where $\\boldsymbol{p} =$ vector of model parameters\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Circulation 1: The 2×2×2 *Primeau* model\n", "\n", "\n", "\n", "\\- **ACC**: Antarctic Circumpolar Current\n", "\n", "\\- **MOC**: Meridional Overturning Circulation\n", "\n", "\\- High-latitude mixing\n", "\n", "\n", "(Credit: François Primeau, and Louis Primeau for the image)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Load the **circulation** via `load`:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Creating François Primeau's 2x2x2 model ✔\n" ] } ], "source": [ "wet3D, grd, T = Primeau_2x2x2.load();" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "\n", "\n", "`wet3D` is the mask of \"wet\" points" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "2×2×2 BitArray{3}:\n", "[:, :, 1] =\n", " 1 1\n", " 1 0\n", "\n", "[:, :, 2] =\n", " 1 0\n", " 1 0" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wet3D" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "`grd` is the grid of the circulation" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "name": "stdout", "output_type": "stream", "text": [ "OceanGrid of size 2×2×2 (lat×lon×depth)\n" ] } ], "source": [ "grd" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "\n", "We can check the depth of the boxes arranged in 3D" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "2×2×2 Array{Quantity{Float64,𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}},3}:\n", "[:, :, 1] =\n", " 100.0 m 100.0 m\n", " 100.0 m 100.0 m\n", "\n", "[:, :, 2] =\n", " 1950.0 m 1950.0 m\n", " 1950.0 m 1950.0 m" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grd.depth_3D" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "\n", "\n", "### The matrix $\\mathbf{T}$ acts on the column vector\n", "\n", "What does `T` look like?" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "5×5 SparseMatrixCSC{Float64,Int64} with 12 stored entries:\n", " [1, 1] = 4.50923e-9\n", " [2, 1] = -5.88161e-10\n", " [3, 1] = -3.92107e-9\n", " [2, 2] = 9.80268e-10\n", " [5, 2] = -5.60153e-11\n", " [1, 3] = -3.92107e-9\n", " [3, 3] = 3.92107e-9\n", " [1, 4] = -5.88161e-10\n", " [4, 4] = 3.36092e-11\n", " [2, 5] = -3.92107e-10\n", " [4, 5] = -3.36092e-11\n", " [5, 5] = 5.60153e-11" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "T" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "A sparse matrix is indexed by its non-zero values,
\n", "but we can check it out in full using `Matrix`:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "5×5 Array{Float64,2}:\n", " 4.50923e-9 0.0 -3.92107e-9 -5.88161e-10 0.0 \n", " -5.88161e-10 9.80268e-10 0.0 0.0 -3.92107e-10\n", " -3.92107e-9 0.0 3.92107e-9 0.0 0.0 \n", " 0.0 0.0 0.0 3.36092e-11 -3.36092e-11\n", " 0.0 -5.60153e-11 0.0 0.0 5.60153e-11" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Matrix(T)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Sources and sinks\n", "\n", "Tracer equation reminder:\n", "\n", "$$\\frac{\\partial \\boldsymbol{x}}{\\partial t} + \\mathbf{T}(\\boldsymbol{p}) \\, \\boldsymbol{x} = \\boldsymbol{G}(\\boldsymbol{x}, \\boldsymbol{p})$$\n", "\n", "Let's write $\\boldsymbol{G}(\\boldsymbol{x}, \\boldsymbol{p}) = \\mathbf{\\Lambda}(\\boldsymbol{x}) - \\boldsymbol{x} / \\tau$" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "G (generic function with 1 method)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "G(x,p) = Λ(x,p) - x / p.τ " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Air–sea gas exchange\n", "\n", "And define the air–sea gas exchange $\\mathbf{\\Lambda}(\\boldsymbol{x}) = \\frac{\\lambda}{h} (R_\\mathsf{atm} - \\boldsymbol{x})$ at the surface with a piston velocity $\\lambda$ over the top layer of height $h$" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "Λ (generic function with 1 method)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function Λ(x,p)\n", " λ, h, Ratm = p.λ, p.h, p.Ratm\n", " return @. λ / h * (Ratm - x) * (z == z₀)\n", "end" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "\n", "\n", "Define `z` the depths in vector form.
\n", "(`iwet` converts from 3D to 1D)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "5-element Array{Quantity{Float64,𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}},1}:\n", " 100.0 m\n", " 100.0 m\n", " 100.0 m\n", " 1950.0 m\n", " 1950.0 m" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iwet = findall(wet3D)\n", "z = grd.depth_3D[iwet] " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Define `z₀` the depth of the top layer" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "100.0 m" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "z₀ = z[1]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "So that `z .== z₀` is `true` at the surface layer" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "5-element BitArray{1}:\n", " 1\n", " 1\n", " 1\n", " 0\n", " 0" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "z .== z₀" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Model parameters\n", "\n", "First, create a table of parameters using the AIBECS API" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/html": [ "

4 rows × 9 columns (omitted printing of 1 columns)

symbolvalueunitprintunitmean_obsvariance_obsoptimizabledescription
SymbolFloat64Unitful…Unitful…Float64Float64BoolString
1τ2.60875e11syrNaNNaN0
2λ1.5844e-7m s^-1m yr^-1NaNNaN0
3h200.0mmNaNNaN0
4Ratm1.0mol m^-3mol m^-3NaNNaN0
" ], "text/latex": [ "\\begin{tabular}{r|ccccccccc}\n", "\t& symbol & value & unit & printunit & mean\\_obs & variance\\_obs & optimizable & description & \\\\\n", "\t\\hline\n", "\t& Symbol & Float64 & Unitful… & Unitful… & Float64 & Float64 & Bool & String & \\\\\n", "\t\\hline\n", "\t1 & τ & 2.60875e11 & s & yr & NaN & NaN & 0 & & $\\dots$ \\\\\n", "\t2 & λ & 1.5844e-7 & m s\\^-1 & m yr\\^-1 & NaN & NaN & 0 & & $\\dots$ \\\\\n", "\t3 & h & 200.0 & m & m & NaN & NaN & 0 & & $\\dots$ \\\\\n", "\t4 & Ratm & 1.0 & mol m\\^-3 & mol m\\^-3 & NaN & NaN & 0 & & $\\dots$ \\\\\n", "\\end{tabular}\n" ], "text/plain": [ "4×9 DataFrames.DataFrame. Omitted printing of 3 columns\n", "│ Row │ symbol │ value │ unit │ printunit │ mean_obs │ variance_obs │\n", "│ │ \u001b[90mSymbol\u001b[39m │ \u001b[90mFloat64\u001b[39m │ \u001b[90mUnitful…\u001b[39m │ \u001b[90mUnitful…\u001b[39m │ \u001b[90mFloat64\u001b[39m │ \u001b[90mFloat64\u001b[39m │\n", "├─────┼────────┼────────────┼──────────┼───────────┼──────────┼──────────────┤\n", "│ 1 │ τ │ 2.60875e11 │ s │ yr │ NaN │ NaN │\n", "│ 2 │ λ │ 1.5844e-7 │ m s^-1 │ m yr^-1 │ NaN │ NaN │\n", "│ 3 │ h │ 200.0 │ m │ m │ NaN │ NaN │\n", "│ 4 │ Ratm │ 1.0 │ mol m^-3 │ mol m^-3 │ NaN │ NaN │" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t = empty_parameter_table()\n", "add_parameter!(t, :τ, 5730u\"yr\" / log(2)) # radioactive decay e-folding timescale\n", "add_parameter!(t, :λ, 50u\"m\" / 10u\"yr\") # piston velocity\n", "add_parameter!(t, :h, grd.δdepth[1]) # top layer height\n", "add_parameter!(t, :Ratm, 1.0u\"mol/m^3\") # atmospheric concentration\n", "t " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Then, chose a name for the parameters (here `C14_parameters`), and create the vector `p`:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ " τ = 8.27e+03 [yr] (fixed)\n", " λ = 5.00e+00 [m yr⁻¹] (fixed)\n", " h = 2.00e+02 [m] (fixed)\n", " Ratm = 1.00e+00 [mol m⁻³] (fixed)\n" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" }, { "name": "stdout", "output_type": "stream", "text": [ "C14_parameters{Float64}\n" ] } ], "source": [ "initialize_Parameters_type(t, \"C14_parameters\")\n", "p = C14_parameters() " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Note `p` has units! \n", "\n", "In AIBECS, you give your parameters units and they are **automatically converted to SI units** under the hood.\n", "\n", "(And they are converted back for pretty printing!)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# State function (and Jacobian)\n", "\n", "$$\\frac{\\partial \\boldsymbol{x}}{\\partial t} = \\boldsymbol{G}(\\boldsymbol{x}, \\boldsymbol{p}) - \\mathbf{T}(\\boldsymbol{p}) \\, \\boldsymbol{x} = \\color{Brown}{\\boldsymbol{F}(\\boldsymbol{x}, \\boldsymbol{p})}$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "We generate `F` and `∇ₓF` via" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "F, ∇ₓF = state_function_and_Jacobian(p -> T, G) ; " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## The state function `F(x,p)`\n", "\n", "Let's try `F` on a random state vector `x`" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "5-element Array{Float64,1}:\n", " 3.941844738773137e-10\n", " 3.941844738773139e-10\n", " 3.941844738773139e-10\n", " -1.916623798048004e-12\n", " -1.916623798048004e-12" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = 0.5p.Ratm * ones(5)\n", "F(x,p)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## The Jacobian `∇ₓF`\n", "\n", "The Jacobian matrix is $\\nabla_{\\boldsymbol{x}}\\boldsymbol{F}(\\boldsymbol{x},\\boldsymbol{p}) = \\left[\\frac{\\partial F_i}{\\partial x_j}\\right]_{i,j}$, is useful for \n", "- **implicit** time-steps\n", "- **solving** the **steady-state** system\n", "- **optimization** / **uncertainty analysis**\n", "\n", "With AIBECS, the **Jacobian** is **computed automatically** for you under the hood... using **dual numbers**!
\n", "(Come to my Applied seminar tomorrow for more on dual numbers and... hyperdual numbers!)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Let's try `∇ₓF` at `x`:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "5×5 Array{Float64,2}:\n", " -5.30527e-9 0.0 3.92107e-9 5.88161e-10 0.0 \n", " 5.88161e-10 -1.7763e-9 0.0 0.0 3.92107e-10\n", " 3.92107e-9 0.0 -4.71711e-9 0.0 0.0 \n", " 0.0 0.0 0.0 -3.74424e-11 3.36092e-11\n", " 0.0 5.60153e-11 0.0 0.0 -5.98486e-11" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Matrix(∇ₓF(x,p))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Time stepping\n", "\n", "AIBECS provides schemes for time-stepping\n", "- Euler forward\n", "- Euler backward\n", "- **Crank-Nicolson**\n", "- Crank-Nicolson leap-frog" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Let's track the evolution of `x` through time\n", "\n", "Define a function to apply the time steps `n` times for a time span of `Δt` starting from `x₀`" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "time_steps (generic function with 1 method)" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function time_steps(x₀, Δt, n, F, ∇ₓF)\n", " x_hist = [x₀]\n", " δt = Δt / n\n", " for i in 1:n\n", " push!(x_hist, AIBECS.crank_nicolson_step(last(x_hist), p, δt, F, ∇ₓF))\n", " end\n", " return reduce(hcat, x_hist), 0:δt:Δt\n", "end" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Let's run the model for 5000 years starting with `x = 1` everywhere:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "([1.0 0.9994296770968054 … 0.9404889218195841 0.9404848396799437; 1.0 0.9994298899213698 … 0.9547523856393718 0.9547501120122107; … ; 1.0 0.9993953427907428 … 0.8048529661244507 0.8048390925665518; 1.0 0.9993954943464941 … 0.8940274609770101 0.8940234459682024], 0.0:1.57788e8:1.57788e11)" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Δt = 5000u\"yr\" |> u\"s\" |> ustrip\n", "x₀ = p.Ratm * ones(5) \n", "x_hist, t_hist = time_steps(x₀, Δt, 1000, F, ∇ₓF) " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Plotting the output is easy\n", "\n", "The radiocarbon age, `C14age`, is given by $\\log(R_{\\mathrm{atm}}/\\boldsymbol{x}) \\tau$ because $\\boldsymbol{x}\\sim R_{\\mathrm{atm}} \\exp(-t/\\tau)$\n", "\n", "Let's plot its evolution with time:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "image/png": "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rr/+eiZMmIDNZmPatGk89thjMdUaC0VRYroMobfq7HrittdPa5rG559/jtFojLo+uDO5ubmMHDkyqm3EiBH885///GEFi7jy7ymjfO5c3GvWAJB46qnk3n8f5lYzsAghhBC9QZcCsMfjYeHChTz99NPU1NQwevRo8vPzsdlsbNu2jXfeeYcZM2YwdepU7r777sh1uAcyadKk/d60daAbusaMGcPKlSsP+D4DBgzg/fff71JNR5q2X7+VK1dSVFSE0Whk5MiRBINBVq1aFbkEoqamhu+//54RI0ZEXvPoo4+yZcsWli9fzplnnsmSJUv4zW9+0+l7Tpgwga1bt0a1ff/99wwcOLAbP5k4VHRdx/n2O+ybNw+tqQnFbif7zjtIvUBGfYUQQvRSehf0799f/+Uvf6m/9957ut/v77DPrl279Pnz5+sDBgzQn3/++a6ctk9xOp06oDudzqh2j8ejb968Wfd4PHGq7OBNnDhRT0pK0mfNmqV/9913+uuvv64nJibqzz77bKTPT3/6U33kyJH6//73P339+vX6WWedpR911FGRvwfr1q3TLRaL/u677+q6rusvvPCCnpycrG/fvr3T9129erVuMpn0efPm6cXFxfprr72m2+12/dVXX+2wf1/+Gh/uAjU1eskNN+ibhw3XNw8bru+86GLdt3t3vMsSQghxhOosr7Wl6PqB583auHEjxxxzTJcCtd/vZ/fu3RQVFf3AaN67uFwuHA4HTqcz6tphr9fLzp07KSwsJCEhIY4Vxm7SpEkcffTRaJrG66+/jtFo5Nprr2X+/PmRkbu6ujpuvvlm3n33Xfx+P6effjpPPvkkRUVFeL1eTjjhBE499VSee+65yHl/8YtfsG/fPlasWIHR2PGlIO+//z5z586luLiYwsJCZs+e3eksEH35a3w4a/jkU8rvugu1pgbMZjJvuomMq65E6eTPXAghhOhpneW1troUgMXhGYD7Cvka9y5aUxMVDz6I8x+ha7atRUXkPfIwCa0uixFCCCHioasBOObJOJcuXcpnn30W2X/qqac47rjjmDZtGnV1dQdXrRCiT/Bs3MTOX/wyFH4VhfQrr2TQP/4u4VcIIUSfEnMAvu2223C5XAB8++233HrrrZxzzjns2LEjMouDEOLwomsaNS8tYdfFF+PfvRtTbi4DXnmZ7Ntvw3CQD4wRQggh4iXm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Sl5e3gXrA7B+/XqXbgXr1q0jICCAlpYWl3J33HEHv/zlL53vN23aRGJiIh4eHsTGxjrrd9rq1auJj4/H09OTyMhIHnjgAerr653rT7ftZ599xpAhQzAYDJw4cYJt27YxevRoPD098fX1ZcKECZw4ccK53dy5c/n0009pamq66HkJIbouCcBCiG6rqKiIefPmce+995Kdnc22bdu4/fbbuVjPrnfffZfAwED27dvH0qVLuf/++/n5z3/O+PHjSU1NZdasWSxYsIDGxsYfXa+6ujruuecedu7cyZ49e+jfvz833XQTdXV1QFtABli7di1FRUXO9+d66aWXePHFF/nTn/7EwYMHmTVrFnPnziU3N9el3JNPPsmjjz5KWloaAwYMYN68eS5B8GyXe2yAb775hsLCQnbs2MHq1atZuXIlN998M35+fuzdu5fFixezePFiTp48CUBjYyPTpk3Dy8uLHTt2sGvXLry8vLjxxhtpbW3t8BhVVVVkZGQwatQo57Kf//zn2O12Nm7c6FxWXl7OZ599xq9+9SsAvvzyS37xi1+wbNkysrKy+Nvf/sY777zDc88959xGq9Xy8ssvk5GRwbvvvss333zD448/7nL8xsZGVq1axVtvvUVmZib+/v7cdtttTJkyhYMHD5KcnMyiRYtcfuEZNWoUVquVffv2XfCzE0J0cUoIIbqplJQUBai8vLwO199zzz3q1ltvdb6fMmWKmjhxovO9zWZTnp6easGCBc5lRUVFClDJyclKKaXWrl2rzGazy343bNigzv7n8+mnn1YJCQkXrKfNZlPe3t5q06ZNzmWA2rBhg0u5c/cTFhamnnvuOZcy1113nXrggQeUUkodP35cAeqtt95yrs/MzFSAys7OvmB9LufY99xzj4qKilJ2u925bODAgWrSpEku5+Xp6ak+/PBDpZRSb7/9tho4cKByOBzOMi0tLcpoNKovv/yyw7rs379fASo/P99l+f33369mz57tfP+Xv/xFxcbGOvc9adIk9cc//tFlm/fee0+FhoZe8Lz/+c9/qoCAAOf7tWvXKkClpaU5l1VUVChAbdu27YL7UUopPz8/9c4771y0jBCi65IrwEKIbishIYHp06cTHx/Pz3/+c9asWUNVVdVFtxk2bJjztZubGwEBAcTHxzuXWSwWAEpLS390vUpLS1m8eDEDBgzAbDZjNpupr68nPz//svdRW1tLYWEhEyZMcFk+YcIEsrOzXZadfU6hoaE/uf6nDR06FK32zNeExWJx+axOf36nj5WSksKRI0fw9vbGy8sLLy8v/P39aW5u5ujRox0e43Q3Ag8PD5fl9913H1u2bKGgoABou2K9cOFC55XYlJQUnn32WedxvLy8uO+++ygqKnJevd+6dSszZ84kPDwcb29vfvnLX1JRUeHsIgOg1+tdPj9/f38WLlzIrFmzuOWWW3jppZcoKio6r95Go/En/S+BEKJzSQAWQnRbbm5uJCUl8cUXXzBkyBBeeeUVBg4cyPHjxy+4jU6nc3mv0Whclp0OWKdvhtJqted1qbBarRet18KFC0lJSeEvf/kLu3fvJi0tjYCAgAt2A7iYc/saK6XOW3ax+v8Ul/qsTi87fSyHw0FiYiJpaWkuj8OHD3P33Xd3eIzAwECA835xGTFiBAkJCaxbt47U1FTS09NZuHChc73D4eCZZ55xOU56ejq5ubl4eHhw4sQJbrrpJuLi4vj4449JSUnh1VdfBVzbz2g0nvd5rl27luTkZMaPH89HH33EgAED2LNnj0uZyspKgoKCLvURCiG6KPfOroAQQvwUGo2GCRMmMGHCBP7whz8QFRXFhg0bWL58+RXZf1BQEHV1dTQ0NODp6QlwyeHOdu7cyWuvvcZNN90EwMmTJykvL3cpo9PpsNvtF9yHj48PYWFh7Nq1i8mTJzuX7969m9GjR//Y07msY/9YI0eO5KOPPiI4OBgfH5/L2qZv3774+PiQlZXFgAEDXNb9+te/5s9//jMFBQXMmDGDyMhIl2Pl5OTQr1+/Dvf7/fffY7PZePHFF51Xsf/5z39e9rmMGDGCESNGsGLFCsaNG8cHH3zA2LFjATh69CjNzc2MGDHisvcnhOha5AqwEKLb2rt3L3/84x/5/vvvyc/P55NPPqGsrIzBgwdfsWOMGTMGk8nEE088wZEjR/jggw945513LrpNv379eO+998jOzmbv3r3Mnz8fo9HoUiY6Opqvv/6a4uLiC3bbeOyxx3jhhRf46KOPyMnJ4Xe/+x1paWk89NBDP+mcLufYP8b8+fMJDAzk1ltvZefOnRw/fpzt27fz0EMPcerUqQ630Wq1zJgxg127dnW4v4KCAtasWcO9997rsu4Pf/gD69atY+XKlWRmZpKdnc1HH33E73//e6AtWNtsNl555RWOHTvGe++9xxtvvHHJczh+/DgrVqwgOTmZEydOsGXLFg4fPuzyM7Vz505iY2Pp27fvD/l4hBBdiARgIUS35ePjw44dO7jpppsYMGAAv//973nxxReZPXv2FTuGv78///jHP/j888+Jj4/nww8/ZOXKlRfd5u9//ztVVVWMGDGCBQsWsGzZMoKDg13KvPjiiyQlJREZGXnBK4nLli3jkUce4ZFHHiE+Pp7NmzezceNG+vfv/5PO6XKO/WOYTCZ27NhBnz59uP322xk8eDD33nsvTU1NF70ivGjRItavX39etw0fHx/uuOMOvLy8zpvRb9asWXz22WckJSVx3XXXMXbsWFavXk1UVBQAw4cPZ/Xq1bzwwgvExcXx/vvvs2rVqss6h0OHDnHHHXcwYMAAFi1axJIlS/jNb37jLPPhhx9y3333/ZCPRgjRxchMcEIIITqVUoqxY8fy8MMPM2/ePJd1M2fOZPDgwbz88sudVDtXGRkZTJ8+ncOHD2M2mzu7OkKIH0muAAshhOhUGo2GN99802Xs4srKStavX88333zDgw8+2Im1c1VYWMi6desk/ArRzckVYCGEEF1OdHQ0VVVVPPXUUzz66KOdXR0hRA8jAVgIIYQQQvQq0gVCCCGEEEL0KhKAhRBCCCFEryIBWAghhBBC9CoSgIUQQgghRK8iAVgIIYQQQvQqEoCFEEIIIUSvIgFYCCGEEEL0KhKAhRBCCCFEr/L/AUj0uMyayP5yAAAAAElFTkSuQmCC", "text/plain": [ "Figure(PyObject
)" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "PyObject Text(0.5, 1, 'Simulation of the evolution of ¹⁴C age with Crank-Nicolson time steps')" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "C14age_hist = log.(p.Ratm ./ x_hist) * (p.τ * u\"s\" |> u\"yr\" |> ustrip)\n", "PyPlot.figure(figsize=(8,4))\n", "PyPlot.plot(t_hist .* 1u\"s\" .|> u\"yr\" .|> ustrip, C14age_hist')\n", "PyPlot.xlabel(\"simulation time (years)\")\n", "PyPlot.ylabel(\"¹⁴C age (years)\")\n", "PyPlot.legend(\"box \" .* string.(findall(vec(wet3D))))\n", "PyPlot.title(\"Simulation of the evolution of ¹⁴C age with Crank-Nicolson time steps\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Solve directly for the steady state\n", "\n", "Instead, we can directly solve for the **steady-state**, $\\boldsymbol{s}$,
\n", "(using `CTKAlg()`, a quasi-Newton root-finding algorithm from C. T. Kelley)\n", "\n", "i.e., such that $\\boldsymbol{F}(\\boldsymbol{s},\\boldsymbol{p}) = 0$:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "5-element Array{Float64,1}:\n", " 0.9395557449765635\n", " 0.9542341322419017\n", " 0.9489433863241392\n", " 0.8016816657976089\n", " 0.8931162915594038" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "prob = SteadyStateProblem(F, ∇ₓF, x, p)\n", "s = solve(prob, CTKAlg()).u" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "gives the age" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "5-element Array{Quantity{Float64,𝐓,Unitful.FreeUnits{(yr,),𝐓,nothing}},1}:\n", " 515.409683042318 yr\n", " 387.2609241614547 yr\n", " 433.2228144719123 yr\n", " 1827.2890596434506 yr\n", " 934.4487196556533 yr" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "log.(p.Ratm ./ s) * (p.τ * u\"s\" |> u\"yr\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# 35'000 years without the steady-state solver!\n", "\n", "How long would it take to reach that steady-state with time-stepping?\n", "\n", "We chan check by tracking the norm of `F(x,p)`:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "image/png": "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nteuXasAtWjRoqeeNyfjxo1TixYtUtu3b1e7d+9W8+bNU05OTmrw4MF69SZNmqQA9eabb6rt27erZcuWKTc3N1WuXDnddVdKqQcPHqi6desqJycnNXfuXLVr1y61YMECZWdnp1555RWVnp6ebSx//vmnAtTatWt1Ze3bt1eWlpaqevXqurLIyEgFqG3btunKADVlyhSllPb6T58+XQHqq6++0l3/mzdvKqW017l06dKqevXqavHixSokJESNHDlSAZm+p0/av3+/0mg0qk+fPmrbtm1q9+7dasWKFap///66Ohmf1eOfZcZ3tmbNmuqTTz5RISEh6v3331eAGj16tPLw8FBffPGFCgkJUYMHD1aA+vHHH3XHr1ixQgEqOjpaL56sfh8DBw5UlSpV0quXm8/51KlTqkmTJsrFxUV3zR7/3j5+jZXK3W/h8Rjd3d3V66+/rrZu3arWrVun3NzcVPXq1VVqamq21/vy5ctqzJgxClAbN27UxXT37l2llP7v/vFrX6lSJdWpUye1ZcsW9e233ypnZ2dVo0YN1b9/fzVkyBD166+/qsWLF6tSpUqpTp066bX52WefKY1Go4YMGaK2bNmiNm7cqPz8/JS1tbU6depUtrGK4keSO1HixcfHq6ZNmypAAcrU1FQ1btxYzZgxQ927d0+v7ksvvaT3D2p2UlNT1aNHj9TQoUNVvXr19PYBytLSUl2/fl2vvoeHh6pWrZquLD/JnVJK3bp1K9MfowwZfyiPHDmiKztw4ECu/rj36dNHmZubq9jYWL3ygIAAZWVlpe7cuaP3HkeNGpXj+ZRSauXKlap06dLKxMRElSpVSpUuXVrdv39fr86Tyd3MmTMVoLZv3/7U8+dWWlqaevTokVq9erUyNjZWf//9t1JKqb///luZm5ur3r1769XPSGAfv+4zZsxQRkZG6uDBg3p1f/jhh0wJWVYqVKighgwZopRSKjk5WVlbW6uJEycqQF26dEkppf3ja2pqqneNnvysN2zYkOl7k6FFixYKUJGRkXrltWvXVu3atcsxvv/+978K0Pucn5RTcjdnzhy9unXr1tUlLhkePXqkypQpo7p3764re9bk7nHZfc5KKfXqq69me+yT1zi3v4WMGDt06KBX7/vvv1fAU//j8/nnn2f53pXKPrnz9vZWaWlpuvL58+crQHXu3Fnv+MDAQAXoksXY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cntISIgaOHCg/n337t1Vly5d9O/z8vKUvb29GjlypL4tLS1NASouLk4ppdTKlSuVk5OTwbgRERHq33+2ZsyYoXx8fIqNMy8vTzk4OKgffvhB3waoiIgIg353j+Ph4aE++OADgz7t27dXr7zyilJKqeTkZAWoL7/8Ur/9yJEjClDHjh0rNp6S7DskJEQ1btxY5efn69tatmypunbtapCXvb29WrdunVJKqRUrVqiWLVuqgoICfZ+cnBxVo0YN9euvvxYZy8GDBxWgUlJSDNpffvll1bdvX/37zz77TDVt2lQ/dteuXdXs2bMNPrN27VpVv379YvP+7rvvlIuLi/79ypUrFaASExP1bZcuXVKAioqKKnYcpZSqU6eOWrVq1T37CFHdycydEKLUfHx86N27N97e3gwbNoywsDAyMzPv+Zm2bdvqf7a0tMTFxQVvb299m7u7OwAZGRlljisjI4Px48fTokULnJyccHJy4tq1a6SkpJR4jKtXr3Lu3Dk6d+5s0N65c2eOHTtm0PbvnOrXr//A8d/Rpk0bLCz+++fZ3d3d4Hd15/d3Z1/x8fGcPHkSBwcHatWqRa1atXB2dubWrVv89ddfRe7jzqlNOzs7g/axY8eybds2zp49C+hmGkePHq2fQYuPj2fWrFn6/dSqVYuxY8eSlpamn3XdsWMHjz32GA899BAODg6MGjWKS5cu6U/bA9jY2Bj8/pydnRk9ejTBwcH079+fzz//nLS0tEJx16hR44Fmd4WoDqS4E0KUmqWlJZGRkfz88894eXmxcOFCWrZsSXJycrGfsba2Nniv0WgM2u4UD3curLewsCh0mvf27dv3jGv06NHEx8fz2WefERsbS2JiIi4uLsWemryXu6/tU0oVartX/A/ifr+rO2139lVQUIC/vz+JiYkGrz///JNnn322yH24uroCFCrK27Vrh4+PD2vWrCEhIYGkpCRGjx6t315QUMDMmTMN9pOUlMSJEyews7PjzJkzPP7442i1WjZt2kR8fDyLFy8GDI9fjRo1Cv0+V65cSVxcHJ06dSI8PJwWLVqwZ88egz6XL1+mbt269/sVClGtWRk7ACFE1aTRaOjcuTOdO3fm/fffp3HjxkRERPD666+Xy/h169YlOzub69evY29vD3DfJU9iYmJYsmQJjz/+OACpqalcvHjRoI+1tTX5+fnFjuHo6IiHhwe7du2iW7du+vbY2FgeeeSRsqZTon2XlZ+fH+Hh4bi5ueHo6FiizzRr1gxHR0eOHj1KixYtDLa9+OKLzJ8/n7Nnz/Loo4/SsGFDg30dP36chx9+uMhxDxw4QF5eHp9++ql+9vG7774rcS7t2rWjXbt2TJ8+ncDAQL799ls6duwIwF9//cWtW7do165diccTojqSmTshRKnt3buX2bNnc+DAAVJSUti8eTMXLlygdevW5baPDh06ULNmTd5++21OnjzJt99+y6pVq+75mYcffpi1a9dy7Ngx9u7dy4gRI6hRo4ZBnyZNmvCf//yH9PT0Yk8lv/HGG3z44YeEh4dz/Phx3nrrLRITE5k8efID5VSSfZfFiBEjcHV1ZeDAgcTExJCcnMzOnTuZPHkyf//9d5GfsbCw4NFHH2XXrl1Fjnf27FnCwsIYM2aMwbb333+fNWvWEBoaypEjRzh27Bjh4eG8++67gK5ozMvLY+HChZw6dYq1a9eybNmy++aQnJzM9OnTiYuL48yZM2zbto0///zT4DsVExND06ZNadasWWl+PUJUO1LcCSFKzdHRkejoaB5//HFatGjBu+++y6effkrfvn3LbR/Ozs58/fXXbN26FW9vb9atW0doaOg9P/PVV1+RmZlJu3btGDlyJJMmTcLNzc2gz6effkpkZCQNGzYsdgZo0qRJTJ06lalTp+Lt7c0vv/zC999/T/PmzR8op5Lsuyxq1qxJdHQ0jRo1YsiQIbRu3ZoxY8Zw8+bNe87kjRs3jvXr1xc6lezo6MjQoUOpVatWoSeNBAcH8+OPPxIZGUn79u3p2LEj8+bNo3HjxgD4+voyb948PvzwQ7RaLd988w1z5swpUQ5//PEHQ4cOpUWLFowbN44JEybw0ksv6fusW7eOsWPHluZXI0S1JE+oEEKIakopRceOHZkyZQrDhw832PbYY4/RunVrFixYYKToDB0+fJjevXvz559/4uTkZOxwhDBpMnMnhBDVlEajYfny5QZr812+fJn169ezfft2Xn31VSNGZ+jcuXOsWbNGCjshSkBm7oQQQug1adKEzMxM3nvvPaZNm2bscIQQZSDFnRBCCCGEGZHTskIIIYQQZkSKOyGEEEIIMyLFnRBCCCGEGZHiTgghhBDCjEhxJ4QQQghhRqS4E0IIIYQwI1LcCSGEEEKYESnuhBBCCCHMyP8Hf5S/Kh7rtqwAAAAASUVORK5CYII=", "text/plain": [ "Figure(PyObject
)" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "PyObject Text(0.5, 1, 'Stability of ¹⁴C age with simulation time')" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Δt = 40000u\"yr\" |> u\"s\" |> ustrip\n", "x_hist, t_hist = time_steps(x₀, Δt, 4000, F, ∇ₓF)\n", "PyPlot.figure(figsize=(7,3))\n", "PyPlot.semilogy(t_hist .* 1u\"s\" .|> u\"yr\" .|> ustrip, [norm(F(s,p)) for i in 1:size(x_hist,2)], label=\"steady-state\")\n", "PyPlot.semilogy(t_hist .* 1u\"s\" .|> u\"yr\" .|> ustrip, [norm(F(x_hist[:,i],p)) for i in 1:size(x_hist,2)], label=\"time-stepping\")\n", "PyPlot.xlabel(\"simulation time (years)\"); PyPlot.ylabel(\"|F(x,p)| (mol m⁻³ s⁻¹)\");\n", "PyPlot.legend(); PyPlot.title(\"Stability of ¹⁴C age with simulation time\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Circulation 2: OCIM1\n", "\n", "The Ocean Circulation Inverse Model (OCIM) version 1 is loaded via" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Loading OCIM1 ✔\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "┌ Info: You are about to use OCIM1 model.\n", "│ If you use it for research, please cite:\n", "│ \n", "│ - DeVries, T., 2014: The oceanic anthropogenic CO2 sink: Storage, air‐sea fluxes, and transports over the industrial era, Global Biogeochem. Cycles, 28, 631–647, doi:10.1002/2013GB004739.\n", "│ - DeVries, T. and F. Primeau, 2011: Dynamically and Observationally Constrained Estimates of Water-Mass Distributions and Ages in the Global Ocean. J. Phys. Oceanogr., 41, 2381–2401, doi:10.1175/JPO-D-10-05011.1\n", "│ \n", "│ You can find the corresponding BibTeX entries in the CITATION.bib file\n", "│ at the root of the AIBECS.jl package repository.\n", "│ (Look for the \"DeVries_Primeau_2011\" and \"DeVries_2014\" keys.)\n", "└ @ AIBECS.OCIM1 /Users/benoitpasquier/.julia/packages/AIBECS/J5NKA/src/OCIM1.jl:53\n" ] } ], "source": [ "wet3D, grd, T = OCIM1.load() ;" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Redefine `F` and `∇ₓF` for the new `T`:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "F, ∇ₓF = state_function_and_Jacobian(p -> T, G) ;" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Redefine `iwet` and `x` for the new grid size" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "200160-element Array{Float64,1}:\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " ⋮ \n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0\n", " 1.0" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iwet = findall(wet3D)\n", "x = p.Ratm * ones(length(iwet))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Redefine `h`, `z₀`, and `z` for the new grid" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "18.0675569520817 m" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.h = grd.δdepth[1] |> upreferred |> ustrip\n", "z = grd.depth_3D[iwet]\n", "z₀ = z[1]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Solve for the steady-state of radio carbon and convert to age" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "200160-element Array{Quantity{Float64,𝐓,Unitful.FreeUnits{(yr,),𝐓,nothing}},1}:\n", " 1364.7245332140983 yr\n", " 1376.8840164692285 yr\n", " 1395.8800725998346 yr\n", " 1383.0420964666407 yr\n", " 1300.9081458733292 yr\n", " 1277.2701118588202 yr\n", " 1304.3367306286373 yr\n", " 1288.1180389541546 yr\n", " 1247.320711595504 yr\n", " 1190.1083953525956 yr\n", " 1138.2190502916894 yr\n", " 1101.7243454551876 yr\n", " 1049.2576207121228 yr\n", " ⋮\n", " 1117.471239994219 yr\n", " 1114.9073996563354 yr\n", " 1120.6568745435516 yr\n", " 1114.550596730836 yr\n", " 1107.5809181396125 yr\n", " 1123.3995401255097 yr\n", " 1119.1390345235536 yr\n", " 1111.8810560871614 yr\n", " 1097.5315397929392 yr\n", " 1118.1355949315896 yr\n", " 1114.1140959317402 yr\n", " 1109.100144965028 yr" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "prob = SteadyStateProblem(F, ∇ₓF, x, p)\n", "s = solve(prob, CTKAlg()).u \n", "C14age = log.(p.Ratm ./ s) * p.τ * u\"s\" .|> u\"yr\"" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "And plot horizontal slices using GR and Interact:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "scrolled": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "┌ Warning: Accessing `scope.id` is deprecated, use `scopeid(scope)` instead.\n", "│ caller = ip:0x0\n", "└ @ Core :-1\n" ] }, { "data": { "application/vnd.webio.node+json": { "children": [ { "children": [ { "children": [ { "children": [ { "children": [ { "children": [ "iz" ], "instanceArgs": { "namespace": "html", "tag": "label" }, "nodeType": "DOM", "props": { "className": "interact ", "style": { "padding": "5px 10px 0px 10px" } }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-left" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "input" }, "nodeType": "DOM", "props": { "attributes": { "data-bind": "numericValue: index, valueUpdate: 'input', event: {change: function (){this.changes(this.changes()+1)}}", "orient": "horizontal", "type": "range" }, "className": "slider slider is-fullwidth", "max": 24, "min": 1, "step": 1, "style": {} }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-center" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "p" }, "nodeType": "DOM", "props": { "attributes": { "data-bind": "text: formatted_val" } }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-right" }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row interact-widget" }, "type": "node" } ], "instanceArgs": { "handlers": { "changes": [ "(function (val){return (val!=this.model[\"changes\"]()) ? (this.valueFromJulia[\"changes\"]=true, this.model[\"changes\"](val)) : undefined})" ], "index": [ "(function (val){return (val!=this.model[\"index\"]()) ? (this.valueFromJulia[\"index\"]=true, this.model[\"index\"](val)) : undefined})" ] }, "id": "453966076138971272", "imports": { "data": [ { "name": "knockout", "type": "js", "url": "/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js" }, { "name": "knockout_punches", "type": "js", "url": "/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js" }, { "name": null, "type": "js", "url": "/assetserver/9cda67a60395433f45d7dd64448e9983594c3d89-all.js" }, { "name": null, "type": "css", "url": "/assetserver/f8657a57be3c3d9bd1b603ffa11049f3a1b07340-style.css" }, { "name": null, "type": "css", "url": "/assetserver/ce4e0a8b544aa8c325b955acaffb5afe8945d9a5-bulma_confined.min.css" } ], "type": "async_block" }, "mount_callbacks": [ "function () {\n var handler = (function (ko, koPunches) {\n ko.punches.enableAll();\n ko.bindingHandlers.numericValue = {\n init: function(element, valueAccessor, allBindings, data, context) {\n var stringified = ko.observable(ko.unwrap(valueAccessor()));\n stringified.subscribe(function(value) {\n var val = parseFloat(value);\n if (!isNaN(val)) {\n valueAccessor()(val);\n }\n });\n valueAccessor().subscribe(function(value) {\n var str = JSON.stringify(value);\n if ((str == \"0\") && ([\"-0\", \"-0.\"].indexOf(stringified()) >= 0))\n return;\n if ([\"null\", \"\"].indexOf(str) >= 0)\n return;\n stringified(str);\n });\n ko.applyBindingsToNode(\n element,\n {\n value: stringified,\n valueUpdate: allBindings.get('valueUpdate'),\n },\n context,\n );\n }\n };\n var json_data = {\"formatted_vals\":[\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"10\",\"11\",\"12\",\"13\",\"14\",\"15\",\"16\",\"17\",\"18\",\"19\",\"20\",\"21\",\"22\",\"23\",\"24\"],\"changes\":WebIO.getval({\"name\":\"changes\",\"scope\":\"453966076138971272\",\"id\":\"ob_02\",\"type\":\"observable\"}),\"index\":WebIO.getval({\"name\":\"index\",\"scope\":\"453966076138971272\",\"id\":\"ob_01\",\"type\":\"observable\"})};\n var self = this;\n function AppViewModel() {\n for (var key in json_data) {\n var el = json_data[key];\n this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);\n }\n \n [this[\"formatted_val\"]=ko.computed( function(){\n return this.formatted_vals()[parseInt(this.index())-(1)];\n }\n,this)]\n [this[\"changes\"].subscribe((function (val){!(this.valueFromJulia[\"changes\"]) ? (WebIO.setval({\"name\":\"changes\",\"scope\":\"453966076138971272\",\"id\":\"ob_02\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"changes\"]=false}),self),this[\"index\"].subscribe((function (val){!(this.valueFromJulia[\"index\"]) ? (WebIO.setval({\"name\":\"index\",\"scope\":\"453966076138971272\",\"id\":\"ob_01\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"index\"]=false}),self)]\n \n }\n self.model = new AppViewModel();\n self.valueFromJulia = {};\n for (var key in json_data) {\n self.valueFromJulia[key] = false;\n }\n ko.applyBindings(self.model, self.dom);\n}\n);\n (WebIO.importBlock({\"data\":[{\"name\":\"knockout\",\"type\":\"js\",\"url\":\"/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js\"},{\"name\":\"knockout_punches\",\"type\":\"js\",\"url\":\"/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js\"}],\"type\":\"async_block\"})).then((imports) => handler.apply(this, imports));\n}\n" ], "observables": { "changes": { "id": "ob_02", "sync": false, "value": 0 }, "index": { "id": "ob_01", "sync": true, "value": 12 } }, "systemjs_options": null }, "nodeType": "Scope", "props": {}, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "field interact-widget" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "id": "ob_08", "name": "obs-node" }, "nodeType": "ObservableNode", "props": {}, "type": "node" } ], "instanceArgs": { "handlers": {}, "id": "4466513465790315358", "imports": { "data": [], "type": "async_block" }, "mount_callbacks": [], "observables": { "obs-node": { "id": "ob_08", "sync": false, "value": { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "setInnerHtml": "\n\n\n \n \n \n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n-\n\n\n50\n\n\n0\n\n\n50\n\n\n\n0\n\n\n100\n\n\n200\n\n\n300\n\n\n\n\n\n14C age [yr] using the OCIM1 circulation at 919.0 m depth\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n\n\n\n\n\n500\n\n\n750\n\n\n1000\n\n\n1250\n\n\n1500\n\n\n1750\n\n\n2000\n\n\n\n" }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row interact-widget" }, "type": "node" } } }, "systemjs_options": null }, "nodeType": "Scope", "props": {}, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": {}, "type": "node" }, "text/html": [ "\n", " \n", "\n" ], "text/plain": [ "Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Scope(Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :label), Any[\"iz\"], Dict{Symbol,Any}(:className => \"interact \",:style => Dict{Any,Any}(:padding => \"5px 10px 0px 10px\")))], Dict{Symbol,Any}(:className => \"interact-flex-row-left\")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :input), Any[], Dict{Symbol,Any}(:max => 24,:min => 1,:attributes => Dict{Any,Any}(:type => \"range\",Symbol(\"data-bind\") => \"numericValue: index, valueUpdate: 'input', event: {change: function (){this.changes(this.changes()+1)}}\",\"orient\" => \"horizontal\"),:step => 1,:className => \"slider slider is-fullwidth\",:style => Dict{Any,Any}()))], Dict{Symbol,Any}(:className => \"interact-flex-row-center\")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :p), Any[], Dict{Symbol,Any}(:attributes => Dict(\"data-bind\" => \"text: formatted_val\")))], Dict{Symbol,Any}(:className => \"interact-flex-row-right\"))], Dict{Symbol,Any}(:className => \"interact-flex-row interact-widget\")), Dict{String,Tuple{Observables.AbstractObservable,Union{Nothing, Bool}}}(\"changes\" => (Observable{Int64} with 1 listeners. Value:\n", "0, nothing),\"index\" => (Observable{Int64} with 2 listeners. Value:\n", "12, nothing)), Set(String[]), nothing, Asset[Asset(\"js\", \"knockout\", \"/Users/benoitpasquier/.julia/packages/Knockout/1sDlc/src/../assets/knockout.js\"), Asset(\"js\", \"knockout_punches\", \"/Users/benoitpasquier/.julia/packages/Knockout/1sDlc/src/../assets/knockout_punches.js\"), Asset(\"js\", nothing, \"/Users/benoitpasquier/.julia/packages/InteractBase/9mFwe/src/../assets/all.js\"), Asset(\"css\", nothing, \"/Users/benoitpasquier/.julia/packages/InteractBase/9mFwe/src/../assets/style.css\"), Asset(\"css\", nothing, \"/Users/benoitpasquier/.julia/packages/Interact/0klKX/src/../assets/bulma_confined.min.css\")], Dict{Any,Any}(\"changes\" => Any[WebIO.JSString(\"(function (val){return (val!=this.model[\\\"changes\\\"]()) ? (this.valueFromJulia[\\\"changes\\\"]=true, this.model[\\\"changes\\\"](val)) : undefined})\")],\"index\" => Any[WebIO.JSString(\"(function (val){return (val!=this.model[\\\"index\\\"]()) ? (this.valueFromJulia[\\\"index\\\"]=true, this.model[\\\"index\\\"](val)) : undefined})\")]), WebIO.ConnectionPool(Channel{Any}(sz_max:32,sz_curr:0), Set(AbstractConnection[]), Channel{AbstractConnection}(sz_max:32,sz_curr:0)), WebIO.JSString[WebIO.JSString(\"function () {\\n var handler = (function (ko, koPunches) {\\n ko.punches.enableAll();\\n ko.bindingHandlers.numericValue = {\\n init: function(element, valueAccessor, allBindings, data, context) {\\n var stringified = ko.observable(ko.unwrap(valueAccessor()));\\n stringified.subscribe(function(value) {\\n var val = parseFloat(value);\\n if (!isNaN(val)) {\\n valueAccessor()(val);\\n }\\n });\\n valueAccessor().subscribe(function(value) {\\n var str = JSON.stringify(value);\\n if ((str == \\\"0\\\") && ([\\\"-0\\\", \\\"-0.\\\"].indexOf(stringified()) >= 0))\\n return;\\n if ([\\\"null\\\", \\\"\\\"].indexOf(str) >= 0)\\n return;\\n stringified(str);\\n });\\n ko.applyBindingsToNode(\\n element,\\n {\\n value: stringified,\\n valueUpdate: allBindings.get('valueUpdate'),\\n },\\n context,\\n );\\n }\\n };\\n var json_data = {\\\"formatted_vals\\\":[\\\"1\\\",\\\"2\\\",\\\"3\\\",\\\"4\\\",\\\"5\\\",\\\"6\\\",\\\"7\\\",\\\"8\\\",\\\"9\\\",\\\"10\\\",\\\"11\\\",\\\"12\\\",\\\"13\\\",\\\"14\\\",\\\"15\\\",\\\"16\\\",\\\"17\\\",\\\"18\\\",\\\"19\\\",\\\"20\\\",\\\"21\\\",\\\"22\\\",\\\"23\\\",\\\"24\\\"],\\\"changes\\\":WebIO.getval({\\\"name\\\":\\\"changes\\\",\\\"scope\\\":\\\"453966076138971272\\\",\\\"id\\\":\\\"ob_02\\\",\\\"type\\\":\\\"observable\\\"}),\\\"index\\\":WebIO.getval({\\\"name\\\":\\\"index\\\",\\\"scope\\\":\\\"453966076138971272\\\",\\\"id\\\":\\\"ob_01\\\",\\\"type\\\":\\\"observable\\\"})};\\n var self = this;\\n function AppViewModel() {\\n for (var key in json_data) {\\n var el = json_data[key];\\n this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);\\n }\\n \\n [this[\\\"formatted_val\\\"]=ko.computed( function(){\\n return this.formatted_vals()[parseInt(this.index())-(1)];\\n }\\n,this)]\\n [this[\\\"changes\\\"].subscribe((function (val){!(this.valueFromJulia[\\\"changes\\\"]) ? (WebIO.setval({\\\"name\\\":\\\"changes\\\",\\\"scope\\\":\\\"453966076138971272\\\",\\\"id\\\":\\\"ob_02\\\",\\\"type\\\":\\\"observable\\\"},val)) : undefined; return this.valueFromJulia[\\\"changes\\\"]=false}),self),this[\\\"index\\\"].subscribe((function (val){!(this.valueFromJulia[\\\"index\\\"]) ? (WebIO.setval({\\\"name\\\":\\\"index\\\",\\\"scope\\\":\\\"453966076138971272\\\",\\\"id\\\":\\\"ob_01\\\",\\\"type\\\":\\\"observable\\\"},val)) : undefined; return this.valueFromJulia[\\\"index\\\"]=false}),self)]\\n \\n }\\n self.model = new AppViewModel();\\n self.valueFromJulia = {};\\n for (var key in json_data) {\\n self.valueFromJulia[key] = false;\\n }\\n ko.applyBindings(self.model, self.dom);\\n}\\n);\\n (WebIO.importBlock({\\\"data\\\":[{\\\"name\\\":\\\"knockout\\\",\\\"type\\\":\\\"js\\\",\\\"url\\\":\\\"/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js\\\"},{\\\"name\\\":\\\"knockout_punches\\\",\\\"type\\\":\\\"js\\\",\\\"url\\\":\\\"/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js\\\"}],\\\"type\\\":\\\"async_block\\\"})).then((imports) => handler.apply(this, imports));\\n}\\n\")])], Dict{Symbol,Any}(:className => \"field interact-widget\")), Observable{Any} with 0 listeners. Value:\n", "Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[GR.SVG(UInt8[0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73 … 0x2f, 0x3e, 0x0a, 0x3c, 0x2f, 0x73, 0x76, 0x67, 0x3e, 0x0a])], Dict{Symbol,Any}(:className => \"interact-flex-row interact-widget\"))], Dict{Symbol,Any}())" ] }, "execution_count": 29, "metadata": { "application/vnd.webio.node+json": { "kernelId": "51aa8b2d-fd5a-4d9f-bda2-35ae38259a07" } }, "output_type": "execute_result" } ], "source": [ "lon, lat = grd.lon |> ustrip, grd.lat |> ustrip\n", "function horizontal_slice(x, levels, title)\n", " x_3D = fill(NaN, size(grd))\n", " x_3D[iwet] .= x .|> ustrip\n", " GR.figure(figsize=(10,5))\n", " @manipulate for iz in 1:size(grd)[3]\n", " GR.xlim([0,360])\n", " GR.title(string(title, \" at $(AIBECS.round(grd.depth[iz])) depth\"))\n", " GR.contourf(lon, lat, x_3D[:,:,iz]', levels=levels)\n", " end\n", "end \n", "horizontal_slice(C14age, 0:100:2400, \"14C age [yr] using the OCIM1 circulation\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Or zonal slices:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "scrolled": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "application/vnd.webio.node+json": { "children": [ { "children": [ { "children": [ { "children": [ { "children": [ { "children": [ "longitude" ], "instanceArgs": { "namespace": "html", "tag": "label" }, "nodeType": "DOM", "props": { "className": "interact ", "style": { "padding": "5px 10px 0px 10px" } }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-left" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "input" }, "nodeType": "DOM", "props": { "attributes": { "data-bind": "numericValue: index, valueUpdate: 'input', event: {change: function (){this.changes(this.changes()+1)}}", "orient": "horizontal", "type": "range" }, "className": "slider slider is-fullwidth", "max": 180, "min": 1, "step": 1, "style": {} }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-center" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "p" }, "nodeType": "DOM", "props": { "attributes": { "data-bind": "text: formatted_val" } }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-right" }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row interact-widget" }, "type": "node" } ], "instanceArgs": { "handlers": { "changes": [ "(function (val){return (val!=this.model[\"changes\"]()) ? (this.valueFromJulia[\"changes\"]=true, this.model[\"changes\"](val)) : undefined})" ], "index": [ "(function (val){return (val!=this.model[\"index\"]()) ? (this.valueFromJulia[\"index\"]=true, this.model[\"index\"](val)) : undefined})" ] }, "id": "2681015493213083999", "imports": { "data": [ { "name": "knockout", "type": "js", "url": "/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js" }, { "name": "knockout_punches", "type": "js", "url": "/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js" }, { "name": null, "type": "js", "url": "/assetserver/9cda67a60395433f45d7dd64448e9983594c3d89-all.js" }, { "name": null, "type": "css", "url": "/assetserver/f8657a57be3c3d9bd1b603ffa11049f3a1b07340-style.css" }, { "name": null, "type": "css", "url": "/assetserver/ce4e0a8b544aa8c325b955acaffb5afe8945d9a5-bulma_confined.min.css" } ], "type": "async_block" }, "mount_callbacks": [ "function () {\n var handler = (function (ko, koPunches) {\n ko.punches.enableAll();\n ko.bindingHandlers.numericValue = {\n init: function(element, valueAccessor, allBindings, data, context) {\n var stringified = ko.observable(ko.unwrap(valueAccessor()));\n stringified.subscribe(function(value) {\n var val = parseFloat(value);\n if (!isNaN(val)) {\n valueAccessor()(val);\n }\n });\n valueAccessor().subscribe(function(value) {\n var str = JSON.stringify(value);\n if ((str == \"0\") && ([\"-0\", \"-0.\"].indexOf(stringified()) >= 0))\n return;\n if ([\"null\", \"\"].indexOf(str) >= 0)\n return;\n stringified(str);\n });\n ko.applyBindingsToNode(\n element,\n {\n value: stringified,\n valueUpdate: allBindings.get('valueUpdate'),\n },\n context,\n );\n }\n };\n var json_data = {\"formatted_vals\":[\"1.0\",\"3.0\",\"5.0\",\"7.0\",\"9.0\",\"11.0\",\"13.0\",\"15.0\",\"17.0\",\"19.0\",\"21.0\",\"23.0\",\"25.0\",\"27.0\",\"29.0\",\"31.0\",\"33.0\",\"35.0\",\"37.0\",\"39.0\",\"41.0\",\"43.0\",\"45.0\",\"47.0\",\"49.0\",\"51.0\",\"53.0\",\"55.0\",\"57.0\",\"59.0\",\"61.0\",\"63.0\",\"65.0\",\"67.0\",\"69.0\",\"71.0\",\"73.0\",\"75.0\",\"77.0\",\"79.0\",\"81.0\",\"83.0\",\"85.0\",\"87.0\",\"89.0\",\"91.0\",\"93.0\",\"95.0\",\"97.0\",\"99.0\",\"101.0\",\"103.0\",\"105.0\",\"107.0\",\"109.0\",\"111.0\",\"113.0\",\"115.0\",\"117.0\",\"119.0\",\"121.0\",\"123.0\",\"125.0\",\"127.0\",\"129.0\",\"131.0\",\"133.0\",\"135.0\",\"137.0\",\"139.0\",\"141.0\",\"143.0\",\"145.0\",\"147.0\",\"149.0\",\"151.0\",\"153.0\",\"155.0\",\"157.0\",\"159.0\",\"161.0\",\"163.0\",\"165.0\",\"167.0\",\"169.0\",\"171.0\",\"173.0\",\"175.0\",\"177.0\",\"179.0\",\"181.0\",\"183.0\",\"185.0\",\"187.0\",\"189.0\",\"191.0\",\"193.0\",\"195.0\",\"197.0\",\"199.0\",\"201.0\",\"203.0\",\"205.0\",\"207.0\",\"209.0\",\"211.0\",\"213.0\",\"215.0\",\"217.0\",\"219.0\",\"221.0\",\"223.0\",\"225.0\",\"227.0\",\"229.0\",\"231.0\",\"233.0\",\"235.0\",\"237.0\",\"239.0\",\"241.0\",\"243.0\",\"245.0\",\"247.0\",\"249.0\",\"251.0\",\"253.0\",\"255.0\",\"257.0\",\"259.0\",\"261.0\",\"263.0\",\"265.0\",\"267.0\",\"269.0\",\"271.0\",\"273.0\",\"275.0\",\"277.0\",\"279.0\",\"281.0\",\"283.0\",\"285.0\",\"287.0\",\"289.0\",\"291.0\",\"293.0\",\"295.0\",\"297.0\",\"299.0\",\"301.0\",\"303.0\",\"305.0\",\"307.0\",\"309.0\",\"311.0\",\"313.0\",\"315.0\",\"317.0\",\"319.0\",\"321.0\",\"323.0\",\"325.0\",\"327.0\",\"329.0\",\"331.0\",\"333.0\",\"335.0\",\"337.0\",\"339.0\",\"341.0\",\"343.0\",\"345.0\",\"347.0\",\"349.0\",\"351.0\",\"353.0\",\"355.0\",\"357.0\",\"359.0\"],\"changes\":WebIO.getval({\"name\":\"changes\",\"scope\":\"2681015493213083999\",\"id\":\"ob_11\",\"type\":\"observable\"}),\"index\":WebIO.getval({\"name\":\"index\",\"scope\":\"2681015493213083999\",\"id\":\"ob_10\",\"type\":\"observable\"})};\n var self = this;\n function AppViewModel() {\n for (var key in json_data) {\n var el = json_data[key];\n this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);\n }\n \n [this[\"formatted_val\"]=ko.computed( function(){\n return this.formatted_vals()[parseInt(this.index())-(1)];\n }\n,this)]\n [this[\"changes\"].subscribe((function (val){!(this.valueFromJulia[\"changes\"]) ? (WebIO.setval({\"name\":\"changes\",\"scope\":\"2681015493213083999\",\"id\":\"ob_11\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"changes\"]=false}),self),this[\"index\"].subscribe((function (val){!(this.valueFromJulia[\"index\"]) ? (WebIO.setval({\"name\":\"index\",\"scope\":\"2681015493213083999\",\"id\":\"ob_10\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"index\"]=false}),self)]\n \n }\n self.model = new AppViewModel();\n self.valueFromJulia = {};\n for (var key in json_data) {\n self.valueFromJulia[key] = false;\n }\n ko.applyBindings(self.model, self.dom);\n}\n);\n (WebIO.importBlock({\"data\":[{\"name\":\"knockout\",\"type\":\"js\",\"url\":\"/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js\"},{\"name\":\"knockout_punches\",\"type\":\"js\",\"url\":\"/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js\"}],\"type\":\"async_block\"})).then((imports) => handler.apply(this, imports));\n}\n" ], "observables": { "changes": { "id": "ob_11", "sync": false, "value": 0 }, "index": { "id": "ob_10", "sync": true, "value": 90 } }, "systemjs_options": null }, "nodeType": "Scope", "props": {}, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "field interact-widget" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "id": "ob_17", "name": "obs-node" }, "nodeType": "ObservableNode", "props": {}, "type": "node" } ], "instanceArgs": { "handlers": {}, "id": "5584032433778856578", "imports": { "data": [], "type": "async_block" }, "mount_callbacks": [], "observables": { "obs-node": { "id": "ob_17", "sync": false, "value": { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "setInnerHtml": "\n\n\n \n \n \n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n-\n\n\n6000\n\n\n-\n\n\n4000\n\n\n-\n\n\n2000\n\n\n0\n\n\n\n-\n\n\n50\n\n\n0\n\n\n50\n\n\n\n\n\n14C age [yr] using the OCIM1 circulation at 179.0°\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n\n\n\n\n\n500\n\n\n750\n\n\n1000\n\n\n1250\n\n\n1500\n\n\n1750\n\n\n2000\n\n\n2250\n\n\n\n" }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row interact-widget" }, "type": "node" } } }, "systemjs_options": null }, "nodeType": "Scope", "props": {}, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": {}, "type": "node" }, "text/html": [ "\n", " \n", "\n" ], "text/plain": [ "Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Scope(Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :label), Any[\"longitude\"], Dict{Symbol,Any}(:className => \"interact \",:style => Dict{Any,Any}(:padding => \"5px 10px 0px 10px\")))], Dict{Symbol,Any}(:className => \"interact-flex-row-left\")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :input), Any[], Dict{Symbol,Any}(:max => 180,:min => 1,:attributes => Dict{Any,Any}(:type => \"range\",Symbol(\"data-bind\") => \"numericValue: index, valueUpdate: 'input', event: {change: function (){this.changes(this.changes()+1)}}\",\"orient\" => \"horizontal\"),:step => 1,:className => \"slider slider is-fullwidth\",:style => Dict{Any,Any}()))], Dict{Symbol,Any}(:className => \"interact-flex-row-center\")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :p), Any[], Dict{Symbol,Any}(:attributes => Dict(\"data-bind\" => \"text: formatted_val\")))], Dict{Symbol,Any}(:className => \"interact-flex-row-right\"))], Dict{Symbol,Any}(:className => \"interact-flex-row interact-widget\")), Dict{String,Tuple{Observables.AbstractObservable,Union{Nothing, Bool}}}(\"changes\" => (Observable{Int64} with 1 listeners. Value:\n", "0, nothing),\"index\" => (Observable{Any} with 2 listeners. Value:\n", "90, nothing)), Set(String[]), nothing, Asset[Asset(\"js\", \"knockout\", \"/Users/benoitpasquier/.julia/packages/Knockout/1sDlc/src/../assets/knockout.js\"), Asset(\"js\", \"knockout_punches\", \"/Users/benoitpasquier/.julia/packages/Knockout/1sDlc/src/../assets/knockout_punches.js\"), Asset(\"js\", nothing, \"/Users/benoitpasquier/.julia/packages/InteractBase/9mFwe/src/../assets/all.js\"), Asset(\"css\", nothing, \"/Users/benoitpasquier/.julia/packages/InteractBase/9mFwe/src/../assets/style.css\"), Asset(\"css\", nothing, \"/Users/benoitpasquier/.julia/packages/Interact/0klKX/src/../assets/bulma_confined.min.css\")], Dict{Any,Any}(\"changes\" => Any[WebIO.JSString(\"(function (val){return (val!=this.model[\\\"changes\\\"]()) ? (this.valueFromJulia[\\\"changes\\\"]=true, this.model[\\\"changes\\\"](val)) : undefined})\")],\"index\" => Any[WebIO.JSString(\"(function (val){return (val!=this.model[\\\"index\\\"]()) ? (this.valueFromJulia[\\\"index\\\"]=true, this.model[\\\"index\\\"](val)) : undefined})\")]), WebIO.ConnectionPool(Channel{Any}(sz_max:32,sz_curr:0), Set(AbstractConnection[]), Channel{AbstractConnection}(sz_max:32,sz_curr:0)), WebIO.JSString[WebIO.JSString(\"function () {\\n var handler = (function (ko, koPunches) {\\n ko.punches.enableAll();\\n ko.bindingHandlers.numericValue = {\\n init: function(element, valueAccessor, allBindings, data, context) {\\n var stringified = ko.observable(ko.unwrap(valueAccessor()));\\n stringified.subscribe(function(value) {\\n var val = parseFloat(value);\\n if (!isNaN(val)) {\\n valueAccessor()(val);\\n }\\n });\\n valueAccessor().subscribe(function(value) {\\n var str = JSON.stringify(value);\\n if ((str == \\\"0\\\") && ([\\\"-0\\\", \\\"-0.\\\"].indexOf(stringified()) >= 0))\\n return;\\n if ([\\\"null\\\", \\\"\\\"].indexOf(str) >= 0)\\n return;\\n stringified(str);\\n });\\n ko.applyBindingsToNode(\\n element,\\n {\\n value: stringified,\\n valueUpdate: allBindings.get('valueUpdate'),\\n },\\n context,\\n );\\n }\\n };\\n var json_data = {\\\"formatted_vals\\\":[\\\"1.0\\\",\\\"3.0\\\",\\\"5.0\\\",\\\"7.0\\\",\\\"9.0\\\",\\\"11.0\\\",\\\"13.0\\\",\\\"15.0\\\",\\\"17.0\\\",\\\"19.0\\\",\\\"21.0\\\",\\\"23.0\\\",\\\"25.0\\\",\\\"27.0\\\",\\\"29.0\\\",\\\"31.0\\\",\\\"33.0\\\",\\\"35.0\\\",\\\"37.0\\\",\\\"39.0\\\",\\\"41.0\\\",\\\"43.0\\\",\\\"45.0\\\",\\\"47.0\\\",\\\"49.0\\\",\\\"51.0\\\",\\\"53.0\\\",\\\"55.0\\\",\\\"57.0\\\",\\\"59.0\\\",\\\"61.0\\\",\\\"63.0\\\",\\\"65.0\\\",\\\"67.0\\\",\\\"69.0\\\",\\\"71.0\\\",\\\"73.0\\\",\\\"75.0\\\",\\\"77.0\\\",\\\"79.0\\\",\\\"81.0\\\",\\\"83.0\\\",\\\"85.0\\\",\\\"87.0\\\",\\\"89.0\\\",\\\"91.0\\\",\\\"93.0\\\",\\\"95.0\\\",\\\"97.0\\\",\\\"99.0\\\",\\\"101.0\\\",\\\"103.0\\\",\\\"105.0\\\",\\\"107.0\\\",\\\"109.0\\\",\\\"111.0\\\",\\\"113.0\\\",\\\"115.0\\\",\\\"117.0\\\",\\\"119.0\\\",\\\"121.0\\\",\\\"123.0\\\",\\\"125.0\\\",\\\"127.0\\\",\\\"129.0\\\",\\\"131.0\\\",\\\"133.0\\\",\\\"135.0\\\",\\\"137.0\\\",\\\"139.0\\\",\\\"141.0\\\",\\\"143.0\\\",\\\"145.0\\\",\\\"147.0\\\",\\\"149.0\\\",\\\"151.0\\\",\\\"153.0\\\",\\\"155.0\\\",\\\"157.0\\\",\\\"159.0\\\",\\\"161.0\\\",\\\"163.0\\\",\\\"165.0\\\",\\\"167.0\\\",\\\"169.0\\\",\\\"171.0\\\",\\\"173.0\\\",\\\"175.0\\\",\\\"177.0\\\",\\\"179.0\\\",\\\"181.0\\\",\\\"183.0\\\",\\\"185.0\\\",\\\"187.0\\\",\\\"189.0\\\",\\\"191.0\\\",\\\"193.0\\\",\\\"195.0\\\",\\\"197.0\\\",\\\"199.0\\\",\\\"201.0\\\",\\\"203.0\\\",\\\"205.0\\\",\\\"207.0\\\",\\\"209.0\\\",\\\"211.0\\\",\\\"213.0\\\",\\\"215.0\\\",\\\"217.0\\\",\\\"219.0\\\",\\\"221.0\\\",\\\"223.0\\\",\\\"225.0\\\",\\\"227.0\\\",\\\"229.0\\\",\\\"231.0\\\",\\\"233.0\\\",\\\"235.0\\\",\\\"237.0\\\",\\\"239.0\\\",\\\"241.0\\\",\\\"243.0\\\",\\\"245.0\\\",\\\"247.0\\\",\\\"249.0\\\",\\\"251.0\\\",\\\"253.0\\\",\\\"255.0\\\",\\\"257.0\\\",\\\"259.0\\\",\\\"261.0\\\",\\\"263.0\\\",\\\"265.0\\\",\\\"267.0\\\",\\\"269.0\\\",\\\"271.0\\\",\\\"273.0\\\",\\\"275.0\\\",\\\"277.0\\\",\\\"279.0\\\",\\\"281.0\\\",\\\"283.0\\\",\\\"285.0\\\",\\\"287.0\\\",\\\"289.0\\\",\\\"291.0\\\",\\\"293.0\\\",\\\"295.0\\\",\\\"297.0\\\",\\\"299.0\\\",\\\"301.0\\\",\\\"303.0\\\",\\\"305.0\\\",\\\"307.0\\\",\\\"309.0\\\",\\\"311.0\\\",\\\"313.0\\\",\\\"315.0\\\",\\\"317.0\\\",\\\"319.0\\\",\\\"321.0\\\",\\\"323.0\\\",\\\"325.0\\\",\\\"327.0\\\",\\\"329.0\\\",\\\"331.0\\\",\\\"333.0\\\",\\\"335.0\\\",\\\"337.0\\\",\\\"339.0\\\",\\\"341.0\\\",\\\"343.0\\\",\\\"345.0\\\",\\\"347.0\\\",\\\"349.0\\\",\\\"351.0\\\",\\\"353.0\\\",\\\"355.0\\\",\\\"357.0\\\",\\\"359.0\\\"],\\\"changes\\\":WebIO.getval({\\\"name\\\":\\\"changes\\\",\\\"scope\\\":\\\"2681015493213083999\\\",\\\"id\\\":\\\"ob_11\\\",\\\"type\\\":\\\"observable\\\"}),\\\"index\\\":WebIO.getval({\\\"name\\\":\\\"index\\\",\\\"scope\\\":\\\"2681015493213083999\\\",\\\"id\\\":\\\"ob_10\\\",\\\"type\\\":\\\"observable\\\"})};\\n var self = this;\\n function AppViewModel() {\\n for (var key in json_data) {\\n var el = json_data[key];\\n this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);\\n }\\n \\n [this[\\\"formatted_val\\\"]=ko.computed( function(){\\n return this.formatted_vals()[parseInt(this.index())-(1)];\\n }\\n,this)]\\n [this[\\\"changes\\\"].subscribe((function (val){!(this.valueFromJulia[\\\"changes\\\"]) ? (WebIO.setval({\\\"name\\\":\\\"changes\\\",\\\"scope\\\":\\\"2681015493213083999\\\",\\\"id\\\":\\\"ob_11\\\",\\\"type\\\":\\\"observable\\\"},val)) : undefined; return this.valueFromJulia[\\\"changes\\\"]=false}),self),this[\\\"index\\\"].subscribe((function (val){!(this.valueFromJulia[\\\"index\\\"]) ? (WebIO.setval({\\\"name\\\":\\\"index\\\",\\\"scope\\\":\\\"2681015493213083999\\\",\\\"id\\\":\\\"ob_10\\\",\\\"type\\\":\\\"observable\\\"},val)) : undefined; return this.valueFromJulia[\\\"index\\\"]=false}),self)]\\n \\n }\\n self.model = new AppViewModel();\\n self.valueFromJulia = {};\\n for (var key in json_data) {\\n self.valueFromJulia[key] = false;\\n }\\n ko.applyBindings(self.model, self.dom);\\n}\\n);\\n (WebIO.importBlock({\\\"data\\\":[{\\\"name\\\":\\\"knockout\\\",\\\"type\\\":\\\"js\\\",\\\"url\\\":\\\"/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js\\\"},{\\\"name\\\":\\\"knockout_punches\\\",\\\"type\\\":\\\"js\\\",\\\"url\\\":\\\"/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js\\\"}],\\\"type\\\":\\\"async_block\\\"})).then((imports) => handler.apply(this, imports));\\n}\\n\")])], Dict{Symbol,Any}(:className => \"field interact-widget\")), Observable{Any} with 0 listeners. Value:\n", "Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[GR.SVG(UInt8[0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73 … 0x2f, 0x3e, 0x0a, 0x3c, 0x2f, 0x73, 0x76, 0x67, 0x3e, 0x0a])], Dict{Symbol,Any}(:className => \"interact-flex-row interact-widget\"))], Dict{Symbol,Any}())" ] }, "execution_count": 30, "metadata": { "application/vnd.webio.node+json": { "kernelId": "51aa8b2d-fd5a-4d9f-bda2-35ae38259a07" } }, "output_type": "execute_result" } ], "source": [ "function zonal_slice(x, levels, title)\n", " x_3D = fill(NaN, size(grd))\n", " x_3D[iwet] .= x .|> ustrip\n", " GR.figure(figsize=(10,5))\n", " @manipulate for longitude in (grd.lon .|> ustrip)\n", " GR.title(string(title, \" at $(round(longitude))°\"))\n", " ilon = findfirst(ustrip.(grd.lon) .== longitude)\n", " GR.contourf(lat, reverse(-grd.depth .|> ustrip), reverse(x_3D[:,ilon,:], dims=2), levels=levels)\n", " end\n", "end \n", "zonal_slice(C14age, 0:100:2400, \"14C age [yr] using the OCIM1 circulation\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "\n", "\n", "

Example 2: A phosphorus cycle

\n", "\n", "Dissolved inorganic phosphrous (**DIP**)
\n", "(transported by the **ocean circulation**)\n", "\n", "$$\\left[\\frac{\\partial}{\\partial t} + \\color{RoyalBlue}{\\nabla \\cdot (\\boldsymbol{u} + \\mathbf{K}\\cdot\\nabla )}\\right] x_\\mathsf{DIP} = \\color{forestgreen}{-U(x_\\mathsf{DIP}) + R(x_\\mathsf{POP})},$$\n", "\n", "and particulate organic phosphrous (**POP**)
\n", "(transported by **sinking particles**)\n", "\n", "\n", "$$\\left[\\frac{\\partial}{\\partial t} + \\color{DarkOrchid}{\\nabla \\cdot \\boldsymbol{w}}\\right] x_\\mathsf{POP} = \\color{forestgreen}{U(x_\\mathsf{DIP}) - R(x_\\mathsf{POP})}.$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Ocean circulation\n", "\n", "For DIP, the **advective–eddy-diffusive transport** operator, $\\nabla \\cdot (\\boldsymbol{u} + \\mathbf{K}\\cdot\\nabla)$, is converted into the matrix `T`:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "T_DIP (generic function with 1 method)" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "T_DIP(p) = T" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Sinking particles\n", "\n", "For POP, the **particle flux divergence (PFD)** operator, $\\nabla \\cdot \\boldsymbol{w}$, is created via `buildPFD`:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "T_POP (generic function with 1 method)" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "T_POP(p) = buildPFD(grd, wet3D, sinking_speed = w(p))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The settling velocity, `w(p)`, is assumed linearly increasing with depth `z` to yield a \"Martin curve profile\"" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "w (generic function with 1 method)" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w(p) = p.w₀ .+ p.w′ * (z .|> ustrip)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Local sources and sinks\n", "\n", "### Uptake:\n", "$$\\frac{1}{τ} \\, \\frac{\\boldsymbol{x}_\\mathrm{DIP}^2}{\\boldsymbol{x}_\\mathrm{DIP} + k}$$" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "uptake (generic function with 1 method)" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "relu(x) = (x .≥ 0) .* x\n", "zₑ = 80u\"m\" # depth of the euphotic zone\n", "function uptake(DIP, p)\n", " τ, k = p.τ, p.k\n", " DIP⁺ = relu(DIP)\n", " return 1/τ * DIP⁺.^2 ./ (DIP⁺ .+ k) .* (z .≤ zₑ)\n", "end" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Local sources and sinks\n", "\n", "### Remineralization:\n", "$$\\kappa \\, \\boldsymbol{x}_\\mathrm{POP}$$" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "remineralization (generic function with 1 method)" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "remineralization(POP, p) = p.κ * POP" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Local sources and sinks\n", "\n", "### \"Geological\" restoring\n", "$$\\frac{x_\\mathrm{geo} - \\boldsymbol{x}_\\mathrm{DIP}}{\\tau_\\mathrm{geo}}$$" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "geores (generic function with 1 method)" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "geores(x, p) = (p.xgeo .- x) / p.τgeo" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Local sources and sinks\n", "\n", "### Net sum of local sources and sinks" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "G_POP (generic function with 1 method)" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "G_DIP(DIP, POP, p) = -uptake(DIP, p) + remineralization(POP, p) + geores(DIP, p)\n", "G_POP(DIP, POP, p) = uptake(DIP, p) - remineralization(POP, p)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Parameters" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ " xgeo = 2.12e+00 [mmol m⁻³] (fixed)\n", " τgeo = 1.00e+00 [Myr] (fixed)\n", " k = 6.62e+00 [μmol m⁻³] (fixed)\n", " w₀ = 6.40e-01 [m d⁻¹] (fixed)\n", " w′ = 1.30e-01 [d⁻¹] (fixed)\n", " κ = 1.90e-01 [d⁻¹] (fixed)\n", " τ = 2.37e+02 [d] (fixed)\n" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" }, { "name": "stdout", "output_type": "stream", "text": [ "Pcycle_Parameters{Float64}\n" ] } ], "source": [ "t = empty_parameter_table() # empty table of parameters\n", "add_parameter!(t, :xgeo, 2.12u\"mmol/m^3\")\n", "add_parameter!(t, :τgeo, 1.0u\"Myr\")\n", "add_parameter!(t, :k, 6.62u\"μmol/m^3\")\n", "add_parameter!(t, :w₀, 0.64u\"m/d\")\n", "add_parameter!(t, :w′, 0.13u\"1/d\")\n", "add_parameter!(t, :κ, 0.19u\"1/d\")\n", "add_parameter!(t, :τ, 236.52u\"d\")\n", "initialize_Parameters_type(t, \"Pcycle_Parameters\") # Generate the parameter type\n", "p = Pcycle_Parameters()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# State function `F` and Jacobian `∇ₓF`" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "nb = length(iwet); x = ones(2nb)\n", "F, ∇ₓF = state_function_and_Jacobian((T_DIP,T_POP), (G_DIP,G_POP), nb) ;" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Solve the steady-state PDE system" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " (No initial Jacobian factors fed to Newton solver)\n", " Solving F(x) = 0 (using Shamanskii Method)\n", " │ iteration |F(x)| |δx|/|x| Jac age fac age\n", " │ 0 2.1e-03 \n", " │ 1 2.2e-11 1.0e+00 1 1 \n", " │ 2 1.9e-12 8.8e-05 2 2 \n", " │ 3 1.7e-13 5.9e-06 3 3 \n", " │ 4 1.5e-14 5.1e-07 4 4 \n", " │ 5 1.3e-15 4.5e-08 5 5 \n", " │ 6 1.1e-16 4.0e-09 6 6 \n", " │ 7 1.0e-17 3.6e-10 7 7 \n", " │ 8 9.0e-19 6.8e-11 8 8 \n", " │ 9 8.0e-20 5.2e-11 9 9 \n", " │ 10 1.1e-20 5.0e-11 10 10 \n", " └─> Newton has converged, |x|/|F(x)| = 2.5e+12 years\n" ] }, { "data": { "text/plain": [ "400320-element Array{Float64,1}:\n", " 0.0022918000192886324 \n", " 0.0023267961203066413 \n", " 0.002373480474578215 \n", " 0.0023047338516968365 \n", " 0.0018232975200373914 \n", " 0.0016642494463875827 \n", " 0.0017612887179033342 \n", " 0.0017580441188026054 \n", " 0.001631759348036656 \n", " 0.0014767294266503604 \n", " 0.0014783166429935737 \n", " 0.001510846182421843 \n", " 0.0014186135299064067 \n", " ⋮ \n", " 4.0121274622784796e-10\n", " 4.312519406197485e-10 \n", " 4.0670957850582036e-10\n", " 3.675952790855922e-10 \n", " 5.806135369242001e-10 \n", " 4.088319981202587e-10 \n", " 3.655906483028011e-10 \n", " 3.9472816882018806e-10\n", " 5.575236548656968e-10 \n", " 3.9112467323640526e-10\n", " 4.139874086701334e-10 \n", " 4.826616419366957e-10 " ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "prob = SteadyStateProblem(F, ∇ₓF, x, p)\n", "s = solve(prob, CTKAlg(), preprint=\" \").u" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Plot DIP" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "application/vnd.webio.node+json": { "children": [ { "children": [ { "children": [ { "children": [ { "children": [ { "children": [ "iz" ], "instanceArgs": { "namespace": "html", "tag": "label" }, "nodeType": "DOM", "props": { "className": "interact ", "style": { "padding": "5px 10px 0px 10px" } }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-left" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "input" }, "nodeType": "DOM", "props": { "attributes": { "data-bind": "numericValue: index, valueUpdate: 'input', event: {change: function (){this.changes(this.changes()+1)}}", "orient": "horizontal", "type": "range" }, "className": "slider slider is-fullwidth", "max": 24, "min": 1, "step": 1, "style": {} }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-center" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "p" }, "nodeType": "DOM", "props": { "attributes": { "data-bind": "text: formatted_val" } }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-right" }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row interact-widget" }, "type": "node" } ], "instanceArgs": { "handlers": { "changes": [ "(function (val){return (val!=this.model[\"changes\"]()) ? (this.valueFromJulia[\"changes\"]=true, this.model[\"changes\"](val)) : undefined})" ], "index": [ "(function (val){return (val!=this.model[\"index\"]()) ? (this.valueFromJulia[\"index\"]=true, this.model[\"index\"](val)) : undefined})" ] }, "id": "15379295305187333299", "imports": { "data": [ { "name": "knockout", "type": "js", "url": "/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js" }, { "name": "knockout_punches", "type": "js", "url": "/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js" }, { "name": null, "type": "js", "url": "/assetserver/9cda67a60395433f45d7dd64448e9983594c3d89-all.js" }, { "name": null, "type": "css", "url": "/assetserver/f8657a57be3c3d9bd1b603ffa11049f3a1b07340-style.css" }, { "name": null, "type": "css", "url": "/assetserver/ce4e0a8b544aa8c325b955acaffb5afe8945d9a5-bulma_confined.min.css" } ], "type": "async_block" }, "mount_callbacks": [ "function () {\n var handler = (function (ko, koPunches) {\n ko.punches.enableAll();\n ko.bindingHandlers.numericValue = {\n init: function(element, valueAccessor, allBindings, data, context) {\n var stringified = ko.observable(ko.unwrap(valueAccessor()));\n stringified.subscribe(function(value) {\n var val = parseFloat(value);\n if (!isNaN(val)) {\n valueAccessor()(val);\n }\n });\n valueAccessor().subscribe(function(value) {\n var str = JSON.stringify(value);\n if ((str == \"0\") && ([\"-0\", \"-0.\"].indexOf(stringified()) >= 0))\n return;\n if ([\"null\", \"\"].indexOf(str) >= 0)\n return;\n stringified(str);\n });\n ko.applyBindingsToNode(\n element,\n {\n value: stringified,\n valueUpdate: allBindings.get('valueUpdate'),\n },\n context,\n );\n }\n };\n var json_data = {\"formatted_vals\":[\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"10\",\"11\",\"12\",\"13\",\"14\",\"15\",\"16\",\"17\",\"18\",\"19\",\"20\",\"21\",\"22\",\"23\",\"24\"],\"changes\":WebIO.getval({\"name\":\"changes\",\"scope\":\"15379295305187333299\",\"id\":\"ob_19\",\"type\":\"observable\"}),\"index\":WebIO.getval({\"name\":\"index\",\"scope\":\"15379295305187333299\",\"id\":\"ob_18\",\"type\":\"observable\"})};\n var self = this;\n function AppViewModel() {\n for (var key in json_data) {\n var el = json_data[key];\n this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);\n }\n \n [this[\"formatted_val\"]=ko.computed( function(){\n return this.formatted_vals()[parseInt(this.index())-(1)];\n }\n,this)]\n [this[\"changes\"].subscribe((function (val){!(this.valueFromJulia[\"changes\"]) ? (WebIO.setval({\"name\":\"changes\",\"scope\":\"15379295305187333299\",\"id\":\"ob_19\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"changes\"]=false}),self),this[\"index\"].subscribe((function (val){!(this.valueFromJulia[\"index\"]) ? (WebIO.setval({\"name\":\"index\",\"scope\":\"15379295305187333299\",\"id\":\"ob_18\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"index\"]=false}),self)]\n \n }\n self.model = new AppViewModel();\n self.valueFromJulia = {};\n for (var key in json_data) {\n self.valueFromJulia[key] = false;\n }\n ko.applyBindings(self.model, self.dom);\n}\n);\n (WebIO.importBlock({\"data\":[{\"name\":\"knockout\",\"type\":\"js\",\"url\":\"/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js\"},{\"name\":\"knockout_punches\",\"type\":\"js\",\"url\":\"/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js\"}],\"type\":\"async_block\"})).then((imports) => handler.apply(this, imports));\n}\n" ], "observables": { "changes": { "id": "ob_19", "sync": false, "value": 0 }, "index": { "id": "ob_18", "sync": true, "value": 12 } }, "systemjs_options": null }, "nodeType": "Scope", "props": {}, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "field interact-widget" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "id": "ob_25", "name": "obs-node" }, "nodeType": "ObservableNode", "props": {}, "type": "node" } ], "instanceArgs": { "handlers": {}, "id": "8210707465404437370", "imports": { "data": [], "type": "async_block" }, "mount_callbacks": [], "observables": { "obs-node": { "id": "ob_25", "sync": false, "value": { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "setInnerHtml": "\n\n\n \n \n \n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n-\n\n\n50\n\n\n0\n\n\n50\n\n\n\n0\n\n\n100\n\n\n200\n\n\n300\n\n\n\n\n\nP\n\n\ncycle model: DIP [mmol m\n\n\n-\n\n\n3\n\n\n-\n\n\n] at 919.0 m depth\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n\n\n\n\n\n0.5\n\n\n1.0\n\n\n1.5\n\n\n2.0\n\n\n2.5\n\n\n3.0\n\n\n3.5\n\n\n4.0\n\n\n4.5\n\n\n\n" }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row interact-widget" }, "type": "node" } } }, "systemjs_options": null }, "nodeType": "Scope", "props": {}, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": {}, "type": "node" }, "text/html": [ "\n", " \n", "\n" ], "text/plain": [ "Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Scope(Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :label), Any[\"iz\"], Dict{Symbol,Any}(:className => \"interact \",:style => Dict{Any,Any}(:padding => \"5px 10px 0px 10px\")))], Dict{Symbol,Any}(:className => \"interact-flex-row-left\")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :input), Any[], Dict{Symbol,Any}(:max => 24,:min => 1,:attributes => Dict{Any,Any}(:type => \"range\",Symbol(\"data-bind\") => \"numericValue: index, valueUpdate: 'input', event: {change: function (){this.changes(this.changes()+1)}}\",\"orient\" => \"horizontal\"),:step => 1,:className => \"slider slider is-fullwidth\",:style => Dict{Any,Any}()))], Dict{Symbol,Any}(:className => \"interact-flex-row-center\")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :p), Any[], Dict{Symbol,Any}(:attributes => Dict(\"data-bind\" => \"text: formatted_val\")))], Dict{Symbol,Any}(:className => \"interact-flex-row-right\"))], Dict{Symbol,Any}(:className => \"interact-flex-row interact-widget\")), Dict{String,Tuple{Observables.AbstractObservable,Union{Nothing, Bool}}}(\"changes\" => (Observable{Int64} with 1 listeners. Value:\n", "0, nothing),\"index\" => (Observable{Int64} with 2 listeners. Value:\n", "12, nothing)), Set(String[]), nothing, Asset[Asset(\"js\", \"knockout\", \"/Users/benoitpasquier/.julia/packages/Knockout/1sDlc/src/../assets/knockout.js\"), Asset(\"js\", \"knockout_punches\", \"/Users/benoitpasquier/.julia/packages/Knockout/1sDlc/src/../assets/knockout_punches.js\"), Asset(\"js\", nothing, \"/Users/benoitpasquier/.julia/packages/InteractBase/9mFwe/src/../assets/all.js\"), Asset(\"css\", nothing, \"/Users/benoitpasquier/.julia/packages/InteractBase/9mFwe/src/../assets/style.css\"), Asset(\"css\", nothing, \"/Users/benoitpasquier/.julia/packages/Interact/0klKX/src/../assets/bulma_confined.min.css\")], Dict{Any,Any}(\"changes\" => Any[WebIO.JSString(\"(function (val){return (val!=this.model[\\\"changes\\\"]()) ? (this.valueFromJulia[\\\"changes\\\"]=true, this.model[\\\"changes\\\"](val)) : undefined})\")],\"index\" => Any[WebIO.JSString(\"(function (val){return (val!=this.model[\\\"index\\\"]()) ? (this.valueFromJulia[\\\"index\\\"]=true, this.model[\\\"index\\\"](val)) : undefined})\")]), WebIO.ConnectionPool(Channel{Any}(sz_max:32,sz_curr:0), Set(AbstractConnection[]), Channel{AbstractConnection}(sz_max:32,sz_curr:0)), WebIO.JSString[WebIO.JSString(\"function () {\\n var handler = (function (ko, koPunches) {\\n ko.punches.enableAll();\\n ko.bindingHandlers.numericValue = {\\n init: function(element, valueAccessor, allBindings, data, context) {\\n var stringified = ko.observable(ko.unwrap(valueAccessor()));\\n stringified.subscribe(function(value) {\\n var val = parseFloat(value);\\n if (!isNaN(val)) {\\n valueAccessor()(val);\\n }\\n });\\n valueAccessor().subscribe(function(value) {\\n var str = JSON.stringify(value);\\n if ((str == \\\"0\\\") && ([\\\"-0\\\", \\\"-0.\\\"].indexOf(stringified()) >= 0))\\n return;\\n if ([\\\"null\\\", \\\"\\\"].indexOf(str) >= 0)\\n return;\\n stringified(str);\\n });\\n ko.applyBindingsToNode(\\n element,\\n {\\n value: stringified,\\n valueUpdate: allBindings.get('valueUpdate'),\\n },\\n context,\\n );\\n }\\n };\\n var json_data = {\\\"formatted_vals\\\":[\\\"1\\\",\\\"2\\\",\\\"3\\\",\\\"4\\\",\\\"5\\\",\\\"6\\\",\\\"7\\\",\\\"8\\\",\\\"9\\\",\\\"10\\\",\\\"11\\\",\\\"12\\\",\\\"13\\\",\\\"14\\\",\\\"15\\\",\\\"16\\\",\\\"17\\\",\\\"18\\\",\\\"19\\\",\\\"20\\\",\\\"21\\\",\\\"22\\\",\\\"23\\\",\\\"24\\\"],\\\"changes\\\":WebIO.getval({\\\"name\\\":\\\"changes\\\",\\\"scope\\\":\\\"15379295305187333299\\\",\\\"id\\\":\\\"ob_19\\\",\\\"type\\\":\\\"observable\\\"}),\\\"index\\\":WebIO.getval({\\\"name\\\":\\\"index\\\",\\\"scope\\\":\\\"15379295305187333299\\\",\\\"id\\\":\\\"ob_18\\\",\\\"type\\\":\\\"observable\\\"})};\\n var self = this;\\n function AppViewModel() {\\n for (var key in json_data) {\\n var el = json_data[key];\\n this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);\\n }\\n \\n [this[\\\"formatted_val\\\"]=ko.computed( function(){\\n return this.formatted_vals()[parseInt(this.index())-(1)];\\n }\\n,this)]\\n [this[\\\"changes\\\"].subscribe((function (val){!(this.valueFromJulia[\\\"changes\\\"]) ? (WebIO.setval({\\\"name\\\":\\\"changes\\\",\\\"scope\\\":\\\"15379295305187333299\\\",\\\"id\\\":\\\"ob_19\\\",\\\"type\\\":\\\"observable\\\"},val)) : undefined; return this.valueFromJulia[\\\"changes\\\"]=false}),self),this[\\\"index\\\"].subscribe((function (val){!(this.valueFromJulia[\\\"index\\\"]) ? (WebIO.setval({\\\"name\\\":\\\"index\\\",\\\"scope\\\":\\\"15379295305187333299\\\",\\\"id\\\":\\\"ob_18\\\",\\\"type\\\":\\\"observable\\\"},val)) : undefined; return this.valueFromJulia[\\\"index\\\"]=false}),self)]\\n \\n }\\n self.model = new AppViewModel();\\n self.valueFromJulia = {};\\n for (var key in json_data) {\\n self.valueFromJulia[key] = false;\\n }\\n ko.applyBindings(self.model, self.dom);\\n}\\n);\\n (WebIO.importBlock({\\\"data\\\":[{\\\"name\\\":\\\"knockout\\\",\\\"type\\\":\\\"js\\\",\\\"url\\\":\\\"/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js\\\"},{\\\"name\\\":\\\"knockout_punches\\\",\\\"type\\\":\\\"js\\\",\\\"url\\\":\\\"/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js\\\"}],\\\"type\\\":\\\"async_block\\\"})).then((imports) => handler.apply(this, imports));\\n}\\n\")])], Dict{Symbol,Any}(:className => \"field interact-widget\")), Observable{Any} with 0 listeners. Value:\n", "Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[GR.SVG(UInt8[0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73 … 0x2f, 0x3e, 0x0a, 0x3c, 0x2f, 0x73, 0x76, 0x67, 0x3e, 0x0a])], Dict{Symbol,Any}(:className => \"interact-flex-row interact-widget\"))], Dict{Symbol,Any}())" ] }, "execution_count": 41, "metadata": { "application/vnd.webio.node+json": { "kernelId": "51aa8b2d-fd5a-4d9f-bda2-35ae38259a07" } }, "output_type": "execute_result" } ], "source": [ "DIP, POP = state_to_tracers(s, nb, 2)\n", "DIP_unit = u\"mmol/m^3\"\n", "horizontal_slice(DIP * u\"mol/m^3\" .|> DIP_unit, 0:0.3:3, \"P-cycle model: DIP [mmol m^{-3}]\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Plot POP" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "application/vnd.webio.node+json": { "children": [ { "children": [ { "children": [ { "children": [ { "children": [ { "children": [ "longitude" ], "instanceArgs": { "namespace": "html", "tag": "label" }, "nodeType": "DOM", "props": { "className": "interact ", "style": { "padding": "5px 10px 0px 10px" } }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-left" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "input" }, "nodeType": "DOM", "props": { "attributes": { "data-bind": "numericValue: index, valueUpdate: 'input', event: {change: function (){this.changes(this.changes()+1)}}", "orient": "horizontal", "type": "range" }, "className": "slider slider is-fullwidth", "max": 180, "min": 1, "step": 1, "style": {} }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-center" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "p" }, "nodeType": "DOM", "props": { "attributes": { "data-bind": "text: formatted_val" } }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-right" }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row interact-widget" }, "type": "node" } ], "instanceArgs": { "handlers": { "changes": [ "(function (val){return (val!=this.model[\"changes\"]()) ? (this.valueFromJulia[\"changes\"]=true, this.model[\"changes\"](val)) : undefined})" ], "index": [ "(function (val){return (val!=this.model[\"index\"]()) ? (this.valueFromJulia[\"index\"]=true, this.model[\"index\"](val)) : undefined})" ] }, "id": "10110007691661942150", "imports": { "data": [ { "name": "knockout", "type": "js", "url": "/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js" }, { "name": "knockout_punches", "type": "js", "url": "/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js" }, { "name": null, "type": "js", "url": "/assetserver/9cda67a60395433f45d7dd64448e9983594c3d89-all.js" }, { "name": null, "type": "css", "url": "/assetserver/f8657a57be3c3d9bd1b603ffa11049f3a1b07340-style.css" }, { "name": null, "type": "css", "url": "/assetserver/ce4e0a8b544aa8c325b955acaffb5afe8945d9a5-bulma_confined.min.css" } ], "type": "async_block" }, "mount_callbacks": [ "function () {\n var handler = (function (ko, koPunches) {\n ko.punches.enableAll();\n ko.bindingHandlers.numericValue = {\n init: function(element, valueAccessor, allBindings, data, context) {\n var stringified = ko.observable(ko.unwrap(valueAccessor()));\n stringified.subscribe(function(value) {\n var val = parseFloat(value);\n if (!isNaN(val)) {\n valueAccessor()(val);\n }\n });\n valueAccessor().subscribe(function(value) {\n var str = JSON.stringify(value);\n if ((str == \"0\") && ([\"-0\", \"-0.\"].indexOf(stringified()) >= 0))\n return;\n if ([\"null\", \"\"].indexOf(str) >= 0)\n return;\n stringified(str);\n });\n ko.applyBindingsToNode(\n element,\n {\n value: stringified,\n valueUpdate: allBindings.get('valueUpdate'),\n },\n context,\n );\n }\n };\n var json_data = {\"formatted_vals\":[\"1.0\",\"3.0\",\"5.0\",\"7.0\",\"9.0\",\"11.0\",\"13.0\",\"15.0\",\"17.0\",\"19.0\",\"21.0\",\"23.0\",\"25.0\",\"27.0\",\"29.0\",\"31.0\",\"33.0\",\"35.0\",\"37.0\",\"39.0\",\"41.0\",\"43.0\",\"45.0\",\"47.0\",\"49.0\",\"51.0\",\"53.0\",\"55.0\",\"57.0\",\"59.0\",\"61.0\",\"63.0\",\"65.0\",\"67.0\",\"69.0\",\"71.0\",\"73.0\",\"75.0\",\"77.0\",\"79.0\",\"81.0\",\"83.0\",\"85.0\",\"87.0\",\"89.0\",\"91.0\",\"93.0\",\"95.0\",\"97.0\",\"99.0\",\"101.0\",\"103.0\",\"105.0\",\"107.0\",\"109.0\",\"111.0\",\"113.0\",\"115.0\",\"117.0\",\"119.0\",\"121.0\",\"123.0\",\"125.0\",\"127.0\",\"129.0\",\"131.0\",\"133.0\",\"135.0\",\"137.0\",\"139.0\",\"141.0\",\"143.0\",\"145.0\",\"147.0\",\"149.0\",\"151.0\",\"153.0\",\"155.0\",\"157.0\",\"159.0\",\"161.0\",\"163.0\",\"165.0\",\"167.0\",\"169.0\",\"171.0\",\"173.0\",\"175.0\",\"177.0\",\"179.0\",\"181.0\",\"183.0\",\"185.0\",\"187.0\",\"189.0\",\"191.0\",\"193.0\",\"195.0\",\"197.0\",\"199.0\",\"201.0\",\"203.0\",\"205.0\",\"207.0\",\"209.0\",\"211.0\",\"213.0\",\"215.0\",\"217.0\",\"219.0\",\"221.0\",\"223.0\",\"225.0\",\"227.0\",\"229.0\",\"231.0\",\"233.0\",\"235.0\",\"237.0\",\"239.0\",\"241.0\",\"243.0\",\"245.0\",\"247.0\",\"249.0\",\"251.0\",\"253.0\",\"255.0\",\"257.0\",\"259.0\",\"261.0\",\"263.0\",\"265.0\",\"267.0\",\"269.0\",\"271.0\",\"273.0\",\"275.0\",\"277.0\",\"279.0\",\"281.0\",\"283.0\",\"285.0\",\"287.0\",\"289.0\",\"291.0\",\"293.0\",\"295.0\",\"297.0\",\"299.0\",\"301.0\",\"303.0\",\"305.0\",\"307.0\",\"309.0\",\"311.0\",\"313.0\",\"315.0\",\"317.0\",\"319.0\",\"321.0\",\"323.0\",\"325.0\",\"327.0\",\"329.0\",\"331.0\",\"333.0\",\"335.0\",\"337.0\",\"339.0\",\"341.0\",\"343.0\",\"345.0\",\"347.0\",\"349.0\",\"351.0\",\"353.0\",\"355.0\",\"357.0\",\"359.0\"],\"changes\":WebIO.getval({\"name\":\"changes\",\"scope\":\"10110007691661942150\",\"id\":\"ob_28\",\"type\":\"observable\"}),\"index\":WebIO.getval({\"name\":\"index\",\"scope\":\"10110007691661942150\",\"id\":\"ob_27\",\"type\":\"observable\"})};\n var self = this;\n function AppViewModel() {\n for (var key in json_data) {\n var el = json_data[key];\n this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);\n }\n \n [this[\"formatted_val\"]=ko.computed( function(){\n return this.formatted_vals()[parseInt(this.index())-(1)];\n }\n,this)]\n [this[\"changes\"].subscribe((function (val){!(this.valueFromJulia[\"changes\"]) ? (WebIO.setval({\"name\":\"changes\",\"scope\":\"10110007691661942150\",\"id\":\"ob_28\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"changes\"]=false}),self),this[\"index\"].subscribe((function (val){!(this.valueFromJulia[\"index\"]) ? (WebIO.setval({\"name\":\"index\",\"scope\":\"10110007691661942150\",\"id\":\"ob_27\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"index\"]=false}),self)]\n \n }\n self.model = new AppViewModel();\n self.valueFromJulia = {};\n for (var key in json_data) {\n self.valueFromJulia[key] = false;\n }\n ko.applyBindings(self.model, self.dom);\n}\n);\n (WebIO.importBlock({\"data\":[{\"name\":\"knockout\",\"type\":\"js\",\"url\":\"/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js\"},{\"name\":\"knockout_punches\",\"type\":\"js\",\"url\":\"/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js\"}],\"type\":\"async_block\"})).then((imports) => handler.apply(this, imports));\n}\n" ], "observables": { "changes": { "id": "ob_28", "sync": false, "value": 0 }, "index": { "id": "ob_27", "sync": true, "value": 90 } }, "systemjs_options": null }, "nodeType": "Scope", "props": {}, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "field interact-widget" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "id": "ob_34", "name": "obs-node" }, "nodeType": "ObservableNode", "props": {}, "type": "node" } ], "instanceArgs": { "handlers": {}, "id": "10263744014572134036", "imports": { "data": [], "type": "async_block" }, "mount_callbacks": [], "observables": { "obs-node": { "id": "ob_34", "sync": false, "value": { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "setInnerHtml": "\n\n\n \n \n \n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n-\n\n\n6000\n\n\n-\n\n\n4000\n\n\n-\n\n\n2000\n\n\n0\n\n\n\n-\n\n\n50\n\n\n0\n\n\n50\n\n\n\n\n\nP\n\n\ncycle model: POP [log(mol m\n\n\n-\n\n\n3\n\n\n-\n\n\n)] at 179.0°\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n\n\n\n\n\n-\n\n\n9\n\n\n-\n\n\n8\n\n\n-\n\n\n7\n\n\n-\n\n\n6\n\n\n-\n\n\n5\n\n\n\n" }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row interact-widget" }, "type": "node" } } }, "systemjs_options": null }, "nodeType": "Scope", "props": {}, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": {}, "type": "node" }, "text/html": [ "\n", " \n", "\n" ], "text/plain": [ "Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Scope(Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :label), Any[\"longitude\"], Dict{Symbol,Any}(:className => \"interact \",:style => Dict{Any,Any}(:padding => \"5px 10px 0px 10px\")))], Dict{Symbol,Any}(:className => \"interact-flex-row-left\")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :input), Any[], Dict{Symbol,Any}(:max => 180,:min => 1,:attributes => Dict{Any,Any}(:type => \"range\",Symbol(\"data-bind\") => \"numericValue: index, valueUpdate: 'input', event: {change: function (){this.changes(this.changes()+1)}}\",\"orient\" => \"horizontal\"),:step => 1,:className => \"slider slider is-fullwidth\",:style => Dict{Any,Any}()))], Dict{Symbol,Any}(:className => \"interact-flex-row-center\")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :p), Any[], Dict{Symbol,Any}(:attributes => Dict(\"data-bind\" => \"text: formatted_val\")))], Dict{Symbol,Any}(:className => \"interact-flex-row-right\"))], Dict{Symbol,Any}(:className => \"interact-flex-row interact-widget\")), Dict{String,Tuple{Observables.AbstractObservable,Union{Nothing, Bool}}}(\"changes\" => (Observable{Int64} with 1 listeners. Value:\n", "0, nothing),\"index\" => (Observable{Any} with 2 listeners. Value:\n", "90, nothing)), Set(String[]), nothing, Asset[Asset(\"js\", \"knockout\", \"/Users/benoitpasquier/.julia/packages/Knockout/1sDlc/src/../assets/knockout.js\"), Asset(\"js\", \"knockout_punches\", \"/Users/benoitpasquier/.julia/packages/Knockout/1sDlc/src/../assets/knockout_punches.js\"), Asset(\"js\", nothing, \"/Users/benoitpasquier/.julia/packages/InteractBase/9mFwe/src/../assets/all.js\"), Asset(\"css\", nothing, \"/Users/benoitpasquier/.julia/packages/InteractBase/9mFwe/src/../assets/style.css\"), Asset(\"css\", nothing, \"/Users/benoitpasquier/.julia/packages/Interact/0klKX/src/../assets/bulma_confined.min.css\")], Dict{Any,Any}(\"changes\" => Any[WebIO.JSString(\"(function (val){return (val!=this.model[\\\"changes\\\"]()) ? (this.valueFromJulia[\\\"changes\\\"]=true, this.model[\\\"changes\\\"](val)) : undefined})\")],\"index\" => Any[WebIO.JSString(\"(function (val){return (val!=this.model[\\\"index\\\"]()) ? (this.valueFromJulia[\\\"index\\\"]=true, this.model[\\\"index\\\"](val)) : undefined})\")]), WebIO.ConnectionPool(Channel{Any}(sz_max:32,sz_curr:0), Set(AbstractConnection[]), Channel{AbstractConnection}(sz_max:32,sz_curr:0)), WebIO.JSString[WebIO.JSString(\"function () {\\n var handler = (function (ko, koPunches) {\\n ko.punches.enableAll();\\n ko.bindingHandlers.numericValue = {\\n init: function(element, valueAccessor, allBindings, data, context) {\\n var stringified = ko.observable(ko.unwrap(valueAccessor()));\\n stringified.subscribe(function(value) {\\n var val = parseFloat(value);\\n if (!isNaN(val)) {\\n valueAccessor()(val);\\n }\\n });\\n valueAccessor().subscribe(function(value) {\\n var str = JSON.stringify(value);\\n if ((str == \\\"0\\\") && ([\\\"-0\\\", \\\"-0.\\\"].indexOf(stringified()) >= 0))\\n return;\\n if ([\\\"null\\\", \\\"\\\"].indexOf(str) >= 0)\\n return;\\n stringified(str);\\n });\\n ko.applyBindingsToNode(\\n element,\\n {\\n value: stringified,\\n valueUpdate: allBindings.get('valueUpdate'),\\n },\\n context,\\n );\\n }\\n };\\n var json_data = {\\\"formatted_vals\\\":[\\\"1.0\\\",\\\"3.0\\\",\\\"5.0\\\",\\\"7.0\\\",\\\"9.0\\\",\\\"11.0\\\",\\\"13.0\\\",\\\"15.0\\\",\\\"17.0\\\",\\\"19.0\\\",\\\"21.0\\\",\\\"23.0\\\",\\\"25.0\\\",\\\"27.0\\\",\\\"29.0\\\",\\\"31.0\\\",\\\"33.0\\\",\\\"35.0\\\",\\\"37.0\\\",\\\"39.0\\\",\\\"41.0\\\",\\\"43.0\\\",\\\"45.0\\\",\\\"47.0\\\",\\\"49.0\\\",\\\"51.0\\\",\\\"53.0\\\",\\\"55.0\\\",\\\"57.0\\\",\\\"59.0\\\",\\\"61.0\\\",\\\"63.0\\\",\\\"65.0\\\",\\\"67.0\\\",\\\"69.0\\\",\\\"71.0\\\",\\\"73.0\\\",\\\"75.0\\\",\\\"77.0\\\",\\\"79.0\\\",\\\"81.0\\\",\\\"83.0\\\",\\\"85.0\\\",\\\"87.0\\\",\\\"89.0\\\",\\\"91.0\\\",\\\"93.0\\\",\\\"95.0\\\",\\\"97.0\\\",\\\"99.0\\\",\\\"101.0\\\",\\\"103.0\\\",\\\"105.0\\\",\\\"107.0\\\",\\\"109.0\\\",\\\"111.0\\\",\\\"113.0\\\",\\\"115.0\\\",\\\"117.0\\\",\\\"119.0\\\",\\\"121.0\\\",\\\"123.0\\\",\\\"125.0\\\",\\\"127.0\\\",\\\"129.0\\\",\\\"131.0\\\",\\\"133.0\\\",\\\"135.0\\\",\\\"137.0\\\",\\\"139.0\\\",\\\"141.0\\\",\\\"143.0\\\",\\\"145.0\\\",\\\"147.0\\\",\\\"149.0\\\",\\\"151.0\\\",\\\"153.0\\\",\\\"155.0\\\",\\\"157.0\\\",\\\"159.0\\\",\\\"161.0\\\",\\\"163.0\\\",\\\"165.0\\\",\\\"167.0\\\",\\\"169.0\\\",\\\"171.0\\\",\\\"173.0\\\",\\\"175.0\\\",\\\"177.0\\\",\\\"179.0\\\",\\\"181.0\\\",\\\"183.0\\\",\\\"185.0\\\",\\\"187.0\\\",\\\"189.0\\\",\\\"191.0\\\",\\\"193.0\\\",\\\"195.0\\\",\\\"197.0\\\",\\\"199.0\\\",\\\"201.0\\\",\\\"203.0\\\",\\\"205.0\\\",\\\"207.0\\\",\\\"209.0\\\",\\\"211.0\\\",\\\"213.0\\\",\\\"215.0\\\",\\\"217.0\\\",\\\"219.0\\\",\\\"221.0\\\",\\\"223.0\\\",\\\"225.0\\\",\\\"227.0\\\",\\\"229.0\\\",\\\"231.0\\\",\\\"233.0\\\",\\\"235.0\\\",\\\"237.0\\\",\\\"239.0\\\",\\\"241.0\\\",\\\"243.0\\\",\\\"245.0\\\",\\\"247.0\\\",\\\"249.0\\\",\\\"251.0\\\",\\\"253.0\\\",\\\"255.0\\\",\\\"257.0\\\",\\\"259.0\\\",\\\"261.0\\\",\\\"263.0\\\",\\\"265.0\\\",\\\"267.0\\\",\\\"269.0\\\",\\\"271.0\\\",\\\"273.0\\\",\\\"275.0\\\",\\\"277.0\\\",\\\"279.0\\\",\\\"281.0\\\",\\\"283.0\\\",\\\"285.0\\\",\\\"287.0\\\",\\\"289.0\\\",\\\"291.0\\\",\\\"293.0\\\",\\\"295.0\\\",\\\"297.0\\\",\\\"299.0\\\",\\\"301.0\\\",\\\"303.0\\\",\\\"305.0\\\",\\\"307.0\\\",\\\"309.0\\\",\\\"311.0\\\",\\\"313.0\\\",\\\"315.0\\\",\\\"317.0\\\",\\\"319.0\\\",\\\"321.0\\\",\\\"323.0\\\",\\\"325.0\\\",\\\"327.0\\\",\\\"329.0\\\",\\\"331.0\\\",\\\"333.0\\\",\\\"335.0\\\",\\\"337.0\\\",\\\"339.0\\\",\\\"341.0\\\",\\\"343.0\\\",\\\"345.0\\\",\\\"347.0\\\",\\\"349.0\\\",\\\"351.0\\\",\\\"353.0\\\",\\\"355.0\\\",\\\"357.0\\\",\\\"359.0\\\"],\\\"changes\\\":WebIO.getval({\\\"name\\\":\\\"changes\\\",\\\"scope\\\":\\\"10110007691661942150\\\",\\\"id\\\":\\\"ob_28\\\",\\\"type\\\":\\\"observable\\\"}),\\\"index\\\":WebIO.getval({\\\"name\\\":\\\"index\\\",\\\"scope\\\":\\\"10110007691661942150\\\",\\\"id\\\":\\\"ob_27\\\",\\\"type\\\":\\\"observable\\\"})};\\n var self = this;\\n function AppViewModel() {\\n for (var key in json_data) {\\n var el = json_data[key];\\n this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);\\n }\\n \\n [this[\\\"formatted_val\\\"]=ko.computed( function(){\\n return this.formatted_vals()[parseInt(this.index())-(1)];\\n }\\n,this)]\\n [this[\\\"changes\\\"].subscribe((function (val){!(this.valueFromJulia[\\\"changes\\\"]) ? (WebIO.setval({\\\"name\\\":\\\"changes\\\",\\\"scope\\\":\\\"10110007691661942150\\\",\\\"id\\\":\\\"ob_28\\\",\\\"type\\\":\\\"observable\\\"},val)) : undefined; return this.valueFromJulia[\\\"changes\\\"]=false}),self),this[\\\"index\\\"].subscribe((function (val){!(this.valueFromJulia[\\\"index\\\"]) ? (WebIO.setval({\\\"name\\\":\\\"index\\\",\\\"scope\\\":\\\"10110007691661942150\\\",\\\"id\\\":\\\"ob_27\\\",\\\"type\\\":\\\"observable\\\"},val)) : undefined; return this.valueFromJulia[\\\"index\\\"]=false}),self)]\\n \\n }\\n self.model = new AppViewModel();\\n self.valueFromJulia = {};\\n for (var key in json_data) {\\n self.valueFromJulia[key] = false;\\n }\\n ko.applyBindings(self.model, self.dom);\\n}\\n);\\n (WebIO.importBlock({\\\"data\\\":[{\\\"name\\\":\\\"knockout\\\",\\\"type\\\":\\\"js\\\",\\\"url\\\":\\\"/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js\\\"},{\\\"name\\\":\\\"knockout_punches\\\",\\\"type\\\":\\\"js\\\",\\\"url\\\":\\\"/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js\\\"}],\\\"type\\\":\\\"async_block\\\"})).then((imports) => handler.apply(this, imports));\\n}\\n\")])], Dict{Symbol,Any}(:className => \"field interact-widget\")), Observable{Any} with 0 listeners. Value:\n", "Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[GR.SVG(UInt8[0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73 … 0x2f, 0x3e, 0x0a, 0x3c, 0x2f, 0x73, 0x76, 0x67, 0x3e, 0x0a])], Dict{Symbol,Any}(:className => \"interact-flex-row interact-widget\"))], Dict{Symbol,Any}())" ] }, "execution_count": 42, "metadata": { "application/vnd.webio.node+json": { "kernelId": "51aa8b2d-fd5a-4d9f-bda2-35ae38259a07" } }, "output_type": "execute_result" } ], "source": [ "zonal_slice(POP .|> relu .|> log10, -10:1:10, \"P-cycle model: POP [log\\\\(mol m^{-3}\\\\)]\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can also make publication-quality plots using Python's Cartopy" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "scrolled": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "application/vnd.webio.node+json": { "children": [ { "children": [ { "children": [ { "children": [ { "children": [ { "children": [ "iz" ], "instanceArgs": { "namespace": "html", "tag": "label" }, "nodeType": "DOM", "props": { "className": "interact ", "style": { "padding": "5px 10px 0px 10px" } }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-left" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "input" }, "nodeType": "DOM", "props": { "attributes": { "data-bind": "numericValue: index, valueUpdate: 'input', event: {change: function (){this.changes(this.changes()+1)}}", "orient": "horizontal", "type": "range" }, "className": "slider slider is-fullwidth", "max": 24, "min": 1, "step": 1, "style": {} }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-center" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "p" }, "nodeType": "DOM", "props": { "attributes": { "data-bind": "text: formatted_val" } }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row-right" }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row interact-widget" }, "type": "node" } ], "instanceArgs": { "handlers": { "changes": [ "(function (val){return (val!=this.model[\"changes\"]()) ? (this.valueFromJulia[\"changes\"]=true, this.model[\"changes\"](val)) : undefined})" ], "index": [ "(function (val){return (val!=this.model[\"index\"]()) ? (this.valueFromJulia[\"index\"]=true, this.model[\"index\"](val)) : undefined})" ] }, "id": "14336471637844589203", "imports": { "data": [ { "name": "knockout", "type": "js", "url": "/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js" }, { "name": "knockout_punches", "type": "js", "url": "/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js" }, { "name": null, "type": "js", "url": "/assetserver/9cda67a60395433f45d7dd64448e9983594c3d89-all.js" }, { "name": null, "type": "css", "url": "/assetserver/f8657a57be3c3d9bd1b603ffa11049f3a1b07340-style.css" }, { "name": null, "type": "css", "url": "/assetserver/ce4e0a8b544aa8c325b955acaffb5afe8945d9a5-bulma_confined.min.css" } ], "type": "async_block" }, "mount_callbacks": [ "function () {\n var handler = (function (ko, koPunches) {\n ko.punches.enableAll();\n ko.bindingHandlers.numericValue = {\n init: function(element, valueAccessor, allBindings, data, context) {\n var stringified = ko.observable(ko.unwrap(valueAccessor()));\n stringified.subscribe(function(value) {\n var val = parseFloat(value);\n if (!isNaN(val)) {\n valueAccessor()(val);\n }\n });\n valueAccessor().subscribe(function(value) {\n var str = JSON.stringify(value);\n if ((str == \"0\") && ([\"-0\", \"-0.\"].indexOf(stringified()) >= 0))\n return;\n if ([\"null\", \"\"].indexOf(str) >= 0)\n return;\n stringified(str);\n });\n ko.applyBindingsToNode(\n element,\n {\n value: stringified,\n valueUpdate: allBindings.get('valueUpdate'),\n },\n context,\n );\n }\n };\n var json_data = {\"formatted_vals\":[\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"10\",\"11\",\"12\",\"13\",\"14\",\"15\",\"16\",\"17\",\"18\",\"19\",\"20\",\"21\",\"22\",\"23\",\"24\"],\"changes\":WebIO.getval({\"name\":\"changes\",\"scope\":\"14336471637844589203\",\"id\":\"ob_36\",\"type\":\"observable\"}),\"index\":WebIO.getval({\"name\":\"index\",\"scope\":\"14336471637844589203\",\"id\":\"ob_35\",\"type\":\"observable\"})};\n var self = this;\n function AppViewModel() {\n for (var key in json_data) {\n var el = json_data[key];\n this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);\n }\n \n [this[\"formatted_val\"]=ko.computed( function(){\n return this.formatted_vals()[parseInt(this.index())-(1)];\n }\n,this)]\n [this[\"changes\"].subscribe((function (val){!(this.valueFromJulia[\"changes\"]) ? (WebIO.setval({\"name\":\"changes\",\"scope\":\"14336471637844589203\",\"id\":\"ob_36\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"changes\"]=false}),self),this[\"index\"].subscribe((function (val){!(this.valueFromJulia[\"index\"]) ? (WebIO.setval({\"name\":\"index\",\"scope\":\"14336471637844589203\",\"id\":\"ob_35\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"index\"]=false}),self)]\n \n }\n self.model = new AppViewModel();\n self.valueFromJulia = {};\n for (var key in json_data) {\n self.valueFromJulia[key] = false;\n }\n ko.applyBindings(self.model, self.dom);\n}\n);\n (WebIO.importBlock({\"data\":[{\"name\":\"knockout\",\"type\":\"js\",\"url\":\"/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js\"},{\"name\":\"knockout_punches\",\"type\":\"js\",\"url\":\"/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js\"}],\"type\":\"async_block\"})).then((imports) => handler.apply(this, imports));\n}\n" ], "observables": { "changes": { "id": "ob_36", "sync": false, "value": 0 }, "index": { "id": "ob_35", "sync": true, "value": 12 } }, "systemjs_options": null }, "nodeType": "Scope", "props": {}, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "field interact-widget" }, "type": "node" }, { "children": [ { "children": [], "instanceArgs": { "id": "ob_42", "name": "obs-node" }, "nodeType": "ObservableNode", "props": {}, "type": "node" } ], "instanceArgs": { "handlers": {}, "id": "9681240831776262415", "imports": { "data": [], "type": "async_block" }, "mount_callbacks": [], "observables": { "obs-node": { "id": "ob_42", "sync": false, "value": { "children": [ { "children": [], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "setInnerHtml": "" }, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": { "className": "interact-flex-row interact-widget" }, "type": "node" } } }, "systemjs_options": null }, "nodeType": "Scope", "props": {}, "type": "node" } ], "instanceArgs": { "namespace": "html", "tag": "div" }, "nodeType": "DOM", "props": {}, "type": "node" }, "text/html": [ "\n", " \n", "\n" ], "text/plain": [ "Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Scope(Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :label), Any[\"iz\"], Dict{Symbol,Any}(:className => \"interact \",:style => Dict{Any,Any}(:padding => \"5px 10px 0px 10px\")))], Dict{Symbol,Any}(:className => \"interact-flex-row-left\")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :input), Any[], Dict{Symbol,Any}(:max => 24,:min => 1,:attributes => Dict{Any,Any}(:type => \"range\",Symbol(\"data-bind\") => \"numericValue: index, valueUpdate: 'input', event: {change: function (){this.changes(this.changes()+1)}}\",\"orient\" => \"horizontal\"),:step => 1,:className => \"slider slider is-fullwidth\",:style => Dict{Any,Any}()))], Dict{Symbol,Any}(:className => \"interact-flex-row-center\")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :p), Any[], Dict{Symbol,Any}(:attributes => Dict(\"data-bind\" => \"text: formatted_val\")))], Dict{Symbol,Any}(:className => \"interact-flex-row-right\"))], Dict{Symbol,Any}(:className => \"interact-flex-row interact-widget\")), Dict{String,Tuple{Observables.AbstractObservable,Union{Nothing, Bool}}}(\"changes\" => (Observable{Int64} with 1 listeners. Value:\n", "0, nothing),\"index\" => (Observable{Int64} with 2 listeners. Value:\n", "12, nothing)), Set(String[]), nothing, Asset[Asset(\"js\", \"knockout\", \"/Users/benoitpasquier/.julia/packages/Knockout/1sDlc/src/../assets/knockout.js\"), Asset(\"js\", \"knockout_punches\", \"/Users/benoitpasquier/.julia/packages/Knockout/1sDlc/src/../assets/knockout_punches.js\"), Asset(\"js\", nothing, \"/Users/benoitpasquier/.julia/packages/InteractBase/9mFwe/src/../assets/all.js\"), Asset(\"css\", nothing, \"/Users/benoitpasquier/.julia/packages/InteractBase/9mFwe/src/../assets/style.css\"), Asset(\"css\", nothing, \"/Users/benoitpasquier/.julia/packages/Interact/0klKX/src/../assets/bulma_confined.min.css\")], Dict{Any,Any}(\"changes\" => Any[WebIO.JSString(\"(function (val){return (val!=this.model[\\\"changes\\\"]()) ? (this.valueFromJulia[\\\"changes\\\"]=true, this.model[\\\"changes\\\"](val)) : undefined})\")],\"index\" => Any[WebIO.JSString(\"(function (val){return (val!=this.model[\\\"index\\\"]()) ? (this.valueFromJulia[\\\"index\\\"]=true, this.model[\\\"index\\\"](val)) : undefined})\")]), WebIO.ConnectionPool(Channel{Any}(sz_max:32,sz_curr:0), Set(AbstractConnection[]), Channel{AbstractConnection}(sz_max:32,sz_curr:0)), WebIO.JSString[WebIO.JSString(\"function () {\\n var handler = (function (ko, koPunches) {\\n ko.punches.enableAll();\\n ko.bindingHandlers.numericValue = {\\n init: function(element, valueAccessor, allBindings, data, context) {\\n var stringified = ko.observable(ko.unwrap(valueAccessor()));\\n stringified.subscribe(function(value) {\\n var val = parseFloat(value);\\n if (!isNaN(val)) {\\n valueAccessor()(val);\\n }\\n });\\n valueAccessor().subscribe(function(value) {\\n var str = JSON.stringify(value);\\n if ((str == \\\"0\\\") && ([\\\"-0\\\", \\\"-0.\\\"].indexOf(stringified()) >= 0))\\n return;\\n if ([\\\"null\\\", \\\"\\\"].indexOf(str) >= 0)\\n return;\\n stringified(str);\\n });\\n ko.applyBindingsToNode(\\n element,\\n {\\n value: stringified,\\n valueUpdate: allBindings.get('valueUpdate'),\\n },\\n context,\\n );\\n }\\n };\\n var json_data = {\\\"formatted_vals\\\":[\\\"1\\\",\\\"2\\\",\\\"3\\\",\\\"4\\\",\\\"5\\\",\\\"6\\\",\\\"7\\\",\\\"8\\\",\\\"9\\\",\\\"10\\\",\\\"11\\\",\\\"12\\\",\\\"13\\\",\\\"14\\\",\\\"15\\\",\\\"16\\\",\\\"17\\\",\\\"18\\\",\\\"19\\\",\\\"20\\\",\\\"21\\\",\\\"22\\\",\\\"23\\\",\\\"24\\\"],\\\"changes\\\":WebIO.getval({\\\"name\\\":\\\"changes\\\",\\\"scope\\\":\\\"14336471637844589203\\\",\\\"id\\\":\\\"ob_36\\\",\\\"type\\\":\\\"observable\\\"}),\\\"index\\\":WebIO.getval({\\\"name\\\":\\\"index\\\",\\\"scope\\\":\\\"14336471637844589203\\\",\\\"id\\\":\\\"ob_35\\\",\\\"type\\\":\\\"observable\\\"})};\\n var self = this;\\n function AppViewModel() {\\n for (var key in json_data) {\\n var el = json_data[key];\\n this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);\\n }\\n \\n [this[\\\"formatted_val\\\"]=ko.computed( function(){\\n return this.formatted_vals()[parseInt(this.index())-(1)];\\n }\\n,this)]\\n [this[\\\"changes\\\"].subscribe((function (val){!(this.valueFromJulia[\\\"changes\\\"]) ? (WebIO.setval({\\\"name\\\":\\\"changes\\\",\\\"scope\\\":\\\"14336471637844589203\\\",\\\"id\\\":\\\"ob_36\\\",\\\"type\\\":\\\"observable\\\"},val)) : undefined; return this.valueFromJulia[\\\"changes\\\"]=false}),self),this[\\\"index\\\"].subscribe((function (val){!(this.valueFromJulia[\\\"index\\\"]) ? (WebIO.setval({\\\"name\\\":\\\"index\\\",\\\"scope\\\":\\\"14336471637844589203\\\",\\\"id\\\":\\\"ob_35\\\",\\\"type\\\":\\\"observable\\\"},val)) : undefined; return this.valueFromJulia[\\\"index\\\"]=false}),self)]\\n \\n }\\n self.model = new AppViewModel();\\n self.valueFromJulia = {};\\n for (var key in json_data) {\\n self.valueFromJulia[key] = false;\\n }\\n ko.applyBindings(self.model, self.dom);\\n}\\n);\\n (WebIO.importBlock({\\\"data\\\":[{\\\"name\\\":\\\"knockout\\\",\\\"type\\\":\\\"js\\\",\\\"url\\\":\\\"/assetserver/c5b5f12c91015c9441bc62503aabac4bb7da401a-knockout.js\\\"},{\\\"name\\\":\\\"knockout_punches\\\",\\\"type\\\":\\\"js\\\",\\\"url\\\":\\\"/assetserver/2afbb4f93688160adb1912d5c2e1b77efa1e2bcc-knockout_punches.js\\\"}],\\\"type\\\":\\\"async_block\\\"})).then((imports) => handler.apply(this, imports));\\n}\\n\")])], Dict{Symbol,Any}(:className => \"field interact-widget\")), Observable{Any} with 0 listeners. Value:\n", "Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Figure(PyObject
)], Dict{Symbol,Any}(:className => \"interact-flex-row interact-widget\"))], Dict{Symbol,Any}())" ] }, "execution_count": 43, "metadata": { "application/vnd.webio.node+json": { "kernelId": "51aa8b2d-fd5a-4d9f-bda2-35ae38259a07" } }, "output_type": "execute_result" } ], "source": [ "ccrs = pyimport(\"cartopy.crs\")\n", "cfeature = pyimport(\"cartopy.feature\")\n", "lon_cyc = [lon; 360+lon[1]]\n", "DIP_3D = fill(NaN, size(grd)); DIP_3D[iwet] = DIP * u\"mol/m^3\" .|> u\"mmol/m^3\" .|> ustrip\n", "DIP_3D_cyc = cat(DIP_3D, DIP_3D[:,[1],:], dims=2)\n", "f1 = PyPlot.figure(figsize=(12,5))\n", "@manipulate for iz in 1:24\n", " withfig(f1, clear=true) do\n", " ax = PyPlot.subplot(projection = ccrs.EqualEarth(central_longitude=-155.0))\n", " ax.add_feature(cfeature.COASTLINE, edgecolor=\"#000000\") # black coast lines\n", " ax.add_feature(cfeature.LAND, facecolor=\"#CCCCCC\") # gray land\n", " plt = PyPlot.contourf(lon_cyc, lat, DIP_3D_cyc[:,:,iz], levels=0:0.1:3.5, \n", " transform=ccrs.PlateCarree(), zorder=-1, extend=\"both\")\n", " plt2 = PyPlot.contour(plt, lon_cyc, lat, DIP_3D_cyc[:,:,iz], levels=plt.levels[1:5:end], \n", " transform=ccrs.PlateCarree(), zorder=0, extend=\"both\", colors=\"k\")\n", " ax.clabel(plt2, fmt=\"%2.1f\", colors=\"k\", fontsize=14)\n", " cbar = PyPlot.colorbar(plt, orientation=\"vertical\", extend=\"both\", ticks=plt2.levels)\n", " cbar.add_lines(plt2)\n", " cbar.ax.tick_params(labelsize=14)\n", " cbar.set_label(label=\"mmol / m³\", fontsize=16)\n", " PyPlot.title(\"Publication-quality DIP with Cartopy; depth = $(string(round(typeof(1u\"m\"),grd.depth[iz])))\", fontsize=20)\n", " end\n", "end" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "@webio": { "lastCommId": "60f24b78f1e44ad19c5232983b5cc5b8", "lastKernelId": "f478ab1d-3d80-4668-be97-58269aee155f" }, "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Julia 1.2.0", "language": "julia", "name": "julia-1.2" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.2.0" }, "rise": { "scroll": true } }, "nbformat": 4, "nbformat_minor": 4 }