diff --git a/.gitignore b/.gitignore index 7289c3e2..25d08a90 100644 --- a/.gitignore +++ b/.gitignore @@ -341,4 +341,5 @@ Manifest.toml # images are by default ignored, force add them if you must *.png *.jpg -*.svg \ No newline at end of file +*.svg +.DS_Store diff --git a/exercises/calib_fermenter_monod_sol.jl b/exercises/calib_fermenter_monod_sol.jl index 56f14cc0..39535f7a 100644 --- a/exercises/calib_fermenter_monod_sol.jl +++ b/exercises/calib_fermenter_monod_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 245ca9d0-10f9-11ef-0ef6-a73594e96db9 @@ -36,10 +36,14 @@ md""" In one of the previous practica we were introduced to a fermenter in which biomass $X$ [$g/L$] grows by breaking down substrate $S$ [$g/L$]. The reactor is fed with a inlet flow rate $Q_{in}$ [$L/h$], which consist of a (manipulable) input concentration of substrate $S_{in}$ [$g/L$]. This process was modelled using Monod kinetics, resulting in the model below: $$\begin{eqnarray*} -%S \xrightarrow[\quad\quad]{\beta} Y \, X -S \xrightarrow[\quad\quad]{r} Y \, X \quad\quad\quad\quad r = \mu \, X \quad \textrm{with} \quad \mu = \mu_{max} \, \cfrac{S}{S + K_s} +S + X \xrightarrow[\quad\quad]{k} (1 + Y) \, X \quad\quad\quad\quad \textrm{with} \quad k = \cfrac{\mu_{max}}{S + K_s} \end{eqnarray*}$$ """ +# $$\begin{eqnarray*} +# %S \xrightarrow[\quad\quad]{\beta} Y \, X +# S \xrightarrow[\quad\quad]{r} Y \, X \quad\quad\quad\quad r = \mu \, X \quad \textrm{with} \quad \mu = \mu_{max} \, \cfrac{S}{S + K_s} +# \end{eqnarray*}$$ + # ╔═╡ 824db995-7a66-4719-a534-7e0f6dec90b5 md""" @@ -48,13 +52,17 @@ The *reaction network object* for this model could be set-up as: # ╔═╡ 245c2636-95da-4c76-8b03-c4d20bbabb48 fermenter_monod = @reaction_network begin - X * mm(S, μmax, Ks), S => Y*X - # Alternative: - # X * mm(S, μmax, Ks), S --> Y*X + μmax/(S+Ks), S + X --> (1 + Y)*X + # Alternatives: + # X * mm(S, μmax, Ks), S => Y*X + # mm(S, μmax, Ks)*X, S + X => (1 + Y)*X Q/V, (S, X) --> 0 Q/V*Sin, 0 --> S end +# ╔═╡ 956790e2-6cac-46c9-886e-24d5aceae1c5 +convert(ODESystem, fermenter_monod, combinatoric_ratelaws=false) + # ╔═╡ 68f9ecb3-15b0-4a53-8864-5dac13a89e95 parameters(fermenter_monod) @@ -123,7 +131,7 @@ u0 = [:S => 0.0, :X => 0.0005] # ╔═╡ 38fe8304-af61-40a7-ac86-480dfb892185 # tspan = missing # Uncomment and complete the instruction -tspan = (0.0, 100) +tspan = (0.0, 100.0) # ╔═╡ 87482f88-8413-4820-9613-7941f3d61bd7 # params = missing # Uncomment and complete the instruction @@ -135,12 +143,12 @@ oprob = ODEProblem(fermenter_monod, u0, tspan, params, combinatoric_ratelaws=fal # ╔═╡ f6a8f134-6db0-4d74-8af5-82826347d8f0 md""" -Declare the Turing model. Use `InverseGamma()` for the standard deviations of the measurements and `LogNormal()` for `μmax` and `K`. +Declare the Turing model. Use `InverseGamma` for the standard deviations of the measurements and `LogNormal` for `μmax` and `K`. """ # ╔═╡ 4c28a66a-ee2c-42a2-95c7-ea4ddb6a232d # Uncomment and complete the instruction -# @model function fermenter_inference(t_meas, S, X) +# @model function fermenter_fun(t_meas, S, X) # σ_S ~ missing # σ_X ~ missing # μmax ~ missing @@ -148,32 +156,29 @@ Declare the Turing model. Use `InverseGamma()` for the standard deviations of th # params = missing # oprob = missing # osol = missing - # S ~ missing - # X ~ missing + # S_s ~ missing + # X_s ~ missing # end -@model function fermenter_inference(t_meas, S, X) +@model function fermenter_fun(t_meas) σ_S ~ InverseGamma() σ_X ~ InverseGamma() μmax ~ LogNormal() Ks ~ LogNormal() - # μmax ~ Normal(0.40, 0.1) - # Ks ~ Normal(0.015, 0.01) params = [:μmax => μmax, :Ks => Ks, :Y => 0.67, :Q => 2, :V => 40, :Sin => 0.022] - oprob = ODEProblem(fermenter_monod, u0, tspan, params) - # , combinatoric_ratelaws=false + oprob = ODEProblem(fermenter_monod, u0, tspan, params, combinatoric_ratelaws=false) osol = solve(oprob, Tsit5(), saveat=t_meas) - S ~ MvNormal(osol[:S], σ_S^2 * I) - X ~ MvNormal(osol[:X], σ_X^2 * I) + S_s ~ MvNormal(osol[:S], σ_S^2 * I) + X_s ~ MvNormal(osol[:X], σ_X^2 * I) end # ╔═╡ 3136b15d-5078-4bcd-954b-e89bcb8aed1b md""" -Provide the measurements to the Turing model. +Provide the time measurements to the defined function and instantly condition the model with the measurements of $S$ and $X$: """ # ╔═╡ 6a508a62-61b9-4273-8e45-b26f594e8da9 -# fermenter_inf = missing # Uncomment and complete the instruction -fermenter_inf = fermenter_inference(t_meas, S_meas, X_meas) +# fermenter_cond_mod = missing # Uncomment and complete the instruction +fermenter_cond_mod = fermenter_fun(t_meas) | (S_s = S_meas, X_s = X_meas,) # ╔═╡ 63420055-55f8-4def-8b0e-11ea61483010 md""" @@ -182,7 +187,7 @@ Optimize the priors ($\sigma_S$, $\sigma_X$, $\mu_{max}$ and $K_s$). Do this wit # ╔═╡ d52c9da8-d8a4-4db0-ac6d-6d16ccf4775c # results_map = missing # Uncomment and complete the instruction -results_mle = optimize(fermenter_inf, MLE(), NelderMead()) +results_mle = optimize(fermenter_cond_mod, MLE(), NelderMead()) # ╔═╡ e1b0ee01-f16c-40e9-a0f9-80072d690936 md""" @@ -191,7 +196,7 @@ Visualize a summary of the optimized parameters. # ╔═╡ f2d7daf8-8218-446d-b1d2-e9e05aeadfd9 # missing # Uncomment and complete the instruction -results_mle |> coeftable +coeftable(results_mle) # ╔═╡ 23d58bb1-d077-402e-8bee-3866c68e069a md""" @@ -227,8 +232,7 @@ Create an ODEProblem and solve it. Use `Tsit5()` and `saveat=0.5`. # ╔═╡ 853c1a92-d50f-4b05-9ed3-d3ee1656665a # oprob_opt = missing # Uncomment and complete the instruction -oprob_opt = ODEProblem(fermenter_monod, u0, tspan, params_opt) -# , combinatoric_ratelaws=false +oprob_opt = ODEProblem(fermenter_monod, u0, tspan, params_opt, combinatoric_ratelaws=false) # ╔═╡ f45e8124-e942-438e-99c5-3032ccc01454 # osol_opt = missing # Uncomment and complete the instruction @@ -252,6 +256,14 @@ begin scatter!(t_meas, X_meas, label="X meas", color=:red) end +# ╔═╡ d7e1f24a-f0f0-44d9-a3b8-6c074d273bdc +md""" +Do your simulations fit well the measurements? +""" + +# ╔═╡ 49cf442e-0c6a-433f-96c0-e10b29bf86a9 +md"- Answer: missing" + # ╔═╡ Cell order: # ╠═245ca9d0-10f9-11ef-0ef6-a73594e96db9 # ╠═78a25bef-31e5-45ef-b0ba-b9a8c8a9edeb @@ -263,6 +275,7 @@ end # ╟─595ea8ee-bc67-4696-9232-982612fb554d # ╟─824db995-7a66-4719-a534-7e0f6dec90b5 # ╠═245c2636-95da-4c76-8b03-c4d20bbabb48 +# ╠═956790e2-6cac-46c9-886e-24d5aceae1c5 # ╠═68f9ecb3-15b0-4a53-8864-5dac13a89e95 # ╟─de8ddc14-8f82-403d-8f42-29673ef2a722 # ╟─b7b7d58f-d406-4596-b834-ced6d8fada83 @@ -296,3 +309,5 @@ end # ╠═f45e8124-e942-438e-99c5-3032ccc01454 # ╟─5a39b0e0-1ea1-4854-8e68-66d0d4bbf25c # ╠═d0156099-ad03-4711-ac0f-94882fb78266 +# ╟─d7e1f24a-f0f0-44d9-a3b8-6c074d273bdc +# ╠═49cf442e-0c6a-433f-96c0-e10b29bf86a9 diff --git a/exercises/calib_intro_sol.jl b/exercises/calib_intro_sol.jl new file mode 100644 index 00000000..327ebf20 --- /dev/null +++ b/exercises/calib_intro_sol.jl @@ -0,0 +1,1020 @@ +### A Pluto.jl notebook ### +# v0.20.4 + +using Markdown +using InteractiveUtils + +# ╔═╡ f8a92690-990b-4341-89e1-322adbcb8d1b +begin + # add this cell if you want the notebook to use the environment from where the Pluto server is launched + using Pkg + Pkg.activate("..") +end + +# ╔═╡ a09f814a-0c6a-11ef-0e79-a50b01287d63 +using Markdown + +# ╔═╡ 7f521435-63ac-4178-a4aa-93d9c45fe820 +using InteractiveUtils + +# ╔═╡ 015050b3-3339-4b1a-ad7d-c358cce73675 +using Catalyst, DifferentialEquations, Plots + +# ╔═╡ dbfe4800-0974-4ca1-bb0a-d8803409a98b +using Turing, StatsPlots, StatsBase + +# ╔═╡ 6e227e07-166a-41ce-839a-4c4c72addb23 +using LinearAlgebra, Optim + +# ╔═╡ b992c080-a0ce-4188-b632-e734a141e67d +using PlutoUI; TableOfContents() + +# ╔═╡ 37da8786-fea0-4c2f-a76f-6e6c68325a78 +md""" +# Introduction to calibration +""" + +# ╔═╡ 4623369d-8c5a-422d-9e40-0f1dd7586260 +md""" +## Goal of this practicum +""" + +# ╔═╡ 3cb0a166-ac53-4c3f-9832-e93742040cfb +md""" +In the models discussed in the previous sessions, i.e., the values of all parameters were known. In reality, the value of a parameter often need to be calibrated, i.e., estimated from experimental data. During this parameter estimation one attempts to find the set of parameter values for which the model predictions are as close as possible to the collected experimental data. +""" + +# ╔═╡ 987f0a4d-e416-4ceb-adbe-3dcdca9d0996 +md""" +The search of optimal parameter values usually involves a function, such as a loss function, a (log) likelihood function or a posterior distribution function. In this session we will be (mainly) using the MLE (Maximum Likelihood Estimation) and MAP (Maximum A Posteriori estimation) methods. + +In the MLE method, a likelihood function of a given probability density function is maximized during the search of optimal parameter values of a model in order to fit experimental data. The parameter values are considered unknown but viewed as fixed points. + +In the MAP method, a posterior distribution function is maximized. Instead of viewing the parameter values as fixed points, they are now treated as random variables in the model which follow a prior distribution. In other words, we have prior belief in which distribution these parameters come from (Normal, Beta, etc). Once new data comes in, we update our prior belief, leading to a posterior belief. Hence, we now have a better idea from which distribution these parameters come. + +One caveat with the MAP method is that it only considers the most likely point without taking into account other values of parameters from posterior distribution, which leads to a huge loss of useful information in posterior distribution. A better, yet computationally exhaustive method is using the MCMC (Markov chain Monte Carlo) sampling methods. Here we will use the NUTS sampler in this session. +""" + +# ╔═╡ 75efff36-8da7-4d04-afa2-a2f8324bc103 +md""" +In this notebook we will calibrate the different parameters involved in the grass growth models with either MLE, MAP or MCMC. To illustrate this concept, we first revisit the three simple models modelling the grass growth yield. +""" + +# ╔═╡ 3dcb9c9d-370b-4031-b7c0-cee80742557a +md""" +## Grass growth models +""" + +# ╔═╡ 7a14aa59-6e6f-4266-a0b3-84ab55f2efc5 +md""" +In this notebook, three different models will be used, each modelling the yield of grass in a grassland: + +- Logistic growth model: $\cfrac{dW}{dt} = \mu \left( 1 - \cfrac{W}{W_f} \right) W$ +- Exponential growth model: $\cfrac{dW}{dt} = \mu \left( W_f - W \right)$ +- Gompertz growth model: $\cfrac{dW}{dt} = \left( \mu - D \ln(W) \right) W$ + +with output $W$ the grass yield, and $W_f$, $\mu$ and $D$ parameters. The table below show the parameter values and the initial condition that will be used as initial values for the optimization algorithm: + +| | $\mu$ | $W_f$ | $D$ | $W_0$ | +|:----------- |:----------:|:-----------:|:------------:|:------------:| +| Logistic | 0.07 | 10.0 | | 2.0 | +| Exponential | 0.02 | 10.0 | | 2.0 | +| Gompertz | 0.09 | | 0.040 | 2.0 | + +Hence, for each grass growth model, we will optimize the parameter values together with the initial value. +""" + +# ╔═╡ 85cd60a8-b448-4375-9b6d-399c4336c319 +md""" +In each of the three models we will use the following timespan: +""" + +# ╔═╡ 5b320989-3e0b-447b-bc9a-25fb221ce609 +tspan = (0.0, 100.0) # this will be the same for the three models + +# ╔═╡ 2481cd4f-0efc-4450-ab3d-4a5492597f36 +md""" +Variables containing the initial condition and parameters values will be defined later in the objective function. +""" + +# ╔═╡ 9a5bc72b-346d-4e95-a873-783037ed98bc +md""" +### Logistic growth model + +We will illustrate the calibration with the logistic growth model: +""" + +# ╔═╡ ba56adb1-9405-40d5-be48-4273b42ab145 +growth_log = @reaction_network begin + μ*(1-W/Wf), W --> 2W +end + +# ╔═╡ 6e3e53ea-4fe7-4a34-8b00-cbf8d63a3203 +osys_log = convert(ODESystem, growth_log) + +# ╔═╡ f4748167-b635-47a1-9015-32e1258c0afa +md""" +Check the order of the parameters: +""" + +# ╔═╡ a022b2ab-68a0-40ca-b914-7a2adcf4ae39 +parameters(growth_log) + +# ╔═╡ acccb2fa-12b2-4fc7-91e3-58a4b1a02892 +md""" +Next, we will need to create an `ODEProblem` in advance before we can optimize some of its parameters. We will provide the values in the aforementioned table as initial values for the problem. +""" + +# ╔═╡ e54ea8d1-0854-44fa-aed8-45d106e921e4 +u0_log = [:W => 2.0] + +# ╔═╡ 8d96eb17-ce19-4523-916f-3cd0441a16ca +params_log = [:μ => 0.07, :Wf => 10.0] + +# ╔═╡ 5c9db9df-0cbd-41ac-afe9-fb5616c967be +oprob_log = ODEProblem(growth_log, u0_log, tspan, params_log) + +# ╔═╡ 1aa44f2b-6f33-437f-b9dd-89762d9f28ea +md""" +### The measurement data +""" + +# ╔═╡ b2b433ed-0266-4bea-a7e8-32adba542d4c +md""" +Assume that the measured grass yields (of a certain plant type) are the following: +""" + +# ╔═╡ 7c966a66-0091-4b81-9a7e-02ccd0d3db10 +W_meas = [1.87, 2.45, 3.72, 4.32, 5.28, 7.01, 6.83, 8.62, 9.45, 10.31, 10.56, 11.72, 11.05, 11.53, 11.39, 11.7, 11.15, 11.49, 12.04, 11.95, 11.68] + +# ╔═╡ 3edd2acc-a865-4675-afef-8868c68256f1 +md""" +They have been measured at the following corresponding time instances: +""" + +# ╔═╡ 877298e8-b61b-4c3a-ba2c-2827acdcfb50 +t_meas = 0:5:100 + +# ╔═╡ acb7b123-831f-47e9-92cc-2dd3e57f86fd +md""" +If you literally want to see the time values, you can use the `collect` function to create a dense vector: +""" + +# ╔═╡ bab8119a-7fe7-4c6b-abb9-5885a88b55ae +collect(t_meas) + +# ╔═╡ ef06cc43-510b-4ff9-b0b7-1c7fc267e9b1 +md""" +We can make a scatter plot of this data (including a title, a legend label, an X-axis label, X- and Y-axis limits) in the following way: +""" + +# ╔═╡ cb2bc6ee-4211-47e1-9956-5cf1b0c0671d +scatter(t_meas, W_meas, title="Grass growth data", + label="Yield", + xlabel="t", + xlims=(0, 100), + ylims=(0, 14)) + +# ╔═╡ d75246d4-e03b-4684-be7d-4bcfb61ed7ef +md""" +### Declaration of the Turing model function +""" + +# ╔═╡ dd3a32f1-bdb6-44a3-acbe-f4269725c9e4 +md""" +In the Turing model function we will define our priors for the following magnitudes: +- the measurement error (standard deviation) $\sigma_W$, +- the initial condition $W_0$, and +- the parameters $\mu$ and $W_f$. + +We will thereby take an `InverseGamma` prior distribution for $\sigma_W$ and `LogNormal` prior distributions for the initial condition and the parameters. You can always plot the priors to have a look at them, e.g., with `plot(LogNormal())`. +""" + +# ╔═╡ 88dd0342-3678-40a2-a432-661e5410e5cf +plot(LogNormal()) # Log-normal with 0 log-mean and unit scale +# plot(LogNormal(log(1), 1.0)) # Log-normal with 0 log-mean and unit scale +# plot(LogNormal(log(10), 0.50)) # Log-normal with 1 log-mean and 0.5 scale + +# ╔═╡ 70ff9f12-e924-4daf-ab32-2394feccc953 +plot(InverseGamma()) # Inverse Gamma with shape 1 and scale 1 +# plot(InverseGamma(3, 1)) # Inverse Gamma with shape 3 and scale 1 +# plot(InverseGamma(5, 0.5)) # Inverse Gamma with shape 5 and scale 0.5 + +# ╔═╡ 0ccf1f1d-20be-4c19-bfc6-2748970547a1 +md""" +Here is our Turing model function: +""" + +# ╔═╡ 6d9d7792-fffa-482d-b785-33482bf2b0ea +@model function growth_log_fun(t_meas) + σ_W ~ InverseGamma() + W0 ~ LogNormal() + μ ~ LogNormal() + Wf ~ LogNormal() + u0_log = [:W => W0] + params_log = [:μ => μ, :Wf => Wf] + oprob_log = ODEProblem(growth_log, u0_log, tspan, params_log) + osol_log = solve(oprob_log, Tsit5(), saveat=t_meas) + W_s ~ MvNormal(osol_log[:W], σ_W^2 * I) + return osol_log # optionally, to be used with MCMC +end + +# ╔═╡ 48c9f616-d298-40da-b917-225abd39b3d9 +md""" +!!! note "Some remarks" + - The time points are the ones from the measurements, therefore, we set: `saveat=t_meas`. + - We need to solve the ODE problem inside the Turing model function with values for $W_0$, $\mu$ and $W_f$ sampled from the distributions. Therefore, we need to remake our ODE problem with the appropriate initial and parameter values and solve it. + - We will consider our solution vector for $W$ as being multivariate normally distributed with mean (vector) the actual solution for $W$ and covariance (matrix) a diagonal matrix with variances $\sigma_W^2$. The function `MvNormal(μ, Σ)` will construct a *multivariate normal distribution* with mean vector μ and covariance matrix Σ. + + Consider the following (small) example. The mean vector here is `[1.7, 4.5, 3.6]` and the variance on the diagonal are `0.5^2 * I` (`I` is the identity matrix). When you sample from it, you get a vector of values with mean `[1.7, 4.5, 3.6]` and each value with variance `0.5^2`. +""" + +# ╔═╡ 4987f361-fcce-4453-8872-11d6faf16e86 +rand(Uniform(0, 20)) + +# ╔═╡ 3d3db44c-db49-436a-9b6e-9f6dd5d6178b +rand(MvNormal([1.7, 4.5, 3.6], 0.5^2 * I)) + +# ╔═╡ 35f158c1-858d-4e4d-ac3d-bf4807dad9a0 +md""" +We now provide the time measurements to the defined function (this results in the Turing model) and instantly condition the Turing model with the measurements of $W$: +""" + +# ╔═╡ 98a71080-e662-4f1a-88fe-3c575386ec77 +growth_log_cond_mod = growth_log_fun(t_meas) | (W_s = W_meas,) + +# ╔═╡ a6972aef-63ad-401c-acf5-6d59f9fc6698 +md""" +We are now ready to optimize the priors ($\sigma_W$, $W_0$, $\mu$ and $W_f$). This is done by calling the `optimize` function, providing the previously created object `growth_log_inf`, the method for estimating the parameters and (optionally) an algorithm (default: Nelder-Mead) to implement the method. +""" + +# ╔═╡ 73e35289-6dc0-4e2e-83eb-b56f83cdbbbf +md""" +### Method - Maximum Likelihood Estimation +""" + +# ╔═╡ 47bd729c-4851-42f7-a03f-6ceacd3c717e +md""" +We will use the MLE (Maximum Likelihood Estimation) method here and store the optimization results in `results_log_mle`. +""" + +# ╔═╡ dff0f8c6-1fed-4ef7-a6d3-2c8f345ed724 +results_log_mle = optimize(growth_log_cond_mod, MLE(), NelderMead()) + +# ╔═╡ e55404ab-6762-4f39-bb42-9c195334a214 +md""" +You can visualize a summary of the optimized parameters by piping them to `coeftable`: +""" + +# ╔═╡ 75ee0ba9-c9f9-496e-bb80-d013328c3ad7 +coeftable(results_log_mle) + +# ╔═╡ a1ca7d0e-639c-42d4-be09-5c61a2008f29 +md""" +You can obtain the actual optimized values using the function `coef` on the results object in conjunction by calling the parameters by name preceded by a colon. Here we assign the optimized parameter values to some suitable variable names: +""" + +# ╔═╡ 30399b9a-1d77-4140-9ad3-5eed636a5b99 +W0_opt1_log = coef(results_log_mle)[:W0] + +# ╔═╡ e1b8e4ba-c1f1-48d5-87a2-edce19c9fe7a +μ_opt1_log = coef(results_log_mle)[:μ] + +# ╔═╡ a943e0fe-1376-4ef1-9c45-25c6f95e3b96 +Wf_opt1_log = coef(results_log_mle)[:Wf] + +# ╔═╡ 72e065d4-7b1b-4f46-b373-935be8d801fc +md""" +Now we can make a plot of $W$ simulated with the optimized initial condition and parameter values. +""" + +# ╔═╡ 0b2ffd6f-01cd-4f11-9062-d38b3c13a5b1 +md""" +Setting up initial condition with optimized initial condition: +""" + +# ╔═╡ 590b1006-0e37-4668-9b4a-3588fab45696 +u0_opt1_log = [:W => W0_opt1_log] + +# ╔═╡ 8ff28a2e-185d-4dca-ad3b-a0b1507646d6 +md""" +Setting up parameter values with optimized parameter values: +""" + +# ╔═╡ 14d24cbd-3259-41bb-9013-b4fe25a3be4c +params_opt1_log = [:μ => μ_opt1_log, :Wf => Wf_opt1_log] + +# ╔═╡ 6c134677-3ec1-4e0a-88b5-01341a096675 +md""" +Next, we create an ODEProblem and solve it: +""" + +# ╔═╡ 7a81f4a0-8f7c-4e05-9c3f-2438eab9b691 +oprob_opt1_log = ODEProblem(growth_log, u0_opt1_log, tspan, params_opt1_log) + +# ╔═╡ ac80099b-d8f0-4eba-809d-d482bd354d35 +osol_opt1_log = solve(oprob_opt1_log, Tsit5(), saveat=0.5) + +# ╔═╡ b58f2c24-e0ea-48a8-b0b7-d0faf9642340 +md""" +Finally, we plot $W$ simulated with the optimized initial value and parameter values together with the measured data that was used to find the optimized values. +""" + +# ╔═╡ 55eba435-6ca4-4f4f-b08a-be700d5bda91 +begin + plot(osol_opt1_log, label="Logistic growth", xlabel="t", + xlims=(0, 100), ylims=(0, 14), lw=2.0, title="MLE") + scatter!(t_meas, W_meas, label="Yield") +end + +# ╔═╡ 5d386b00-93b5-4a88-b4e3-e5c3eebd6dd5 +md""" +### Method - Maximum A Posterior +""" + +# ╔═╡ 6f0e91d0-6b99-4cf1-8145-523589a21e89 +md""" +We will use the MAP (Maximum A Posterior) method here and store the optimization results in `results_log_map`. +""" + +# ╔═╡ 209742ca-36bb-42a5-bf8a-291a40c47757 +results_log_map = optimize(growth_log_cond_mod, MAP(), NelderMead()) + +# ╔═╡ 07efb21a-0dac-46d5-b9e1-8f4757c6cedf +md""" +You can visualize a summary of the optimized parameters by piping them to `coeftable`: +""" + +# ╔═╡ a93a7eeb-aad1-49f3-a05f-1512adb08b6b +coeftable(results_log_map) + +# ╔═╡ ccc66805-efce-4f25-b76b-7cff23901ba4 +md""" +You can obtain the actual optimized values using the function `coef` on the results object in conjunction by calling the parameters by name preceded by a colon. Here we assign the optimized parameter values to some suitable variable names: +""" + +# ╔═╡ 57ef7d03-a6dc-40da-858d-5f9b9be613cd +W0_opt2_log = coef(results_log_map)[:W0] + +# ╔═╡ 62bd2e58-343a-4155-a65e-cf326d0975f4 +μ_opt2_log = coef(results_log_map)[:μ] + +# ╔═╡ 4d6cba88-be68-412d-aeec-28300c26a9da +Wf_opt2_log = coef(results_log_map)[:Wf] + +# ╔═╡ 4bc97af7-debc-4170-a2d5-4e6c928e5183 +md""" +Now we can make a plot of $W$ simulated with the optimized initial condition and parameter values. +""" + +# ╔═╡ a0033986-4946-45a2-a53e-29c38f35ed5c +md""" +Setting up initial condition with optimized initial condition: +""" + +# ╔═╡ a570ebab-64de-4934-b887-77a8e2fb42e8 +u0_opt2_log = [:W => W0_opt2_log] + +# ╔═╡ feee9cc1-ebe2-4c77-a11e-53ca00864ccf +md""" +Setting up parameter values with optimized parameter values: +""" + +# ╔═╡ 73e86176-f314-463c-8821-51c0f3cc1a56 +params_opt2_log = [:μ => μ_opt2_log, :Wf => Wf_opt2_log] + +# ╔═╡ c17c4e00-8688-4f9c-b0ae-741d70601aba +md""" +Next, we create an ODEProblem and solve it: +""" + +# ╔═╡ f751b962-1810-429c-b34b-658b63fa9ba0 +oprob_opt2_log = ODEProblem(growth_log, u0_opt2_log, tspan, params_opt2_log) + +# ╔═╡ 0fd058cc-9bd8-4e12-b5dd-79818519165b +osol_opt2_log = solve(oprob_opt2_log, Tsit5(), saveat=0.5) + +# ╔═╡ 57c95382-69cc-47e7-aa94-4767136bb23b +md""" +Finally, we plot $W$ simulated with the optimized initial value and parameter values together with the measured data that was used to find the optimized values. +""" + +# ╔═╡ 4e07c39b-502d-4b38-ae7f-f103cb4bae16 +begin + plot(osol_opt2_log, label="Logistic growth", xlabel="t", + xlims=(0, 100), ylims=(0, 14), lw=2.0, title="MAP") + scatter!(t_meas, W_meas, label="Yield") +end + +# ╔═╡ 29170e2a-9916-438e-92ca-9f4783397b5e +md""" +### Method - MCMC with NUTS +""" + +# ╔═╡ 7ff9fe52-156b-4a92-9058-781670de3abb +md""" +We will use Markov chain Monte Carlo (MCMC) method in combination with the No U-Turn Sampler (NUTS) here and store the optimization results in `results_log_nuts`. +""" + +# ╔═╡ 0c047043-3284-422a-9c88-2f4f4c170edf +results_log_nuts = sample(growth_log_cond_mod, NUTS(), 1000) + +# ╔═╡ 19c362cb-2764-41c9-a571-2e8e2bfcde93 +summarize(results_log_nuts) + +# ╔═╡ 93db47b2-34e8-43b4-beac-b5620fd444e7 +# Get element at row 'W0', column 'mean' in the summary table: +W0_opt3_log = summarize(results_log_nuts)[:W0, :mean] +# Alternative: +# W0_opt3_log = mean(results_log_nuts[:W0]) + +# ╔═╡ 68c71cd2-6cdc-4b80-b6e7-75bfea344295 +# Get element at row 'μ', column 'mean' in the summary table: +μ_opt3_log = summarize(results_log_nuts)[:μ ,:mean] +# Alternative: +# μ_opt3_log = mean(results_log_nuts[:μ]) + +# ╔═╡ d6b9eaba-1d43-4e56-8fa1-bb2f87f6fe79 +# Get element at row 'Wf', column 'mean' in the summary table: +Wf_opt3_log = summarize(results_log_nuts)[:Wf ,:mean] +# Alternative: +# Wf_opt3_log = mean(results_log_nuts[:Wf]) + +# ╔═╡ b843ee5e-9618-4b50-93db-77e19b4be366 +md""" +Now we can make a plot of $W$ simulated with the optimized initial condition and parameter values. +""" + +# ╔═╡ 58014411-128c-41f4-b192-b815a3a8cc60 +md""" +Setting up initial condition with optimized initial condition: +""" + +# ╔═╡ ecf4b951-9b5f-441a-89f5-b0ccd040ba02 +u0_opt3_log = [:W => W0_opt3_log] + +# ╔═╡ b92bf532-5610-4ce8-b469-154b20cc5956 +md""" +Setting up parameter values with optimized parameter values: +""" + +# ╔═╡ e629fbd1-a7c7-4dc3-8b7d-bdca380fe5ad +params_opt3_log = [:μ => μ_opt3_log, :Wf => Wf_opt3_log] + +# ╔═╡ a48df980-4847-418e-813d-1875d032ffd9 +md""" +Next, we create an ODEProblem and solve it: +""" + +# ╔═╡ 348e7454-c6dc-4d1e-b18b-6b34bc2fc0fc +oprob_opt3_log = ODEProblem(growth_log, u0_opt3_log, tspan, params_opt3_log) + +# ╔═╡ f71f0cf4-b63e-452c-b971-f30d7503f1e5 +osol_opt3_log = solve(oprob_opt3_log, Tsit5(), saveat=0.5) + +# ╔═╡ 8a382a8e-e433-4b17-9649-aac81ebc20f4 +md""" +Optionally, you can get 100 sampled solutions from the posterior parameter distributions in the following way. We will plot these together with the solution based on the mean (optimized) values for the parameters. +""" + +# ╔═╡ ba62d7fe-e30e-4e7b-a9c1-0ddd39abc42c +osol_log_sampled = generated_quantities(growth_log_cond_mod, results_log_nuts[1:10:1000]); + +# ╔═╡ 7346a003-aa05-41e3-a420-c97c1994cf3c +md""" +Finally, we plot $W$ simulated with the optimized initial value and parameter values together with the measured data that was used to find the optimized values. +""" + +# ╔═╡ 20a6f165-449a-42cc-9565-f342a7535422 +begin + h = plot(title="Fit + posterior") # Make empty plot and return handle to it + # We first plot the 20 sampled solutions (this is optional!) + for i in eachindex(osol_log_sampled) + plot!(h, osol_log_sampled[i], color=:blue, opacity=0.2, label=false) + end + # Now we plot the solution based on the mean (optimized) values + plot!(h, osol_opt3_log, label="Logistic growth", xlabel="t", + xlims=(0, 100), ylims=(0, 14), lw=1.5, color=:black) + # Finally, we add the measured values + scatter!(h, t_meas, W_meas, label="Yield") +end + +# ╔═╡ 137bde23-76f2-4ebf-8bc2-ea8640001436 +md""" +## Exercises +""" + +# ╔═╡ 4aa71200-006b-4a15-ae75-67e36aa81522 +md""" +### Exercise 1 - Calibration of the exponential growth model + +Calibrate the initial condition and both parameters of the exponential growth model. Use the values mentioned in the *Table* as initials values for the optimization of the parameters. +""" + +# ╔═╡ cdab3079-04b0-4a44-b770-468c20e321e4 +md""" +We have seen before that a possible *reaction network object* for the exponential growth model can be implemented as follows: +""" + +# ╔═╡ cf1a144e-09e9-42a3-b2a3-b8676a200a39 +growth_exp = @reaction_network begin + μ*Wf, 0 --> W + μ, W --> 0 +end + +# ╔═╡ 85c57cd3-bf00-437e-937b-f0c3b62f74ff +parameters(growth_exp) + +# ╔═╡ c6d373f4-f13c-4135-823d-ee8fbeb71b56 +md""" +Create an `ODEProblem`. Use the values in the aforementioned table as initial values for the problem. Use the same `tspan` as before. +""" + +# ╔═╡ a97abaa7-b642-4201-86f1-5c8995b07536 +# u0_exp = missing # Uncomment and complete the instruction +u0_exp = [:W => 2.0] + +# ╔═╡ 387730b4-bd06-492f-94e6-231bd68b3436 +# params_exp = missing # Uncomment and complete the instruction +params_exp = [:μ => 0.02, :Wf => 10.0] + +# ╔═╡ 290a7fe8-3b1e-423f-8b30-9bd8903d2e8f +# oprob_exp = missing # Uncomment and complete the instruction +oprob_exp = ODEProblem(growth_exp, u0_exp, tspan, params_exp) + +# ╔═╡ febe2b67-2a8f-4575-946d-30877bd5f2d4 +md""" +Use the same measurement data (`W_meas`, `t_meas`) as before. +""" + +# ╔═╡ b4300e8a-8052-419b-98c8-0508ebee2393 +md""" +Declare the Turing model function. +""" + +# ╔═╡ 2c6ae74c-2da4-4867-ad8a-f4e835101d63 +# Uncomment and complete the instruction +# @model function growth_exp_fun(t_meas) +# σ_W ~ missing +# W0 ~ missing +# μ ~ missing +# Wf ~ missing +# u0_exp = missing +# params_exp = missing +# oprob_exp = missing +# osol_exp = missing +# W_s ~ missing +# end +@model function growth_exp_fun(t_meas) + σ_W ~ InverseGamma() + W0 ~ LogNormal() + μ ~ LogNormal() + Wf ~ LogNormal() + u0_exp = [:W => W0] + params_exp = [:μ => μ, :Wf => Wf] + oprob_exp = ODEProblem(growth_exp, u0_exp, tspan, params_exp) + osol_exp = solve(oprob_exp, Tsit5(), saveat=t_meas) + W_s ~ MvNormal(osol_exp[:W], σ_W^2 * I) +end + +# ╔═╡ c6a5d453-d610-4f65-847c-c878dd41726c +md""" +Provide the time measurements to the defined function (this results in the Turing model) and instantly condition the Turing model with the measurements of $W$: +""" + +# ╔═╡ fff17cf7-173d-4f64-94a9-4bf46acc882d +# growth_exp_cond_mod = missing # Uncomment and complete the instruction +growth_exp_cond_mod = growth_exp_fun(t_meas) | (W_s = W_meas,) + +# ╔═╡ eee55784-a641-445e-be75-0b19e2a94754 +md""" +Optimize the priors ($\sigma_W$, $W_0$, $\mu$ and $W_f$). Do this with `MLE` method and Nelder-Mead. Store the optimization results in `results_exp_mle`. +""" + +# ╔═╡ 7844e4f5-3c7d-4b4b-beee-970c998c67a6 +# results_exp_mle = missing # Uncomment and complete the instruction +results_exp_mle = optimize(growth_exp_cond_mod, MLE(), NelderMead()) + +# ╔═╡ c81d0140-3f4e-4eb4-8a77-1f48c5e0ecbf +md""" +Visualize a summary of the optimized parameters. +""" + +# ╔═╡ 7456455b-4f31-488f-990f-6ce534038e08 +# missing # Uncomment and complete the instruction +coeftable(results_exp_mle) + +# ╔═╡ b10c2ce4-d363-429c-a64c-ec29652137a5 +md""" +Get the optimized values and assign them to `W0_opt_exp`, `μ_opt_exp` and `Wf_opt_exp`. +""" + +# ╔═╡ 23b629a6-6866-416a-a768-9617ce6301db +# W0_opt_exp = missing # Uncomment and complete the instruction +W0_opt_exp = coef(results_exp_mle)[:W0] + +# ╔═╡ 8788082d-f5d1-4385-8037-a0d360a841c7 +# μ_opt_exp = missing # Uncomment and complete the instruction +μ_opt_exp = coef(results_exp_mle)[:μ] + +# ╔═╡ 03a4fa85-08db-46d4-bb53-c0ccea90a211 +# Wf_opt_exp = missing # Uncomment and complete the instruction +Wf_opt_exp = coef(results_exp_mle)[:Wf] + +# ╔═╡ 8f5e1413-227c-44fa-bb2d-3653cbc27e38 +md""" +Make a plot of $W$ simulated with the optimized initial condition and parameter values. +""" + +# ╔═╡ 8a7f7aab-878e-41b5-b9da-d06747df042e +md" +Set up initial condition with optimized initial condition: +" + +# ╔═╡ 30602ff1-041b-4fca-bf8e-55ff57df9e37 +# u0_opt_exp = missing # Uncomment and complete the instruction +u0_opt_exp = [:W => W0_opt_exp] + +# ╔═╡ 881011be-6434-416f-915b-3333e8dea32f +md""" +Set up parameter values with optimized parameter values: +""" + +# ╔═╡ 5602b88a-07f8-438b-994c-65f11e17a0ba +# params_opt_exp = missing # Uncomment and complete the instruction +params_opt_exp = [:μ => μ_opt_exp, :Wf => Wf_opt_exp] + +# ╔═╡ 25be4255-0888-4ecd-a2fd-d66402c5cb50 +md""" +Create an ODEProblem and solve it. Use `Tsit5()` and `saveas=0.5`. +""" + +# ╔═╡ 36e8a174-d526-45ee-b3c6-88d698ad5d5f +# oprob_opt_exp = missing # Uncomment and complete the instruction +oprob_opt_exp = ODEProblem(growth_exp, u0_opt_exp, tspan, params_opt_exp) + +# ╔═╡ 7594147d-b3da-4e0d-896d-41baacb6d7be +# osol_opt_exp = missing # Uncomment and complete the instruction +osol_opt_exp = solve(oprob_opt_exp, Tsit5(), saveat=0.5) + +# ╔═╡ 8e047be9-f0f0-4a75-91b5-c523f55f8c67 +md""" +Plot $W$ simulated with the optimized initial value and parameter values together with the measured data that was used to find the optimized values. +""" + +# ╔═╡ 1a9587aa-2356-48df-abcc-2ce874fa5d24 +# Uncomment and complete the instruction +# begin +# missing +# missing +# end +begin + plot(osol_opt_exp, label="Exponential growth", xlabel="t", + xlims=(0, 100),ylims=(0, 14)) + scatter!(t_meas, W_meas, label="Yield") +end + +# ╔═╡ 785d500b-f8ea-446a-9952-2a5fd5d83d24 +md""" +### Exercise 2 - Calibration of the Gompertz growth model + +Calibrate the initial condition and both parameters of the Gompertz growth model. Use the values mentioned in the *Table* as initials values for the optimization of the parameters. +""" + +# ╔═╡ e754826a-7411-4072-b0dc-a4bad7a15f98 +md""" +We have seen before that a possible *reaction network object* for the Gompertz growth model can be implemented as follows: +""" + +# ╔═╡ bc1edcbe-46eb-4531-9c5f-dee8d5dc2ff9 +growth_gom = @reaction_network begin + μ-D*log(W), W --> 2W +end + +# ╔═╡ 47fb9e4c-df6a-4811-9980-99d595a34908 +md""" +Create an `ODEProblem`. Use the values in the aforementioned table as initial values for the problem. Use the same `tspan` as before. +""" + +# ╔═╡ bbd150de-ff9a-4127-a0dd-2f9762f92b07 +# u0_gom = missing # Uncomment and complete the instruction +u0_gom = [:W => 2.0] + +# ╔═╡ da5a0cbb-b033-46f1-a300-3954de138835 +# params_gom = missing # Uncomment and complete the instruction +params_gom = [:μ => 0.09, :D => 0.04] + +# ╔═╡ 73da8f53-c3af-43b0-9b23-60471f1e3587 +# oprob_gom = missing # Uncomment and complete the instruction +oprob_gom = ODEProblem(growth_gom, u0_gom, tspan, params_gom) + +# ╔═╡ b0e67564-efe8-4fb2-bcf2-a711b770244e +md""" +Use the same measurement data (`W_meas`, `t_meas`) as before. +""" + +# ╔═╡ e5081280-d226-4834-8932-c89becd8313c +md""" +Declare the Turing model. Take the same priors as before. +""" +# Take for $\sigma_W$ and $W_0$ the same priors (and distributions) as before, but take for $\mu$ a Uniform prior distribution in the range $[0, 2]$ and the same for $D$ but in the range $[0, 1]$. + +# ╔═╡ c739a908-2353-4e7a-8fbd-f640dc8cabe0 +# Uncomment and complete the instruction +# @model function growth_gom_fun(t_meas) +# σ_W ~ missing +# W0 ~ missing +# μ ~ missing +# D ~ missing +# u0_gom = missing +# params_gom = missing +# oprob_gom = missing +# osol_gom = missing +# W_s ~ missing +# end +@model function growth_gom_fun(t_meas) + σ_W ~ InverseGamma() + W0 ~ LogNormal() + μ ~ LogNormal() + D ~ LogNormal() + u0_gom = [:W => W0] + params_gom = [:μ => μ, :D => D] + oprob_gom = ODEProblem(growth_gom, u0_gom, tspan, params_gom) + osol_gom = solve(oprob_gom, Tsit5(), saveat=t_meas) + W_s ~ MvNormal(osol_gom[:W], σ_W^2 * I) +end + +# ╔═╡ 1d0383ad-54d6-4ff2-8555-def83bfff0e6 +md""" +Provide the time measurements to the defined function (this results in the Turing model) and instantly condition the Turing model with the measurements of $W$: +""" + +# ╔═╡ cd1cf2f8-9f7f-4ed4-9cb7-1a6efee68ab4 +# growth_gom_cond_mod = missing # Uncomment and complete the instruction +growth_gom_cond_mod = growth_gom_fun(t_meas) | (W_s = W_meas,) + +# ╔═╡ aba74ee0-0163-4e15-8b49-d8dcad4839f7 +md""" +Optimize the priors ($\sigma_W$, $W_0$, $\mu$ and $D$). Do this with `MAP` method and Nelder-Mead. Store the optimization results in `results_gom_map`. +""" + +# ╔═╡ 0eda4142-1aaf-4e17-bd78-857e13e94acd +# results_gom_map = missing # Uncomment and complete the instruction +results_gom_map = optimize(growth_gom_cond_mod, MAP(), NelderMead()) + +# ╔═╡ 50629194-98ed-4d45-86a2-95ac22daac29 +md""" +Visualize a summary of the optimized parameters. +""" + +# ╔═╡ 9c239fc6-275c-4d64-9fa2-6fd57295b757 +# missing # Uncomment and complete the instruction +coeftable(results_gom_map) + +# ╔═╡ dede17f2-655d-4871-b6de-5a32804947dd +md""" +Get the optimized values and assign them to `W0_opt_gom`, `μ_opt_gom` and `D_opt_gom`. +""" + +# ╔═╡ e8c3f042-6058-4040-a67e-18563c04ee93 +# W0_opt_gom = missing # Uncomment and complete the instruction +W0_opt_gom = coef(results_gom_map)[:W0] + +# ╔═╡ 665f4d03-3521-475a-a195-f861fd26bb69 +# μ_opt_gom = missing # Uncomment and complete the instruction +μ_opt_gom = coef(results_gom_map)[:μ] + +# ╔═╡ 13775d58-ac61-431c-a6c9-447c1eec7942 +# D_opt_gom = missing # Uncomment and complete the instruction +D_opt_gom = coef(results_gom_map)[:D] + +# ╔═╡ bc92f996-b626-4965-a286-d2c848eb1a21 +md""" +Make a plot of $W$ simulated with the optimized initial condition and parameter values. +""" + +# ╔═╡ e2fde8e9-1f87-4ffe-8dae-2794664bfaa4 +md""" +Set up initial condition with optimized initial condition: +""" + +# ╔═╡ 23fd9fd9-a13c-4c56-a0b4-daec6f1d2cd8 +# u0_opt_gom = missing # Uncomment and complete the instruction +u0_opt_gom = [:W => W0_opt_gom] + +# ╔═╡ 6f414d15-af0a-452a-98a1-dc0b7e54d617 +md""" +Set up parameter values with optimized parameter values: +""" + +# ╔═╡ 57ee8a12-24df-4598-935c-f5e259b504cb +# params_opt_gom = missing # Uncomment and complete the instruction +params_opt_gom = [:μ => μ_opt_gom, :D => D_opt_gom] + +# ╔═╡ 48bc085c-9ce6-4752-a5a9-a814f803f571 +md""" +Create an ODEProblem and solve it. Use `Tsit5()` and `saveas=0.5`. +""" + +# ╔═╡ 5b9b2e5b-9deb-4ff6-a923-b15b8b08f0c9 +# oprob_opt_gom = missing # Uncomment and complete the instruction +oprob_opt_gom = ODEProblem(growth_gom, u0_opt_gom, tspan, params_opt_gom) + +# ╔═╡ 66ee9655-a006-4c0f-b1f1-5576efa8f896 +# osol_opt_gom = missing # Uncomment and complete the instruction +osol_opt_gom = solve(oprob_opt_gom, Tsit5(), saveat=0.5) + +# ╔═╡ 52d7975a-5346-447f-9aad-4ecd11b6460a +md""" +Finally, we plot $W$ simulated with the optimized initial value and parameter values together with the measured data that was used to find the optimized values. +""" + +# ╔═╡ e96efd6a-a666-4120-8480-9423e5d82ae1 +# Uncomment and complete the instruction +# begin +# missing +# missing +# end +begin + plot(osol_opt_gom, label="Gompertz growth", xlabel="t", + xlims=(0, 100), ylims=(0, 14)) + scatter!(t_meas, W_meas, label="Yield") +end + +# ╔═╡ f0b4772d-a72b-44e0-a3a1-ba9ad4c4dfeb +md""" +Which grass growth model fits best these data? How can you prove this numerically? +""" + +# ╔═╡ 7e98a771-52bb-484e-82ab-2e42e7cb4053 +md"- Answer: missing" + +# ╔═╡ Cell order: +# ╠═a09f814a-0c6a-11ef-0e79-a50b01287d63 +# ╠═7f521435-63ac-4178-a4aa-93d9c45fe820 +# ╠═f8a92690-990b-4341-89e1-322adbcb8d1b +# ╠═015050b3-3339-4b1a-ad7d-c358cce73675 +# ╠═dbfe4800-0974-4ca1-bb0a-d8803409a98b +# ╠═6e227e07-166a-41ce-839a-4c4c72addb23 +# ╠═b992c080-a0ce-4188-b632-e734a141e67d +# ╟─37da8786-fea0-4c2f-a76f-6e6c68325a78 +# ╟─4623369d-8c5a-422d-9e40-0f1dd7586260 +# ╟─3cb0a166-ac53-4c3f-9832-e93742040cfb +# ╟─987f0a4d-e416-4ceb-adbe-3dcdca9d0996 +# ╟─75efff36-8da7-4d04-afa2-a2f8324bc103 +# ╟─3dcb9c9d-370b-4031-b7c0-cee80742557a +# ╟─7a14aa59-6e6f-4266-a0b3-84ab55f2efc5 +# ╟─85cd60a8-b448-4375-9b6d-399c4336c319 +# ╠═5b320989-3e0b-447b-bc9a-25fb221ce609 +# ╟─2481cd4f-0efc-4450-ab3d-4a5492597f36 +# ╟─9a5bc72b-346d-4e95-a873-783037ed98bc +# ╠═ba56adb1-9405-40d5-be48-4273b42ab145 +# ╠═6e3e53ea-4fe7-4a34-8b00-cbf8d63a3203 +# ╟─f4748167-b635-47a1-9015-32e1258c0afa +# ╠═a022b2ab-68a0-40ca-b914-7a2adcf4ae39 +# ╟─acccb2fa-12b2-4fc7-91e3-58a4b1a02892 +# ╠═e54ea8d1-0854-44fa-aed8-45d106e921e4 +# ╠═8d96eb17-ce19-4523-916f-3cd0441a16ca +# ╠═5c9db9df-0cbd-41ac-afe9-fb5616c967be +# ╟─1aa44f2b-6f33-437f-b9dd-89762d9f28ea +# ╟─b2b433ed-0266-4bea-a7e8-32adba542d4c +# ╠═7c966a66-0091-4b81-9a7e-02ccd0d3db10 +# ╟─3edd2acc-a865-4675-afef-8868c68256f1 +# ╠═877298e8-b61b-4c3a-ba2c-2827acdcfb50 +# ╟─acb7b123-831f-47e9-92cc-2dd3e57f86fd +# ╠═bab8119a-7fe7-4c6b-abb9-5885a88b55ae +# ╟─ef06cc43-510b-4ff9-b0b7-1c7fc267e9b1 +# ╠═cb2bc6ee-4211-47e1-9956-5cf1b0c0671d +# ╟─d75246d4-e03b-4684-be7d-4bcfb61ed7ef +# ╟─dd3a32f1-bdb6-44a3-acbe-f4269725c9e4 +# ╠═88dd0342-3678-40a2-a432-661e5410e5cf +# ╠═70ff9f12-e924-4daf-ab32-2394feccc953 +# ╟─0ccf1f1d-20be-4c19-bfc6-2748970547a1 +# ╠═6d9d7792-fffa-482d-b785-33482bf2b0ea +# ╟─48c9f616-d298-40da-b917-225abd39b3d9 +# ╠═4987f361-fcce-4453-8872-11d6faf16e86 +# ╠═3d3db44c-db49-436a-9b6e-9f6dd5d6178b +# ╟─35f158c1-858d-4e4d-ac3d-bf4807dad9a0 +# ╠═98a71080-e662-4f1a-88fe-3c575386ec77 +# ╟─a6972aef-63ad-401c-acf5-6d59f9fc6698 +# ╟─73e35289-6dc0-4e2e-83eb-b56f83cdbbbf +# ╟─47bd729c-4851-42f7-a03f-6ceacd3c717e +# ╠═dff0f8c6-1fed-4ef7-a6d3-2c8f345ed724 +# ╟─e55404ab-6762-4f39-bb42-9c195334a214 +# ╠═75ee0ba9-c9f9-496e-bb80-d013328c3ad7 +# ╟─a1ca7d0e-639c-42d4-be09-5c61a2008f29 +# ╠═30399b9a-1d77-4140-9ad3-5eed636a5b99 +# ╠═e1b8e4ba-c1f1-48d5-87a2-edce19c9fe7a +# ╠═a943e0fe-1376-4ef1-9c45-25c6f95e3b96 +# ╟─72e065d4-7b1b-4f46-b373-935be8d801fc +# ╟─0b2ffd6f-01cd-4f11-9062-d38b3c13a5b1 +# ╠═590b1006-0e37-4668-9b4a-3588fab45696 +# ╟─8ff28a2e-185d-4dca-ad3b-a0b1507646d6 +# ╠═14d24cbd-3259-41bb-9013-b4fe25a3be4c +# ╟─6c134677-3ec1-4e0a-88b5-01341a096675 +# ╠═7a81f4a0-8f7c-4e05-9c3f-2438eab9b691 +# ╠═ac80099b-d8f0-4eba-809d-d482bd354d35 +# ╟─b58f2c24-e0ea-48a8-b0b7-d0faf9642340 +# ╠═55eba435-6ca4-4f4f-b08a-be700d5bda91 +# ╟─5d386b00-93b5-4a88-b4e3-e5c3eebd6dd5 +# ╟─6f0e91d0-6b99-4cf1-8145-523589a21e89 +# ╠═209742ca-36bb-42a5-bf8a-291a40c47757 +# ╟─07efb21a-0dac-46d5-b9e1-8f4757c6cedf +# ╠═a93a7eeb-aad1-49f3-a05f-1512adb08b6b +# ╟─ccc66805-efce-4f25-b76b-7cff23901ba4 +# ╠═57ef7d03-a6dc-40da-858d-5f9b9be613cd +# ╠═62bd2e58-343a-4155-a65e-cf326d0975f4 +# ╠═4d6cba88-be68-412d-aeec-28300c26a9da +# ╟─4bc97af7-debc-4170-a2d5-4e6c928e5183 +# ╟─a0033986-4946-45a2-a53e-29c38f35ed5c +# ╠═a570ebab-64de-4934-b887-77a8e2fb42e8 +# ╟─feee9cc1-ebe2-4c77-a11e-53ca00864ccf +# ╠═73e86176-f314-463c-8821-51c0f3cc1a56 +# ╟─c17c4e00-8688-4f9c-b0ae-741d70601aba +# ╠═f751b962-1810-429c-b34b-658b63fa9ba0 +# ╠═0fd058cc-9bd8-4e12-b5dd-79818519165b +# ╟─57c95382-69cc-47e7-aa94-4767136bb23b +# ╠═4e07c39b-502d-4b38-ae7f-f103cb4bae16 +# ╟─29170e2a-9916-438e-92ca-9f4783397b5e +# ╟─7ff9fe52-156b-4a92-9058-781670de3abb +# ╠═0c047043-3284-422a-9c88-2f4f4c170edf +# ╠═19c362cb-2764-41c9-a571-2e8e2bfcde93 +# ╠═93db47b2-34e8-43b4-beac-b5620fd444e7 +# ╠═68c71cd2-6cdc-4b80-b6e7-75bfea344295 +# ╠═d6b9eaba-1d43-4e56-8fa1-bb2f87f6fe79 +# ╟─b843ee5e-9618-4b50-93db-77e19b4be366 +# ╟─58014411-128c-41f4-b192-b815a3a8cc60 +# ╠═ecf4b951-9b5f-441a-89f5-b0ccd040ba02 +# ╟─b92bf532-5610-4ce8-b469-154b20cc5956 +# ╠═e629fbd1-a7c7-4dc3-8b7d-bdca380fe5ad +# ╟─a48df980-4847-418e-813d-1875d032ffd9 +# ╠═348e7454-c6dc-4d1e-b18b-6b34bc2fc0fc +# ╠═f71f0cf4-b63e-452c-b971-f30d7503f1e5 +# ╟─8a382a8e-e433-4b17-9649-aac81ebc20f4 +# ╠═ba62d7fe-e30e-4e7b-a9c1-0ddd39abc42c +# ╟─7346a003-aa05-41e3-a420-c97c1994cf3c +# ╠═20a6f165-449a-42cc-9565-f342a7535422 +# ╟─137bde23-76f2-4ebf-8bc2-ea8640001436 +# ╟─4aa71200-006b-4a15-ae75-67e36aa81522 +# ╟─cdab3079-04b0-4a44-b770-468c20e321e4 +# ╠═cf1a144e-09e9-42a3-b2a3-b8676a200a39 +# ╠═85c57cd3-bf00-437e-937b-f0c3b62f74ff +# ╟─c6d373f4-f13c-4135-823d-ee8fbeb71b56 +# ╠═a97abaa7-b642-4201-86f1-5c8995b07536 +# ╠═387730b4-bd06-492f-94e6-231bd68b3436 +# ╠═290a7fe8-3b1e-423f-8b30-9bd8903d2e8f +# ╟─febe2b67-2a8f-4575-946d-30877bd5f2d4 +# ╟─b4300e8a-8052-419b-98c8-0508ebee2393 +# ╠═2c6ae74c-2da4-4867-ad8a-f4e835101d63 +# ╟─c6a5d453-d610-4f65-847c-c878dd41726c +# ╠═fff17cf7-173d-4f64-94a9-4bf46acc882d +# ╟─eee55784-a641-445e-be75-0b19e2a94754 +# ╠═7844e4f5-3c7d-4b4b-beee-970c998c67a6 +# ╟─c81d0140-3f4e-4eb4-8a77-1f48c5e0ecbf +# ╠═7456455b-4f31-488f-990f-6ce534038e08 +# ╟─b10c2ce4-d363-429c-a64c-ec29652137a5 +# ╠═23b629a6-6866-416a-a768-9617ce6301db +# ╠═8788082d-f5d1-4385-8037-a0d360a841c7 +# ╠═03a4fa85-08db-46d4-bb53-c0ccea90a211 +# ╟─8f5e1413-227c-44fa-bb2d-3653cbc27e38 +# ╟─8a7f7aab-878e-41b5-b9da-d06747df042e +# ╠═30602ff1-041b-4fca-bf8e-55ff57df9e37 +# ╟─881011be-6434-416f-915b-3333e8dea32f +# ╠═5602b88a-07f8-438b-994c-65f11e17a0ba +# ╟─25be4255-0888-4ecd-a2fd-d66402c5cb50 +# ╠═36e8a174-d526-45ee-b3c6-88d698ad5d5f +# ╠═7594147d-b3da-4e0d-896d-41baacb6d7be +# ╟─8e047be9-f0f0-4a75-91b5-c523f55f8c67 +# ╠═1a9587aa-2356-48df-abcc-2ce874fa5d24 +# ╟─785d500b-f8ea-446a-9952-2a5fd5d83d24 +# ╟─e754826a-7411-4072-b0dc-a4bad7a15f98 +# ╠═bc1edcbe-46eb-4531-9c5f-dee8d5dc2ff9 +# ╟─47fb9e4c-df6a-4811-9980-99d595a34908 +# ╠═bbd150de-ff9a-4127-a0dd-2f9762f92b07 +# ╠═da5a0cbb-b033-46f1-a300-3954de138835 +# ╠═73da8f53-c3af-43b0-9b23-60471f1e3587 +# ╟─b0e67564-efe8-4fb2-bcf2-a711b770244e +# ╟─e5081280-d226-4834-8932-c89becd8313c +# ╠═c739a908-2353-4e7a-8fbd-f640dc8cabe0 +# ╟─1d0383ad-54d6-4ff2-8555-def83bfff0e6 +# ╠═cd1cf2f8-9f7f-4ed4-9cb7-1a6efee68ab4 +# ╟─aba74ee0-0163-4e15-8b49-d8dcad4839f7 +# ╠═0eda4142-1aaf-4e17-bd78-857e13e94acd +# ╟─50629194-98ed-4d45-86a2-95ac22daac29 +# ╠═9c239fc6-275c-4d64-9fa2-6fd57295b757 +# ╟─dede17f2-655d-4871-b6de-5a32804947dd +# ╠═e8c3f042-6058-4040-a67e-18563c04ee93 +# ╠═665f4d03-3521-475a-a195-f861fd26bb69 +# ╠═13775d58-ac61-431c-a6c9-447c1eec7942 +# ╟─bc92f996-b626-4965-a286-d2c848eb1a21 +# ╟─e2fde8e9-1f87-4ffe-8dae-2794664bfaa4 +# ╠═23fd9fd9-a13c-4c56-a0b4-daec6f1d2cd8 +# ╟─6f414d15-af0a-452a-98a1-dc0b7e54d617 +# ╠═57ee8a12-24df-4598-935c-f5e259b504cb +# ╟─48bc085c-9ce6-4752-a5a9-a814f803f571 +# ╠═5b9b2e5b-9deb-4ff6-a923-b15b8b08f0c9 +# ╠═66ee9655-a006-4c0f-b1f1-5576efa8f896 +# ╟─52d7975a-5346-447f-9aad-4ecd11b6460a +# ╠═e96efd6a-a666-4120-8480-9423e5d82ae1 +# ╟─f0b4772d-a72b-44e0-a3a1-ba9ad4c4dfeb +# ╟─7e98a771-52bb-484e-82ab-2e42e7cb4053 diff --git a/exercises/calib_irrigation_sol.jl b/exercises/calib_irrigation_sol.jl index 0211dbc4..b70bee54 100644 --- a/exercises/calib_irrigation_sol.jl +++ b/exercises/calib_irrigation_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 2b010e5c-1121-11ef-16fe-a5e3317122e4 @@ -39,14 +39,14 @@ md" # ╔═╡ 8f1afdec-b78d-4aba-a74f-cd3e4b35fab1 md""" -In one of the previous practica we were introduced to an irrigation experiment carried out on a soil column consisting of two layers of soil, each with specific soil characteristics. However, here the volume of water per unit of time, $R$, irrigated evenly over the soil column, will be kept constant at $5\;mm\,h^{-1}$ in these new experiments. +In one of the previous practica we were introduced to an irrigation experiment carried out on a soil column consisting of two layers of soil, each with specific soil characteristics. However, here the volume of water per unit of time, $r$, irrigated evenly over the soil column, will be kept constant at $5\;mm\,h^{-1}$ in these new experiments. The water falls on the upper layer and percolates to the lower layer. The relative moisture content in both layers (i.e., relative to their residual moisture contents) is denoted by $S_1$ and $S_2$. A model description of the relative moisture content in both soil layers is given by: $$\begin{align} -\frac{dS_1}{dt} &= R\left(1-\cfrac{S_{1,res}}{S_{max}}\right) - \cfrac{R}{S_{max}}S_1 - \cfrac{k}{S_{max}}S_1 \\ +\frac{dS_1}{dt} &= r\left(1-\cfrac{S_{1,res}}{S_{max}}\right) - \cfrac{r}{S_{max}}S_1 - \cfrac{k}{S_{max}}S_1 \\ \frac{dS_2}{dt} &= \cfrac{k}{S_{max}}S_1 - v \,S_2^2 \end{align}$$ @@ -62,8 +62,8 @@ The *reaction network object* for this model could be set up as: irrigation_mod = @reaction_network begin k/Smax, S1 --> S2 v, 2S2 --> 0 - R * (1 - S1res / Smax), 0 --> S1 - R/Smax, S1 --> 0 + r * (1 - S1res / Smax), 0 --> S1 + r/Smax, S1 --> 0 end # ╔═╡ e5d7520d-fd8c-48c0-bd36-826766212217 @@ -143,57 +143,56 @@ tspan = (0.0, 150.0) # ╔═╡ 777ce59f-c849-4a2e-a6dc-ae309d2a2e7c # params = missing # Uncomment and complete the instruction -params = [:k => 3.0, :Smax => 150.0, :v => 1e-3, :R => 5.0, :S1res => 10.0] +params = [:k => 3.0, :Smax => 150.0, :v => 1e-3, :r => 5.0, :S1res => 10.0] # ╔═╡ 43b83336-aea6-4914-bc26-b2e84994ce57 oprob = ODEProblem(irrigation_mod, u0, tspan, params) # ╔═╡ 923d04ce-b4d2-44b0-afff-7062c4628ad0 md""" -Declare the Turing model. Make sure you take both experiments into account for optimizing $k$ and $S_{max}$. +Declare the Turing model. Make sure you take both experiments into account for optimizing $k$ and $S_{max}$. Use `InverseGamma` for the standard deviations of the measurements and `LogNormal` for `k` and a `Uniform` (between 100 and 200) for `Smax`. """ # ╔═╡ 481eb8b9-5de2-4f68-b06a-ec18e054c9f5 # Uncomment and complete the instruction -# @model function irrigation_inference(t_meas, S1_meas1, S2_meas1, S1_meas2, S2_meas2) +# @model function irrigation_fun(t_meas) # σ_S1 ~ missing # σ_S2 ~ missing # k ~ missing # Smax ~ missing # osol1 = missing -# S1_meas1 ~ missing -# S2_meas1 ~ missing +# S1_s1 ~ missing +# S2_s1 ~ missing # osol2 = missing -# S1_meas2 ~ missing -# S2_meas2 ~ missing +# S1_s2 ~ missing +# S2_s2 ~ missing # end -@model function irrigation_inference(t_meas, S1_meas1, S2_meas1, S1_meas2, S2_meas2) +@model function irrigation_fun(t_meas) σ_S1 ~ InverseGamma() σ_S2 ~ InverseGamma() - # k ~ Uniform(0, 10) k ~ LogNormal() Smax ~ Uniform(100, 200) - params = [:k => k, :Smax => Smax, :v => 1e-3, :R => 5.0, :S1res => 10.0] + params = [:k => k, :Smax => Smax, :v => 1e-3, :r => 5.0, :S1res => 10.0] u0 = [:S1 => 0.0, :S2 => 0.0] oprob = ODEProblem(irrigation_mod, u0, tspan, params) osol1 = solve(oprob, Tsit5(), saveat=t_meas) - S1_meas1 ~ MvNormal(osol1[:S1], σ_S1^2 * I) - S2_meas1 ~ MvNormal(osol1[:S2], σ_S2^2 * I) + S1_s1 ~ MvNormal(osol1[:S1], σ_S1^2 * I) + S2_s1 ~ MvNormal(osol1[:S2], σ_S2^2 * I) u0 = [:S1 => 140.0, :S2 => 135.0] oprob = ODEProblem(irrigation_mod, u0, tspan, params) osol2 = solve(oprob, Tsit5(), saveat=t_meas) - S1_meas2 ~ MvNormal(osol2[:S1], σ_S1^2 * I) - S2_meas2 ~ MvNormal(osol2[:S2], σ_S2^2 * I) + S1_s2 ~ MvNormal(osol2[:S1], σ_S1^2 * I) + S2_s2 ~ MvNormal(osol2[:S2], σ_S2^2 * I) end # ╔═╡ df933ae8-1f51-4467-93a7-33f153e5e4f8 md""" -Provide the measurements to the Turing model. +Provide the time measurements to the defined function and instantly condition the model with the measurements of $S_1$ and $S_2$ from both experiments: """ # ╔═╡ 0e2aa675-9e09-4e06-b5f8-118707ee652a -# irrigation_inf = missing # Uncomment and complete the instruction -irrigation_inf = irrigation_inference(t_meas, S1_meas1, S2_meas1, S1_meas2, S2_meas2) +# irrigation_cond_mod = missing # Uncomment and complete the instruction +irrigation_cond_mod = irrigation_fun(t_meas) | (S1_s1 = S1_meas1, S2_s1 = S2_meas1, S1_s2 = S1_meas2, S2_s2 = S2_meas2,) # ╔═╡ f7f47956-7c3b-44cc-bff7-fb7d32af874a md""" @@ -202,7 +201,7 @@ Optimize the priors ($\sigma_{S1}$, $\sigma_{S2}$, $k$ and $S_{max}$). Do this w # ╔═╡ 8c254d5a-225b-4772-9fdd-e9f700495fbd # results_mle = missing # Uncomment and complete the instruction -results_mle = optimize(irrigation_inf, MLE(), NelderMead()) +results_mle = optimize(irrigation_cond_mod, MLE(), NelderMead()) # ╔═╡ f15a1df5-047a-4f46-9419-8492ac1248e0 md""" @@ -211,7 +210,7 @@ Visualize a summary of the optimized parameters. # ╔═╡ 00d944e4-2c88-4a5d-b809-69f435df4684 # missing # Uncomment and complete the instruction -results_mle |> coeftable +coeftable(results_mle) # ╔═╡ 89eb31ef-b24f-44c8-bbe5-19101d859937 md""" @@ -238,7 +237,7 @@ Set up parameter values with optimized parameter values: # ╔═╡ 97d53e48-590a-485b-bcf3-edc6a6124faf # params_opt = missing # Uncomment and complete the instruction -params_opt = [:k => k_opt, :Smax => Smax_opt, :v => 1e-3, :R => 5.0, :S1res => 10.0] +params_opt = [:k => k_opt, :Smax => Smax_opt, :v => 1e-3, :r => 5.0, :S1res => 10.0] # ╔═╡ dfd2ac98-5cdc-4627-b6cf-71b33c0ff0d4 md""" @@ -300,6 +299,14 @@ begin scatter!(t_meas, S2_meas2, label="S2 meas2", color=:red) end +# ╔═╡ 3c243670-2ba7-4396-8c6d-084726636741 +md""" +Do your simulations fit well the measurements? +""" + +# ╔═╡ 1aeb0d86-b276-4bd6-9811-faf4a297ae6f +md"- Answer: missing" + # ╔═╡ Cell order: # ╠═2b010e5c-1121-11ef-16fe-a5e3317122e4 # ╠═6750d246-8e7a-4cfb-810e-d1100aa4fdef @@ -355,3 +362,5 @@ end # ╠═fe8f4961-68bd-42dc-a3f5-6692e918e241 # ╠═7f280230-7846-4529-a2ff-a81a2b9480bf # ╠═ad9818a9-ccbe-4645-8b91-0c3fa773632a +# ╟─3c243670-2ba7-4396-8c6d-084726636741 +# ╠═1aeb0d86-b276-4bd6-9811-faf4a297ae6f diff --git a/exercises/ode_model_anaerobic_fermentation.jl b/exercises/ode_model_anaerobic_fermentation.jl index 5da2b792..4ece37c9 100644 --- a/exercises/ode_model_anaerobic_fermentation.jl +++ b/exercises/ode_model_anaerobic_fermentation.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 84e21b44-a1b0-11ef-014d-c58a169e3de3 @@ -128,7 +128,7 @@ Create the ODE problem and store it in `oprob1`: """ # ╔═╡ 04816732-3419-40e3-a927-d6e102949553 -# oprob1 = missing # Uncomment and complete the instruction +# oprob1 = missing; # Uncomment and complete the instruction # ╔═╡ 9a517512-a7c0-4a92-a104-b19a8bf786c7 md""" @@ -241,7 +241,7 @@ Create the ODE problem and store it in `oprob2`: """ # ╔═╡ 18a3513f-8ecc-4c2f-bb39-5d0cb39a3d92 -# oprob2 = missing # Uncomment and complete the instruction +# oprob2 = missing; # Uncomment and complete the instruction # ╔═╡ 5318708e-3410-4675-8162-827c0c6e039c md""" @@ -348,7 +348,7 @@ Create a new ODE problem. """ # ╔═╡ 16d0d671-464c-4de3-bd73-593e1a73168b -# oprob3 = missing # Uncomment and complete the instruction +# oprob3 = missing; # Uncomment and complete the instruction # ╔═╡ 66015536-5f23-45b5-8d57-f1d27d604f8c md""" diff --git a/exercises/ode_model_anaerobic_fermentation_sol.jl b/exercises/ode_model_anaerobic_fermentation_sol.jl index f3c3f7fd..5d3a5091 100644 --- a/exercises/ode_model_anaerobic_fermentation_sol.jl +++ b/exercises/ode_model_anaerobic_fermentation_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 84e21b44-a1b0-11ef-014d-c58a169e3de3 @@ -141,7 +141,7 @@ Create the ODE problem and store it in `oprob1`: # ╔═╡ 04816732-3419-40e3-a927-d6e102949553 # oprob1 = missing # Uncomment and complete the instruction -oprob1 = ODEProblem(anaerobic_fermentation1, u01, tspan1, params1) +oprob1 = ODEProblem(anaerobic_fermentation1, u01, tspan1, params1); # ╔═╡ 9a517512-a7c0-4a92-a104-b19a8bf786c7 md""" @@ -280,7 +280,7 @@ Create the ODE problem and store it in `oprob2`: # ╔═╡ 18a3513f-8ecc-4c2f-bb39-5d0cb39a3d92 # oprob2 = missing # Uncomment and complete the instruction -oprob2 = ODEProblem(anaerobic_fermentation2, u02, tspan2, params2) +oprob2 = ODEProblem(anaerobic_fermentation2, u02, tspan2, params2); # ╔═╡ 5318708e-3410-4675-8162-827c0c6e039c md""" @@ -399,7 +399,7 @@ Create a new ODE problem. # ╔═╡ 16d0d671-464c-4de3-bd73-593e1a73168b # oprob3 = missing # Uncomment and complete the instruction -oprob3 = ODEProblem(anaerobic_fermentation3_c_com, u02, tspan2, params2) +oprob3 = ODEProblem(anaerobic_fermentation3_c_com, u02, tspan2, params2); # ╔═╡ 66015536-5f23-45b5-8d57-f1d27d604f8c md""" diff --git a/exercises/ode_model_birth_death.jl b/exercises/ode_model_birth_death.jl index 1203f546..df88fff5 100644 --- a/exercises/ode_model_birth_death.jl +++ b/exercises/ode_model_birth_death.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 4a3d066c-f5b1-11ee-0145-2da7c11147a5 @@ -105,7 +105,7 @@ Create the ODE problem and store it in `oprob`: """ # ╔═╡ 9432f90b-7141-4518-b6fd-d55a1389e14a -# oprob = missing # Uncomment and complete the instruction +# oprob = missing; # Uncomment and complete the instruction # ╔═╡ ab197ac7-413b-4305-8352-2723bf9f2aff md""" @@ -170,7 +170,7 @@ Create the ODE problem and store it in `oprob2`: """ # ╔═╡ 65e24cee-06c3-4cb7-8f8c-61e02b7dcd29 -# oprob2 = missing # Uncomment and complete the instruction +# oprob2 = missing; # Uncomment and complete the instruction # ╔═╡ 9cab94b5-6d2d-4b5a-96f3-3b8eee1c61a1 md""" diff --git a/exercises/ode_model_birth_death_sol.jl b/exercises/ode_model_birth_death_sol.jl index 236fc70d..dfc849f0 100644 --- a/exercises/ode_model_birth_death_sol.jl +++ b/exercises/ode_model_birth_death_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 4a3d066c-f5b1-11ee-0145-2da7c11147a5 @@ -115,7 +115,7 @@ Create the ODE problem and store it in `oprob`: # ╔═╡ 9432f90b-7141-4518-b6fd-d55a1389e14a # oprob = missing # Uncomment and complete the instruction -oprob = ODEProblem(birth_death, u0, tspan, params) +oprob = ODEProblem(birth_death, u0, tspan, params); # ╔═╡ ab197ac7-413b-4305-8352-2723bf9f2aff md""" @@ -145,6 +145,18 @@ Interpret the results. Ask yourself the following questions: # ╔═╡ f5718c08-c8aa-4d74-b70f-8c08c6decab2 md"- Answer: missing" +# ╔═╡ e26db23b-82ac-4a67-9580-a3125cd10fc8 +osol[:X][end] + +# ╔═╡ 50ec2f87-c10f-42c9-99bd-ad6ca496a6f7 +u_guess = [:X => osol[:X][end]] + +# ╔═╡ be84871f-dfc5-4cf9-98b5-8eab1472cd52 +sol_eq = solve(SteadyStateProblem(ODEProblem(birth_death, u_guess, tspan, params))) + +# ╔═╡ 8a768ce3-bc6f-4ce2-bd7f-34d6718bde1d +sol_eq[:X] + # ╔═╡ fe4526c8-4504-4d91-841a-a83aeef55fc7 md""" ## Part 2 @@ -186,7 +198,7 @@ Create the ODE problem and store it in `oprob2`: # ╔═╡ 65e24cee-06c3-4cb7-8f8c-61e02b7dcd29 # oprob2 = missing # Uncomment and complete the instruction -oprob2 = ODEProblem(birth_death2_com, u0, tspan, params) +oprob2 = ODEProblem(birth_death2_com, u0, tspan, params); # ╔═╡ 9cab94b5-6d2d-4b5a-96f3-3b8eee1c61a1 md""" @@ -207,7 +219,7 @@ Plot the results: plot(osol2) # ╔═╡ 86e7af42-acb4-45e4-9a05-1c3ee2733dae -# osol2.u[end] +osol2[:X][end] # ╔═╡ 1f869579-7019-4120-8d14-b38f48d05bdd md""" @@ -256,6 +268,10 @@ md"- Answer: missing" # ╠═83e36e63-7e6b-4c17-8f7d-ed0e07f36fc5 # ╟─5fc64787-795c-4e17-b751-cd3683f8016b # ╟─f5718c08-c8aa-4d74-b70f-8c08c6decab2 +# ╠═e26db23b-82ac-4a67-9580-a3125cd10fc8 +# ╠═50ec2f87-c10f-42c9-99bd-ad6ca496a6f7 +# ╠═be84871f-dfc5-4cf9-98b5-8eab1472cd52 +# ╠═8a768ce3-bc6f-4ce2-bd7f-34d6718bde1d # ╟─fe4526c8-4504-4d91-841a-a83aeef55fc7 # ╟─1e869025-c537-4bf1-9c38-93e24b598156 # ╠═1c5d8daa-5c7e-49ef-a6da-6459a1131320 diff --git a/exercises/ode_model_catalyst_intro.jl b/exercises/ode_model_catalyst_intro.jl index 008548e3..13e87126 100644 --- a/exercises/ode_model_catalyst_intro.jl +++ b/exercises/ode_model_catalyst_intro.jl @@ -20,7 +20,7 @@ end begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ be326550-25ea-4c5f-ac4a-dd74d12bc89a @@ -150,6 +150,8 @@ The following code creates a so called *reaction network object*, that we have n # ╔═╡ 7d2f8bf9-3a00-4631-84ff-1a36b6d7e19b infection_model = @reaction_network begin + @species S(t)=9_999_000.0 I(t)=0.0 + @parameters α=1e-6 α * β, S + I --> 2I r * m, I --> D r * (1 - m), I --> R @@ -168,8 +170,8 @@ The substrates and the products may contain one or more reactants, separated by # ╔═╡ bb5578b8-40d4-48c9-be87-cfaeadb8c5f9 md""" -!!! hint "Hint" -The Greek letters can be visualized by typing a **backslash** followed by the **name of the Greek letter** and then the **TAB** key. For example `\alpha` followed by the TAB key results in in a list where you can choose `α`. +!!! tip "Tip" + The Greek letters can be visualized by typing a **backslash** followed by the **name of the Greek letter** and then the **TAB** key. For example `\alpha` followed by the TAB key results in in a list where you can choose `α`. """ # ╔═╡ af6b169d-55c3-4384-9f57-ad629e02bad6 @@ -196,7 +198,7 @@ parameters(infection_model) # ╔═╡ 2bd02577-7321-46b5-9f42-1484ed86d1d3 md""" !!! important "Important" -You can also get the different species and parameters using `@unpack` followed by comma separated species and/or parameter names followed by the equal sign and the name of the reaction network model. For example: + You can also get the different species and parameters using `@unpack` followed by comma separated species and/or parameter names followed by the equal sign and the name of the reaction network model. For example: """ # ╔═╡ 64455b26-4374-435f-b71b-8b9600cab263 @@ -212,7 +214,7 @@ osys = convert(ODESystem, infection_model) # ╔═╡ eeb25e50-165b-4e93-8397-5b09fe8e7242 md""" -Note that the model equations are essencially: +Note that the model equations are essentially: $$\cfrac{dS(t)}{dt} = -\alpha \beta S(t) I(t)$$ $$\cfrac{dI(t)}{dt} = \alpha \beta S(t) I(t) - r I(t)$$ @@ -248,18 +250,18 @@ parameters(osys) md""" ### Simulating the system as an ODE-problem -We first need to load the Differential and Plot package, which is required for simulating the system and plotting the results. +We first need to load the `DifferentialEquations` and `Plots` packages, which are required for simulating the system and plotting the results. """ # ╔═╡ 3197244f-655b-4dca-80f3-794b30722551 md""" -Now we wish to simulate our model. To do this, we need to provide some the following information: +Now we wish to simulate our model. To do this, we need to provide the following information: - Initial conditions for the state variables $S$, $I$, $D$ and $R$. - The parameter values for $\alpha$, $\beta$, $r$ and $m$. - The timespan, which is the timeframe over which we wish to run the simulation. -Assume in this example that there are $10\,000\,000$ people in the country, and that initially $1\,000$ person are infected. Hence, $I_0 = 1\,000$, $S_0 = 10\,000\,000-I_0 = 9\,999\,000$, $D_0 = 0$ and $R_0 = 0$.\ +Assume in this example that there are $10\,000\,000$ people in the country, and that initially $1\,000$ persons are infected. Hence, $I_0 = 1\,000$, $S_0 = 10\,000\,000-I_0 = 9\,999\,000$, $D_0 = 0$ and $R_0 = 0$.\ Furthermore, we take the following values for the parameters: $\alpha = 0.08\;person/contact$, $\beta = 10^{-6}\;contact/(person^2\,day)$, $r = 0.2\;day^{-1}$ (i.e. a person is contagious for an average of $5\;days$) and $m=0.4$. The following table summarizes the above values: |Initial conditions |Parameters | @@ -279,7 +281,7 @@ md""" # ╔═╡ 1ba859fa-46a5-434f-a99c-e710ba85caf8 md""" -The initial conditions are given as a *Vector*. This is a type which collects several different values. To declare a vector, the values are specific within brackets, `[]`, and separated by `,`. Since we have four species, the vector holds four elements. E.g., we set the value of $I$ using the `:I => 1` syntax. Here, we first denote the name of the species (with a colon `:` pre-appended), next follows a `=>` and then the value of `I`.\ +The initial conditions are given as a *Vector*. This is a type which collects several different values. To declare a vector, the values are specified within brackets, `[]`, and separated by `,`. Since we have four species, the vector holds four elements. E.g., we set the value of $I$ using the `:I => 1` syntax. Here, we first denote the name of the species (with a colon `:` pre-appended), next follows a `=>` and then the value of `I`.\ The vector holding the initial conditions for $S$, $I$, $D$ and $R$ can be created in the following way: """ @@ -288,7 +290,7 @@ u0 = [:S => 9_999_000.0, :I => 1_000.0, :D => 0.0, :R => 0.0] # ╔═╡ 95c1c0ea-51d0-47ee-8948-a5b87c42a70d md" -Note that the order of the vector elements doesn't matter, because the initial values of each of the species is indicated using its variable name. +Note that the order of the vector elements doesn't matter here, since the initial values of each of the species is indicated using its variable name. " # ╔═╡ 57036f49-2f1f-4327-89ed-2c96098a1c22 @@ -298,7 +300,7 @@ md""" # ╔═╡ 56ebb72d-2351-4e67-b268-1f48bbb77cb3 md""" -The timespan sets the time point at which we start the simulation (typically `0.0` is used) and the final time point of the simulation. These are combined into a two-valued Tuple. Tuples are similar to vectors, but are enclosed by `()` and not `[]`. Again, we will let both time points be decimal valued. +The timespan sets the time point at which we start the simulation (typically `0.0` is used) and the final time point of the simulation. These are combined into a two-valued *Tuple*. Tuples are similar to vectors, but are enclosed by `()` and not `[]`. Again, we will let both time points be decimal valued. """ # ╔═╡ a25d5925-a254-488b-b782-d29cff4470a2 @@ -311,7 +313,7 @@ md""" # ╔═╡ a235c7ce-f14a-4c7c-86a1-08aa5f2d9c85 md""" -Similarly, the parameters values are also given as a vector. We have four parameters, hence, the parameter vector will also contain four elements. We use a similar notation for setting the parameter values as the initial condition (first the colon, then the parameter name, then an arrow, then the value). +Similarly, the parameter values are also given as a vector. We have four parameters, hence, the parameter vector will also contain four elements. We use a similar notation for setting the parameter values as the initial condition (first the colon, then the parameter name, then an arrow, then the value). """ # ╔═╡ 9a9440fa-d8a3-44bc-8037-4bf1f8af40b0 @@ -328,7 +330,7 @@ Next, before we can simulate our model, we bundle all the required information t " # ╔═╡ c6d2dd69-8c61-4a40-894f-664b2d2d14be -oprob = ODEProblem(infection_model, u0, tspan, params) +oprob = ODEProblem(infection_model, u0, tspan, params); # ╔═╡ 3c253bf3-886d-4e86-82ac-7751d23f342f md""" @@ -358,7 +360,7 @@ md""" # ╔═╡ 0af3c166-46b6-455d-af6b-a72c4d2a5ce4 md""" -Finally, we can plot the solution through the plot function. +Finally, we can plot the solution through the `plot` function. """ # ╔═╡ 513c037b-c54c-47fa-b97a-06f69a983386 @@ -374,7 +376,7 @@ plot(osol, idxs=[:S, :I]) # brackets [ ] # ╔═╡ f3cf01a1-3c65-4a37-bf9a-cd2233cb470b md""" -If you want a fase plot of for example just $I$ versus $S$, you can specify this with the option `idxs=(:S, :I)` (*notice the parentheses*) in the plot function. You can indicate the $S$ and $I$ axes with the additional options `xlab="S"` and `ylab="I"`. +If you want a phase plot of, for example, just $I$ versus $S$, you can specify this with the option `idxs=(:S, :I)` (*notice the parentheses*) in the plot function. You can indicate the $S$ and $I$ axes with the additional options `xlab="S"` and `ylab="I"`. """ # ╔═╡ ff8f4c23-5695-48aa-9965-02677103f2c9 @@ -437,7 +439,7 @@ You may have noticed that while using the Pluto notebooks, when you change the v md""" ### Example 1 - Influence of $r$ -Influence of the duration of infection $1/r$ for average infection periods of between $10$, days and $1$ day contagious ($r$ between $0.1$ and $1.0$, step $0.1$, default value $0.1$). +Influence of the duration of infection $1/r$ for average infection periods of between $10$ days and $1$ day of being contagious ($r$ between $0.1$ and $1.0$, step $0.1$, default value $0.1$). """ # ╔═╡ b6baafc2-6d5e-43c3-8ef9-845961cdd20b @@ -446,18 +448,21 @@ We will create a slider for the $r$-values between $0.1$ and $1.0$, stepsize $0. """ # ╔═╡ cd32beba-67cf-4b12-a77b-99f96263f0a4 -@bind r Slider(0.1:0.1:1, default=0.1, show_value=true) +# @bind r Slider(0.1:0.1:1, default=0.1, show_value=true) # ╔═╡ ae38c663-0ee4-409e-bfca-5f13ed88b67d md""" -We will create een new parameter value vector, ODE problem and solution object by putting `1` at the end of the corresponding variable names. In that way, the previous simulation results will be unaffected! The model, the initial conditions and the timespan are identical as before. In there we also use the variable `r` coupled to the slider. +We will create a new parameter value vector, ODE problem and solution object by putting `1` at the end of the corresponding variable names. In that way, the previous simulation results will be unaffected! The model, the initial conditions and the timespan are identical as before. In there we also use the variable `r` coupled to the slider. """ +# ╔═╡ b65e948d-b13a-4021-a545-b7912fd86e94 +@bind r Slider(0.1:0.1:1, default=0.1, show_value=true) + # ╔═╡ d44da6c6-c93d-4c61-8125-9eee464c897e params1 = [:α => 0.08, :β => 1.0e-6, :r => r, :m => 0.4] # ╔═╡ 00a72697-d36a-41cc-9eec-8e821829ce0e -# put semi-colon at end of instruction to avoid seeing its output. +# type a semi-colon at end of an instruction to avoid seeing its output oprob1 = ODEProblem(infection_model, u0, tspan, params1); # ╔═╡ cf39b4cf-9cd0-4755-80db-ca4aea7c1084 @@ -471,33 +476,16 @@ md""" Now, change the value of $r$ in the `param1` vector and analyze the effect in the plot. """ -# ╔═╡ f6cbafbf-98b4-4286-86d2-fe95821a5ff4 -md""" -Try to interpret the results yourself. -Ask yourself the following questions: - -1. What are the trends in the results obtained? -""" - -# ╔═╡ ff9ce0c5-931f-44f4-aa0d-4aead0284160 -md"- Answer: missing" - -# ╔═╡ f5f98168-119c-4b49-a8e3-a3cc775faeb0 -md"""2. How can this be explained from the model structure?""" - -# ╔═╡ a308de53-80a2-4b37-a752-cb2c383cf7a4 -md"- Answer: missing" - # ╔═╡ ade413c2-d7d9-4250-8490-75534900a389 md""" ### Example 2 - Discrete Event -Suppose that regulations are such that on day 14, people need to reduce their contacts by 50%. Hence, this means that the parameter value $\beta$ needs to be divided by a factor of 2 at timepoint 14. In order to realize that we need to now the order of the parameters in the model because we will need to address the value of $\beta$ by means of an index. +Suppose that regulations are such that on day 14, people need to reduce their contacts by 50%. Hence, this means that the parameter value $\beta$ needs to be divided by a factor of 2 at timepoint 14. """ # ╔═╡ 58730ac6-d83b-420d-a000-2f50545f0d39 md""" -We need to state that the parameter $\beta$ needs to be reduce by $50\%$ at time $t=14\,days$. We put this in a condition named `condition2`. +We need to state that the parameter $\beta$ needs to be reduced by $50\%$ at time $t=14$. We include this condition in a variable named `condition2` in the following way: """ # ╔═╡ 7411474c-fac7-4b7c-8ded-4c2df5956fb0 @@ -505,7 +493,7 @@ condition2 = [14.0] => [infection_model.β ~ infection_model.β/2] # ╔═╡ e6949052-6d12-4414-ac67-cb9435b46290 md""" -The discrete time event needs to be included in our model. +The discrete time event needs to be now included in our model. """ # ╔═╡ 8752373f-a602-437b-9b3a-2602c8babf87 @@ -513,7 +501,7 @@ The discrete time event needs to be included in our model. # ╔═╡ ee596a6c-29bf-4d18-b687-be943c128aa7 md""" -After that, we need to *complete* our *reaction network model*. +After that, we need to *complete* our *reaction network model*, so that the model can be simulated. """ # ╔═╡ 40f849cb-20f9-4bbe-806e-512abd6f3210 @@ -525,7 +513,7 @@ Then we need to create a new ODE problem. """ # ╔═╡ 4a6f357c-afd7-4b0d-b1d2-15f5c0e4298b -oprob2 = ODEProblem(infection_model2_com, u0, tspan, params) +oprob2 = ODEProblem(infection_model2_com, u0, tspan, params); # ╔═╡ e76e77be-9f15-4aa5-8506-cdb32a6ec9b1 md""" @@ -541,7 +529,11 @@ Now we can plot the results. """ # ╔═╡ 0af84963-ca64-4958-a544-42d445da5a7c -plot(osol2) +# We can compare the result now to the solution without contact reduction +begin + plot(osol2) + plot!(osol; linestyle=:dash, label=:none, color=:grey, lw=0.5) +end # ╔═╡ 18151ab1-1e4e-48d8-be70-4fa4c8a43af1 md""" @@ -553,21 +545,18 @@ osol2.u[end] # ╔═╡ 7375edbc-24a4-4300-bdef-2686cb377cfc md""" -Try to interpret the results yourself. Ask yourself the following questions: - -1. What are the trends in the results obtained? +!!! question + How do we interpret this event? Is the number of deceased and infections reduced? How much? """ -# ╔═╡ a736a17b-ee8e-491b-840a-6319619a8dab -md"- Answer: missing" +# ╔═╡ 6eb368f5-8d43-4fb8-b6eb-c783675d1dd9 +osol2[:D][end]/osol[:D][end] - 1 # The number of deceased is reduced 13% -# ╔═╡ 2ba54805-e901-4281-9b07-cc7137b8c809 -md""" -2. How much less casualties are there compared to not altering the contact rate? -""" +# ╔═╡ 247c3c88-7ba7-4db1-ad56-de1758851ade +osol2[:S][end]/osol[:S][end] - 1 # 6 times less infections with contact measures -# ╔═╡ 20d56d2f-2532-4286-88cc-b42ccb22d246 -md"- Answer: missing" +# ╔═╡ 7911963b-e663-4fbc-9113-98cc1a091628 +osol2[:R][end]/osol[:R][end] - 1 # 13% less recoveries (due to fewer infections) # ╔═╡ cb8a6f77-f08c-4fc8-9445-bd1c17521fcc md""" @@ -578,12 +567,12 @@ Suppose that when the number of infected individuals reaches $1\,000\,000$, then # ╔═╡ 5005a09d-a844-4f9d-a058-0d93583d5bab md""" -Normally in a continuous event the value of one or more species can be changed when a certain condition is met. In our specific case we want the change in the species happening only once! So, if you want that the continuous event: ''when $I$ reaches $10^6$ then $999000$ is subtrated from $I$'' happens only once, then we need to include a ficticious new *species* in our *reaction network model*. We will call this ficticious *species* `pwc` (a short for _**p**roceed **w**ith **c**ondition_) and we set it default to `true`. +Normally in a continuous event the value of one or more species can be changed when a certain condition is met. In our specific case we want the change in the species happening only once! So, if you want that the continuous event "when $I$ reaches $10^6$ then $999\,000$ is subtracted from $I$" happens only once, then we need to include a ficticious new *species* in our *reaction network model*. We will call this ficticious species `thr` (a short for _**thr**eshold_) and we set its default value to `1e6`. """ # ╔═╡ f77d2d75-468f-4746-b81e-0bbbf33fc8d7 infection_model3 = @reaction_network begin - @species pwc(t)=true + @species thr(t)=1e6 α * β, S + I --> 2I r * m, I --> D r * (1 - m), I --> R @@ -594,11 +583,11 @@ species(infection_model3) # ╔═╡ 30bcea84-f7ca-4907-9a0f-54934e1731d0 md""" -We create the condition in the following way. When `pwc` is true then $I$ will be changed and also `pwc` will become `false`, so that the condition happens only once. We assume hereby that $I$ will never reach $0$! +We create the condition in the following way. When `thr` is `1e6` then $I$ will change at some point and also `thr` will become `1e9`, so that the condition happens only once. By the way, $I$ will never reach $1\,000\,000\,000$! """ # ╔═╡ 87d9be87-3bc7-4442-a396-fb501355fe8c -condition3 = [infection_model3.I ~ 1e6*infection_model3.pwc] => [infection_model3.I ~ infection_model3.I - 0.999e6, infection_model3.pwc ~ false] +condition3 = [infection_model3.I ~ infection_model3.thr] => [infection_model3.I ~ infection_model3.I - 999_000, infection_model3.thr ~ 1e9] # ╔═╡ 467834b5-0063-4e91-b446-2828a1d44d78 md""" @@ -622,7 +611,7 @@ Then we need to create a new ODE problem. """ # ╔═╡ e0562699-d065-4ae1-9c39-f9e0bf561fa3 -oprob3 = ODEProblem(infection_model3_c_com, u0, tspan, params) +oprob3 = ODEProblem(infection_model3_c_com, u0, tspan, params); # ╔═╡ 6b3ea888-1238-46ae-9eaf-52e86c76bc1c md""" @@ -630,7 +619,7 @@ Finally, the ODE problem can be solved. Notice that you need to make a deepcopy """ # ╔═╡ abe11178-7177-418c-98b4-da1afc56842e -osol3 = solve(deepcopy(oprob3), Tsit5(), saveat=0.1) +osol3 = solve(deepcopy(oprob3), Tsit5(), saveat=0.5) # ╔═╡ 23804c2a-d031-4025-92d3-5cdb74f87353 md""" @@ -638,7 +627,10 @@ Now we can plot the results. """ # ╔═╡ 02173eaa-1178-4383-b57a-03e53ce38af8 -plot(osol3) +begin + plot(osol3; idxs=[:S, :I, :D, :R]) + plot!(osol; linestyle=:dash, label=:none, color=:grey, lw=0.5) +end # ╔═╡ 6d1aa79b-8614-4a77-a327-f7e6962d1944 md""" @@ -650,21 +642,32 @@ osol3.u[end] # ╔═╡ 70fd136e-5ded-4c30-818e-a5de61fbbf86 md""" -Try to interpret the results yourself. Ask yourself the following questions: - -1. What are the trends in the results obtained? +!!! question + How do we interpret this new event? Is this a better measure than contact reduction alone? Would you know how we call such an event? """ -# ╔═╡ 7872701b-8506-4303-b615-32d3c1afa50d -md"- Answer: missing" +# ╔═╡ f6dd15c0-8aa0-424b-8134-45245a077186 +0.4*0.999e6 # Amount of people deceased during isolation (infected) + +# ╔═╡ 4bd15c53-44b7-42ad-b225-79a9d90b38a8 +(osol3[:D][end] + 0.4*0.999e6)/osol[:D][end] - 1 # Deceased are reduced only 1%! + +# ╔═╡ aeeb2fc7-fa7d-4a89-97d4-f2c12373bbdc +osol3[:S][end]/osol[:S][end] - 1 # 56% less infections (wrt. example 1) -# ╔═╡ 0d6c2233-35c5-4257-9dfd-398704080ba3 +# ╔═╡ c8986056-3b29-4574-a43d-d0e051a4bee9 +(osol3[:R][end] + 0.6*0.999e6)/osol[:R][end] - 1 # 1% less recoveries + +# ╔═╡ f5d23dba-02a9-4d27-8eb1-ff89d2902cdf md""" -2. How much less casualties are there compared to not putting $999\,000$ individuals into isolation? (Hint: you also need to take into account the casualties in the $999\,000$ individuals that had been put into isolation.) +- Answer: """ -# ╔═╡ 029a2024-1ec7-4af9-9e73-717f13483468 -md"- Answer: missing" +# ╔═╡ ef982f58-9deb-4ac2-93d8-e7677332d80d +md""" +!!! hint + Isolation alone is not effective to protect the part of the population that's already been infected. The peak of infections is not avoided, only delayed. However, the proportion of the population exposed is much lower thanks to isolation. *Would then a combined set of rules be best in that case?* +""" # ╔═╡ Cell order: # ╠═be326550-25ea-4c5f-ac4a-dd74d12bc89a @@ -752,12 +755,9 @@ md"- Answer: missing" # ╠═d44da6c6-c93d-4c61-8125-9eee464c897e # ╠═00a72697-d36a-41cc-9eec-8e821829ce0e # ╠═cf39b4cf-9cd0-4755-80db-ca4aea7c1084 +# ╠═b65e948d-b13a-4021-a545-b7912fd86e94 # ╠═52901bbf-e47b-4da1-95c4-f0869812398c # ╟─102b4fbc-23b1-46ed-bb72-124eb88517ce -# ╟─f6cbafbf-98b4-4286-86d2-fe95821a5ff4 -# ╟─ff9ce0c5-931f-44f4-aa0d-4aead0284160 -# ╟─f5f98168-119c-4b49-a8e3-a3cc775faeb0 -# ╟─a308de53-80a2-4b37-a752-cb2c383cf7a4 # ╟─ade413c2-d7d9-4250-8490-75534900a389 # ╟─58730ac6-d83b-420d-a000-2f50545f0d39 # ╠═7411474c-fac7-4b7c-8ded-4c2df5956fb0 @@ -774,9 +774,9 @@ md"- Answer: missing" # ╟─18151ab1-1e4e-48d8-be70-4fa4c8a43af1 # ╠═7d7ed974-7c9c-4c30-ab2a-e3028ce702dd # ╟─7375edbc-24a4-4300-bdef-2686cb377cfc -# ╟─a736a17b-ee8e-491b-840a-6319619a8dab -# ╟─2ba54805-e901-4281-9b07-cc7137b8c809 -# ╟─20d56d2f-2532-4286-88cc-b42ccb22d246 +# ╠═6eb368f5-8d43-4fb8-b6eb-c783675d1dd9 +# ╠═247c3c88-7ba7-4db1-ad56-de1758851ade +# ╠═7911963b-e663-4fbc-9113-98cc1a091628 # ╟─cb8a6f77-f08c-4fc8-9445-bd1c17521fcc # ╟─5005a09d-a844-4f9d-a058-0d93583d5bab # ╠═f77d2d75-468f-4746-b81e-0bbbf33fc8d7 @@ -796,6 +796,9 @@ md"- Answer: missing" # ╟─6d1aa79b-8614-4a77-a327-f7e6962d1944 # ╠═d04b8d97-e9d3-4428-a695-bfde4b44a291 # ╟─70fd136e-5ded-4c30-818e-a5de61fbbf86 -# ╟─7872701b-8506-4303-b615-32d3c1afa50d -# ╟─0d6c2233-35c5-4257-9dfd-398704080ba3 -# ╟─029a2024-1ec7-4af9-9e73-717f13483468 +# ╠═f6dd15c0-8aa0-424b-8134-45245a077186 +# ╠═4bd15c53-44b7-42ad-b225-79a9d90b38a8 +# ╠═aeeb2fc7-fa7d-4a89-97d4-f2c12373bbdc +# ╠═c8986056-3b29-4574-a43d-d0e051a4bee9 +# ╟─f5d23dba-02a9-4d27-8eb1-ff89d2902cdf +# ╟─ef982f58-9deb-4ac2-93d8-e7677332d80d diff --git a/exercises/ode_model_fermenter_firstorder.jl b/exercises/ode_model_fermenter_firstorder.jl index cbe3f49f..e778e727 100644 --- a/exercises/ode_model_fermenter_firstorder.jl +++ b/exercises/ode_model_fermenter_firstorder.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 2e58f4ae-f711-11ee-2598-7f3a6f2e2013 @@ -122,7 +122,7 @@ Create the ODE problem and store it in `oprob`: """ # ╔═╡ ed56f8d6-2260-4829-9190-69b60b7d7599 -# oprob = missing +# oprob = missing; # ╔═╡ 8b73b16b-7f7d-4d2e-a1c2-7e1adf2336e9 md""" diff --git a/exercises/ode_model_fermenter_firstorder_sol.jl b/exercises/ode_model_fermenter_firstorder_sol.jl index da3f9ccb..0a17c62d 100644 --- a/exercises/ode_model_fermenter_firstorder_sol.jl +++ b/exercises/ode_model_fermenter_firstorder_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 2e58f4ae-f711-11ee-2598-7f3a6f2e2013 @@ -136,7 +136,7 @@ Create the ODE problem and store it in `oprob`: # ╔═╡ ed56f8d6-2260-4829-9190-69b60b7d7599 # oprob = missing -oprob = ODEProblem(fermenter_firstorder_c_com, u0, tspan, params, combinatoric_ratelaws=false) +oprob = ODEProblem(fermenter_firstorder_c_com, u0, tspan, params, combinatoric_ratelaws=false); # ╔═╡ 8b73b16b-7f7d-4d2e-a1c2-7e1adf2336e9 md""" diff --git a/exercises/ode_model_fermenter_monod.jl b/exercises/ode_model_fermenter_monod.jl index 19a7a475..f925c85c 100644 --- a/exercises/ode_model_fermenter_monod.jl +++ b/exercises/ode_model_fermenter_monod.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 2e58f4ae-f711-11ee-2598-7f3a6f2e2013 @@ -103,7 +103,7 @@ Create the ODE problem and store it in `oprob`: """ # ╔═╡ ab2a9842-6a9c-46bd-812b-db01629d6a1c -# oprob = missing # Uncomment and complete the instruction +# oprob = missing; # Uncomment and complete the instruction # ╔═╡ b6a526bd-6ee5-442b-9fb8-3fbe1e280dd4 md""" @@ -151,7 +151,13 @@ Then we make a so-called SteadyStateProblem based on the ODEProblem but now with """ # ╔═╡ 1777503e-b793-4be2-b80b-b4edcd7041b5 -# Seq1, Xeq1 = missing +# eq1 = missing + +# ╔═╡ b9b9c5f0-02fa-4544-8865-a07271e8941f +# Seq1 = missing + +# ╔═╡ 0ddf9ea1-3f45-48b1-bb9c-5a08df45bd5b +# Xeq1 = missing # ╔═╡ 1d5a2118-96e9-49b2-9931-5d4b201cb8f5 md""" @@ -216,7 +222,7 @@ Create the ODE problem and store it in `oprob2`: """ # ╔═╡ 7af72709-2f82-4971-8342-f02943f947c8 -# oprob2 = missing # Uncomment and complete the instruction +# oprob2 = missing; # Uncomment and complete the instruction # ╔═╡ e019f797-a6ad-4f8f-8f9e-69db00ed3c39 md""" @@ -270,7 +276,13 @@ Make and solve the steady state problem. Call the output values `Seq2` and `Xeq2 """ # ╔═╡ 0b992750-a446-447b-b2a1-26658c11c0bf -# Seq2, Xeq2 = missing # Uncomment and complete the instruction +# eq2 = missing # Uncomment and complete the instruction + +# ╔═╡ 7b985909-bc75-4c03-8949-b689e90c9fea +# Seq2 = missing + +# ╔═╡ c4417b5c-a7cf-497b-8b7a-2a90ebe428f2 +# Xeq2 = missing # ╔═╡ 4ed59602-ad9d-4aae-8a21-83dabbfd3846 md""" @@ -343,7 +355,7 @@ Create the ODE problem and store it in `oprob3`: """ # ╔═╡ dd388e88-53af-48d3-800e-09b5c182a83b -# oprob3 = missing # Uncomment and complete the instruction +# oprob3 = missing; # Uncomment and complete the instruction # ╔═╡ 5133d846-e6a6-4b50-9ce1-cb91cf04cbd1 md""" @@ -411,6 +423,8 @@ md"- Answer: missing" # ╠═8d96d79f-6ddb-4bba-a6ea-821588e13107 # ╟─e8969045-27ac-460e-86a2-7494903534e8 # ╠═1777503e-b793-4be2-b80b-b4edcd7041b5 +# ╠═b9b9c5f0-02fa-4544-8865-a07271e8941f +# ╠═0ddf9ea1-3f45-48b1-bb9c-5a08df45bd5b # ╟─1d5a2118-96e9-49b2-9931-5d4b201cb8f5 # ╠═cb57997e-c3ec-47e0-b9a0-b10aa9f5608d # ╟─bb2d06f8-1940-4585-961a-54068da50e91 @@ -439,6 +453,8 @@ md"- Answer: missing" # ╠═f121efc5-4e64-4e82-8672-2765ad85443e # ╟─9fe054e0-cf21-49ba-a777-a8200b34b7dd # ╠═0b992750-a446-447b-b2a1-26658c11c0bf +# ╠═7b985909-bc75-4c03-8949-b689e90c9fea +# ╠═c4417b5c-a7cf-497b-8b7a-2a90ebe428f2 # ╟─4ed59602-ad9d-4aae-8a21-83dabbfd3846 # ╠═47a63fd8-f805-4c7d-8695-c9ee6550f24f # ╟─4d962d0f-da41-405e-9438-733d5668cde3 diff --git a/exercises/ode_model_fermenter_monod_sol.jl b/exercises/ode_model_fermenter_monod_sol.jl index 2c8bdaa5..037468de 100644 --- a/exercises/ode_model_fermenter_monod_sol.jl +++ b/exercises/ode_model_fermenter_monod_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 2e58f4ae-f711-11ee-2598-7f3a6f2e2013 @@ -121,7 +121,7 @@ Create the ODE problem and store it in `oprob`: # ╔═╡ ab2a9842-6a9c-46bd-812b-db01629d6a1c # oprob = missing # Uncomment and complete the instruction -oprob = ODEProblem(fermenter_monod, u0, tspan, params, combinatoric_ratelaws=false) +oprob = ODEProblem(fermenter_monod, u0, tspan, params, combinatoric_ratelaws=false); # ╔═╡ b6a526bd-6ee5-442b-9fb8-3fbe1e280dd4 md""" @@ -172,7 +172,14 @@ Then we make a so-called SteadyStateProblem based on the ODEProblem but now with """ # ╔═╡ 1777503e-b793-4be2-b80b-b4edcd7041b5 -Seq1, Xeq1 = solve(SteadyStateProblem(ODEProblem(fermenter_monod, u_guess1, tspan, params))) +# Seq1, Xeq1 = solve(SteadyStateProblem(ODEProblem(fermenter_monod, u_guess1, tspan, params))) +eq1 = solve(SteadyStateProblem(ODEProblem(fermenter_monod, u_guess1, tspan, params))) + +# ╔═╡ 36312d33-909b-47a9-8fab-fc70950ff07e +Seq1 = eq1[:S] + +# ╔═╡ 6cd388c4-f2a6-45d6-9b51-a1659b2dec07 +Xeq1 = eq1[:X] # ╔═╡ 1d5a2118-96e9-49b2-9931-5d4b201cb8f5 md""" @@ -247,7 +254,7 @@ Create the ODE problem and store it in `oprob2`: # ╔═╡ 7af72709-2f82-4971-8342-f02943f947c8 # oprob2 = missing # Uncomment and complete the instruction -oprob2 = ODEProblem(fermenter_monod2_com, u0, tspan, params) +oprob2 = ODEProblem(fermenter_monod2_com, u0, tspan, params); # ╔═╡ e019f797-a6ad-4f8f-8f9e-69db00ed3c39 md""" @@ -306,7 +313,13 @@ Make and solve the steady state problem. Call the output values `Seq2` and `Xeq2 # ╔═╡ 0b992750-a446-447b-b2a1-26658c11c0bf # Seq2, Xeq2 = missing # Uncomment and complete the instruction -Seq2, Xeq2 = solve(SteadyStateProblem(ODEProblem(fermenter_monod, u_guess2, tspan, params_mod))) +eq2 = solve(SteadyStateProblem(ODEProblem(fermenter_monod, u_guess2, tspan, params_mod))) + +# ╔═╡ e1e2e214-7bd9-4f00-b434-a63861dde1bf +Seq2 = eq2[:S] + +# ╔═╡ dcaf1565-6d11-409c-aa80-e9f77fe729fd +Xeq2 = eq2[:X] # ╔═╡ 4ed59602-ad9d-4aae-8a21-83dabbfd3846 md""" @@ -395,7 +408,7 @@ Create the ODE problem and store it in `oprob3`: # ╔═╡ dd388e88-53af-48d3-800e-09b5c182a83b # oprob3 = missing # Uncomment and complete the instruction -oprob3 = ODEProblem(fermenter_monod3_com, u0, tspan, params) +oprob3 = ODEProblem(fermenter_monod3_com, u0, tspan, params); # ╔═╡ 5133d846-e6a6-4b50-9ce1-cb91cf04cbd1 md""" @@ -472,6 +485,8 @@ md"- Answer: missing" # ╠═8d96d79f-6ddb-4bba-a6ea-821588e13107 # ╟─e8969045-27ac-460e-86a2-7494903534e8 # ╠═1777503e-b793-4be2-b80b-b4edcd7041b5 +# ╠═36312d33-909b-47a9-8fab-fc70950ff07e +# ╠═6cd388c4-f2a6-45d6-9b51-a1659b2dec07 # ╟─1d5a2118-96e9-49b2-9931-5d4b201cb8f5 # ╠═cb57997e-c3ec-47e0-b9a0-b10aa9f5608d # ╟─bb2d06f8-1940-4585-961a-54068da50e91 @@ -500,6 +515,8 @@ md"- Answer: missing" # ╠═f121efc5-4e64-4e82-8672-2765ad85443e # ╟─9fe054e0-cf21-49ba-a777-a8200b34b7dd # ╠═0b992750-a446-447b-b2a1-26658c11c0bf +# ╠═e1e2e214-7bd9-4f00-b434-a63861dde1bf +# ╠═dcaf1565-6d11-409c-aa80-e9f77fe729fd # ╟─4ed59602-ad9d-4aae-8a21-83dabbfd3846 # ╠═47a63fd8-f805-4c7d-8695-c9ee6550f24f # ╟─4d962d0f-da41-405e-9438-733d5668cde3 diff --git a/exercises/ode_model_infection.jl b/exercises/ode_model_infection.jl index 8122e906..dc75982f 100644 --- a/exercises/ode_model_infection.jl +++ b/exercises/ode_model_infection.jl @@ -20,7 +20,7 @@ end begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 18a4df05-0349-400d-a29e-b3fa71aa4d88 @@ -45,7 +45,7 @@ md" # ╔═╡ fab49cb7-c41e-498a-98f6-33b4821ceb90 md""" -We will work here with the same infection model as in the **Introdution to Catalyst** (revisit the concerned notebook if necessay). We shortly summarize some important aspects of the model and give a condensed version of the solution method and the examples. +We will work here with the same infection model as in the **Introdution to Catalyst** (revisit the concerned notebook if necessary). We shortly summarize some important aspects of the model and give a condensed version of the solution method and the examples. """ # ╔═╡ 8ff0b57e-acc1-4ebd-a562-a82c9efa7ffc @@ -77,14 +77,14 @@ The **parameters**: md""" The infection model has three reaction events: -- Infection, where a susceptible persons meets an infected persons and also becomes infected. The infection rate is $\alpha \beta$. -- Deceasing, where an infected person die. The death rate is $m r$. -- Recovery, where an infected person recovers. The recovery rate: $(1-m) r$. +- **Infection**, where a susceptible persons meets an infected person and also becomes infected. The infection rate is $\alpha \beta$. +- **Decease**, where an infected person dies. The death rate is $m r$. +- **Recovery**, where an infected person recovers. The recovery rate is $(1-m) r$. """ # ╔═╡ afb751b9-39b8-4430-af4b-02f010667518 md""" -The *infection reactions* are: +The involved reactions are: $$S + I \xrightarrow[]{\alpha \beta} 2I$$ $$I \xrightarrow[]{mr} D$$ @@ -106,6 +106,11 @@ md" ### Implementation of the system " +# ╔═╡ 13d94ba6-425e-471b-aa99-2f321891d1f0 +md""" +Implement the *reaction model* in Catalyst: +""" + # ╔═╡ 3f6080e1-ab43-47f7-a82b-95956bf4cafd infection_model = @reaction_network begin α * β, S + I --> 2I @@ -147,7 +152,7 @@ osys = convert(ODESystem, infection_model) # ╔═╡ a432a88a-8db3-4729-b9a3-8ca9322fc81e md""" -Getting a list of the differential equations, the state variables and the parameters: +We can get a list of the differential equations, the state variables and the parameters: """ # ╔═╡ 7e268605-8314-4e7b-8c38-a65212e148a9 @@ -182,7 +187,7 @@ params = [:α => 0.08, :β => 1.0e-6, :r => 0.2, :m => 0.4] # ╔═╡ 6d2580f7-f882-449d-a9b8-629ab41e2671 md""" -### Creating and solving the ODEProblem and plotting results +### Creating and solving the ODE problem and plotting results """ # ╔═╡ d3f39b29-71f5-4674-a52f-3ba63279fca7 @@ -196,25 +201,26 @@ plot(osol) # ╔═╡ 006bfc98-3c95-4763-b0ed-f4714ad5bd02 plot(osol, idxs=[:S, :I]) # only S and I +# plot(osol, idxs=[S, I]) # also possible when S and I are unpacked # ╔═╡ 4c5d2e5d-3237-4886-b852-3142fb996dd6 -plot(osol, idxs=(:S, :I), xlab="S", ylab="I") # fase plot I vs S +plot(osol, idxs=(:S, :I), xlab="S", ylab="I") # phase plot I vs S # ╔═╡ f9bd32f5-c473-44d4-af9d-4d99032a2d21 -osol.u[end] +osol.u[end] # final values in the order of defined species # ╔═╡ 000495a6-e91d-438e-ab6d-7a5e95a99f27 md""" ### Example 1 - Influence of $r$ -Influence of the duration of infection $1/r$ for average infection periods of between $10$, days and $1$ day contagious ($r$ between $0.1$ and $1.0$, step $0.1$, default value $0.1$). +Influence of the duration of infection, $1/r$, for average infection periods between $1$ and $10$ days of being contagious ($r$ between $0.1$ and $1.0$, with a step of $0.1$, and default value $0.1$). """ # ╔═╡ d73f8ed8-ac25-4c1c-b834-989a2a929df3 @bind r Slider(0.1:0.1:1, default=0.1, show_value=true) # ╔═╡ 4ca0e1df-7765-4f36-a442-2749ea493426 -params1 = [:α => 0.08, :β => 1.0e-6, :r => r, :m => 0.4] +params1 = [:α => 0.08, :β => 1.0e-6, :r => r, :m => 0.4] # r specified by slider # ╔═╡ d56b486e-44e5-4db7-9c4e-00db5c1b733f oprob1 = ODEProblem(infection_model, u0, tspan, params1); @@ -253,11 +259,30 @@ oprob2 = ODEProblem(infection_model2_com, u0, tspan, params) osol2 = solve(deepcopy(oprob2), Tsit5(), saveat=0.5) # ╔═╡ 31ceb303-dbb1-4f4d-9082-14ea1d83ab66 -plot(osol2) +# We can compare the result now to the solution without contact reduction +begin + plot(osol2) + plot!(osol; linestyle=:dash, label=:none, color=:grey, lw=0.5) +end # ╔═╡ 14143212-53f1-4753-8c25-e22559cdbccd osol2.u[end] +# ╔═╡ 9c668254-3c54-4d95-9e1e-e2bd2d3eb1df +md""" +!!! question + How do we interpret this event? Is the number of deceased and infections reduced? How much? +""" + +# ╔═╡ 130a6ce2-dd8c-4a05-8863-953a77a407aa +osol2[:D][end]/osol[:D][end] - 1 # The number of deceased is reduced 13% + +# ╔═╡ 9abcc2f9-5c24-4840-8a14-fa7a197ffef0 +osol2[:S][end]/osol[:S][end] - 1 # 6 times less infections with contact measures + +# ╔═╡ 1f970a9e-abde-422b-a793-eb51ad2001bc +osol2[:R][end]/osol[:R][end] - 1 # 13% less recoveries (due to fewer infections) + # ╔═╡ bdf9cfa0-9dc4-4ea5-9024-63813ec30d09 md""" ### Example 3 - Continuous event @@ -267,14 +292,14 @@ Suppose that when the number of infected individuals reaches $1\,000\,000$, then # ╔═╡ cbf0a768-f6ac-43fb-8d05-e7dac51d4cc0 infection_model3 = @reaction_network begin - @species pwc(t)=true + @species thr(t)=1e6 α * β, S + I --> 2I r * m, I --> D r * (1 - m), I --> R end # ╔═╡ fee597e0-97cb-40bc-a5b9-166631e8b9f6 -condition3 = [infection_model3.I ~ 1e6*infection_model3.pwc] => [infection_model3.I ~ infection_model3.I - 0.999e6, infection_model3.pwc ~ false] +condition3 = [infection_model3.I ~ infection_model3.thr] => [infection_model3.I ~ infection_model3.I - 999_000, infection_model3.thr ~ 1e9] # ╔═╡ 51363f3c-7aa9-48ed-808e-d1f7a4aadc0c @named infection_model3_c = ReactionSystem(equations(infection_model3), continuous_events=condition3) @@ -289,11 +314,43 @@ oprob3 = ODEProblem(infection_model3_c_com, u0, tspan, params) osol3 = solve(deepcopy(oprob3), Tsit5(), saveat=0.5) # ╔═╡ 2b511237-7739-44e5-b6bd-26a2fdc76bb5 -plot(osol3) +begin + plot(osol3; idxs=[:S, :I, :D, :R]) + plot!(osol; linestyle=:dash, label=:none, color=:grey, lw=0.5) +end # ╔═╡ 3a131f92-aa09-4e8c-98a1-0c4c1c74878a osol3.u[end] +# ╔═╡ 96792abd-2b86-4245-aaaf-15c43b4eabb0 +md""" +!!! question + How do we interpret this new event? Is this a better measure than contact reduction alone? Would you know how we call such an event? +""" + +# ╔═╡ 1116b608-e6b9-4e6d-a0eb-1ac58ef9e2f7 +0.4*0.999e6 # Amount of people deceased during isolation (infected) + +# ╔═╡ 4111ae36-ddef-42a8-b8a9-61f9f464a5c0 +(osol3[:D][end] + 0.4*0.999e6)/osol[:D][end] - 1 # Deceased are reduced only 1%! + +# ╔═╡ 6c8a9e97-0a60-4e42-ad7f-78c0dece2b30 +osol3[:S][end]/osol[:S][end] - 1 # Infections have increased 56% (wrt. example 1) + +# ╔═╡ 801a038b-7485-40b6-b7a5-92b0b3c11c0e +(osol3[:R][end] + 0.6*0.999e6)/osol[:R][end] - 1 # 1% less recoveries + +# ╔═╡ 62adbc28-cec2-4da8-9842-2153563497d0 +md""" +- Answer: +""" + +# ╔═╡ 3bc2d36a-6efc-4631-baae-0d3e62bf7e3f +md""" +!!! hint + Isolation alone is not effective to protect the part of the population that's already been infected. The peak of infections is not avoided, only delayed. However, the proportion of the population exposed is much lower thanks to isolation. *Would then a combined set of rules be best in that case?* +""" + # ╔═╡ ad83a851-e424-4e8f-bae9-38b9283db2fa md""" ## Exercises @@ -303,7 +360,7 @@ md""" md""" ### Exercise 1 - Influence of $\alpha$ -Evaluate the effect of a decreasing risk of infection after contact with an infected person, i.e. $r = 0.2$, $\beta = 0.1$ and $\alpha$ between $8\%$ and $20\%$. +Evaluate the effect of a decreasing risk of infection after contact with an infected person, i.e. $r = 0.2$, $\beta = 10^{-6}$ and $\alpha$ between $8\%$ and $20\%$. Use the same initial values and timespan as before. """ @@ -353,23 +410,35 @@ md""" Change the value of $\alpha$ in the `params_ex1` vector to visualize the effect in the plot. """ +# ╔═╡ f85bd6be-8984-49f0-a36b-7aa7bb937c54 +md""" +!!! warning "Tip" + You can move the cell containing the slider next to the figure to visualize the changes in $\alpha$. +""" + # ╔═╡ c14d45b8-3af1-4e05-b10a-081ccd62a34d md""" Try to interpret the results yourself. Ask yourself the following questions: -1. What are the trends in the obtained results? +!!! question + 1. What are the trends in the obtained results? """ # ╔═╡ 04f89fb3-f856-4206-9871-4d92f2816332 -md"- Answer: missing" +md""" +- Answer: +""" # ╔═╡ a39eeec9-d816-4d35-90ae-e602a24bb056 md""" -2. How can this be explained from the model structure? +!!! question + 2. How can this be explained from the model structure? """ # ╔═╡ fcad8ede-8295-46d6-a637-728b3986a761 -md"- Answer: missing" +md""" +- Answer: +""" # ╔═╡ b3f08d61-187d-4f99-b95f-508ff1b3d52d md""" @@ -455,19 +524,25 @@ Change the value of $b$ in the `params_ex2` vector to visualize the effect in th md""" Try to answer the following questions: -1. Why does the peak in the number of infected individuals shift to the right when the value of $b$ increases? +!!! question + 1. Why does the peak in the number of infected individuals shift to the right when the value of $b$ increases? """ # ╔═╡ 381d3a54-0e4f-4203-874f-4a4716d481d4 -md"- Answer: missing" +md""" +- Answer: +""" # ╔═╡ fd7d89f3-9ab8-4b17-b26f-571bad862718 md""" -2. Why does the number of recovered individuals first rise when the value of $b$ increases and then fall when the value of $b$ continues to increase? +!!! question + 2. Why does the number of recovered individuals first rise when the value of $b$ increases and then fall when the value of $b$ continues to increase? """ # ╔═╡ 96de4f0d-c2d1-4fad-bded-a314cbca848b -md"- Answer: missing" +md""" +- Answer: +""" # ╔═╡ dedb1ac1-cb54-416f-a092-12a50080c69f md""" @@ -494,7 +569,7 @@ The vaccination programme is launched $2$ days after the outbreak of the disease Assume that individuals are still being treated ($b = 0.2$ and $h = 0.5$). Extend the model obtained in the previous exercise for the launch of a vaccination campaign after the outbreak of the disease. -Find out via trial and error what the minimum vaccination rate need to be so that the number of fatalities is $10$ times smaller after a period of $90$ days compared to those in absence of vaccination (cf. Exercise 2). Consider an initial step size in $v$ of $0.01$ and then fine tune with a step size of $0.001$. +Find out via trial and error what the minimum vaccination rate need to be so that the number of fatalities is $10$ times smaller after a period of $90$ days compared to those in absence of vaccination (cf. Exercise 2). Use the same initial values and timespan as before. """ @@ -547,7 +622,7 @@ Create the ODE problem and store it in `oprob_ex3`: # ╔═╡ 69983b90-b6ef-4732-a4af-a772bb1364e5 md""" -Solve the ODE problem for (step wise) increasing values of $v$ and store the solution in `osol_ex3_vac`. Consider an initial step size in $v$ of $0.01$ and then fine tune with a step size of $0.001$. +Solve the ODE problem for (step wise) increasing values of $v$ and store the solution in `osol_ex3_vac`. """ # ╔═╡ 16211bc6-cd97-43c0-8faf-25bb490930b6 @@ -555,7 +630,7 @@ Solve the ODE problem for (step wise) increasing values of $v$ and store the sol # ╔═╡ 461eada9-5f9c-4439-8b65-226382b6d148 md""" -Compare the latter with the number of fatalities when no vaccination is/was available (cf. Exercise 2) by setting up a condition (a boolean expression return either `true` or `false`) here below where the final number of fatalities (with vaccination) divided by 10 is compared with (use larger than or smaller than) the number of fatalities (without vaccination): +First, put the value of $b$ in Exercise 2 to $0.2$. Compare the latter with the number of fatalities when no vaccination is/was available (cf. Exercise 2) by setting up a condition (a boolean expression return either `true` or `false`) here below where the final number of fatalities (with vaccination) divided by 10 is compared with (use larger than or smaller than) the number of fatalities (without vaccination): """ # ╔═╡ 0994d790-0fe8-46ab-bba2-a0a4ea466f64 @@ -609,6 +684,31 @@ Plot the solutions: # ╔═╡ ed9472a0-09c9-4d1c-8f1d-1b7d87b97640 # missing # Uncomment and complete the instruction +# ╔═╡ 6e213afb-fd4b-4ab9-8986-a319bee6be0c +md""" +Check the number of fatalities now and compare to the case without vaccination. +""" + +# ╔═╡ 3af06996-bd43-4783-a5e0-3c11c23ca280 +# missing # Uncomment and complete the instruction + +# ╔═╡ 93400573-ad1f-408d-b514-854998e7836a +md""" +!!! question + 3. What can you say about the rate of infection in the case of no vaccination? How would you measure this in the plot? +""" + +# ╔═╡ 008cc499-fce9-43e7-b969-2419b847d24c +md""" +- Answer: +""" + +# ╔═╡ 14c3b2f1-14b4-415c-85c6-922361423826 +md""" +!!! hint + The rate of infection has to do with how many people get infected during a certain period... +""" + # ╔═╡ Cell order: # ╠═18a4df05-0349-400d-a29e-b3fa71aa4d88 # ╠═65b3536b-c9b3-485e-87e1-4f6657381503 @@ -624,6 +724,7 @@ Plot the solutions: # ╠═e97637b0-446c-44ac-bd08-c56632f9b57f # ╟─a91f1024-4800-4ffe-8bb2-5f6cf3c2bde1 # ╟─47f4a7cc-1a74-4ff0-ae21-2a5e4c495935 +# ╟─13d94ba6-425e-471b-aa99-2f321891d1f0 # ╠═3f6080e1-ab43-47f7-a82b-95956bf4cafd # ╟─5d5fae40-a4ed-4908-ba65-f3a16c38ab4f # ╠═fd347a58-5cad-4073-aadb-176fa54dcdfa @@ -665,6 +766,10 @@ Plot the solutions: # ╠═35d6bce7-9778-4f42-bdcd-271cedd8bad9 # ╠═31ceb303-dbb1-4f4d-9082-14ea1d83ab66 # ╠═14143212-53f1-4753-8c25-e22559cdbccd +# ╟─9c668254-3c54-4d95-9e1e-e2bd2d3eb1df +# ╠═130a6ce2-dd8c-4a05-8863-953a77a407aa +# ╠═9abcc2f9-5c24-4840-8a14-fa7a197ffef0 +# ╠═1f970a9e-abde-422b-a793-eb51ad2001bc # ╟─bdf9cfa0-9dc4-4ea5-9024-63813ec30d09 # ╠═cbf0a768-f6ac-43fb-8d05-e7dac51d4cc0 # ╠═fee597e0-97cb-40bc-a5b9-166631e8b9f6 @@ -674,6 +779,13 @@ Plot the solutions: # ╠═fc2dc11e-7022-4c6f-b7ed-5b077fc21ac5 # ╠═2b511237-7739-44e5-b6bd-26a2fdc76bb5 # ╠═3a131f92-aa09-4e8c-98a1-0c4c1c74878a +# ╟─96792abd-2b86-4245-aaaf-15c43b4eabb0 +# ╠═1116b608-e6b9-4e6d-a0eb-1ac58ef9e2f7 +# ╠═4111ae36-ddef-42a8-b8a9-61f9f464a5c0 +# ╠═6c8a9e97-0a60-4e42-ad7f-78c0dece2b30 +# ╠═801a038b-7485-40b6-b7a5-92b0b3c11c0e +# ╠═62adbc28-cec2-4da8-9842-2153563497d0 +# ╟─3bc2d36a-6efc-4631-baae-0d3e62bf7e3f # ╟─ad83a851-e424-4e8f-bae9-38b9283db2fa # ╟─b580ef9b-7d53-4bf0-8511-213920d59ee2 # ╟─090a949f-c18f-4e07-8c94-21a71bb0ceed @@ -687,10 +799,11 @@ Plot the solutions: # ╟─e7947165-b244-4ff6-bdf3-61d03aefe696 # ╠═adc0aa15-e0a9-4549-9609-967a9dc78b78 # ╟─7a1effe4-776c-4143-8085-f98a213a2cc3 +# ╟─f85bd6be-8984-49f0-a36b-7aa7bb937c54 # ╟─c14d45b8-3af1-4e05-b10a-081ccd62a34d -# ╟─04f89fb3-f856-4206-9871-4d92f2816332 +# ╠═04f89fb3-f856-4206-9871-4d92f2816332 # ╟─a39eeec9-d816-4d35-90ae-e602a24bb056 -# ╟─fcad8ede-8295-46d6-a637-728b3986a761 +# ╠═fcad8ede-8295-46d6-a637-728b3986a761 # ╟─b3f08d61-187d-4f99-b95f-508ff1b3d52d # ╟─08ba4614-e4fa-4203-9e28-c5c4bd9fcdd5 # ╠═e4087441-7d0d-4716-b9fa-eef45e9f3b87 @@ -706,9 +819,9 @@ Plot the solutions: # ╠═5f9a9838-099d-457f-9402-915f42d0cd33 # ╟─ef3ca25d-c110-452d-877a-6304ae6cd5a7 # ╟─f8dbab24-55aa-466f-a978-5f8db93b4b93 -# ╟─381d3a54-0e4f-4203-874f-4a4716d481d4 +# ╠═381d3a54-0e4f-4203-874f-4a4716d481d4 # ╟─fd7d89f3-9ab8-4b17-b26f-571bad862718 -# ╟─96de4f0d-c2d1-4fad-bded-a314cbca848b +# ╠═96de4f0d-c2d1-4fad-bded-a314cbca848b # ╟─dedb1ac1-cb54-416f-a092-12a50080c69f # ╠═a912f449-6c9d-4595-863f-a2ba523bad95 # ╟─089707c3-1df6-4799-a87b-0d4872a0267d @@ -738,3 +851,8 @@ Plot the solutions: # ╠═8814c42b-16c7-466a-8ad8-58ee1c0921b2 # ╟─25158ea5-1930-4fee-aab4-490b475d8635 # ╠═ed9472a0-09c9-4d1c-8f1d-1b7d87b97640 +# ╟─6e213afb-fd4b-4ab9-8986-a319bee6be0c +# ╠═3af06996-bd43-4783-a5e0-3c11c23ca280 +# ╟─93400573-ad1f-408d-b514-854998e7836a +# ╠═008cc499-fce9-43e7-b969-2419b847d24c +# ╟─14c3b2f1-14b4-415c-85c6-922361423826 diff --git a/exercises/ode_model_infection_sol.jl b/exercises/ode_model_infection_sol.jl index 4299aad6..7fb67aa1 100644 --- a/exercises/ode_model_infection_sol.jl +++ b/exercises/ode_model_infection_sol.jl @@ -20,7 +20,7 @@ end begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 18a4df05-0349-400d-a29e-b3fa71aa4d88 @@ -45,7 +45,7 @@ md" # ╔═╡ fab49cb7-c41e-498a-98f6-33b4821ceb90 md""" -We will work here with the same infection model as in the **Introdution to Catalyst** (revisit the concerned notebook if necessay). We shortly summarize some important aspects of the model and give a condensed version of the solution method and the examples. +We will work here with the same infection model as in the **Introdution to Catalyst** (revisit the concerned notebook if necessary). We shortly summarize some important aspects of the model and give a condensed version of the solution method and the examples. """ # ╔═╡ 8ff0b57e-acc1-4ebd-a562-a82c9efa7ffc @@ -77,14 +77,14 @@ The **parameters**: md""" The infection model has three reaction events: -- Infection, where a susceptible persons meets an infected persons and also becomes infected. The infection rate is $\alpha \beta$. -- Deceasing, where an infected person die. The death rate is $m r$. -- Recovery, where an infected person recovers. The recovery rate: $(1-m) r$. +- **Infection**, where a susceptible persons meets an infected person and also becomes infected. The infection rate is $\alpha \beta$. +- **Decease**, where an infected person dies. The death rate is $m r$. +- **Recovery**, where an infected person recovers. The recovery rate is $(1-m) r$. """ # ╔═╡ afb751b9-39b8-4430-af4b-02f010667518 md""" -The *infection reactions* are: +The involved reactions are: $$S + I \xrightarrow[]{\alpha \beta} 2I$$ $$I \xrightarrow[]{mr} D$$ @@ -106,6 +106,11 @@ md" ### Implementation of the system " +# ╔═╡ 3f530e32-15e4-4f0c-8765-dee59553a7b3 +md""" +Implement the *reaction model* in Catalyst: +""" + # ╔═╡ 3f6080e1-ab43-47f7-a82b-95956bf4cafd infection_model = @reaction_network begin α * β, S + I --> 2I @@ -147,7 +152,7 @@ osys = convert(ODESystem, infection_model) # ╔═╡ a432a88a-8db3-4729-b9a3-8ca9322fc81e md""" -Getting a list of the differential equations, the state variables and the parameters: +We can get a list of the differential equations, the state variables and the parameters: """ # ╔═╡ 7e268605-8314-4e7b-8c38-a65212e148a9 @@ -182,7 +187,7 @@ params = [:α => 0.08, :β => 1.0e-6, :r => 0.2, :m => 0.4] # ╔═╡ 6d2580f7-f882-449d-a9b8-629ab41e2671 md""" -### Creating and solving the ODEProblem and plotting results +### Creating and solving the ODE problem and plotting results """ # ╔═╡ d3f39b29-71f5-4674-a52f-3ba63279fca7 @@ -198,23 +203,23 @@ plot(osol) plot(osol, idxs=[:S, :I]) # only S and I # ╔═╡ 4c5d2e5d-3237-4886-b852-3142fb996dd6 -plot(osol, idxs=(:S, :I), xlab="S", ylab="I") # fase plot I vs S +plot(osol, idxs=(:S, :I), xlab="S", ylab="I") # phase plot I vs S # ╔═╡ f9bd32f5-c473-44d4-af9d-4d99032a2d21 -osol.u[end] +osol.u[end] # final values in the order of defined species # ╔═╡ 000495a6-e91d-438e-ab6d-7a5e95a99f27 md""" ### Example 1 - Influence of $r$ -Influence of the duration of infection $1/r$ for average infection periods of between $10$, days and $1$ day contagious ($r$ between $0.1$ and $1.0$, step $0.1$, default value $0.1$). +Influence of the duration of infection, $1/r$, for average infection periods between $1$ and $10$ days of being contagious ($r$ between $0.1$ and $1.0$, with a step of $0.1$, and default value $0.1$). """ # ╔═╡ d73f8ed8-ac25-4c1c-b834-989a2a929df3 @bind r Slider(0.1:0.1:1, default=0.1, show_value=true) # ╔═╡ 4ca0e1df-7765-4f36-a442-2749ea493426 -params1 = [:α => 0.08, :β => 1.0e-6, :r => r, :m => 0.4] +params1 = [:α => 0.08, :β => 1.0e-6, :r => r, :m => 0.4] # r specified by slider # ╔═╡ d56b486e-44e5-4db7-9c4e-00db5c1b733f oprob1 = ODEProblem(infection_model, u0, tspan, params1); @@ -253,11 +258,30 @@ oprob2 = ODEProblem(infection_model2_com, u0, tspan, params) osol2 = solve(deepcopy(oprob2), Tsit5(), saveat=0.5) # ╔═╡ 31ceb303-dbb1-4f4d-9082-14ea1d83ab66 -plot(osol2) +# We can compare the result now to the solution without contact reduction +begin + plot(osol2) + plot!(osol; linestyle=:dash, label=:none, color=:grey, lw=0.5) +end # ╔═╡ 14143212-53f1-4753-8c25-e22559cdbccd osol2.u[end] +# ╔═╡ c808c8ee-6de2-4ac3-a5b6-9dd2adb09ca9 +md""" +!!! question + How do we interpret this event? Is the number of deceased and infections reduced? How much? +""" + +# ╔═╡ 110aff6b-ef50-45b5-b4f0-81540b472254 +osol2[:D][end]/osol[:D][end] - 1 # The number of deceased is reduced 13% + +# ╔═╡ f6ec7911-bd4e-4566-a259-0dc3a0700e8c +osol2[:S][end]/osol[:S][end] - 1 # 6 times less infections with contact measures + +# ╔═╡ 05cc2399-60f6-42e7-b9f6-1b2ecc2b8ada +osol2[:R][end]/osol[:R][end] - 1 # 13% less recoveries (due to fewer infections) + # ╔═╡ bdf9cfa0-9dc4-4ea5-9024-63813ec30d09 md""" ### Example 3 - Continuous Event @@ -267,14 +291,14 @@ Suppose that when the number of infected individuals reaches $1\,000\,000$, then # ╔═╡ cbf0a768-f6ac-43fb-8d05-e7dac51d4cc0 infection_model3 = @reaction_network begin - @species pwc(t)=true + @species thr(t)=1e6 α * β, S + I --> 2I r * m, I --> D r * (1 - m), I --> R end # ╔═╡ fee597e0-97cb-40bc-a5b9-166631e8b9f6 -condition3 = [infection_model3.I ~ 1e6*infection_model3.pwc] => [infection_model3.I ~ infection_model3.I - 0.999e6, infection_model3.pwc ~ false] +condition3 = [infection_model3.I ~ infection_model3.thr] => [infection_model3.I ~ infection_model3.I - 0.999e6, infection_model3.thr ~ 1e9] # ╔═╡ 51363f3c-7aa9-48ed-808e-d1f7a4aadc0c @named infection_model3_c = ReactionSystem(equations(infection_model3), continuous_events=condition3) @@ -289,11 +313,43 @@ oprob3 = ODEProblem(infection_model3_c_com, u0, tspan, params) osol3 = solve(deepcopy(oprob3), Tsit5(), saveat=0.5) # ╔═╡ 2b511237-7739-44e5-b6bd-26a2fdc76bb5 -plot(osol3) +begin + plot(osol3; idxs=[:S, :I, :D, :R]) + plot!(osol; linestyle=:dash, label=:none, color=:grey, lw=0.5) +end # ╔═╡ 3a131f92-aa09-4e8c-98a1-0c4c1c74878a osol3.u[end] +# ╔═╡ 652f4832-a3eb-4c8d-a408-23594d305b38 +md""" +!!! question + How do we interpret this new event? Is this a better measure than contact reduction alone? Would you know how we call such an event? +""" + +# ╔═╡ ada57044-50bc-49ca-a753-319fa8e9ec89 +0.4*0.999e6 # Amount of people deceased during isolation (infected) + +# ╔═╡ f1e5ee9a-9636-46ab-8c07-23e64ba8d4c6 +(osol3[:D][end] + 0.4*0.999e6)/osol[:D][end] - 1 # Deceased are reduced only 1%! + +# ╔═╡ 8507a09a-5b19-4c37-b0cf-411732960315 +osol3[:S][end]/osol[:S][end] - 1 # 56% less infections (wrt. example 1) + +# ╔═╡ ea00eba1-af9d-48d3-a893-0dc57777b7a5 +(osol3[:R][end] + 0.6*0.999e6)/osol[:R][end] - 1 # 1% less recoveries + +# ╔═╡ 38b507e1-a046-4432-a756-21287681242f +md""" +- Answer: +""" + +# ╔═╡ 201716e7-8df4-4052-812b-9a04c921caea +md""" +!!! hint + Isolation alone is not effective to protect the part of the population that's already been infected. The peak of infections is not avoided, only delayed. However, the proportion of the population exposed is much lower thanks to isolation. *Would then a combined set of rules be best in that case?* +""" + # ╔═╡ ad83a851-e424-4e8f-bae9-38b9283db2fa md""" ## Exercises @@ -303,11 +359,37 @@ md""" md""" ### Exercise 1 - Influence of $\alpha$ -Evaluate the effect of a decreasing risk of infection after contact with an infected person, i.e. $r = 0.2$, $\beta = 0.1$ and $\alpha$ between $8\%$ and $20\%$. +Evaluate the effect of a decreasing risk of infection after contact with an infected person, i.e. $r = 0.2$, $\beta = 10^{-6}$ and $\alpha$ between $8\%$ and $20\%$. Use the same initial values and timespan as before. """ +# ╔═╡ a2a109e3-ea74-4e74-91d0-6ea12ddf28d4 +md" +Initialize vector `params_ex1` with parameter values: +" + +# ╔═╡ e0a8a397-4500-47de-8be3-49d3174648b1 +md""" +Create the ODE problem and store it in `oprob_ex1`: +""" + +# ╔═╡ 0590bc0b-45d6-4a8e-8078-af057984523f +md""" +Solve the ODE problem and store the solution in `osol_ex1`: +""" + +# ╔═╡ 7a1effe4-776c-4143-8085-f98a213a2cc3 +md""" +Change the value of $\alpha$ in the `params_ex1` vector to visualize the effect in the plot. +""" + +# ╔═╡ b2f61eed-b8d4-45e5-983a-5315964322b0 +md""" +!!! warning "Tip" + You can move the cell containing the slider next to the figure to visualize the changes in $\alpha$. +""" + # ╔═╡ 090a949f-c18f-4e07-8c94-21a71bb0ceed md""" Make a slider for $\alpha$ in the range of $0.08$ and $0.20$ with a step of $0.02$. Take a default value of $0.08$. @@ -317,29 +399,14 @@ Make a slider for $\alpha$ in the range of $0.08$ and $0.20$ with a step of $0.0 # missing # Uncomment and complete the instruction @bind α Slider(0.08:0.02:0.20, default=0.08, show_value=true) -# ╔═╡ a2a109e3-ea74-4e74-91d0-6ea12ddf28d4 -md" -Initialize vector `params_ex1` with parameter values: -" - # ╔═╡ 27a4c4f5-0b2b-4d23-9bb0-a1a8ff6cfc4d # params_ex1 = missing # Uncomment and complete the instruction params_ex1 = [:α => α, :β => 1.0e-6, :r => 0.2, :m => 0.4] -# ╔═╡ e0a8a397-4500-47de-8be3-49d3174648b1 -md""" -Create the ODE problem and store it in `oprob_ex1`: -""" - # ╔═╡ 7955722d-fc35-4cce-8bf2-ee40ee7fbc82 # oprob_ex1 = missing; # Uncomment and complete the instruction oprob_ex1 = ODEProblem(infection_model, u0, tspan, params_ex1); -# ╔═╡ 0590bc0b-45d6-4a8e-8078-af057984523f -md""" -Solve the ODE problem and store the solution in `osol_ex1`: -""" - # ╔═╡ f7b09e96-cf30-4bd0-841b-46621df693ab # osol_ex1 = missing; # Uncomment and complete the instruction osol_ex1 = solve(oprob_ex1, Tsit5(), saveat=0.5); @@ -353,28 +420,29 @@ Plot the solutions: # missing # Uncomment and complete the instruction plot(osol_ex1, ylim=(0.0, 1.0e7)) -# ╔═╡ 7a1effe4-776c-4143-8085-f98a213a2cc3 -md""" -Change the value of $\alpha$ in the `params_ex1` vector to visualize the effect in the plot. -""" - # ╔═╡ c14d45b8-3af1-4e05-b10a-081ccd62a34d md""" Try to interpret the results yourself. Ask yourself the following questions: -1. What are the trends in the obtained results? +!!! question + 1. What are the trends in the obtained results? """ # ╔═╡ 04f89fb3-f856-4206-9871-4d92f2816332 -md"- Answer: missing" +md""" +- Answer: +""" # ╔═╡ a39eeec9-d816-4d35-90ae-e602a24bb056 md""" -2. How can this be explained from the model structure? +!!! question + 2. How can this be explained from the model structure? """ # ╔═╡ fcad8ede-8295-46d6-a637-728b3986a761 -md"- Answer: missing" +md""" +- Answer: +""" # ╔═╡ b3f08d61-187d-4f99-b95f-508ff1b3d52d md""" @@ -430,24 +498,32 @@ md""" Set-up parameter values: """ -# ╔═╡ cc31567f-631b-41b9-aa2d-3408ca951bcf -# params_ex2 = missing # Uncomment and complete the instruction -params_ex2 = [:α => 0.08, :β => 1.0e-6, :b => 0.2, :m => 0.4, :r => 0.2, :h => 0.5] - # ╔═╡ 82f8c50c-511d-4399-ac87-0890b678c6c1 md""" Create the ODE problem and store it in `oprob_ex2`: """ -# ╔═╡ ec08adb2-561c-4f17-a0b5-019d7b1f1098 -# oprob_ex2 = missing # Uncomment and complete the instruction -oprob_ex2 = ODEProblem(infection_med, u0, tspan, params_ex2); - # ╔═╡ c55ec157-6ec8-45db-9a54-0f39aceb9607 md""" Solve the ODE problem and store the solution in `osol_ex2`: """ +# ╔═╡ ef3ca25d-c110-452d-877a-6304ae6cd5a7 +md""" +Change the value of $b$ in the `params_ex2` vector to visualize the effect in the plot. Interpret the obtained plots. +""" + +# ╔═╡ 3b3339db-70a0-464e-aecb-17b1a800c686 +@bind b Slider(0:0.2:1, default=0.2, show_value=true) + +# ╔═╡ cc31567f-631b-41b9-aa2d-3408ca951bcf +# params_ex2 = missing # Uncomment and complete the instruction +params_ex2 = [:α => 0.08, :β => 1.0e-6, :b => b, :m => 0.4, :r => 0.2, :h => 0.5] + +# ╔═╡ ec08adb2-561c-4f17-a0b5-019d7b1f1098 +# oprob_ex2 = missing # Uncomment and complete the instruction +oprob_ex2 = ODEProblem(infection_med, u0, tspan, params_ex2); + # ╔═╡ 67668918-624e-4adf-be5d-6fdbc62555f6 # osol_ex2 = missing # Uncomment and complete the instruction osol_ex2 = solve(oprob_ex2, Tsit5(), saveat=0.5); @@ -458,31 +534,35 @@ Plot the solutions: """ # ╔═╡ 5f9a9838-099d-457f-9402-915f42d0cd33 -# missing # Uncomment and complete the instruction -plot(osol_ex2) - -# ╔═╡ ef3ca25d-c110-452d-877a-6304ae6cd5a7 -md""" -Change the value of $b$ in the `params_ex2` vector to visualize the effect in the plot. Interpret the obtained plots. -""" +begin + # missing # Uncomment and complete the instruction + plot(osol_ex2) + plot!(osol_ex1; linestyle=:dash, label=:none, color=:grey, lw=0.5) +end # ╔═╡ f8dbab24-55aa-466f-a978-5f8db93b4b93 md""" Try to answer the following questions: -1. Why does the peak in the number of infected individuals shift to the right when the value of $b$ increases? +!!! question + 1. Why does the peak in the number of infected individuals shift to the right when the value of $b$ increases? """ # ╔═╡ 381d3a54-0e4f-4203-874f-4a4716d481d4 -md"- Answer: missing" +md""" +- Answer: +""" # ╔═╡ fd7d89f3-9ab8-4b17-b26f-571bad862718 md""" -2. Why does the number of recovered individuals first rise when the value of $b$ increases and then fall when the value of $b$ continues to increase? +!!! question + 2. Why does the number of recovered individuals first rise when the value of $b$ increases and then fall when the value of $b$ continues to increase? """ # ╔═╡ 96de4f0d-c2d1-4fad-bded-a314cbca848b -md"- Answer: missing" +md""" +- Answer: +""" # ╔═╡ dedb1ac1-cb54-416f-a092-12a50080c69f md""" @@ -491,7 +571,7 @@ Check the number of fatalities: # ╔═╡ a912f449-6c9d-4595-863f-a2ba523bad95 # missing -osol_ex2[:D][end] +osol_ex2[:D][end]/osol_ex1[:D][end]-1 # 41% less deaths # ╔═╡ 089707c3-1df6-4799-a87b-0d4872a0267d md""" @@ -510,7 +590,7 @@ The vaccination programme is launched $2$ days after the outbreak of the disease Assume that individuals are still being treated ($b = 0.2$ and $h = 0.5$). Extend the model obtained in the previous exercise for the launch of a vaccination campaign after the outbreak of the disease. -Find out via trial and error what the minimum vaccination rate need to be so that the number of fatalities is $10$ times smaller after a period of $90$ days compared to those in absence of vaccination (cf. Exercise 2). Consider an initial step size in $v$ of $0.01$ and then fine tune with a step size of $0.001$. +Find out via trial and error what the minimum vaccination rate need to be so that the number of fatalities is $10$ times smaller after a period of $90$ days compared to those in absence of vaccination (cf. Exercise 2). Use the same initial values and timespan as before. """ @@ -544,6 +624,21 @@ Convert to an ODE system. Check the differential equations and make sure you und # osys_ex3 = missing # Uncomment and complete the instruction osys_ex3 = convert(ODESystem, infection_med_vac) +# ╔═╡ 0274fbd8-c025-4e36-bbb0-f65f21b962c7 +md""" +Set-up parameter values: +""" + +# ╔═╡ 060a5c5b-9834-42e2-98e9-ac23e7403b60 +md""" +Create the ODE problem and store it in `oprob_ex3`: +""" + +# ╔═╡ 69983b90-b6ef-4732-a4af-a772bb1364e5 +md""" +Solve the ODE problem for (step wise) increasing values of $v$ and store the solution in `osol_ex3_vac`. +""" + # ╔═╡ 2ee20493-2dc2-4bd4-8ec3-78032f1fcc2d md""" Make a slider and bind it to the variable `v`. Use a range $[0.0, 0.1]$, step size $0.001$ and default value of $0.0$. @@ -553,36 +648,21 @@ Make a slider and bind it to the variable `v`. Use a range $[0.0, 0.1]$, step si # missing # Uncomment and complete the instruction @bind v Slider(0.0:0.001:0.1, default=0.0, show_value=true) -# ╔═╡ 0274fbd8-c025-4e36-bbb0-f65f21b962c7 -md""" -Set-up parameter values: -""" - # ╔═╡ 34c4d746-45f7-43c4-a0f0-6e570373a35d # params_ex3 = missing # Uncomment and complete the instruction params_ex3 = [:α => 0.08, :β => 1.0e-6, :b => 0.2, :m => 0.4, :r => 0.2, :h => 0.5, :v => v] -# ╔═╡ 060a5c5b-9834-42e2-98e9-ac23e7403b60 -md""" -Create the ODE problem and store it in `oprob_ex3`: -""" - # ╔═╡ c61ae8b6-2324-43fa-a5ae-274a919af559 # oprob_ex3 = missing # Uncomment and complete the instruction oprob_ex3 = ODEProblem(infection_med_vac, u0, tspan, params_ex3); -# ╔═╡ 69983b90-b6ef-4732-a4af-a772bb1364e5 -md""" -Solve the ODE problem for (step wise) increasing values of $v$ and store the solution in `osol_ex3_vac`. Consider an initial step size in $v$ of $0.01$ and then fine tune with a step size of $0.001$. -""" - # ╔═╡ 16211bc6-cd97-43c0-8faf-25bb490930b6 # osol_ex3_no_vac = missing; # Uncomment and complete the instruction osol_ex3_vac = solve(oprob_ex3, Tsit5(), saveat=0.5); # ╔═╡ 461eada9-5f9c-4439-8b65-226382b6d148 md""" -Compare the latter with the number of fatalities when no vaccination is/was available (cf. Exercise 2) by setting up a condition (a boolean expression return either `true` or `false`) here below where the final number of fatalities (with vaccination) divided by 10 is compared with (use larger than or smaller than) the number of fatalities (without vaccination): +First, put the value of $b$ in Exercise 2 to $0.2$. Compare the latter with the number of fatalities when no vaccination is/was available (cf. Exercise 2) by setting up a condition (a boolean expression return either `true` or `false`) here below where the final number of fatalities (with vaccination) divided by 10 is compared with (use larger than or smaller than) the number of fatalities (without vaccination): """ # ╔═╡ 0994d790-0fe8-46ab-bba2-a0a4ea466f64 @@ -623,7 +703,7 @@ Create the ODE problem and store it in `oprob_ex3_c`: # ╔═╡ 7e4114d6-932a-4def-9bb5-b534072ea513 # oprob_ex3_c = missing # Uncomment and complete the instruction -oprob_ex3_c = ODEProblem(infection_med_vac_c_com, u0, tspan, params_ex3) +oprob_ex3_c = ODEProblem(infection_med_vac_c_com, u0, tspan, params_ex3); # ╔═╡ 1bf8bc58-6848-4783-a614-7ac11646de92 md""" @@ -640,12 +720,43 @@ Plot the solutions: """ # ╔═╡ ed9472a0-09c9-4d1c-8f1d-1b7d87b97640 -# missing # Uncomment and complete the instruction -plot(osol_ex3) +begin + # missing # Uncomment and complete the instruction + plot(osol_ex3) + plot!(osol_ex2; linestyle=:dash, label=:none, color=:grey, lw=0.5) +end + +# ╔═╡ 3c094d93-65b9-427c-a2d0-ef6b2d7f5520 +md""" +Check the number of fatalities now and compare to the case without vaccination. +""" # ╔═╡ 47243051-bb8f-444a-aca5-fb686680ca8b osol_ex3[:D][end] +# ╔═╡ 817cdd07-cdef-4e57-8925-bbc01a29452c +osol_ex2[:D][end] + +# ╔═╡ 57bdd356-ae37-4708-98bb-25e0dcf06a7b +osol_ex3[:D][end]/osol_ex2[:D][end]-1 # 94% less deaths + +# ╔═╡ 93fa1da1-d9cd-4441-8fd4-26120327bdf6 +md""" +!!! question + 3. What can you say about the rate of infection in the case of no vaccination? How would you measure this in the plot? +""" + +# ╔═╡ 4d9f74e0-455e-44bb-bffa-57b5f65d0639 +md""" +- Answer: +""" + +# ╔═╡ 0b27b7cc-d7fa-4b16-80a4-23571e918c6b +md""" +!!! hint + The rate of infection has to do with how many people get infected during a certain period... +""" + # ╔═╡ Cell order: # ╠═18a4df05-0349-400d-a29e-b3fa71aa4d88 # ╠═65b3536b-c9b3-485e-87e1-4f6657381503 @@ -661,6 +772,7 @@ osol_ex3[:D][end] # ╠═e97637b0-446c-44ac-bd08-c56632f9b57f # ╟─a91f1024-4800-4ffe-8bb2-5f6cf3c2bde1 # ╟─47f4a7cc-1a74-4ff0-ae21-2a5e4c495935 +# ╟─3f530e32-15e4-4f0c-8765-dee59553a7b3 # ╠═3f6080e1-ab43-47f7-a82b-95956bf4cafd # ╟─5d5fae40-a4ed-4908-ba65-f3a16c38ab4f # ╠═fd347a58-5cad-4073-aadb-176fa54dcdfa @@ -702,6 +814,10 @@ osol_ex3[:D][end] # ╠═35d6bce7-9778-4f42-bdcd-271cedd8bad9 # ╠═31ceb303-dbb1-4f4d-9082-14ea1d83ab66 # ╠═14143212-53f1-4753-8c25-e22559cdbccd +# ╟─c808c8ee-6de2-4ac3-a5b6-9dd2adb09ca9 +# ╠═110aff6b-ef50-45b5-b4f0-81540b472254 +# ╠═f6ec7911-bd4e-4566-a259-0dc3a0700e8c +# ╠═05cc2399-60f6-42e7-b9f6-1b2ecc2b8ada # ╟─bdf9cfa0-9dc4-4ea5-9024-63813ec30d09 # ╠═cbf0a768-f6ac-43fb-8d05-e7dac51d4cc0 # ╠═fee597e0-97cb-40bc-a5b9-166631e8b9f6 @@ -711,23 +827,31 @@ osol_ex3[:D][end] # ╠═fc2dc11e-7022-4c6f-b7ed-5b077fc21ac5 # ╠═2b511237-7739-44e5-b6bd-26a2fdc76bb5 # ╠═3a131f92-aa09-4e8c-98a1-0c4c1c74878a +# ╟─652f4832-a3eb-4c8d-a408-23594d305b38 +# ╠═ada57044-50bc-49ca-a753-319fa8e9ec89 +# ╠═f1e5ee9a-9636-46ab-8c07-23e64ba8d4c6 +# ╠═8507a09a-5b19-4c37-b0cf-411732960315 +# ╠═ea00eba1-af9d-48d3-a893-0dc57777b7a5 +# ╠═38b507e1-a046-4432-a756-21287681242f +# ╟─201716e7-8df4-4052-812b-9a04c921caea # ╟─ad83a851-e424-4e8f-bae9-38b9283db2fa # ╟─b580ef9b-7d53-4bf0-8511-213920d59ee2 -# ╟─090a949f-c18f-4e07-8c94-21a71bb0ceed -# ╠═85e81822-2ea6-4d05-b879-1791bff255b9 # ╟─a2a109e3-ea74-4e74-91d0-6ea12ddf28d4 # ╠═27a4c4f5-0b2b-4d23-9bb0-a1a8ff6cfc4d # ╟─e0a8a397-4500-47de-8be3-49d3174648b1 # ╠═7955722d-fc35-4cce-8bf2-ee40ee7fbc82 # ╟─0590bc0b-45d6-4a8e-8078-af057984523f # ╠═f7b09e96-cf30-4bd0-841b-46621df693ab +# ╟─7a1effe4-776c-4143-8085-f98a213a2cc3 +# ╟─b2f61eed-b8d4-45e5-983a-5315964322b0 +# ╟─090a949f-c18f-4e07-8c94-21a71bb0ceed +# ╠═85e81822-2ea6-4d05-b879-1791bff255b9 # ╟─e7947165-b244-4ff6-bdf3-61d03aefe696 # ╠═adc0aa15-e0a9-4549-9609-967a9dc78b78 -# ╟─7a1effe4-776c-4143-8085-f98a213a2cc3 # ╟─c14d45b8-3af1-4e05-b10a-081ccd62a34d -# ╟─04f89fb3-f856-4206-9871-4d92f2816332 +# ╠═04f89fb3-f856-4206-9871-4d92f2816332 # ╟─a39eeec9-d816-4d35-90ae-e602a24bb056 -# ╟─fcad8ede-8295-46d6-a637-728b3986a761 +# ╠═fcad8ede-8295-46d6-a637-728b3986a761 # ╟─b3f08d61-187d-4f99-b95f-508ff1b3d52d # ╟─08ba4614-e4fa-4203-9e28-c5c4bd9fcdd5 # ╠═e4087441-7d0d-4716-b9fa-eef45e9f3b87 @@ -739,13 +863,14 @@ osol_ex3[:D][end] # ╠═ec08adb2-561c-4f17-a0b5-019d7b1f1098 # ╟─c55ec157-6ec8-45db-9a54-0f39aceb9607 # ╠═67668918-624e-4adf-be5d-6fdbc62555f6 +# ╟─ef3ca25d-c110-452d-877a-6304ae6cd5a7 +# ╠═3b3339db-70a0-464e-aecb-17b1a800c686 # ╟─832f984a-176d-4187-8476-5026d29a63d8 # ╠═5f9a9838-099d-457f-9402-915f42d0cd33 -# ╟─ef3ca25d-c110-452d-877a-6304ae6cd5a7 # ╟─f8dbab24-55aa-466f-a978-5f8db93b4b93 -# ╟─381d3a54-0e4f-4203-874f-4a4716d481d4 +# ╠═381d3a54-0e4f-4203-874f-4a4716d481d4 # ╟─fd7d89f3-9ab8-4b17-b26f-571bad862718 -# ╟─96de4f0d-c2d1-4fad-bded-a314cbca848b +# ╠═96de4f0d-c2d1-4fad-bded-a314cbca848b # ╟─dedb1ac1-cb54-416f-a092-12a50080c69f # ╠═a912f449-6c9d-4595-863f-a2ba523bad95 # ╟─089707c3-1df6-4799-a87b-0d4872a0267d @@ -753,14 +878,14 @@ osol_ex3[:D][end] # ╠═a1795123-876b-4bd3-ac3a-711367b500d1 # ╟─6b46d116-0da3-428a-b25f-221622dfa7e0 # ╠═710fe13c-bd43-4d1e-867e-72330722ac1e -# ╟─2ee20493-2dc2-4bd4-8ec3-78032f1fcc2d -# ╠═2943b515-fb4b-45a2-88dd-d0267ec95b09 # ╟─0274fbd8-c025-4e36-bbb0-f65f21b962c7 # ╠═34c4d746-45f7-43c4-a0f0-6e570373a35d # ╟─060a5c5b-9834-42e2-98e9-ac23e7403b60 # ╠═c61ae8b6-2324-43fa-a5ae-274a919af559 # ╟─69983b90-b6ef-4732-a4af-a772bb1364e5 # ╠═16211bc6-cd97-43c0-8faf-25bb490930b6 +# ╟─2ee20493-2dc2-4bd4-8ec3-78032f1fcc2d +# ╠═2943b515-fb4b-45a2-88dd-d0267ec95b09 # ╟─461eada9-5f9c-4439-8b65-226382b6d148 # ╠═0994d790-0fe8-46ab-bba2-a0a4ea466f64 # ╟─8bb5dafd-6c26-4634-8be4-c2963efba056 @@ -775,4 +900,10 @@ osol_ex3[:D][end] # ╠═8814c42b-16c7-466a-8ad8-58ee1c0921b2 # ╟─25158ea5-1930-4fee-aab4-490b475d8635 # ╠═ed9472a0-09c9-4d1c-8f1d-1b7d87b97640 +# ╟─3c094d93-65b9-427c-a2d0-ef6b2d7f5520 # ╠═47243051-bb8f-444a-aca5-fb686680ca8b +# ╠═817cdd07-cdef-4e57-8925-bbc01a29452c +# ╠═57bdd356-ae37-4708-98bb-25e0dcf06a7b +# ╟─93fa1da1-d9cd-4441-8fd4-26120327bdf6 +# ╠═4d9f74e0-455e-44bb-bffa-57b5f65d0639 +# ╟─0b27b7cc-d7fa-4b16-80a4-23571e918c6b diff --git a/exercises/ode_model_irrigation.jl b/exercises/ode_model_irrigation.jl index 96276d8a..cc250d31 100644 --- a/exercises/ode_model_irrigation.jl +++ b/exercises/ode_model_irrigation.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ f3ae43dc-f7e1-11ee-3615-695b9e85b621 @@ -138,7 +138,7 @@ Create the ODE problem and store it in `oprob`: """ # ╔═╡ f222f889-d602-4654-9c90-a813738377c3 -# oprob = missing # Uncomment and complete the instruction +# oprob = missing; # Uncomment and complete the instruction # ╔═╡ 18717738-ae99-4b41-8414-4c1823307dde md""" diff --git a/exercises/ode_model_irrigation_sol.jl b/exercises/ode_model_irrigation_sol.jl index 9cb7908a..5c91b7bb 100644 --- a/exercises/ode_model_irrigation_sol.jl +++ b/exercises/ode_model_irrigation_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ f3ae43dc-f7e1-11ee-3615-695b9e85b621 @@ -112,7 +112,7 @@ params = [:k => 3.0, :Smax => 150.0, :v => 1.0e-3, :r => 5.0, :S₁res => 10.0] # ╔═╡ 493d0d3d-cc43-4c2e-931f-f4acbc2f41ae md""" -Unpack the variables and parameters so that we can use them in an intuitive way to calculate to observables. +Unpack the variables and parameters so that we can use them in an intuitive way the calculate to observables. """ # ╔═╡ 67f62789-a5f0-4e05-a4fb-dbade2ad7891 @@ -153,7 +153,7 @@ Create the ODE problem and store it in `oprob`: # ╔═╡ f222f889-d602-4654-9c90-a813738377c3 # oprob = missing # Uncomment and complete the instruction -oprob = ODEProblem(deepcopy(irrigation_mod_c_com), u0, tspan, params) +oprob = ODEProblem(deepcopy(irrigation_mod_c_com), u0, tspan, params); # ╔═╡ 18717738-ae99-4b41-8414-4c1823307dde md""" @@ -255,6 +255,6 @@ md"- Answer: missing" # ╟─3e1beea6-0fe4-4d77-9e5d-0ca78a662253 # ╠═15f14688-cf6e-4562-bcca-d3d0774c2d5c # ╟─d1a9c363-3ef6-4bbb-a150-63b44f9e7cf1 -# ╠═63ca9bf9-8b49-41ee-a062-eecc54f88e28 +# ╟─63ca9bf9-8b49-41ee-a062-eecc54f88e28 # ╟─85e8869e-5859-4b8f-a72d-f0c979191ec7 -# ╠═8b2459ca-9982-4c3a-b872-184c34289ec9 +# ╟─8b2459ca-9982-4c3a-b872-184c34289ec9 diff --git a/exercises/ode_model_soil_cont_plant_uptake.jl b/exercises/ode_model_soil_cont_plant_uptake.jl index b01c516b..3a571a63 100644 --- a/exercises/ode_model_soil_cont_plant_uptake.jl +++ b/exercises/ode_model_soil_cont_plant_uptake.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 121df656-f57a-11ee-140e-dfb61e112370 @@ -101,7 +101,7 @@ Create the ODE problem and store it in `oprob`: """ # ╔═╡ 6f84b532-a718-4d42-9829-91366693b51c -# oprob = missing # Uncomment and complete the instruction +# oprob = missing; # Uncomment and complete the instruction # ╔═╡ ca65797f-a1dd-42dd-992c-ba067932a018 md""" diff --git a/exercises/ode_model_soil_cont_plant_uptake_sol.jl b/exercises/ode_model_soil_cont_plant_uptake_sol.jl index c2e8fe9d..a79fcf5d 100644 --- a/exercises/ode_model_soil_cont_plant_uptake_sol.jl +++ b/exercises/ode_model_soil_cont_plant_uptake_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 121df656-f57a-11ee-140e-dfb61e112370 @@ -114,7 +114,7 @@ Create the ODE problem and store it in `oprob`: # ╔═╡ 6f84b532-a718-4d42-9829-91366693b51c # oprob = missing # Uncomment and complete the instruction -oprob = ODEProblem(soil_cont_plant_uptake, u0, tspan, params) +oprob = ODEProblem(soil_cont_plant_uptake, u0, tspan, params); # ╔═╡ ca65797f-a1dd-42dd-992c-ba067932a018 md""" @@ -185,7 +185,19 @@ u_guess = [osol[:C][end], osol[:P][end]] # ╔═╡ bf1ee7fb-027f-4b8b-8ce4-57a46ac1b4f4 # ╠═╡ disabled = true #=╠═╡ -Ceq, Peq = solve(SteadyStateProblem(ODEProblem(soil_cont_plant_uptake, u_guess, tspan, params))) +eq = solve(SteadyStateProblem(ODEProblem(soil_cont_plant_uptake, u_guess, tspan, params))) + ╠═╡ =# + +# ╔═╡ 9cd89fbe-1add-4ba1-beef-8936a83f6987 +# ╠═╡ disabled = true +#=╠═╡ +Ceq = eq[:C] + ╠═╡ =# + +# ╔═╡ 3b8c6453-2a7b-4c10-beda-dacbd1edc6c6 +# ╠═╡ disabled = true +#=╠═╡ +Peq = eq[:P] ╠═╡ =# # ╔═╡ 542d505f-8d65-4f68-8ac3-ee897b957b5e @@ -228,4 +240,6 @@ Ceq, Peq = solve(SteadyStateProblem(ODEProblem(soil_cont_plant_uptake, u_guess, # ╠═12af799d-54aa-4bde-8133-98c3b4dfe1e4 # ╠═3647ca59-c09e-40f8-8a95-03741e198428 # ╠═bf1ee7fb-027f-4b8b-8ce4-57a46ac1b4f4 +# ╠═9cd89fbe-1add-4ba1-beef-8936a83f6987 +# ╠═3b8c6453-2a7b-4c10-beda-dacbd1edc6c6 # ╠═542d505f-8d65-4f68-8ac3-ee897b957b5e diff --git a/exercises/ode_model_water_evap_infil.jl b/exercises/ode_model_water_evap_infil.jl index 8841043c..ceb9270e 100644 --- a/exercises/ode_model_water_evap_infil.jl +++ b/exercises/ode_model_water_evap_infil.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 62dc7706-f58a-11ee-2d3d-f78f7ceca914 @@ -136,7 +136,7 @@ Create the ODE problem and store it in `oprob`: """ # ╔═╡ a25d3652-13f5-47ef-9f16-c6698547a734 -# oprob = missing # Uncomment and complete the instruction +# oprob = missing; # Uncomment and complete the instruction # ╔═╡ 451a3c66-5bcc-4161-af81-f89af33b5862 md""" diff --git a/exercises/ode_model_water_evap_infil_sol.jl b/exercises/ode_model_water_evap_infil_sol.jl index ac8dfce6..6420be1c 100644 --- a/exercises/ode_model_water_evap_infil_sol.jl +++ b/exercises/ode_model_water_evap_infil_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 62dc7706-f58a-11ee-2d3d-f78f7ceca914 @@ -153,7 +153,7 @@ Create the ODE problem and store it in `oprob`: # ╔═╡ a25d3652-13f5-47ef-9f16-c6698547a734 # oprob = missing # Uncomment and complete the instruction -oprob = ODEProblem(water_evap_infil_c_com, u0, tspan, params) +oprob = ODEProblem(water_evap_infil_c_com, u0, tspan, params); # ╔═╡ 451a3c66-5bcc-4161-af81-f89af33b5862 md""" diff --git a/exercises/optim_wastewater_treatment_sol.jl b/exercises/optim_wastewater_treatment_sol.jl index 31a416bf..1be72bff 100644 --- a/exercises/optim_wastewater_treatment_sol.jl +++ b/exercises/optim_wastewater_treatment_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ f08fa69c-a744-11ef-0e79-3daf5bf297ea @@ -74,14 +74,22 @@ Tips: """ # ╔═╡ 8708de16-3532-4352-b211-c092f95c82d3 +# Uncomment and complete the instruction +# wastewater_treatment = @reaction_network begin +# @parameters missing +# @species missing +# missing +# missing +# missing +# missing +# end wastewater_treatment = @reaction_network begin @parameters q=5.0 V=50 r=0.4 Cin=3.0 Ks=5.2 kd=0.10 Y=1.2 @species C(t)=4 X(t)=1.0e-2 mmr(C, r, Ks), C + X --> (1+Y)*X # r*Ks/(C+Ks), C + X --> (1+Y)*X # mmr(C, r, Ks)*X, C --> Y*X - q/V*Cin, 0 --> C - q/V, C --> 0 + (q/V, q/V*Cin), 0 <--> C q/V, X --> 0 kd, X --> 0 end @@ -152,7 +160,7 @@ osol = solve(oprob, Tsit5(), saveat=0.1) # ╔═╡ 70871ee8-b0a4-4a9a-af39-5a63459b55f7 md""" -Plot the results. Use `ylim=(0, 4)` and `linewidth=2` as options. +Plot the results. Use `ylim=(0, 3)` and `lw=2` (or `linewidth=2`) as options. """ # ╔═╡ 34309734-3751-47e0-a602-d113ffaae510 @@ -160,12 +168,12 @@ Plot the results. Use `ylim=(0, 4)` and `linewidth=2` as options. # begin # missing # plot!([tspan[1], tspan[2]], [0.28, 0.28], -# linestyle=:dash, linewidth=2, linecolor=:green, label="") +# ls=:dash, lw=2, lc=:green, lab="C=0.28") # end begin - plot(osol, ylim=(0, 4), linewidth=2) + plot(osol, ylim=(0, 3), lw=2) plot!([tspan[1], tspan[2]], [0.28, 0.28], - linestyle=:dash, linewidth=2, linecolor=:green, label="C=0.28") + ls=:dash, lw=2, lc=:green, lab="C=0.28") end # ╔═╡ a0e735ad-09c2-4aa8-bc41-b294a9d56ea8 @@ -198,16 +206,16 @@ Declare the Turing model function. Sample the flow rate $q$ prior from an unifor # params = missing # oprob = missing # osol = missing -# C_val ~ missing +# C_d ~ missing # end -@model function wastewater_treatment_inference(C_val) +@model function wastewater_treatment_fun() q ~ Uniform(0, 5.0) u0 = [:C=>3.0, :X=>0.5] tspan = (0.0, 72.0) # the time interval to solve on params = [:q=>q, :V=>50, :r=>0.4, :Cin=>3.0, :Ks=>5.2, :kd=>0.10, :Y=>1.2] oprob = ODEProblem(wastewater_treatment, u0, tspan, params) osol = solve(oprob, Tsit5(), saveat=0.1) - C_val ~ Normal(osol[:C][end], 1e-3) + C_dis ~ Normal(osol[:C][end], 1e-3) end # ╔═╡ b3a40556-0c00-4f6d-8cd9-c5fca79d8bbf @@ -219,14 +227,25 @@ Define the desired value for the organic waste with the variable name `C_val`. # missing # Uncomment and complete the instruction C_val = 0.28 +# ╔═╡ 70cafd87-63f7-4674-ae49-43d422fdeae7 +md""" +Provide the time measurements to the defined function and instantly condition the model with the desired value: +""" + +# ╔═╡ ee108190-2dbc-42e0-b58b-aaa9fd985e66 +wastewater_treatment_cond_mod = wastewater_treatment_fun() | (C_dis = C_val,) + # ╔═╡ ee1ffc12-55a1-47ef-ac5b-33148706a09b md""" -Provide the measurement to the Turing model and optimize the prior. Do this with `MLE` method and Nelder-Mead. Store the optimization results in `results_mle`. +Optimize the prior for $q$. Do this with `MLE` method and Nelder-Mead. Store the optimization results in `results_mle`. """ # ╔═╡ afc035be-075b-464b-8ba2-20235082f005 # results_mle = missing # Uncomment and complete the instruction -results_mle = optimize(wastewater_treatment_inference(C_val), MLE(), NelderMead()) +results_mle = optimize(wastewater_treatment_cond_mod, MLE(), NelderMead()) + +# ╔═╡ 64844b47-1578-4e47-9cc7-7f242a583067 +coeftable(results_mle) # ╔═╡ 3ee8121e-3e78-4901-a32d-f04d0c6a0996 md""" @@ -261,7 +280,7 @@ osol_opt = solve(oprob_opt, Tsit5(), saveat=0.1) # ╔═╡ 82809c26-4cab-405e-8107-a8a43e81f699 md""" -Plot $C$ and $X$ simulated with the optimized parameter value. Use `ylim=(0, 4)` and `linewidth=2` as options. The dashed line indicates $C = 0.28\; kg\,m^{-3}$. +Plot $C$ and $X$ simulated with the optimized parameter value. Use `ylim=(0, 3)` and `lw=2` (or `linewidth=2`) as options. The dashed line indicates $C = 0.28\; kg\,m^{-3}$. """ # ╔═╡ 81429279-4190-41d1-a72a-20da0ce90528 @@ -269,12 +288,12 @@ Plot $C$ and $X$ simulated with the optimized parameter value. Use `ylim=(0, 4)` # begin # missing # plot!([tspan[1], tspan[2]], [C_val, C_val], -# linestyle=:dash, linewidth=2, linecolor=:green, label="C=0.28") +# ls=:dash, lw=2, lc=:green, lab="C=0.28") # end begin - plot(osol_opt, ylim=(0, 4), linewidth=2) + plot(osol_opt, ylim=(0, 3), lw=2) plot!([tspan[1], tspan[2]], [C_val, C_val], - linestyle=:dash, linewidth=2, linecolor=:green, label="C=0.28") + ls=:dash, lw=2, lc=:green, lab="C=0.28") end # ╔═╡ 6589acfd-1d81-4c10-adea-34ca7fa1ab5d @@ -320,8 +339,11 @@ Draw your conclusion. # ╠═b6bac48a-4a3d-47e4-90ea-788ca20dadff # ╟─b3a40556-0c00-4f6d-8cd9-c5fca79d8bbf # ╠═2df409ef-bd95-4ac3-a2b8-c5e17c490eba +# ╟─70cafd87-63f7-4674-ae49-43d422fdeae7 +# ╠═ee108190-2dbc-42e0-b58b-aaa9fd985e66 # ╟─ee1ffc12-55a1-47ef-ac5b-33148706a09b # ╠═afc035be-075b-464b-8ba2-20235082f005 +# ╠═64844b47-1578-4e47-9cc7-7f242a583067 # ╟─3ee8121e-3e78-4901-a32d-f04d0c6a0996 # ╠═98a157a1-8c20-474d-acb8-00373ee6d224 # ╟─ceb146c9-a09a-458b-b7d8-3bb7d3de38e0 diff --git a/exercises/sde_model_aging.jl b/exercises/sde_model_aging.jl index ea208185..c4ddb3b7 100644 --- a/exercises/sde_model_aging.jl +++ b/exercises/sde_model_aging.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 0c457482-95fe-11ef-0873-65164704c7a6 @@ -44,7 +44,7 @@ A possible model is the following differential equation: $$\cfrac{dX}{dt} = \mu t - \beta \cfrac{X}{X + \kappa}$$ -Lets denote $X$ in trillions [$tn$]. The term $\mu t$ stands for the procution of senescent cells, and the term $- \beta \cfrac{X}{X + \kappa}$ for the removal of senescent cells. The time $t$ is in years [$y$]. The coefficient $\eta$ [$tn/y^2$] is a proportionality factor for the production, $\beta$ [$tn/y$] is the removal rate coefficient and $\cfrac{X}{X + \kappa}$ [$-$] is the corresponding saturation factor, with $\kappa$ [$tn$] the amount of $X$ at which they inhibit half of their own removal rate. +Lets denote the amount of senescent cells as $X$ in trillions [$tn$]. The term $\mu t$ stands for the procution of senescent cells, and the term $- \beta \cfrac{X}{X + \kappa}$ for the removal of senescent cells. The time $t$ is in years [$y$]. The coefficient $\eta$ [$tn/y^2$] is a proportionality factor for the production, $\beta$ [$tn/y$] is the removal rate coefficient and $\cfrac{X}{X + \kappa}$ [$-$] is the corresponding saturation factor, with $\kappa$ [$tn$] the amount of $X$ at which they inhibit half of their own removal rate. If this model was all there was, then all individuals would age at the same rate and die at the same age. The model does not explain why genetically identical organisms could differ in the number of senenscent cells. Therefore, we will introduce noise in the model by treating it as a **Stochastic Differential Equation** (SDE) model, where noise will be added to both, production and removal processes. """ @@ -58,7 +58,7 @@ md""" md""" Implement the above ODE into a *reaction network object*, and name it `senescent_cells_rn`. -Take a default initial value $X(t=0)=0.0$ for the *species* $X$, and default values of $\mu=0.00558$, $\beta=0.4464$, $\kappa=1.116$ for the *parameters* in the model. In addition to the parameters, take $\eta=0.1$ as the *default noise scaling* factor, and, furthermore, set the noise scaling to $0.5$ for the process exhibiting the saturating removal of damage. +Take a default initial value $X(t=0)=$0.0 for the *species* $X$, and default values of $\mu=$0.00558, $\beta=$0.4464, $\kappa=$1.116 for the *parameters* in the model. In addition to the parameters, take $\eta=$0.1 as the *default noise scaling* factor, and, furthermore, set the noise scaling to 0.5 for the process exhibiting the saturating removal of damage. """ # ╔═╡ 38edfb50-7d6f-4fcc-b328-95ecb26d6de1 @@ -71,6 +71,11 @@ Take a default initial value $X(t=0)=0.0$ for the *species* $X$, and default val # missing # end +# ╔═╡ 8358d849-87ac-4d22-b2f9-86c957a1691b +md""" +You could use the `mm` function. For information about it, click [here](https://docs.sciml.ai/Catalyst/stable/api/#Catalyst.mm). +""" + # ╔═╡ 51edb519-2086-45a5-a666-b5a58c51b5e8 md""" Convert this *reaction model* into a symbolic differential equation model and verify that you get the correct differential equation as mentioned above. @@ -86,7 +91,7 @@ md""" # ╔═╡ 98c1f94e-aea5-40c5-bee7-8df8794fedb3 md""" -Initialize a vector `u0` with the default initial condition, set the timespan for the simulation (we will simulate from $0\;y$ to $120\;y$), and initialize a vector `param` with the default parameter values. In that way, later, you can change the initial condition and the parameter values if you want to try other values. +Initialize a vector `u0` with the default initial condition, set the timespan for the simulation (we will simulate from $0\;y$ to $120\;y$), and initialize a vector `parms` with the default parameter values. In that way, later, you can change the initial condition and the parameter values if you want to try other values. """ # ╔═╡ 80db134e-bc57-41b0-8e1b-2ac6bff0c806 @@ -109,7 +114,7 @@ Create the SDE problem. """ # ╔═╡ 7d164cdf-fd63-4c85-b168-3279d6d658eb -# sprob = missing # Uncomment and complete the instruction +# sprob = missing; # Uncomment and complete the instruction # ╔═╡ 9f9a616a-4353-4f9a-8da5-effe4d214ed0 md""" @@ -152,7 +157,7 @@ Create an `EnsembleProblem` based on `sprob`. # ╔═╡ 7d531f11-1a64-4b43-aa4f-04d282a615bd md""" -Solve the ensemble problem. Use `EM()` as solver, take a time step `dt=0.1`, use the options `save_everystep=true`, and `trajectories=100`. +Solve the ensemble problem. Use `EM()` as solver, take a time step `dt=0.1`, use the option `trajectories=100`. """ # ╔═╡ 5aaf1395-9b7c-451f-b1a3-44e5ba3c4d6a @@ -181,7 +186,7 @@ md""" !!! hints - The number of senescent cells of the `i`-th trajoctory can be accessed with: `essol.u[i][:X]`. - The index of the first element in the `i`-th trajectory that is greater than 5 can be found with: `findfirst(>(5), essol.u[i][:X])`. -- An index is a valid index when it if not `nothing`. +- An index is a valid index when it is not `nothing`. - The time at index position `j` can be accessed with `essol.u[i].t[j]` - Appending an element, e.g., `x` to an array `times` can be done as follow: `append!(times, x)` """ @@ -201,7 +206,7 @@ md""" # ╔═╡ 65edc40f-430f-4d1a-9062-17bf8e1d7d59 md""" -Make a histogram with the array `times`. Use `bins=range(0, 120, length=121)`. +Make a histogram with the array `times`. Use `bins=range(0, 120, length=121)` or `bins=0:120`. """ # ╔═╡ 17a51f9e-0adf-4802-8d13-c43eb7801bc7 @@ -285,6 +290,7 @@ md"- Answer: missing" # ╟─d917e75d-eefb-415f-ba45-2f1d7c62d63c # ╟─7bda135b-2e0a-425f-b30c-e5a09dbb8a4a # ╠═38edfb50-7d6f-4fcc-b328-95ecb26d6de1 +# ╟─8358d849-87ac-4d22-b2f9-86c957a1691b # ╟─51edb519-2086-45a5-a666-b5a58c51b5e8 # ╠═b3dd11e4-1209-46f3-a47a-07b54c5e9d77 # ╟─0524da26-35cb-4846-b7ef-f5842ae5db74 diff --git a/exercises/sde_model_aging_sol.jl b/exercises/sde_model_aging_sol.jl index 84eb3c0f..73ff29ed 100644 --- a/exercises/sde_model_aging_sol.jl +++ b/exercises/sde_model_aging_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 0c457482-95fe-11ef-0873-65164704c7a6 @@ -44,7 +44,7 @@ A possible model is the following differential equation: $$\cfrac{dX}{dt} = \mu t - \beta \cfrac{X}{X + \kappa}$$ -Lets denote $X$ in trillions [$tn$]. The term $\mu t$ stands for the procution of senescent cells, and the term $- \beta \cfrac{X}{X + \kappa}$ for the removal of senescent cells. The time $t$ is in years [$y$]. The coefficient $\eta$ [$tn/y^2$] is a proportionality factor for the production, $\beta$ [$tn/y$] is the removal rate coefficient and $\cfrac{X}{X + \kappa}$ [$-$] is the corresponding saturation factor, with $\kappa$ [$tn$] the amount of $X$ at which they inhibit half of their own removal rate. +Lets denote the amount of senescent cells as $X$ in trillions [$tn$]. The term $\mu t$ stands for the procution of senescent cells, and the term $- \beta \cfrac{X}{X + \kappa}$ for the removal of senescent cells. The time $t$ is in years [$y$]. The coefficient $\mu$ [$tn/y^2$] is a proportionality factor for the production, $\beta$ [$tn/y$] is the removal rate coefficient and $\cfrac{X}{X + \kappa}$ [$-$] is the corresponding saturation factor, with $\kappa$ [$tn$] the amount of $X$ at which they inhibit half of their own removal rate. If this model was all there was, then all individuals would age at the same rate and die at the same age. The model does not explain why genetically identical organisms could differ in the number of senenscent cells. Therefore, we will introduce noise in the model by treating it as a **Stochastic Differential Equation** (SDE) model, where noise will be added to both, production and removal processes. """ @@ -58,18 +58,10 @@ md""" md""" Implement the above ODE into a *reaction network object*, and name it `senescent_cells_rn`. -Take a default initial value $X(t=0)=0.0$ for the *species* $X$, and default values of $\mu=0.00558$, $\beta=0.4464$, $\kappa=1.116$ for the *parameters* in the model. In addition to the parameters, take $\eta=0.1$ as the *default noise scaling* factor, and, furthermore, set the noise scaling to $0.5$ for the process exhibiting the saturating removal of damage. +Take a default initial value $X(t=0)=$0.0 for the *species* $X$, and default values of $\mu=$0.00558, $\beta=$0.4464, $\kappa=$1.116 for the *parameters* in the model. In addition to the parameters, take $\eta=$0.1 as the *default noise scaling* factor, and, furthermore, set the noise scaling to 0.5 for the process exhibiting the saturating removal of damage. """ # ╔═╡ 38edfb50-7d6f-4fcc-b328-95ecb26d6de1 -# Uncomment and complete the instruction -# senescent_cells_rn = @reaction_network begin -# @species missing -# @parameters missing -# @default_noise_scaling missing -# missing -# missing -# end senescent_cells_rn = @reaction_network begin @species X(t)=0.0 @parameters μ=0.00558 β=0.4464 κ=1.116 η=0.1 @@ -79,13 +71,17 @@ senescent_cells_rn = @reaction_network begin mm(X, β, κ), X => 0, [noise_scaling = 0.5] end +# ╔═╡ 00a1a641-f959-4275-8ed6-7991761be26a +md""" +You could use the `mm` function. For information about it, click [here](https://docs.sciml.ai/Catalyst/stable/api/#Catalyst.mm). +""" + # ╔═╡ 51edb519-2086-45a5-a666-b5a58c51b5e8 md""" Convert this *reaction model* into a symbolic differential equation model and verify that you get the correct differential equation as mentioned above. """ # ╔═╡ b3dd11e4-1209-46f3-a47a-07b54c5e9d77 -# osys = missing # Uncomment and complete the instruction osys = convert(ODESystem, senescent_cells_rn) # ╔═╡ 0524da26-35cb-4846-b7ef-f5842ae5db74 @@ -95,19 +91,16 @@ md""" # ╔═╡ 98c1f94e-aea5-40c5-bee7-8df8794fedb3 md""" -Initialize a vector `u0` with the default initial condition, set the timespan for the simulation (we will simulate from $0\;y$ to $120\;y$), and initialize a vector `param` with the default parameter values. In that way, later, you can change the initial condition and the parameter values if you want to try other values. +Initialize a vector `u0` with the default initial condition, set the timespan for the simulation (we will simulate from $0\;y$ to $120\;y$), and initialize a vector `parms` with the default parameter values. In that way, later, you can change the initial condition and the parameter values if you want to try other values. """ # ╔═╡ 80db134e-bc57-41b0-8e1b-2ac6bff0c806 -# u0 = missing # Uncomment and complete the instruction u0 = [:X => 0.0] # ╔═╡ ab8bef21-8c4f-4962-b9cb-e87ac1db049a -# tspan = missing # Uncomment and complete the instruction tspan = (0.0, 120.0) # ╔═╡ ab302108-e9a7-4941-a762-c0dc109c9b1d -# params = missing # Uncomment and complete the instruction parms = [:μ=>0.00558, :β=>0.4464, :κ=>1.116] # ╔═╡ 3934ba8f-49c9-4f0c-8373-c8010f397d66 @@ -121,8 +114,7 @@ Create the SDE problem. """ # ╔═╡ 7d164cdf-fd63-4c85-b168-3279d6d658eb -# sprob = missing # Uncomment and complete the instruction -sprob = SDEProblem(senescent_cells_rn, u0, tspan, parms) +sprob = SDEProblem(senescent_cells_rn, u0, tspan, parms); # ╔═╡ 9f9a616a-4353-4f9a-8da5-effe4d214ed0 md""" @@ -130,7 +122,6 @@ Solve the SDE problem using `EM()`as solver and time step `dt=0.1`. """ # ╔═╡ e4b9393d-d33c-4e16-814e-347b35435a82 -# ssol = missing # Uncomment and complete the instruction ssol = solve(sprob, EM(), dt=0.1) # ╔═╡ 91881bc3-a1f0-48f7-82e8-7d7acea2f4de @@ -139,7 +130,6 @@ Plot the solutions. Use the option `ylim=(0, 6)` in order to limit the range of """ # ╔═╡ 7128ae66-c576-435b-8e33-4221f469ba1c -# missing # Uncomment and complete the instruction plot(ssol, ylim=(0, 6)) # ╔═╡ 1bce56da-0c35-41df-adbd-b5dee116be11 @@ -163,17 +153,18 @@ Create an `EnsembleProblem` based on `sprob`. """ # ╔═╡ 1f25730d-d93e-462a-ac02-f83381633849 -# esprob = missing # Uncomment and complete the instruction esprob = EnsembleProblem(sprob) # ╔═╡ 7d531f11-1a64-4b43-aa4f-04d282a615bd md""" -Solve the ensemble problem. Use `EM()` as solver, take a time step `dt=0.1`, use the options `save_everystep=true`, and `trajectories=100`. +Solve the ensemble problem. Use `EM()` as solver, take a time step `dt=0.1`, use the option `trajectories=100`. """ +#= +Solve the ensemble problem. Use `EM()` as solver, take a time step `dt=0.1`, use the options `save_everystep=true`, and `trajectories=100`. +=# # ╔═╡ 5aaf1395-9b7c-451f-b1a3-44e5ba3c4d6a -# essol = missing # Uncomment and complete the instruction -essol = solve(esprob, EM(), dt=0.1, save_everystep=true, trajectories=100) +essol = solve(esprob, EM(), dt=0.1, trajectories=100) # ╔═╡ c048528f-58a2-415d-a338-fc87302367b8 md""" @@ -181,7 +172,6 @@ Plot the solutions. Use the option `ylim=(0, 6)` in order to limit the range of """ # ╔═╡ 147adea6-e7ed-4f7b-b753-127e41500109 -# missing # Uncomment and complete the instruction plot(essol, ylim=(0, 6)) # ╔═╡ 1db274cd-3b01-4f45-8aa0-ffe6878a1dd1 @@ -197,25 +187,14 @@ Set up a histogram that shows the distribution of ages once the 5 trillion senes # ╔═╡ 3fe09628-cbfb-4e56-85e8-b97285b32e87 md""" !!! hints -- The number of senescent cells of the `i`-th trajoctory can be accessed with: `essol.u[i][:X]`. -- The index of the first element in the `i`-th trajectory that is greater than 5 can be found with: `findfirst(>(5), essol.u[i][:X])`. -- An index is a valid index when it if not `nothing`. -- The time at index position `j` can be accessed with `essol.u[i].t[j]` -- Appending an element, e.g., `x` to an array `times` can be done as follow: `append!(times, x)` + - The number of senescent cells of the `i`-th trajoctory can be accessed with: `essol.u[i][:X]`. + - The index of the first element in the `i`-th trajectory that is greater than 5 can be found with: `findfirst(>(5), essol.u[i][:X])`. + - An index is a valid index when it is not `nothing`. + - The time at index position `j` can be accessed with `essol.u[i].t[j]` + - Appending an element, e.g., `x` to an array `times` can be done as follow: `append!(times, x)` """ # ╔═╡ 0f901112-e504-4b7d-b7ec-3a80153903ca -# Uncomment and complete the instruction -# begin -# times = [] # make empty vector -# for missing # for loop from 1 to 100, default step is 1 -# # find index of first element that is greater than 5 -# missing -# if missing # if index is a valid index -# missing # append time to vector times -# end -# end -# end begin times = [] # make empty vector for i = 1:100 # for loop from 1 to 100, default step is 1 @@ -229,12 +208,12 @@ end # ╔═╡ 65edc40f-430f-4d1a-9062-17bf8e1d7d59 md""" -Make a histogram with the array `times`. Use `bins=range(0, 120, length=121)`. +Make a histogram with the array `times`. Use `bins=range(0, 120, length=121)` or `bins=0:120`. """ # ╔═╡ 17a51f9e-0adf-4802-8d13-c43eb7801bc7 -# missing # Uncomment and complete the instruction histogram(times, bins=range(0, 120, length=121), xlab="Age (years)", ylab="Frequency") +# histogram(times, bins=0:120, xlab="Age (years)", ylab="Frequency") # ╔═╡ dad744a4-0fd2-406d-a600-429ad7619efd md""" @@ -242,7 +221,6 @@ Check the mean. """ # ╔═╡ a41d2ab4-ffad-4b27-9811-ab57c51526cb -# missing # Uncomment and complete the instruction mean(times) # ╔═╡ 98ca03e1-9c4e-40db-9dd7-68f1898c1ef7 @@ -251,7 +229,6 @@ Check the standard deviation. """ # ╔═╡ 7ac54e2a-9c8e-4743-a1a0-38490b04f759 -# missing # Uncomment and complete the instruction std(times) # ╔═╡ 0f9118f5-93f4-42f8-a0cf-754ce9ce9dbe @@ -260,7 +237,6 @@ Check the minimum value. """ # ╔═╡ a07565f7-31d9-4c50-8345-5777adb8a77a -# missing # Uncomment and complete the instruction minimum(times) # ╔═╡ 6f4253ce-e686-4061-ae13-9b35065464d9 @@ -269,7 +245,6 @@ Check the maximum value. """ # ╔═╡ 70628044-aaa5-46d6-a2df-deabbd8f2df8 -# missing # Uncomment and complete the instruction maximum(times) # ╔═╡ b10a73a1-63ae-4a15-9a83-394f6ed4e36e @@ -321,6 +296,7 @@ md"- Answer: missing" # ╟─d917e75d-eefb-415f-ba45-2f1d7c62d63c # ╟─7bda135b-2e0a-425f-b30c-e5a09dbb8a4a # ╠═38edfb50-7d6f-4fcc-b328-95ecb26d6de1 +# ╟─00a1a641-f959-4275-8ed6-7991761be26a # ╟─51edb519-2086-45a5-a666-b5a58c51b5e8 # ╠═b3dd11e4-1209-46f3-a47a-07b54c5e9d77 # ╟─0524da26-35cb-4846-b7ef-f5842ae5db74 diff --git a/exercises/sde_model_catalyst_intro.jl b/exercises/sde_model_catalyst_intro.jl index 724ca0bc..22f33e63 100644 --- a/exercises/sde_model_catalyst_intro.jl +++ b/exercises/sde_model_catalyst_intro.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 71118b72-1db2-11ef-1f5b-a163b0b7c390 @@ -26,6 +26,9 @@ using Catalyst # ╔═╡ 99229de2-1e9b-470f-b532-ed1afb91c971 using DifferentialEquations, Plots +# ╔═╡ c7c90b19-764e-41b6-a887-78e80d09ef59 +using Distributions + # ╔═╡ 5308b9d5-8068-48d7-b7a2-9e6ae043321b md""" # Solving SDE problems with Catalyst @@ -198,7 +201,7 @@ In the parameter list, you could also mention another default value for the defa """ # ╔═╡ 38e28866-8c09-4675-a9c1-d9ba4012070b -params = [:α => 0.08, :β => 1.0e-6, :r => 0.2, :m => 0.4, :η => 50] +parms = [:α => 0.08, :β => 1.0e-6, :r => 0.2, :m => 0.4, :η => 50] # ╔═╡ 5ef6414d-943c-4a1e-a528-af0fb61d4f9a md""" @@ -208,7 +211,7 @@ Create the SDE problem. """ # ╔═╡ 1d5c6ff5-6a63-4491-981e-9c1ab5d37d60 -sprob = SDEProblem(infection_sde_model, u0, tspan, params) +sprob = SDEProblem(infection_sde_model, u0, tspan, parms); # ╔═╡ 0da84898-6170-4d71-acaf-23d97bfd7be9 md""" @@ -268,7 +271,7 @@ You can try this by uncommenting the instruction below and run the cell. # ╔═╡ 5b91a7c2-64a3-4987-a9c6-6b1432d9b226 md""" -You will have noticed the detection of instabilities and the abortions. This is because of the stochastic effects that can cause calculations to become unstable. In order to cope with that, we will make sure that at every step the states $S$, $I$, $R$ and $D$ always remain within their boundaries. Here this is in the interval $[0, 10000000]$. To realize this we can create a so-called `DisceteCallback` function using the functions below, namely, `condition` and `affect!`. Both put in a `DisceteCallback` function they basically will make sure that at each (integration) step, the states (cf. `integrator.u[i]`) will not go below $0$ or above $10000000$. +You will have noticed the detection of instabilities and the abortions. This is because of the stochastic effects that can cause calculations to become unstable for this particular case. In order to cope with that, we will make sure that at every step the states $S$, $I$, $R$ and $D$ always remain within their boundaries. Here this is in the interval $[0, 10\,000\,000]$. To realize this we can create a so-called `DisceteCallback` function using the functions below, namely, `condition` and `affect!`. Both put in a `DisceteCallback` function they basically will make sure that at each (integration) step, the states (cf. `integrator.u[i]`) will not go below $0$ or above $10\,000\,000$. """ # ╔═╡ 3aebcf0b-717b-49bd-ae6b-ca7fffd9b75b @@ -307,11 +310,119 @@ Now we can solve the ensemble problem while including the callback function. """ # ╔═╡ 3f57d613-0042-4df9-9892-edaa90c0f52e -essol = solve(esprob, EM(), dt=0.1, callback=cb, save_everystep=true, trajectories=100) +essol = solve(esprob, EM(), dt=0.1, callback=cb, save_everystep=false, trajectories=100) # ╔═╡ 72770915-e1f5-41c5-84d2-9e6cbc0c24ff plot(essol) +# ╔═╡ 573f9c4d-9616-48e6-8d5a-a0660710bcdc +essol.u + +# ╔═╡ 9b5275ed-cdae-44aa-a86a-c6131a2bcc46 +md""" +We are now interested in the times of the infection peak when there is an epidemic. Notice that some simulations do not show an infection peak. We will later discard these cases. +""" + +# ╔═╡ cf098875-edef-4d98-a1db-660ae99679c3 +md""" +Suppose you take the index of a simulation where there is a clear infection peak. +""" + +# ╔═╡ bc6364c4-997d-4e31-be0b-2b8e92e96aa5 +i = 3 + +# ╔═╡ f01a76a4-95e8-4b20-b1b7-104284064420 +md""" +The time vector corresponding to this simulation is: +""" + +# ╔═╡ 44acee7b-1928-4c88-b4a9-f15bb2be8299 +essol.u[i].t + +# ╔═╡ d4c039c5-35fa-4f06-947f-b8fb709fe285 +md""" +The corresponding $I$-vector is: +""" + +# ╔═╡ d4e37e1e-8a8c-471e-9148-f3fd996fc164 +essol.u[i][:I] + +# ╔═╡ b99761c3-6275-431f-a23e-54faae0262e0 +md""" +You can determine the maximum with the function `maximum`: +""" + +# ╔═╡ 7e33cf89-dc3c-4db3-9a4a-a6042de302db +I_max = maximum(essol.u[i][:I]) + +# ╔═╡ a4d7650a-a952-4317-8f40-f74f6499706d +md""" +For element wise comparing `I_max` with `essol.u[i][:I]` you need to use the operator `.==` (notice the *dot* before `==`). +""" + +# ╔═╡ 9cb3fe2a-77f9-443b-8b7e-842839bfcdf9 +I_max .== essol.u[i][:I] + +# ╔═╡ a1b8b355-2f41-4810-b29e-5d911e7905b5 +md""" +Now you can find the (first) index in `essol.u[i][:I]` where this maximum is located with the function `findfirst`. +""" + +# ╔═╡ dac7b56f-8b3d-47c6-a68a-f56fc9037402 +i_max = findfirst(I_max .== essol.u[i][:I]) + +# ╔═╡ 260da0ca-38f5-40e4-9f33-814c03439c5c +md""" +Using this index in the time vector gives you the time at which the maximum occurred. +""" + +# ╔═╡ 2fe1a126-b8fd-4adb-95be-37fe87561d13 +essol.u[i].t[i_max] + +# ╔═╡ 0dc9d34b-4127-498f-935c-600867dcae65 +md""" +The next small piece of code will fill the vector `times` with the times at which a maximum occurred in the $I$-vector in the case of an epidemic. To do that, we only consider times that are geater than $10\;days$. +""" + +# ╔═╡ af6c2b51-2d9a-4785-a194-6e9cdd54473a +begin + times = [] # to store the relevant times + for i = 1:100 # iterate from 1 to 100 + I_max = maximum(essol.u[i][:I]) # get the maximum of I + i_max = findfirst(I_max .== essol.u[i][:I]) # get the corresponding index + t_max = essol.u[i].t[i_max] # get the time + if t_max > 10 # make sure it is greater than 10 days + append!(times, t_max) # append to times + end + end +end + +# ╔═╡ 01d9195f-7e76-4c64-9196-86be4b34fad5 +# histogram(times, bins=range(0, 90, length=91)) +histogram(times, bins=0:90) + +# ╔═╡ 67328358-a4f3-477d-a350-1c3b3c63b941 +md""" +If you want to get some statistical numbers, you will need to use the package `Distributions`. +""" + +# ╔═╡ 27ce94ea-389c-427c-b55a-a92a0b555992 +md""" +Now you can for example calculate the mean and standard deviation. +""" + +# ╔═╡ c164b2f8-0265-4378-b0e8-c2569fdc1ea4 +mean(times) + +# ╔═╡ 04995e30-0d5f-4ebf-b4ee-4311c54ab3de +std(times) + +# ╔═╡ 2ab0e26e-cf2b-4490-929a-cd29a0842b26 +maximum(times) + +# ╔═╡ b08d316d-772d-4a78-a65c-6b9d52e6274f +minimum(times) + # ╔═╡ Cell order: # ╠═71118b72-1db2-11ef-1f5b-a163b0b7c390 # ╠═dbf68cf4-7a18-4bf2-90a3-e36216a41a70 @@ -369,3 +480,29 @@ plot(essol) # ╟─094d7363-7918-4bd5-ae2b-52f283468317 # ╠═3f57d613-0042-4df9-9892-edaa90c0f52e # ╠═72770915-e1f5-41c5-84d2-9e6cbc0c24ff +# ╠═573f9c4d-9616-48e6-8d5a-a0660710bcdc +# ╟─9b5275ed-cdae-44aa-a86a-c6131a2bcc46 +# ╟─cf098875-edef-4d98-a1db-660ae99679c3 +# ╠═bc6364c4-997d-4e31-be0b-2b8e92e96aa5 +# ╟─f01a76a4-95e8-4b20-b1b7-104284064420 +# ╠═44acee7b-1928-4c88-b4a9-f15bb2be8299 +# ╟─d4c039c5-35fa-4f06-947f-b8fb709fe285 +# ╠═d4e37e1e-8a8c-471e-9148-f3fd996fc164 +# ╟─b99761c3-6275-431f-a23e-54faae0262e0 +# ╠═7e33cf89-dc3c-4db3-9a4a-a6042de302db +# ╟─a4d7650a-a952-4317-8f40-f74f6499706d +# ╠═9cb3fe2a-77f9-443b-8b7e-842839bfcdf9 +# ╟─a1b8b355-2f41-4810-b29e-5d911e7905b5 +# ╠═dac7b56f-8b3d-47c6-a68a-f56fc9037402 +# ╟─260da0ca-38f5-40e4-9f33-814c03439c5c +# ╠═2fe1a126-b8fd-4adb-95be-37fe87561d13 +# ╟─0dc9d34b-4127-498f-935c-600867dcae65 +# ╠═af6c2b51-2d9a-4785-a194-6e9cdd54473a +# ╠═01d9195f-7e76-4c64-9196-86be4b34fad5 +# ╟─67328358-a4f3-477d-a350-1c3b3c63b941 +# ╠═c7c90b19-764e-41b6-a887-78e80d09ef59 +# ╟─27ce94ea-389c-427c-b55a-a92a0b555992 +# ╠═c164b2f8-0265-4378-b0e8-c2569fdc1ea4 +# ╠═04995e30-0d5f-4ebf-b4ee-4311c54ab3de +# ╠═2ab0e26e-cf2b-4490-929a-cd29a0842b26 +# ╠═b08d316d-772d-4a78-a65c-6b9d52e6274f diff --git a/exercises/sde_model_fermenter_secondorder.jl b/exercises/sde_model_fermenter_secondorder.jl index afa92a4b..848ea1b4 100644 --- a/exercises/sde_model_fermenter_secondorder.jl +++ b/exercises/sde_model_fermenter_secondorder.jl @@ -1,5 +1,5 @@ ### A Pluto.jl notebook ### -# v0.19.46 +# v0.20.4 using Markdown using InteractiveUtils @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ eb142900-1d94-11ef-12ed-6951b45f1817 @@ -33,10 +33,10 @@ md""" In a fermenter reactor biomass grows on substrate. The reactor is fed with a inlet flow rate $Q_{in}$ [$L/h$], which consist of a (manipulable) input concentration of substrate $S_{in}$ [$g/L$]. Inside the reactor, biomass, with a concentration of $X$ [$g/L$], is produced through second-order kinetics: $$\begin{eqnarray*} -%S \xrightarrow[\quad\quad]{\beta} Y \, X -S \xrightarrow[\quad\quad]{r} Y \, X \quad\quad\quad\quad r = k \, S\,X +S + X \xrightarrow[\quad\quad]{k} X + YX \end{eqnarray*}$$ + with $k$ [$L\,gS^{-1}h^{-1}$] the reaction rate constant, and $Y$ [$gX/gS$] the yield coefficient which is defined here by the amount of produced biomass by consumption of one unit of substrate. Futhermore, the reactor is drained with an outlet flow $Q$ [$L/h$], which consist of the current concentrations of substrate $S$ [$g/L$] and biomass $X$ [$g/L$] inside the reactor. The volume $V$ [$L$] of the reactor content is kept constant by setting $Q_{in} = Q$. """ @@ -53,6 +53,11 @@ Assign the following noise scaling values: - noise scaling of `0.0` for the remaining *reactions* """ +# ╔═╡ 8e1a3734-d03c-4d0c-a808-a79bcaa7f899 +md""" +The parameter values are $k =$ 0.2, $Y =$ 0.76, $Q =$ 2.0, $V =$ 40.0 and $S_{in} =$ 2.2$\;g/L$. Suppose that at $t=$0$\;h$ no substrate $S$ is present in the reactor but that there is initially some biomass with a concetration of 0.1$\;g/L$. Simulate the evolution of $S$ and $X$ during $120$ hours. +""" + # ╔═╡ 6b627d84-b6a5-444d-8163-40a4cab181bd # Uncomment and complete the instruction # fermenter_sde_secondorder = @reaction_network begin @@ -65,6 +70,11 @@ Assign the following noise scaling values: # ╔═╡ 47ca3573-691c-4127-85b9-d5b5a1a23fbb md""" Convert the system to a symbolic differential equation model and verify, by analyzing the differential equation, that your model is correctly implemented. + +Hint: +- Use the option: `combinatoric_ratelaws=false` + +For information about this option, click [here](https://docs.sciml.ai/Catalyst/stable/introduction_to_catalyst/introduction_to_catalyst/#introduction_to_catalyst_ratelaws). """ # ╔═╡ e1f11068-e489-4c54-a30d-981f5cb19b47 @@ -87,7 +97,7 @@ Set the timespan for the simulation: # tspan = missing # Uncomment and complete the instruction # ╔═╡ a4d28c40-e315-4bb9-87a5-2b45dd633e5f -# params = missing # Uncomment and complete the instruction +# parms = missing # Uncomment and complete the instruction # ╔═╡ aeddc31e-9de2-4792-a2d8-59a14dfc8173 # sprob = missing # Uncomment and complete the instruction @@ -126,7 +136,7 @@ Solve the `EnsembleProblem` using the same solver (and time step) as before, for # ╔═╡ 26746cab-d3e7-4a01-bbbd-9fcb49ef652f md""" -Plot the results. Use as option again `ylim=(0.0,2.0)` and also `linealpha=0.5` to modify the line boldness. +Plot the results. Use as option again `ylim=(0.0,2.0)` and also `linealpha=0.5` (or `la=0.5`) to modify the line boldness. """ # ╔═╡ 4fcc1d0a-9d30-4056-b8a3-3d802edc42e5 @@ -142,6 +152,7 @@ Plot the results. Use as option again `ylim=(0.0,2.0)` and also `linealpha=0.5` # ╟─959d6307-a30d-4ae7-970d-b2c7584c2c8f # ╟─98858b9c-d4f9-451f-a7b9-fcaa012ee28e # ╟─d2e2680c-01c6-449a-bb5f-7472bc1de243 +# ╟─8e1a3734-d03c-4d0c-a808-a79bcaa7f899 # ╠═6b627d84-b6a5-444d-8163-40a4cab181bd # ╟─47ca3573-691c-4127-85b9-d5b5a1a23fbb # ╠═e1f11068-e489-4c54-a30d-981f5cb19b47 diff --git a/exercises/sde_model_fermenter_secondorder_sol backup 1.jl b/exercises/sde_model_fermenter_secondorder_sol backup 1.jl new file mode 100644 index 00000000..427c742e --- /dev/null +++ b/exercises/sde_model_fermenter_secondorder_sol backup 1.jl @@ -0,0 +1,175 @@ +### A Pluto.jl notebook ### +# v0.20.4 + +using Markdown +using InteractiveUtils + +# ╔═╡ 8152f632-af15-4164-a8ff-07c33a9a49b3 +begin + # add this cell if you want the notebook to use the environment from where the Pluto server is launched + using Pkg + Pkg.activate("..") +end + +# ╔═╡ eb142900-1d94-11ef-12ed-6951b45f1817 +using Markdown + +# ╔═╡ 7139a11b-64db-46b9-a41c-dca83a9eab26 +using InteractiveUtils + +# ╔═╡ 1ca1d1db-1fdd-4a76-b350-126add7e013c +using Catalyst + +# ╔═╡ e04f782d-67da-4e21-a3bf-d2ddff4bba0b +using DifferentialEquations, Plots + +# ╔═╡ a28e7ddf-76e9-4628-888c-e1d838da75ce +md""" +# Exercise: Fermenter - 2nd order kinetics - SDE +""" + +# ╔═╡ 959d6307-a30d-4ae7-970d-b2c7584c2c8f +md""" +In a fermenter reactor biomass grows on substrate. The reactor is fed with a inlet flow rate $Q_{in}$ [$L/h$], which consist of a (manipulable) input concentration of substrate $S_{in}$ [$g/L$]. Inside the reactor, biomass, with a concentration of $X$ [$g/L$], is produced through second-order kinetics: + +$$\begin{eqnarray*} +%S \xrightarrow[\quad\quad]{\beta} Y \, X +S \xrightarrow[\quad\quad]{r} Y \, X \quad\quad\quad\quad r = k \, S\,X +\end{eqnarray*}$$ + +with $k$ [$L\,gS^{-1}h^{-1}$] the reaction rate constant, and $Y$ [$gX/gS$] the yield coefficient which is defined here by the amount of produced biomass by consumption of one unit of substrate. Futhermore, the reactor is drained with an outlet flow $Q$ [$L/h$], which consist of the current concentrations of substrate $S$ [$g/L$] and biomass $X$ [$g/L$] inside the reactor. The volume $V$ [$L$] of the reactor content is kept constant by setting $Q_{in} = Q$. +""" + +# ╔═╡ 98858b9c-d4f9-451f-a7b9-fcaa012ee28e +md""" +Create a *reaction network object* model for the aforementioned problem in order to simulate the evolution of substrate $S$ and biomass $X$ with time as a Stochastic Differential Equation (SDE) problem with noise scaling. Name it `fermenter_sde_secondorder`. +""" + +# ╔═╡ d2e2680c-01c6-449a-bb5f-7472bc1de243 +md""" +Assign the following noise scaling values: +- `η = 0.10` for the main *reaction* (default value for `η`) +- noise scaling of `0.05` for the *reaction* describing the inlet $S_{in}$ +- noise scaling of `0.0` for the remaining *reactions* +""" + +# ╔═╡ 6b627d84-b6a5-444d-8163-40a4cab181bd +fermenter_sde_secondorder = @reaction_network begin + @parameters η=0.10 + @default_noise_scaling η + k, S + X --> (1 + Y)*X + # Alternatively: + # k*S*X, S => Y*X + Q/V*Sin, 0 --> S, [noise_scaling = 0.05] + Q/V, (S, X) --> 0, [noise_scaling = 0.00] +end + +# ╔═╡ 47ca3573-691c-4127-85b9-d5b5a1a23fbb +md""" +Convert the system to a symbolic differential equation model and verify, by analyzing the differential equation, that your model is correctly implemented. +""" + +# ╔═╡ e1f11068-e489-4c54-a30d-981f5cb19b47 +osys = convert(ODESystem, fermenter_sde_secondorder, combinatoric_ratelaws=false) + +# ╔═╡ a65c84c8-d2ec-44e4-9a07-cbd59f190c57 +md""" +Initialize a vector `u0` with the initial conditions: +""" + +# ╔═╡ ef3f7a41-61ab-4449-8ffc-784cf1e5cbe6 +u0 = [:S => 0.0, :X => 0.1] + +# ╔═╡ 9d113e7f-8499-4b2a-a884-d34ce3da0b82 +md""" +Set the timespan for the simulation: +""" + +# ╔═╡ 839a624b-ca62-4c57-9511-207b626ce864 +tspan = (0.0, 120.0) + +# ╔═╡ a4d28c40-e315-4bb9-87a5-2b45dd633e5f +params = [:k => 0.2, :Y => 0.76, :Q => 2, :V => 40, :Sin => 2.2, :η => 0.10] + +# ╔═╡ b2973e86-d89f-476a-8c41-de25a9e5c69d +#=╠═╡ +md""" +Create the SDE problem and store it in `sprob`.\ +Hint: +- Use the option: `combinatoric_ratelaws=false` +""" + ╠═╡ =# + +# ╔═╡ aeddc31e-9de2-4792-a2d8-59a14dfc8173 +sprob = SDEProblem(fermenter_sde_secondorder, u0, tspan, params, combinatoric_ratelaws=false); + +# ╔═╡ 3a981326-2031-4c63-ad31-c44ddd7a88d5 +md""" +Solve the SDE problem. Use `EM()` with `dt=0.1`. Store the solution in `ssol`: +""" + +# ╔═╡ 6a69c369-4743-48c1-aed9-4f0ccb095707 +ssol = solve(sprob, EM(), dt=0.1) + +# ╔═╡ 6b6d2229-913b-41a2-8101-00e9fef0945a +md""" +Plot the results with the option `ylim=(0.0, 2.0)`: +""" + +# ╔═╡ 593a0e0a-c4d8-4b12-b38b-15b47705f8a7 +plot(ssol, ylim=(0.0, 2.0)) + +# ╔═╡ 08746e97-d794-4261-9ba6-9002cf17e4c1 +md""" +Create an `EnsembleProblem` in order to visualize a multiple solutions. Store it in `esprob`. +""" + +# ╔═╡ 3d07836a-60b1-4584-a89a-3d8bbc72b8cd +esprob = EnsembleProblem(sprob) + +# ╔═╡ 98c4ee2b-20ef-43a1-b420-7644d568810b +md""" +Solve the `EnsembleProblem` using the same solver (and time step) as before, for $100$ trajectories. Store the solution in `essol`. +""" + +# ╔═╡ 683fe575-887b-4bd1-8960-10c04f68354d +essol = solve(esprob, EM(), dt=0.1; trajectories=100) + +# ╔═╡ 26746cab-d3e7-4a01-bbbd-9fcb49ef652f +md""" +Plot the results. Use as option again `ylim=(0.0,2.0)` and also `linealpha=0.5` to modify the line boldness. +""" + +# ╔═╡ 4fcc1d0a-9d30-4056-b8a3-3d802edc42e5 +plot(essol, ylim=(0.0,2.0), linealpha=0.5) + +# ╔═╡ Cell order: +# ╠═eb142900-1d94-11ef-12ed-6951b45f1817 +# ╠═7139a11b-64db-46b9-a41c-dca83a9eab26 +# ╠═8152f632-af15-4164-a8ff-07c33a9a49b3 +# ╠═1ca1d1db-1fdd-4a76-b350-126add7e013c +# ╠═e04f782d-67da-4e21-a3bf-d2ddff4bba0b +# ╟─a28e7ddf-76e9-4628-888c-e1d838da75ce +# ╟─959d6307-a30d-4ae7-970d-b2c7584c2c8f +# ╟─98858b9c-d4f9-451f-a7b9-fcaa012ee28e +# ╟─d2e2680c-01c6-449a-bb5f-7472bc1de243 +# ╠═6b627d84-b6a5-444d-8163-40a4cab181bd +# ╟─47ca3573-691c-4127-85b9-d5b5a1a23fbb +# ╠═e1f11068-e489-4c54-a30d-981f5cb19b47 +# ╟─a65c84c8-d2ec-44e4-9a07-cbd59f190c57 +# ╠═ef3f7a41-61ab-4449-8ffc-784cf1e5cbe6 +# ╟─9d113e7f-8499-4b2a-a884-d34ce3da0b82 +# ╠═839a624b-ca62-4c57-9511-207b626ce864 +# ╠═a4d28c40-e315-4bb9-87a5-2b45dd633e5f +# ╟─b2973e86-d89f-476a-8c41-de25a9e5c69d +# ╠═aeddc31e-9de2-4792-a2d8-59a14dfc8173 +# ╟─3a981326-2031-4c63-ad31-c44ddd7a88d5 +# ╠═6a69c369-4743-48c1-aed9-4f0ccb095707 +# ╟─6b6d2229-913b-41a2-8101-00e9fef0945a +# ╠═593a0e0a-c4d8-4b12-b38b-15b47705f8a7 +# ╟─08746e97-d794-4261-9ba6-9002cf17e4c1 +# ╠═3d07836a-60b1-4584-a89a-3d8bbc72b8cd +# ╟─98c4ee2b-20ef-43a1-b420-7644d568810b +# ╠═683fe575-887b-4bd1-8960-10c04f68354d +# ╟─26746cab-d3e7-4a01-bbbd-9fcb49ef652f +# ╠═4fcc1d0a-9d30-4056-b8a3-3d802edc42e5 diff --git a/exercises/sde_model_fermenter_secondorder_sol.jl b/exercises/sde_model_fermenter_secondorder_sol.jl index 1f43eef0..e6671506 100644 --- a/exercises/sde_model_fermenter_secondorder_sol.jl +++ b/exercises/sde_model_fermenter_secondorder_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ eb142900-1d94-11ef-12ed-6951b45f1817 @@ -23,6 +23,9 @@ using Catalyst # ╔═╡ e04f782d-67da-4e21-a3bf-d2ddff4bba0b using DifferentialEquations, Plots +# ╔═╡ b02df672-970c-4fa1-9107-cce8ad25d878 +using Distributions + # ╔═╡ a28e7ddf-76e9-4628-888c-e1d838da75ce md""" # Exercise: Fermenter - 2nd order kinetics - SDE @@ -34,7 +37,8 @@ In a fermenter reactor biomass grows on substrate. The reactor is fed with a inl $$\begin{eqnarray*} %S \xrightarrow[\quad\quad]{\beta} Y \, X -S \xrightarrow[\quad\quad]{r} Y \, X \quad\quad\quad\quad r = k \, S\,X +%S \xrightarrow[\quad\quad]{r} Y \, X \quad\quad\quad\quad r = k \, S\,X +S + X \xrightarrow[\quad\quad]{k} X + YX % \, X \quad\quad\quad\quad r = k \, S\,X \end{eqnarray*}$$ with $k$ [$L\,gS^{-1}h^{-1}$] the reaction rate constant, and $Y$ [$gX/gS$] the yield coefficient which is defined here by the amount of produced biomass by consumption of one unit of substrate. Futhermore, the reactor is drained with an outlet flow $Q$ [$L/h$], which consist of the current concentrations of substrate $S$ [$g/L$] and biomass $X$ [$g/L$] inside the reactor. The volume $V$ [$L$] of the reactor content is kept constant by setting $Q_{in} = Q$. @@ -53,14 +57,12 @@ Assign the following noise scaling values: - noise scaling of `0.0` for the remaining *reactions* """ +# ╔═╡ f7941ddf-f1e7-41d1-9764-b644dfed68c0 +md""" +The parameter values are $k =$ 0.2, $Y =$ 0.76, $Q =$ 2.0, $V =$ 40.0 and $S_{in} =$ 2.2$\;g/L$. Suppose that at $t=$0$\;h$ no substrate $S$ is present in the reactor but that there is initially some biomass with a concetration of 0.1$\;g/L$. Simulate the evolution of $S$ and $X$ during $120$ hours. +""" + # ╔═╡ 6b627d84-b6a5-444d-8163-40a4cab181bd -# Uncomment and complete the instruction -# fermenter_sde_secondorder = @reaction_network begin -# @parameters missing -# missing -# missing -# missing -# end fermenter_sde_secondorder = @reaction_network begin @parameters η=0.10 @default_noise_scaling η @@ -74,10 +76,14 @@ end # ╔═╡ 47ca3573-691c-4127-85b9-d5b5a1a23fbb md""" Convert the system to a symbolic differential equation model and verify, by analyzing the differential equation, that your model is correctly implemented. + +Hint: +- Use the option: `combinatoric_ratelaws=false` + +For information about this option, click [here](https://docs.sciml.ai/Catalyst/stable/introduction_to_catalyst/introduction_to_catalyst/#introduction_to_catalyst_ratelaws). """ # ╔═╡ e1f11068-e489-4c54-a30d-981f5cb19b47 -# osys = missing # Uncomment and complete the instruction osys = convert(ODESystem, fermenter_sde_secondorder, combinatoric_ratelaws=false) # ╔═╡ a65c84c8-d2ec-44e4-9a07-cbd59f190c57 @@ -86,7 +92,6 @@ Initialize a vector `u0` with the initial conditions: """ # ╔═╡ ef3f7a41-61ab-4449-8ffc-784cf1e5cbe6 -# u0 = missing # Uncomment and complete the instruction u0 = [:S => 0.0, :X => 0.1] # ╔═╡ 9d113e7f-8499-4b2a-a884-d34ce3da0b82 @@ -95,27 +100,20 @@ Set the timespan for the simulation: """ # ╔═╡ 839a624b-ca62-4c57-9511-207b626ce864 -# tspan = missing # Uncomment and complete the instruction tspan = (0.0, 120.0) # ╔═╡ a4d28c40-e315-4bb9-87a5-2b45dd633e5f -# params = missing # Uncomment and complete the instruction -params = [:k => 0.2, :Y => 0.76, :Q => 2, :V => 40, :Sin => 2.2, :η => 0.10] +parms = [:k => 0.2, :Y => 0.76, :Q => 2, :V => 40, :Sin => 2.2, :η => 0.10] # ╔═╡ b2973e86-d89f-476a-8c41-de25a9e5c69d -# ╠═╡ disabled = true -#=╠═╡ md""" Create the SDE problem and store it in `sprob`.\ Hint: - Use the option: `combinatoric_ratelaws=false` """ - ╠═╡ =# # ╔═╡ aeddc31e-9de2-4792-a2d8-59a14dfc8173 -# sprob = missing # Uncomment and complete the instruction -# sprob = SDEProblem(fermenter_sde_secondorder, u0, tspan, params, combinatoric_ratelaws=false) -sprob = SDEProblem(fermenter_sde_secondorder, u0, tspan, params, combinatoric_ratelaws=false) +sprob = SDEProblem(fermenter_sde_secondorder, u0, tspan, parms, combinatoric_ratelaws=false); # ╔═╡ 3a981326-2031-4c63-ad31-c44ddd7a88d5 md""" @@ -123,7 +121,6 @@ Solve the SDE problem. Use `EM()` with `dt=0.1`. Store the solution in `ssol`: """ # ╔═╡ 6a69c369-4743-48c1-aed9-4f0ccb095707 -# ssol = missing # Uncomment and complete the instruction ssol = solve(sprob, EM(), dt=0.1) # ╔═╡ 6b6d2229-913b-41a2-8101-00e9fef0945a @@ -132,7 +129,6 @@ Plot the results with the option `ylim=(0.0, 2.0)`: """ # ╔═╡ 593a0e0a-c4d8-4b12-b38b-15b47705f8a7 -# missing plot(ssol, ylim=(0.0, 2.0)) # ╔═╡ 08746e97-d794-4261-9ba6-9002cf17e4c1 @@ -141,7 +137,6 @@ Create an `EnsembleProblem` in order to visualize a multiple solutions. Store it """ # ╔═╡ 3d07836a-60b1-4584-a89a-3d8bbc72b8cd -# esprob = missing # Uncomment and complete the instruction esprob = EnsembleProblem(sprob) # ╔═╡ 98c4ee2b-20ef-43a1-b420-7644d568810b @@ -150,17 +145,36 @@ Solve the `EnsembleProblem` using the same solver (and time step) as before, for """ # ╔═╡ 683fe575-887b-4bd1-8960-10c04f68354d -# essol = missing # Uncomment and complete the instruction -essol = solve(esprob, EM(), dt=0.1; trajectories=100) +essol = solve(esprob, EM(), dt=0.1, trajectories=100) # ╔═╡ 26746cab-d3e7-4a01-bbbd-9fcb49ef652f md""" -Plot the results. Use as option again `ylim=(0.0,2.0)` and also `linealpha=0.5` to modify the line boldness. +Plot the results. Use as option again `ylim=(0.0,2.0)` and also `linealpha=0.5` (or `la=0.5`) to modify the line boldness. """ # ╔═╡ 4fcc1d0a-9d30-4056-b8a3-3d802edc42e5 -# missing plot(essol, ylim=(0.0,2.0), linealpha=0.5) +# plot(essol, ylim=(0.0,2.0), la=0.5) + +# ╔═╡ 28da57db-ff57-4ade-887c-a132a616abd4 +essol.u[1][:X][end] + +# ╔═╡ 2b61187f-12f4-4b80-b927-f6fb587b486a +begin + Xeq_values = [] + for i=1:100 + append!(Xeq_values, essol.u[i][:X][end]) + end +end + +# ╔═╡ 89f2a414-ba53-43aa-bf61-1a7fbe252986 +histogram(Xeq_values, bins=1.0:0.01:1.8) + +# ╔═╡ ac5a78ad-6575-4c0b-9f9e-a632b648552a +mean(Xeq_values) + +# ╔═╡ fffe5c34-f0e0-400e-bb0f-44f9d9595919 +std(Xeq_values) # ╔═╡ Cell order: # ╠═eb142900-1d94-11ef-12ed-6951b45f1817 @@ -168,10 +182,12 @@ plot(essol, ylim=(0.0,2.0), linealpha=0.5) # ╠═8152f632-af15-4164-a8ff-07c33a9a49b3 # ╠═1ca1d1db-1fdd-4a76-b350-126add7e013c # ╠═e04f782d-67da-4e21-a3bf-d2ddff4bba0b +# ╠═b02df672-970c-4fa1-9107-cce8ad25d878 # ╟─a28e7ddf-76e9-4628-888c-e1d838da75ce # ╟─959d6307-a30d-4ae7-970d-b2c7584c2c8f # ╟─98858b9c-d4f9-451f-a7b9-fcaa012ee28e # ╟─d2e2680c-01c6-449a-bb5f-7472bc1de243 +# ╟─f7941ddf-f1e7-41d1-9764-b644dfed68c0 # ╠═6b627d84-b6a5-444d-8163-40a4cab181bd # ╟─47ca3573-691c-4127-85b9-d5b5a1a23fbb # ╠═e1f11068-e489-4c54-a30d-981f5cb19b47 @@ -180,7 +196,7 @@ plot(essol, ylim=(0.0,2.0), linealpha=0.5) # ╟─9d113e7f-8499-4b2a-a884-d34ce3da0b82 # ╠═839a624b-ca62-4c57-9511-207b626ce864 # ╠═a4d28c40-e315-4bb9-87a5-2b45dd633e5f -# ╠═b2973e86-d89f-476a-8c41-de25a9e5c69d +# ╟─b2973e86-d89f-476a-8c41-de25a9e5c69d # ╠═aeddc31e-9de2-4792-a2d8-59a14dfc8173 # ╟─3a981326-2031-4c63-ad31-c44ddd7a88d5 # ╠═6a69c369-4743-48c1-aed9-4f0ccb095707 @@ -192,3 +208,8 @@ plot(essol, ylim=(0.0,2.0), linealpha=0.5) # ╠═683fe575-887b-4bd1-8960-10c04f68354d # ╟─26746cab-d3e7-4a01-bbbd-9fcb49ef652f # ╠═4fcc1d0a-9d30-4056-b8a3-3d802edc42e5 +# ╠═28da57db-ff57-4ade-887c-a132a616abd4 +# ╠═2b61187f-12f4-4b80-b927-f6fb587b486a +# ╠═89f2a414-ba53-43aa-bf61-1a7fbe252986 +# ╠═ac5a78ad-6575-4c0b-9f9e-a632b648552a +# ╠═fffe5c34-f0e0-400e-bb0f-44f9d9595919 diff --git a/exercises/ssa_model_bike_sharing.jl b/exercises/ssa_model_bike_sharing.jl new file mode 100644 index 00000000..5308b652 --- /dev/null +++ b/exercises/ssa_model_bike_sharing.jl @@ -0,0 +1,333 @@ +### A Pluto.jl notebook ### +# v0.20.4 + +using Markdown +using InteractiveUtils + +# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). +macro bind(def, element) + #! format: off + quote + local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end + local el = $(esc(element)) + global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) + el + end + #! format: on +end + +# ╔═╡ 309035dd-5653-48a6-a53d-817e743279fa +begin + # add this cell if you want the notebook to use the environment from where the Pluto server is launched + using Pkg + Pkg.activate("..") +end + +# ╔═╡ 6b342f14-e7d5-11ef-1ea0-77ceb0d78f32 +using Markdown + +# ╔═╡ 7bfcc024-7d7f-4c0b-b918-8f7626b10974 +using InteractiveUtils + +# ╔═╡ 71140c81-af29-4857-8020-4f94c8bd64b3 +using Catalyst, DifferentialEquations, Plots, Distributions + +# ╔═╡ 284f5847-9c15-41f3-a595-1e12a22df69f +using PlutoUI; TableOfContents() + +# ╔═╡ 1f975552-b0b8-4830-8dcc-214574d4fc38 +md""" +# Exercise: Modeling a simple Bike Sharing System +""" + +# ╔═╡ d2f32eab-0b35-4794-9219-5bcbb4c069c5 +md""" +Imagine a bike sharing system for students traveling between Olin College and Wellesley College, which are about three miles apart in eastern Massachusetts. Suppose the system contains 12 bikes and two bike racks, one at Olin and one at Wellesley, each with the capacity to hold 12 bikes. As students arrive, check out a bike, and ride to the other campus, the number of bikes in each location changes. +Initially there are 10 bikes at Olin and, hence, 2 bikes at Wellesley. For this simple model, we will aslo assume that the changes in the number of bikes at both locations is instantenuously. The rate at which a bike is moved from Olin to Wellesley is denoted as $p_1$ ($\#bikes\;min^{-1}$); the rate at which a bike is moved from Wellesley to Olin is denoted as $p_2$ ($\#bikes\;min^{-1}$). Both processes are zeroth-order and we want to see the evolution of bikes during $1\,h = 60\,min$. + +This is a discreet and stochastic problem and you need to solve it with SSA. +""" + +# ╔═╡ 016842c9-9479-4061-a27e-9dc006121f23 +md""" +Create a *reaction network object* model for the aforementioned problem in order to simulate the evolution of the number of bikes at Olin ($O$) and Wellesley ($W$) with time. Name it `bike_sharing`. +""" + +# ╔═╡ 6c97bf81-ef32-45a4-aa7c-c8c26ba2d2c3 +# bike_sharing = @reaction_network begin +# missing +# ... +# end + +# ╔═╡ 6500aebf-70de-453b-bf0d-f47006aaa4e0 +md""" +!!! tip "Tip" + Subscripts 1, 2, etc, can be visualized by typing, after the letter, a **backslash** followed by an **underscore** and then the **TAB** key. For example `p\_1` followed by the TAB key will result in `p₁`. +""" + +# ╔═╡ 9c7ab7fb-7380-41a3-85ea-714478ade218 +md""" +Convert the system to a symbolic differential equation model and verify, by analyzing the differential equation, that your model is correctly implemented. +""" + +# ╔═╡ 1536fe23-0f8d-4b86-98d2-076248b35954 +# osys = missing + +# ╔═╡ e6e2ff5c-38eb-4ba3-b430-c9031483a0a5 +md""" +Initialize a vector `u0` with the initial conditions: +""" + +# ╔═╡ ab6af765-1cde-4da8-bbc1-a5fab391db54 +# u0 = missing + +# ╔═╡ 378878a0-5c09-4eb0-ac43-1031014ff12a +md""" +Set the timespan for the simulation: +""" + +# ╔═╡ 3ae98e83-7beb-4597-89be-80c813d4349b +# tspan = missing + +# ╔═╡ 988f79c0-9c7b-4752-a7f2-d4473ad73ce6 +md""" +Create a slider for the variable `p₁` in the range of $0.0$ and $1.0$ with a step of $0.1$. Take a default value of $0.0$. +""" + +# ╔═╡ 0d8f53f8-0a14-4ac6-bd0c-2190d4db0909 +# @bind p₁ missing + +# ╔═╡ 08d43ac8-a973-4d7b-baf7-4c37e54cfe24 +md" +Initialize vector `parms` with parameter values, `p₁` is the slider value and assign a constant value of `0.3` to `p₂`. +" + +# ╔═╡ e20e4dd8-bdbb-4005-af68-6bf7e4ec130e +# parms = missing + +# ╔═╡ 238e1120-34af-4d57-8efa-aa80ab28a874 +md""" +Create a DiscreteProblem and store it in `dprob`: +""" + +# ╔═╡ d4c45709-70c9-4ba0-8fb8-6b600473723d +# dprob = missing; + +# ╔═╡ d06fb076-76e4-4248-a940-96804ea68833 +md""" +Create a JumpProblem and store it in `jdprob`. Use the simulation method `Direct()` and an additional option `save_positions=(false, false)`. The latter prohibits to save the values just before and after the jump event (later, when solving the problem we will namely use `saveat=1.0`). +""" + +# ╔═╡ 7644adf4-d992-48b1-b40a-12fdf30f6cb5 +# jdprob = missing; + +# ╔═╡ 59d2d3e1-354b-4444-b8a1-16ad8ea2ba94 +md""" +If we would now solve the problem, you might for example encounter negative values for the number of bikes at Olin and, hence, a value larger than 12 at Wellesley. Of course, this makes no sense. Therefore, we will create the so-called `condition` function that needs to invoke the so-called `affect!` function at each jump event in order to check on $O$ and $W$ and setting them to valid values if necessary. +""" + +# ╔═╡ 53e15d08-7d1d-4bc2-9fd3-4bc6fbb9de84 +md""" +Create the `condition` function. +""" + +# ╔═╡ 1511d269-9706-41b1-b8e2-f85ebcedc2d8 +# function condition(u, t, integrator) +# missing +# end + +# ╔═╡ fd9b4521-30d2-4af3-a080-40e9dbf27aa4 +md""" +Create the `affect` function. + +Hints: +- If the number of bikes at Olin is larger than 12 (this implies that the number of bikes at Wellesley is negative), then the number of bikes at Olin should be set to 12 and the number of bikes at Wellesley should be set to 0. +- If the number of bikes at Olin is negative (this implies that the number of bikes at Wellesley is larger than 12), then the number of bikes at Olin should be set to 0 and the number of bikes at Wellesley should be set to 12. +- The number of bikes at Olin is accessed through `integrator.u[1]` and the number of bikes at Wellesley is accessed through `integrator.u[2]`. +""" + +# ╔═╡ 3cac94d6-14ae-42f2-b0b6-f47d87cdb518 +# function affect!(integrator) +# if missing +# missing +# missing +# end +# if missing +# missing +# missing +# end +# end + +# ╔═╡ b2797fd2-b6e1-4bb0-af23-26931fe8be69 +md""" +Create the discrete callback function. Store it in `cb`. Again use the option `save_positions=(false,false)`. +""" + +# ╔═╡ f947c2d9-9123-422d-8972-157717c85b3c +# cb = missing; + +# ╔═╡ 74708270-b1ec-48c7-af32-3b970b92c706 +md""" +Solve the problem and store it in `jdsol`. Use the `SSAStepper()` stepping algorithm, the option `saveat=1.0` and the callback function. +""" + +# ╔═╡ 2b00df5d-994e-47a1-8068-c93ce3f1a618 +# jdsol = missing; + +# ╔═╡ 9d06c31e-3525-4889-a1de-3fe02413c7d8 +md""" +Plot the solution. +""" + +# ╔═╡ 9a90f800-3669-4831-b50b-c5405bbb9a03 +# missing + +# ╔═╡ a554fd16-aa3d-48ca-8de6-5582725c27d8 +md""" +Analyse the results. See what happens when you: +- run the notebook cell with the `solve` function repeatly +- change the value of `p₁` using the slider +""" + +# ╔═╡ d6872046-b5ef-4c2d-a9bb-2418f57f715d +md""" +!!! question "Question" + From what value of `p₁` do you start to get empty bike racks at Olin? +""" + +# ╔═╡ 747e20c4-b06b-4e78-a09a-55053cf42bf4 +md"- Answer: missing" + +# ╔═╡ 92181028-60fc-4830-afba-2380ac91455d +md""" +You can inspect the actual number of bike values at Olin by using `jdsol[:O]`: +""" + +# ╔═╡ f8942b10-773a-4b22-baad-8004fba8bd34 +# missing + +# ╔═╡ 43d41284-053d-4dfe-8d5b-96be70c0495c +md""" +If you want to have a `true` boolean value on positions where the vector value is zero (and `false` on non-zero values), then you would compare `jdsol[:O]` element wise with `0`. In Julia, if you want to do element wise operations with/on vectors, you always need to place a dot (`.`) in front of the operator, like for example `.==`. + +Compare in that way `jdsol[:O]` with `0`: +""" + +# ╔═╡ a999ae2a-7567-41e7-9c0c-e94fad6f5d46 +# missing + +# ╔═╡ 9ebb5b44-04d7-4b89-acdb-e40a245703d2 +md""" +Furthermore, if you want the count the number of `true` values in the latter (hence, the zero element values), you can simply use the function `count(...)`. Count the number of zeros: +""" + +# ╔═╡ 049de8d5-b221-452b-b2c4-9bc1e0c17f48 +# missing + +# ╔═╡ a73a2853-1f48-4179-9771-083794d3f137 +md""" +Using the aforementioned way to count zeros in a vector, we will now count the zeros for a range of $p$ values. Because of the stochastic behaviour of the system, for each $p$ values we will count the zeros for a $1000$ simulations and then storing only the average value. + +To introduce a new value for $p_1$ you can take a deepcopy of the problem and remake the problem like this: +- `jdprob_re = remake(deepcopy(jdprob); p=[:p₁=>p_val])` +and then solving the problem and store it in `jdsol_re`. + +In the layout below, `mean_zero_counts` while contain the final mean values of the averaged numbers of zeros from a 1000 simulations using a specific $p$ value, `zero_counts_p_val` will contain the actual number of zeros for a 1000 simulations using a specific $p$ value. + +Use the layout below to fill in `mean_zero_counts`. +""" + +# ╔═╡ 682e9120-0e1c-4dfa-9ec6-66bb0a3f4374 +# begin +# p_values = 0.0:0.1:1.0 # different p-values +# mean_zero_counts = [] # vector to store the corresponding mean zero values +# for p_val = p_values # p_val will be each of the p_values +# zero_counts_p_val = [] # vector to store the zeros for the 1000 simulations +# for i = 1:1000 # do a 1000 simulations +# # take a deepcopy and remake the problem for the specific p-value +# jdprob_re = missing +# # solve the problem +# jdsol_re = missing +# # append the number of zeros to zero_counts_p_val +# append!(..., ...) +# end +# # append the mean number of zeros to mean_zero_counts +# append!(..., ...) +# end +# end + +# ╔═╡ 705d3fcb-20b6-4481-a304-1d3ccd623674 +md""" +Have a look at the mean zero counts by typing `mean_zero_counts`: +""" + +# ╔═╡ 5968317a-6c07-4655-8137-6702656bb3b4 +# missing + +# ╔═╡ ff9370d8-3395-4382-9f51-afa11748319e +md""" +Plot the mean zero counts as a function of the $p$-values. +""" + +# ╔═╡ 48be49d0-0b60-44f3-8152-1ca917a4232e +# missing + +# ╔═╡ d6452915-bdf0-48f0-8c7d-3df83c7bce72 +md""" +!!! question "Question" + - From what value of $p$ do the empty number of bike racks at Olin clearly begin to rise? + - Reflect on this, does this make sense? Hint: change the value of $p_2$ and observe what happens. +""" + +# ╔═╡ Cell order: +# ╠═6b342f14-e7d5-11ef-1ea0-77ceb0d78f32 +# ╠═7bfcc024-7d7f-4c0b-b918-8f7626b10974 +# ╠═309035dd-5653-48a6-a53d-817e743279fa +# ╠═71140c81-af29-4857-8020-4f94c8bd64b3 +# ╠═284f5847-9c15-41f3-a595-1e12a22df69f +# ╟─1f975552-b0b8-4830-8dcc-214574d4fc38 +# ╟─d2f32eab-0b35-4794-9219-5bcbb4c069c5 +# ╟─016842c9-9479-4061-a27e-9dc006121f23 +# ╠═6c97bf81-ef32-45a4-aa7c-c8c26ba2d2c3 +# ╟─6500aebf-70de-453b-bf0d-f47006aaa4e0 +# ╟─9c7ab7fb-7380-41a3-85ea-714478ade218 +# ╠═1536fe23-0f8d-4b86-98d2-076248b35954 +# ╟─e6e2ff5c-38eb-4ba3-b430-c9031483a0a5 +# ╠═ab6af765-1cde-4da8-bbc1-a5fab391db54 +# ╟─378878a0-5c09-4eb0-ac43-1031014ff12a +# ╠═3ae98e83-7beb-4597-89be-80c813d4349b +# ╟─988f79c0-9c7b-4752-a7f2-d4473ad73ce6 +# ╠═0d8f53f8-0a14-4ac6-bd0c-2190d4db0909 +# ╟─08d43ac8-a973-4d7b-baf7-4c37e54cfe24 +# ╠═e20e4dd8-bdbb-4005-af68-6bf7e4ec130e +# ╟─238e1120-34af-4d57-8efa-aa80ab28a874 +# ╠═d4c45709-70c9-4ba0-8fb8-6b600473723d +# ╟─d06fb076-76e4-4248-a940-96804ea68833 +# ╠═7644adf4-d992-48b1-b40a-12fdf30f6cb5 +# ╟─59d2d3e1-354b-4444-b8a1-16ad8ea2ba94 +# ╟─53e15d08-7d1d-4bc2-9fd3-4bc6fbb9de84 +# ╠═1511d269-9706-41b1-b8e2-f85ebcedc2d8 +# ╟─fd9b4521-30d2-4af3-a080-40e9dbf27aa4 +# ╠═3cac94d6-14ae-42f2-b0b6-f47d87cdb518 +# ╟─b2797fd2-b6e1-4bb0-af23-26931fe8be69 +# ╠═f947c2d9-9123-422d-8972-157717c85b3c +# ╟─74708270-b1ec-48c7-af32-3b970b92c706 +# ╠═2b00df5d-994e-47a1-8068-c93ce3f1a618 +# ╟─9d06c31e-3525-4889-a1de-3fe02413c7d8 +# ╠═9a90f800-3669-4831-b50b-c5405bbb9a03 +# ╟─a554fd16-aa3d-48ca-8de6-5582725c27d8 +# ╟─d6872046-b5ef-4c2d-a9bb-2418f57f715d +# ╟─747e20c4-b06b-4e78-a09a-55053cf42bf4 +# ╟─92181028-60fc-4830-afba-2380ac91455d +# ╠═f8942b10-773a-4b22-baad-8004fba8bd34 +# ╟─43d41284-053d-4dfe-8d5b-96be70c0495c +# ╠═a999ae2a-7567-41e7-9c0c-e94fad6f5d46 +# ╟─9ebb5b44-04d7-4b89-acdb-e40a245703d2 +# ╠═049de8d5-b221-452b-b2c4-9bc1e0c17f48 +# ╟─a73a2853-1f48-4179-9771-083794d3f137 +# ╠═682e9120-0e1c-4dfa-9ec6-66bb0a3f4374 +# ╟─705d3fcb-20b6-4481-a304-1d3ccd623674 +# ╠═5968317a-6c07-4655-8137-6702656bb3b4 +# ╟─ff9370d8-3395-4382-9f51-afa11748319e +# ╠═48be49d0-0b60-44f3-8152-1ca917a4232e +# ╟─d6452915-bdf0-48f0-8c7d-3df83c7bce72 diff --git a/exercises/ssa_model_bike_sharing_sol.jl b/exercises/ssa_model_bike_sharing_sol.jl new file mode 100644 index 00000000..e9f895b6 --- /dev/null +++ b/exercises/ssa_model_bike_sharing_sol.jl @@ -0,0 +1,334 @@ +### A Pluto.jl notebook ### +# v0.20.4 + +using Markdown +using InteractiveUtils + +# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). +macro bind(def, element) + #! format: off + quote + local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end + local el = $(esc(element)) + global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) + el + end + #! format: on +end + +# ╔═╡ 309035dd-5653-48a6-a53d-817e743279fa +begin + # add this cell if you want the notebook to use the environment from where the Pluto server is launched + using Pkg + Pkg.activate("..") +end + +# ╔═╡ 6b342f14-e7d5-11ef-1ea0-77ceb0d78f32 +using Markdown + +# ╔═╡ 7bfcc024-7d7f-4c0b-b918-8f7626b10974 +using InteractiveUtils + +# ╔═╡ 71140c81-af29-4857-8020-4f94c8bd64b3 +using Catalyst, DifferentialEquations, Plots, Distributions + +# ╔═╡ 284f5847-9c15-41f3-a595-1e12a22df69f +using PlutoUI; TableOfContents() + +# ╔═╡ 1f975552-b0b8-4830-8dcc-214574d4fc38 +md""" +# Exercise: Modeling a simple Bike Sharing System +""" + +# ╔═╡ d2f32eab-0b35-4794-9219-5bcbb4c069c5 +md""" +Imagine a bike sharing system for students traveling between Olin College and Wellesley College, which are about three miles apart in eastern Massachusetts. Suppose the system contains 12 bikes and two bike racks, one at Olin and one at Wellesley, each with the capacity to hold 12 bikes. As students arrive, check out a bike, and ride to the other campus, the number of bikes in each location changes. +Initially there are 10 bikes at Olin and, hence, 2 bikes at Wellesley. For this simple model, we will also assume that the changes in the number of bikes at both locations is instantaneous. The rate at which a bike is moved from Olin to Wellesley is denoted as $p_1$ ($\#bikes\;min^{-1}$); the rate at which a bike is moved from Wellesley to Olin is denoted as $p_2$ ($\#bikes\;min^{-1}$). Both processes are zeroth-order and we want to see the evolution of bikes during $1\,h = 60\,min$. + +This is a discreet and stochastic problem and you need to solve it with SSA. +""" + +# ╔═╡ 016842c9-9479-4061-a27e-9dc006121f23 +md""" +Create a *reaction network object* model for the aforementioned problem in order to simulate the evolution of the number of bikes at Olin ($O$) and Wellesley ($W$) with time. Name it `bike_sharing`. +""" + +# ╔═╡ 6c97bf81-ef32-45a4-aa7c-c8c26ba2d2c3 +bike_sharing = @reaction_network begin + @species O(t)=10 W(t)=2 + p₁, O => W + p₂, W => O +end + +# ╔═╡ 7227a95a-ba0c-44dc-b0b8-18d6bbf362e8 +md""" +!!! tip "Tip" + Subscripts 1, 2, etc, can be visualized by typing, after the letter, a **backslash** followed by an **underscore** and then the **TAB** key. For example `p\_1` followed by the TAB key will result in `p₁`. +""" + +# ╔═╡ 9c7ab7fb-7380-41a3-85ea-714478ade218 +md""" +Convert the system to a symbolic differential equation model and verify, by analyzing the differential equation, that your model is correctly implemented. +""" + +# ╔═╡ 1536fe23-0f8d-4b86-98d2-076248b35954 +osys = convert(ODESystem, bike_sharing) + +# ╔═╡ e6e2ff5c-38eb-4ba3-b430-c9031483a0a5 +md""" +Initialize a vector `u0` with the initial conditions: +""" + +# ╔═╡ ab6af765-1cde-4da8-bbc1-a5fab391db54 +u0 = [:O => 10, :W => 2] + +# ╔═╡ 378878a0-5c09-4eb0-ac43-1031014ff12a +md""" +Set the timespan for the simulation: +""" + +# ╔═╡ 3ae98e83-7beb-4597-89be-80c813d4349b +tspan = (0.0, 60.0) + +# ╔═╡ 988f79c0-9c7b-4752-a7f2-d4473ad73ce6 +md""" +Create a slider for the variable `p₁` in the range of $0.0$ and $1.0$ with a step of $0.1$. Take a default value of $0.0$. +""" + +# ╔═╡ 0d8f53f8-0a14-4ac6-bd0c-2190d4db0909 +@bind p₁ Slider(0.0:0.1:1, default=0.0, show_value=true) + +# ╔═╡ 08d43ac8-a973-4d7b-baf7-4c37e54cfe24 +md" +Initialize vector `parms` with parameter values, `p₁` is the slider value and assign a constant value of `0.3` to `p₂`. +" + +# ╔═╡ e20e4dd8-bdbb-4005-af68-6bf7e4ec130e +parms = [:p₁=>p₁, :p₂=>0.30] + +# ╔═╡ 238e1120-34af-4d57-8efa-aa80ab28a874 +md""" +Create a DiscreteProblem and store it in `dprob`: +""" + +# ╔═╡ d4c45709-70c9-4ba0-8fb8-6b600473723d +dprob = DiscreteProblem(bike_sharing, u0, tspan, parms); + +# ╔═╡ d06fb076-76e4-4248-a940-96804ea68833 +md""" +Create a JumpProblem and store it in `jdprob`. Use the simulation method `Direct()` and an additional option `save_positions=(false, false)` (for info about this, click [here](https://docs.sciml.ai/JumpProcesses/dev/jump_solve/#JumpProcesses.jl)). The latter prohibits to save the values just before and after the jump event (later, when solving the problem we will namely use `saveat=1.0`). +""" + +# ╔═╡ 7644adf4-d992-48b1-b40a-12fdf30f6cb5 +jdprob = JumpProblem(bike_sharing, dprob, Direct(), save_positions=(false, false)); + +# ╔═╡ 59d2d3e1-354b-4444-b8a1-16ad8ea2ba94 +md""" +If we would now solve the problem, you might for example encounter negative values for the number of bikes at Olin and, hence, a value larger than 12 at Wellesley. Of course, this makes no sense. Therefore, we will create the so-called `condition` function that needs to invoke the so-called `affect!` function at each jump event in order to check on $O$ and $W$ and setting them to valid values if necessary. +""" + +# ╔═╡ 53e15d08-7d1d-4bc2-9fd3-4bc6fbb9de84 +md""" +Create the `condition` function. +""" + +# ╔═╡ 1511d269-9706-41b1-b8e2-f85ebcedc2d8 +function condition(u, t, integrator) + true +end + +# ╔═╡ fd9b4521-30d2-4af3-a080-40e9dbf27aa4 +md""" +Create the `affect` function. + +Hints: +- If the number of bikes at Olin is larger than 12 (this implies that the number of bikes at Wellesley is negative), then the number of bikes at Olin should be set to 12 and the number of bikes at Wellesley should be set to 0. +- If the number of bikes at Olin is negative (this implies that the number of bikes at Wellesley is larger than 12), then the number of bikes at Olin should be set to 0 and the number of bikes at Wellesley should be set to 12. +- The number of bikes at Olin is accessed through `integrator.u[1]` and the number of bikes at Wellesley is accessed through `integrator.u[2]`. +""" + +# ╔═╡ 3cac94d6-14ae-42f2-b0b6-f47d87cdb518 +function affect!(integrator) + if integrator.u[1] > 12 + integrator.u[1] = 12 + integrator.u[2] = 0 + end + if integrator.u[1] < 0 + integrator.u[1] = 0 + integrator.u[2] = 12 + end +end + +# ╔═╡ b2797fd2-b6e1-4bb0-af23-26931fe8be69 +md""" +Create the discrete callback function. Store it in `cb`. Again use the option `save_positions=(false,false)`. +""" + +# ╔═╡ f947c2d9-9123-422d-8972-157717c85b3c +cb = DiscreteCallback(condition, affect!, save_positions=(false,false)); + +# ╔═╡ 74708270-b1ec-48c7-af32-3b970b92c706 +md""" +Solve the problem and store it in `jdsol`. Use the `SSAStepper()` stepping algorithm, the option `saveat=1.0` and the callback function. +""" + +# ╔═╡ 2b00df5d-994e-47a1-8068-c93ce3f1a618 +jdsol = solve(jdprob, SSAStepper(), saveat=1.0, callback=cb); + +# ╔═╡ 9d06c31e-3525-4889-a1de-3fe02413c7d8 +md""" +Plot the solution. +""" + +# ╔═╡ 9a90f800-3669-4831-b50b-c5405bbb9a03 +plot(jdsol, ylim=(0, 12)) + +# ╔═╡ a554fd16-aa3d-48ca-8de6-5582725c27d8 +md""" +Analyse the results. See what happens when you: +- run the notebook cell with the `solve` function repeatly +- change the value of `p₁` using the slider +""" + +# ╔═╡ d6872046-b5ef-4c2d-a9bb-2418f57f715d +md""" +!!! question "Question" + From what value of `p₁` do you start to get empty bike racks at Olin? +""" + +# ╔═╡ 747e20c4-b06b-4e78-a09a-55053cf42bf4 +md"- Answer: missing" + +# ╔═╡ 92181028-60fc-4830-afba-2380ac91455d +md""" +You can inspect the actual number of bike values at Olin by using `jdsol[:O]`: +""" + +# ╔═╡ f8942b10-773a-4b22-baad-8004fba8bd34 +jdsol[:O] + +# ╔═╡ 43d41284-053d-4dfe-8d5b-96be70c0495c +md""" +If you want to have a `true` boolean value on positions where the vector value is zero (and `false` on non-zero values), then you would compare `jdsol[:O]` element wise with `0`. In Julia, if you want to do element wise operations with/on vectors, you always need to place a dot (`.`) in front of the operator, like for example `.==`. + +Compare in that way `jdsol[:O]` with `0`: +""" + +# ╔═╡ a999ae2a-7567-41e7-9c0c-e94fad6f5d46 +jdsol[:O] .== 0 + +# ╔═╡ 9ebb5b44-04d7-4b89-acdb-e40a245703d2 +md""" +Furthermore, if you want the count the number of `true` values in the latter (hence, the zero element values), you can simply use the function `count(...)`. Count the number of zeros: +""" + +# ╔═╡ 049de8d5-b221-452b-b2c4-9bc1e0c17f48 +count(jdsol[:O] .== 0) + +# ╔═╡ a73a2853-1f48-4179-9771-083794d3f137 +md""" +Using the aforementioned way to count zeros in a vector, we will now count the zeros for a range of $p$ values. Because of the stochastic behaviour of the system, for each $p$ values we will count the zeros for a $1000$ simulations and then storing only the average value. + +To introduce a new value for $p_1$ you can take a deepcopy of the problem and remake the problem like this: +- `jdprob_re = remake(deepcopy(jdprob); p=[:p₁=>p_val])` +and then solving the problem and store it in `jdsol_re`. + +In the layout below, `mean_zero_counts` while contain the final mean values of the averaged numbers of zeros from a 1000 simulations using a specific $p$ value, `zero_counts_p_val` will contain the actual number of zeros for a 1000 simulations using a specific $p$ value. + +Use the layout below to fill in `mean_zero_counts`. +""" + +# ╔═╡ 682e9120-0e1c-4dfa-9ec6-66bb0a3f4374 +begin + p_values = 0.0:0.1:1.0 # different p-values + mean_zero_counts = [] # vector to store the corresponding mean zero values + for p_val = p_values # p_val will be each of the p_values + zero_counts_p_val = [] # vector to store the zeros for the 1000 simulations + for i = 1:1000 # do a 1000 simulation + # take a deepcopy and remake the problem for the specific p-value + jdprob_re = remake(deepcopy(jdprob); p=[:p₁=>p_val]) + # solve the problem + jdsol_re = solve(jdprob_re, SSAStepper(), saveat=1.0, callback=cb); + # append the number of zeros to zero_counts_p_val + append!(zero_counts_p_val, count(jdsol_re[:O] .== 0)) + end + # append the mean number of zeros to mean_zero_counts + append!(mean_zero_counts, mean(zero_counts_p_val)) + end +end + +# ╔═╡ 705d3fcb-20b6-4481-a304-1d3ccd623674 +md""" +Have a look at the mean zero counts by typing `mean_zero_counts`: +""" + +# ╔═╡ 5968317a-6c07-4655-8137-6702656bb3b4 +mean_zero_counts + +# ╔═╡ ff9370d8-3395-4382-9f51-afa11748319e +md""" +Plot the mean zero counts as a function of the $p$-values. +""" + +# ╔═╡ 48be49d0-0b60-44f3-8152-1ca917a4232e +plot(p_values, mean_zero_counts) + +# ╔═╡ d6452915-bdf0-48f0-8c7d-3df83c7bce72 +md""" +!!! question "Question" + - From what value of $p$ do the empty number of bike racks at Olin clearly begin to rise? + - Reflect on this, does this make sense? Hint: change the value of $p_2$ and observe what happens. +""" + +# ╔═╡ Cell order: +# ╠═6b342f14-e7d5-11ef-1ea0-77ceb0d78f32 +# ╠═7bfcc024-7d7f-4c0b-b918-8f7626b10974 +# ╠═309035dd-5653-48a6-a53d-817e743279fa +# ╠═71140c81-af29-4857-8020-4f94c8bd64b3 +# ╠═284f5847-9c15-41f3-a595-1e12a22df69f +# ╟─1f975552-b0b8-4830-8dcc-214574d4fc38 +# ╟─d2f32eab-0b35-4794-9219-5bcbb4c069c5 +# ╟─016842c9-9479-4061-a27e-9dc006121f23 +# ╠═6c97bf81-ef32-45a4-aa7c-c8c26ba2d2c3 +# ╟─7227a95a-ba0c-44dc-b0b8-18d6bbf362e8 +# ╟─9c7ab7fb-7380-41a3-85ea-714478ade218 +# ╠═1536fe23-0f8d-4b86-98d2-076248b35954 +# ╟─e6e2ff5c-38eb-4ba3-b430-c9031483a0a5 +# ╠═ab6af765-1cde-4da8-bbc1-a5fab391db54 +# ╟─378878a0-5c09-4eb0-ac43-1031014ff12a +# ╠═3ae98e83-7beb-4597-89be-80c813d4349b +# ╟─988f79c0-9c7b-4752-a7f2-d4473ad73ce6 +# ╠═0d8f53f8-0a14-4ac6-bd0c-2190d4db0909 +# ╟─08d43ac8-a973-4d7b-baf7-4c37e54cfe24 +# ╠═e20e4dd8-bdbb-4005-af68-6bf7e4ec130e +# ╟─238e1120-34af-4d57-8efa-aa80ab28a874 +# ╠═d4c45709-70c9-4ba0-8fb8-6b600473723d +# ╟─d06fb076-76e4-4248-a940-96804ea68833 +# ╠═7644adf4-d992-48b1-b40a-12fdf30f6cb5 +# ╟─59d2d3e1-354b-4444-b8a1-16ad8ea2ba94 +# ╟─53e15d08-7d1d-4bc2-9fd3-4bc6fbb9de84 +# ╠═1511d269-9706-41b1-b8e2-f85ebcedc2d8 +# ╟─fd9b4521-30d2-4af3-a080-40e9dbf27aa4 +# ╠═3cac94d6-14ae-42f2-b0b6-f47d87cdb518 +# ╟─b2797fd2-b6e1-4bb0-af23-26931fe8be69 +# ╠═f947c2d9-9123-422d-8972-157717c85b3c +# ╟─74708270-b1ec-48c7-af32-3b970b92c706 +# ╠═2b00df5d-994e-47a1-8068-c93ce3f1a618 +# ╟─9d06c31e-3525-4889-a1de-3fe02413c7d8 +# ╠═9a90f800-3669-4831-b50b-c5405bbb9a03 +# ╟─a554fd16-aa3d-48ca-8de6-5582725c27d8 +# ╟─d6872046-b5ef-4c2d-a9bb-2418f57f715d +# ╟─747e20c4-b06b-4e78-a09a-55053cf42bf4 +# ╟─92181028-60fc-4830-afba-2380ac91455d +# ╠═f8942b10-773a-4b22-baad-8004fba8bd34 +# ╟─43d41284-053d-4dfe-8d5b-96be70c0495c +# ╠═a999ae2a-7567-41e7-9c0c-e94fad6f5d46 +# ╟─9ebb5b44-04d7-4b89-acdb-e40a245703d2 +# ╠═049de8d5-b221-452b-b2c4-9bc1e0c17f48 +# ╟─a73a2853-1f48-4179-9771-083794d3f137 +# ╠═682e9120-0e1c-4dfa-9ec6-66bb0a3f4374 +# ╟─705d3fcb-20b6-4481-a304-1d3ccd623674 +# ╠═5968317a-6c07-4655-8137-6702656bb3b4 +# ╟─ff9370d8-3395-4382-9f51-afa11748319e +# ╠═48be49d0-0b60-44f3-8152-1ca917a4232e +# ╟─d6452915-bdf0-48f0-8c7d-3df83c7bce72 diff --git a/exercises/ssa_model_bike_sharing_sol1.jl b/exercises/ssa_model_bike_sharing_sol1.jl new file mode 100644 index 00000000..e9f895b6 --- /dev/null +++ b/exercises/ssa_model_bike_sharing_sol1.jl @@ -0,0 +1,334 @@ +### A Pluto.jl notebook ### +# v0.20.4 + +using Markdown +using InteractiveUtils + +# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). +macro bind(def, element) + #! format: off + quote + local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end + local el = $(esc(element)) + global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) + el + end + #! format: on +end + +# ╔═╡ 309035dd-5653-48a6-a53d-817e743279fa +begin + # add this cell if you want the notebook to use the environment from where the Pluto server is launched + using Pkg + Pkg.activate("..") +end + +# ╔═╡ 6b342f14-e7d5-11ef-1ea0-77ceb0d78f32 +using Markdown + +# ╔═╡ 7bfcc024-7d7f-4c0b-b918-8f7626b10974 +using InteractiveUtils + +# ╔═╡ 71140c81-af29-4857-8020-4f94c8bd64b3 +using Catalyst, DifferentialEquations, Plots, Distributions + +# ╔═╡ 284f5847-9c15-41f3-a595-1e12a22df69f +using PlutoUI; TableOfContents() + +# ╔═╡ 1f975552-b0b8-4830-8dcc-214574d4fc38 +md""" +# Exercise: Modeling a simple Bike Sharing System +""" + +# ╔═╡ d2f32eab-0b35-4794-9219-5bcbb4c069c5 +md""" +Imagine a bike sharing system for students traveling between Olin College and Wellesley College, which are about three miles apart in eastern Massachusetts. Suppose the system contains 12 bikes and two bike racks, one at Olin and one at Wellesley, each with the capacity to hold 12 bikes. As students arrive, check out a bike, and ride to the other campus, the number of bikes in each location changes. +Initially there are 10 bikes at Olin and, hence, 2 bikes at Wellesley. For this simple model, we will also assume that the changes in the number of bikes at both locations is instantaneous. The rate at which a bike is moved from Olin to Wellesley is denoted as $p_1$ ($\#bikes\;min^{-1}$); the rate at which a bike is moved from Wellesley to Olin is denoted as $p_2$ ($\#bikes\;min^{-1}$). Both processes are zeroth-order and we want to see the evolution of bikes during $1\,h = 60\,min$. + +This is a discreet and stochastic problem and you need to solve it with SSA. +""" + +# ╔═╡ 016842c9-9479-4061-a27e-9dc006121f23 +md""" +Create a *reaction network object* model for the aforementioned problem in order to simulate the evolution of the number of bikes at Olin ($O$) and Wellesley ($W$) with time. Name it `bike_sharing`. +""" + +# ╔═╡ 6c97bf81-ef32-45a4-aa7c-c8c26ba2d2c3 +bike_sharing = @reaction_network begin + @species O(t)=10 W(t)=2 + p₁, O => W + p₂, W => O +end + +# ╔═╡ 7227a95a-ba0c-44dc-b0b8-18d6bbf362e8 +md""" +!!! tip "Tip" + Subscripts 1, 2, etc, can be visualized by typing, after the letter, a **backslash** followed by an **underscore** and then the **TAB** key. For example `p\_1` followed by the TAB key will result in `p₁`. +""" + +# ╔═╡ 9c7ab7fb-7380-41a3-85ea-714478ade218 +md""" +Convert the system to a symbolic differential equation model and verify, by analyzing the differential equation, that your model is correctly implemented. +""" + +# ╔═╡ 1536fe23-0f8d-4b86-98d2-076248b35954 +osys = convert(ODESystem, bike_sharing) + +# ╔═╡ e6e2ff5c-38eb-4ba3-b430-c9031483a0a5 +md""" +Initialize a vector `u0` with the initial conditions: +""" + +# ╔═╡ ab6af765-1cde-4da8-bbc1-a5fab391db54 +u0 = [:O => 10, :W => 2] + +# ╔═╡ 378878a0-5c09-4eb0-ac43-1031014ff12a +md""" +Set the timespan for the simulation: +""" + +# ╔═╡ 3ae98e83-7beb-4597-89be-80c813d4349b +tspan = (0.0, 60.0) + +# ╔═╡ 988f79c0-9c7b-4752-a7f2-d4473ad73ce6 +md""" +Create a slider for the variable `p₁` in the range of $0.0$ and $1.0$ with a step of $0.1$. Take a default value of $0.0$. +""" + +# ╔═╡ 0d8f53f8-0a14-4ac6-bd0c-2190d4db0909 +@bind p₁ Slider(0.0:0.1:1, default=0.0, show_value=true) + +# ╔═╡ 08d43ac8-a973-4d7b-baf7-4c37e54cfe24 +md" +Initialize vector `parms` with parameter values, `p₁` is the slider value and assign a constant value of `0.3` to `p₂`. +" + +# ╔═╡ e20e4dd8-bdbb-4005-af68-6bf7e4ec130e +parms = [:p₁=>p₁, :p₂=>0.30] + +# ╔═╡ 238e1120-34af-4d57-8efa-aa80ab28a874 +md""" +Create a DiscreteProblem and store it in `dprob`: +""" + +# ╔═╡ d4c45709-70c9-4ba0-8fb8-6b600473723d +dprob = DiscreteProblem(bike_sharing, u0, tspan, parms); + +# ╔═╡ d06fb076-76e4-4248-a940-96804ea68833 +md""" +Create a JumpProblem and store it in `jdprob`. Use the simulation method `Direct()` and an additional option `save_positions=(false, false)` (for info about this, click [here](https://docs.sciml.ai/JumpProcesses/dev/jump_solve/#JumpProcesses.jl)). The latter prohibits to save the values just before and after the jump event (later, when solving the problem we will namely use `saveat=1.0`). +""" + +# ╔═╡ 7644adf4-d992-48b1-b40a-12fdf30f6cb5 +jdprob = JumpProblem(bike_sharing, dprob, Direct(), save_positions=(false, false)); + +# ╔═╡ 59d2d3e1-354b-4444-b8a1-16ad8ea2ba94 +md""" +If we would now solve the problem, you might for example encounter negative values for the number of bikes at Olin and, hence, a value larger than 12 at Wellesley. Of course, this makes no sense. Therefore, we will create the so-called `condition` function that needs to invoke the so-called `affect!` function at each jump event in order to check on $O$ and $W$ and setting them to valid values if necessary. +""" + +# ╔═╡ 53e15d08-7d1d-4bc2-9fd3-4bc6fbb9de84 +md""" +Create the `condition` function. +""" + +# ╔═╡ 1511d269-9706-41b1-b8e2-f85ebcedc2d8 +function condition(u, t, integrator) + true +end + +# ╔═╡ fd9b4521-30d2-4af3-a080-40e9dbf27aa4 +md""" +Create the `affect` function. + +Hints: +- If the number of bikes at Olin is larger than 12 (this implies that the number of bikes at Wellesley is negative), then the number of bikes at Olin should be set to 12 and the number of bikes at Wellesley should be set to 0. +- If the number of bikes at Olin is negative (this implies that the number of bikes at Wellesley is larger than 12), then the number of bikes at Olin should be set to 0 and the number of bikes at Wellesley should be set to 12. +- The number of bikes at Olin is accessed through `integrator.u[1]` and the number of bikes at Wellesley is accessed through `integrator.u[2]`. +""" + +# ╔═╡ 3cac94d6-14ae-42f2-b0b6-f47d87cdb518 +function affect!(integrator) + if integrator.u[1] > 12 + integrator.u[1] = 12 + integrator.u[2] = 0 + end + if integrator.u[1] < 0 + integrator.u[1] = 0 + integrator.u[2] = 12 + end +end + +# ╔═╡ b2797fd2-b6e1-4bb0-af23-26931fe8be69 +md""" +Create the discrete callback function. Store it in `cb`. Again use the option `save_positions=(false,false)`. +""" + +# ╔═╡ f947c2d9-9123-422d-8972-157717c85b3c +cb = DiscreteCallback(condition, affect!, save_positions=(false,false)); + +# ╔═╡ 74708270-b1ec-48c7-af32-3b970b92c706 +md""" +Solve the problem and store it in `jdsol`. Use the `SSAStepper()` stepping algorithm, the option `saveat=1.0` and the callback function. +""" + +# ╔═╡ 2b00df5d-994e-47a1-8068-c93ce3f1a618 +jdsol = solve(jdprob, SSAStepper(), saveat=1.0, callback=cb); + +# ╔═╡ 9d06c31e-3525-4889-a1de-3fe02413c7d8 +md""" +Plot the solution. +""" + +# ╔═╡ 9a90f800-3669-4831-b50b-c5405bbb9a03 +plot(jdsol, ylim=(0, 12)) + +# ╔═╡ a554fd16-aa3d-48ca-8de6-5582725c27d8 +md""" +Analyse the results. See what happens when you: +- run the notebook cell with the `solve` function repeatly +- change the value of `p₁` using the slider +""" + +# ╔═╡ d6872046-b5ef-4c2d-a9bb-2418f57f715d +md""" +!!! question "Question" + From what value of `p₁` do you start to get empty bike racks at Olin? +""" + +# ╔═╡ 747e20c4-b06b-4e78-a09a-55053cf42bf4 +md"- Answer: missing" + +# ╔═╡ 92181028-60fc-4830-afba-2380ac91455d +md""" +You can inspect the actual number of bike values at Olin by using `jdsol[:O]`: +""" + +# ╔═╡ f8942b10-773a-4b22-baad-8004fba8bd34 +jdsol[:O] + +# ╔═╡ 43d41284-053d-4dfe-8d5b-96be70c0495c +md""" +If you want to have a `true` boolean value on positions where the vector value is zero (and `false` on non-zero values), then you would compare `jdsol[:O]` element wise with `0`. In Julia, if you want to do element wise operations with/on vectors, you always need to place a dot (`.`) in front of the operator, like for example `.==`. + +Compare in that way `jdsol[:O]` with `0`: +""" + +# ╔═╡ a999ae2a-7567-41e7-9c0c-e94fad6f5d46 +jdsol[:O] .== 0 + +# ╔═╡ 9ebb5b44-04d7-4b89-acdb-e40a245703d2 +md""" +Furthermore, if you want the count the number of `true` values in the latter (hence, the zero element values), you can simply use the function `count(...)`. Count the number of zeros: +""" + +# ╔═╡ 049de8d5-b221-452b-b2c4-9bc1e0c17f48 +count(jdsol[:O] .== 0) + +# ╔═╡ a73a2853-1f48-4179-9771-083794d3f137 +md""" +Using the aforementioned way to count zeros in a vector, we will now count the zeros for a range of $p$ values. Because of the stochastic behaviour of the system, for each $p$ values we will count the zeros for a $1000$ simulations and then storing only the average value. + +To introduce a new value for $p_1$ you can take a deepcopy of the problem and remake the problem like this: +- `jdprob_re = remake(deepcopy(jdprob); p=[:p₁=>p_val])` +and then solving the problem and store it in `jdsol_re`. + +In the layout below, `mean_zero_counts` while contain the final mean values of the averaged numbers of zeros from a 1000 simulations using a specific $p$ value, `zero_counts_p_val` will contain the actual number of zeros for a 1000 simulations using a specific $p$ value. + +Use the layout below to fill in `mean_zero_counts`. +""" + +# ╔═╡ 682e9120-0e1c-4dfa-9ec6-66bb0a3f4374 +begin + p_values = 0.0:0.1:1.0 # different p-values + mean_zero_counts = [] # vector to store the corresponding mean zero values + for p_val = p_values # p_val will be each of the p_values + zero_counts_p_val = [] # vector to store the zeros for the 1000 simulations + for i = 1:1000 # do a 1000 simulation + # take a deepcopy and remake the problem for the specific p-value + jdprob_re = remake(deepcopy(jdprob); p=[:p₁=>p_val]) + # solve the problem + jdsol_re = solve(jdprob_re, SSAStepper(), saveat=1.0, callback=cb); + # append the number of zeros to zero_counts_p_val + append!(zero_counts_p_val, count(jdsol_re[:O] .== 0)) + end + # append the mean number of zeros to mean_zero_counts + append!(mean_zero_counts, mean(zero_counts_p_val)) + end +end + +# ╔═╡ 705d3fcb-20b6-4481-a304-1d3ccd623674 +md""" +Have a look at the mean zero counts by typing `mean_zero_counts`: +""" + +# ╔═╡ 5968317a-6c07-4655-8137-6702656bb3b4 +mean_zero_counts + +# ╔═╡ ff9370d8-3395-4382-9f51-afa11748319e +md""" +Plot the mean zero counts as a function of the $p$-values. +""" + +# ╔═╡ 48be49d0-0b60-44f3-8152-1ca917a4232e +plot(p_values, mean_zero_counts) + +# ╔═╡ d6452915-bdf0-48f0-8c7d-3df83c7bce72 +md""" +!!! question "Question" + - From what value of $p$ do the empty number of bike racks at Olin clearly begin to rise? + - Reflect on this, does this make sense? Hint: change the value of $p_2$ and observe what happens. +""" + +# ╔═╡ Cell order: +# ╠═6b342f14-e7d5-11ef-1ea0-77ceb0d78f32 +# ╠═7bfcc024-7d7f-4c0b-b918-8f7626b10974 +# ╠═309035dd-5653-48a6-a53d-817e743279fa +# ╠═71140c81-af29-4857-8020-4f94c8bd64b3 +# ╠═284f5847-9c15-41f3-a595-1e12a22df69f +# ╟─1f975552-b0b8-4830-8dcc-214574d4fc38 +# ╟─d2f32eab-0b35-4794-9219-5bcbb4c069c5 +# ╟─016842c9-9479-4061-a27e-9dc006121f23 +# ╠═6c97bf81-ef32-45a4-aa7c-c8c26ba2d2c3 +# ╟─7227a95a-ba0c-44dc-b0b8-18d6bbf362e8 +# ╟─9c7ab7fb-7380-41a3-85ea-714478ade218 +# ╠═1536fe23-0f8d-4b86-98d2-076248b35954 +# ╟─e6e2ff5c-38eb-4ba3-b430-c9031483a0a5 +# ╠═ab6af765-1cde-4da8-bbc1-a5fab391db54 +# ╟─378878a0-5c09-4eb0-ac43-1031014ff12a +# ╠═3ae98e83-7beb-4597-89be-80c813d4349b +# ╟─988f79c0-9c7b-4752-a7f2-d4473ad73ce6 +# ╠═0d8f53f8-0a14-4ac6-bd0c-2190d4db0909 +# ╟─08d43ac8-a973-4d7b-baf7-4c37e54cfe24 +# ╠═e20e4dd8-bdbb-4005-af68-6bf7e4ec130e +# ╟─238e1120-34af-4d57-8efa-aa80ab28a874 +# ╠═d4c45709-70c9-4ba0-8fb8-6b600473723d +# ╟─d06fb076-76e4-4248-a940-96804ea68833 +# ╠═7644adf4-d992-48b1-b40a-12fdf30f6cb5 +# ╟─59d2d3e1-354b-4444-b8a1-16ad8ea2ba94 +# ╟─53e15d08-7d1d-4bc2-9fd3-4bc6fbb9de84 +# ╠═1511d269-9706-41b1-b8e2-f85ebcedc2d8 +# ╟─fd9b4521-30d2-4af3-a080-40e9dbf27aa4 +# ╠═3cac94d6-14ae-42f2-b0b6-f47d87cdb518 +# ╟─b2797fd2-b6e1-4bb0-af23-26931fe8be69 +# ╠═f947c2d9-9123-422d-8972-157717c85b3c +# ╟─74708270-b1ec-48c7-af32-3b970b92c706 +# ╠═2b00df5d-994e-47a1-8068-c93ce3f1a618 +# ╟─9d06c31e-3525-4889-a1de-3fe02413c7d8 +# ╠═9a90f800-3669-4831-b50b-c5405bbb9a03 +# ╟─a554fd16-aa3d-48ca-8de6-5582725c27d8 +# ╟─d6872046-b5ef-4c2d-a9bb-2418f57f715d +# ╟─747e20c4-b06b-4e78-a09a-55053cf42bf4 +# ╟─92181028-60fc-4830-afba-2380ac91455d +# ╠═f8942b10-773a-4b22-baad-8004fba8bd34 +# ╟─43d41284-053d-4dfe-8d5b-96be70c0495c +# ╠═a999ae2a-7567-41e7-9c0c-e94fad6f5d46 +# ╟─9ebb5b44-04d7-4b89-acdb-e40a245703d2 +# ╠═049de8d5-b221-452b-b2c4-9bc1e0c17f48 +# ╟─a73a2853-1f48-4179-9771-083794d3f137 +# ╠═682e9120-0e1c-4dfa-9ec6-66bb0a3f4374 +# ╟─705d3fcb-20b6-4481-a304-1d3ccd623674 +# ╠═5968317a-6c07-4655-8137-6702656bb3b4 +# ╟─ff9370d8-3395-4382-9f51-afa11748319e +# ╠═48be49d0-0b60-44f3-8152-1ca917a4232e +# ╟─d6452915-bdf0-48f0-8c7d-3df83c7bce72 diff --git a/exercises/ssa_model_bike_sharing_sol2.jl b/exercises/ssa_model_bike_sharing_sol2.jl new file mode 100644 index 00000000..cea0ec8e --- /dev/null +++ b/exercises/ssa_model_bike_sharing_sol2.jl @@ -0,0 +1,287 @@ +### A Pluto.jl notebook ### +# v0.20.4 + +using Markdown +using InteractiveUtils + +# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). +macro bind(def, element) + #! format: off + quote + local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end + local el = $(esc(element)) + global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) + el + end + #! format: on +end + +# ╔═╡ 309035dd-5653-48a6-a53d-817e743279fa +begin + # add this cell if you want the notebook to use the environment from where the Pluto server is launched + using Pkg + Pkg.activate("..") +end + +# ╔═╡ 6b342f14-e7d5-11ef-1ea0-77ceb0d78f32 +using Markdown + +# ╔═╡ 7bfcc024-7d7f-4c0b-b918-8f7626b10974 +using InteractiveUtils + +# ╔═╡ 71140c81-af29-4857-8020-4f94c8bd64b3 +using Catalyst, DifferentialEquations, Plots, Distributions + +# ╔═╡ 284f5847-9c15-41f3-a595-1e12a22df69f +using PlutoUI; TableOfContents() + +# ╔═╡ 1f975552-b0b8-4830-8dcc-214574d4fc38 +md""" +# Exercise: Modeling a simple Bike Sharing System +""" + +# ╔═╡ d2f32eab-0b35-4794-9219-5bcbb4c069c5 +md""" +Imagine a bike sharing system for students traveling between Olin College and Wellesley College, which are about three miles apart in eastern Massachusetts. Suppose the system contains 12 bikes and two bike racks, one at Olin and one at Wellesley, each with the capacity to hold 12 bikes. As students arrive, check out a bike, and ride to the other campus, the number of bikes in each location changes. +Initially there are 10 bikes at Olin and, hence, 2 bikes at Wellesley. For this simple model, we will also assume that the changes in the number of bikes at both locations is instantaneous. The rate at which a bike is moved from Olin to Wellesley is denoted as $p_1$ ($\#bikes\;min^{-1}$); the rate at which a bike is moved from Wellesley to Olin is denoted as $p_2$ ($\#bikes\;min^{-1}$). Both processes are zeroth-order and we want to see the evolution of bikes during $1\,h = 60\,min$. + +This is a discreet and stochastic problem and you need to solve it with SSA. +""" + +# ╔═╡ 016842c9-9479-4061-a27e-9dc006121f23 +md""" +Create a *reaction network object* model for the aforementioned problem in order to simulate the evolution of the number of bikes at Olin ($O$) and Wellesley ($W$) with time. Name it `bike_sharing`. +""" + +# ╔═╡ 6c97bf81-ef32-45a4-aa7c-c8c26ba2d2c3 +bike_sharing = @reaction_network begin + @species O(t)=10 W(t)=2 + p₁*ifelse(O>0, 1, 0), O => W + p₂*ifelse(W>0, 1, 0), W => O +end +#= +If O becomes zero, then no bike will be transfered to W, hence, O will not go below zeros and W will not go above 12. +If W becomes zero, then no bike will be transfered to O, hence, W will not go below zeros and O will not go above 12. +Here, no callback function needed because everything is taken care of in the Catalyst-model. +=# + +# ╔═╡ 7227a95a-ba0c-44dc-b0b8-18d6bbf362e8 +md""" +!!! tip "Tip" + Subscripts 1, 2, etc, can be visualized by typing, after the letter, a **backslash** followed by an **underscore** and then the **TAB** key. For example `p\_1` followed by the TAB key will result in `p₁`. +""" + +# ╔═╡ 9c7ab7fb-7380-41a3-85ea-714478ade218 +md""" +Convert the system to a symbolic differential equation model and verify, by analyzing the differential equation, that your model is correctly implemented. +""" + +# ╔═╡ 1536fe23-0f8d-4b86-98d2-076248b35954 +osys = convert(ODESystem, bike_sharing) + +# ╔═╡ e6e2ff5c-38eb-4ba3-b430-c9031483a0a5 +md""" +Initialize a vector `u0` with the initial conditions: +""" + +# ╔═╡ ab6af765-1cde-4da8-bbc1-a5fab391db54 +u0 = [:O => 10, :W => 2] + +# ╔═╡ 378878a0-5c09-4eb0-ac43-1031014ff12a +md""" +Set the timespan for the simulation: +""" + +# ╔═╡ 3ae98e83-7beb-4597-89be-80c813d4349b +tspan = (0.0, 60.0) + +# ╔═╡ 988f79c0-9c7b-4752-a7f2-d4473ad73ce6 +md""" +Create a slider for the variable `p₁` in the range of $0.0$ and $1.0$ with a step of $0.1$. Take a default value of $0.0$. +""" + +# ╔═╡ 0d8f53f8-0a14-4ac6-bd0c-2190d4db0909 +@bind p₁ Slider(0.0:0.1:1, default=0.0, show_value=true) + +# ╔═╡ 08d43ac8-a973-4d7b-baf7-4c37e54cfe24 +md" +Initialize vector `parms` with parameter values, `p₁` is the slider value and assign a constant value of `0.3` to `p₂`. +" + +# ╔═╡ e20e4dd8-bdbb-4005-af68-6bf7e4ec130e +parms = [:p₁=>p₁, :p₂=>0.30] + +# ╔═╡ 238e1120-34af-4d57-8efa-aa80ab28a874 +md""" +Create a DiscreteProblem and store it in `dprob`: +""" + +# ╔═╡ d4c45709-70c9-4ba0-8fb8-6b600473723d +dprob = DiscreteProblem(bike_sharing, u0, tspan, parms); + +# ╔═╡ d06fb076-76e4-4248-a940-96804ea68833 +md""" +Create a JumpProblem and store it in `jdprob`. Use the simulation method `Direct()`.""" + +# ╔═╡ 7644adf4-d992-48b1-b40a-12fdf30f6cb5 +jdprob = JumpProblem(bike_sharing, dprob, Direct()); + +# ╔═╡ 74708270-b1ec-48c7-af32-3b970b92c706 +md""" +Solve the problem and store it in `jdsol`. Use the `SSAStepper()` stepping algorithm. +""" + +# ╔═╡ 2b00df5d-994e-47a1-8068-c93ce3f1a618 +jdsol = solve(jdprob, SSAStepper()) + +# ╔═╡ 9d06c31e-3525-4889-a1de-3fe02413c7d8 +md""" +Plot the solution. +""" + +# ╔═╡ 9a90f800-3669-4831-b50b-c5405bbb9a03 +plot(jdsol, ylim=(0, 12)) + + +# ╔═╡ a554fd16-aa3d-48ca-8de6-5582725c27d8 +md""" +Analyse the results. See what happens when you: +- run the notebook cell with the `solve` function repeatly +- change the value of `p₁` using the slider +""" + +# ╔═╡ d6872046-b5ef-4c2d-a9bb-2418f57f715d +md""" +!!! question "Question" + From what value of `p₁` do you start to get empty bike racks at Olin? +""" + +# ╔═╡ 747e20c4-b06b-4e78-a09a-55053cf42bf4 +md"- Answer: missing" + +# ╔═╡ 92181028-60fc-4830-afba-2380ac91455d +md""" +You can inspect the actual number of bike values at Olin by using `jdsol[:O]`: +""" + +# ╔═╡ f8942b10-773a-4b22-baad-8004fba8bd34 +jdsol[:O] + +# ╔═╡ 43d41284-053d-4dfe-8d5b-96be70c0495c +md""" +If you want to have a `true` boolean value on positions where the vector value is zero (and `false` on non-zero values), then you would compare `jdsol[:O]` element wise with `0`. In Julia, if you want to do element wise operations with/on vectors, you always need to place a dot (`.`) in front of the operator, like for example `.==`. + +Compare in that way `jdsol[:O]` with `0`: +""" + +# ╔═╡ a999ae2a-7567-41e7-9c0c-e94fad6f5d46 +jdsol[:O] .== 0 + +# ╔═╡ 9ebb5b44-04d7-4b89-acdb-e40a245703d2 +md""" +Furthermore, if you want the count the number of `true` values in the latter (hence, the zero element values), you can simply use the function `count(...)`. Count the number of zeros: +""" + +# ╔═╡ 049de8d5-b221-452b-b2c4-9bc1e0c17f48 +count(jdsol[:O] .== 0) + +# ╔═╡ a73a2853-1f48-4179-9771-083794d3f137 +md""" +Using the aforementioned way to count zeros in a vector, we will now count the zeros for a range of $p$ values. Because of the stochastic behaviour of the system, for each $p$ values we will count the zeros for a $1000$ simulations and then storing only the average value. + +To introduce a new value for $p_1$ you can take a deepcopy of the problem and remake the problem like this: +- `jdprob_re = remake(deepcopy(jdprob); p=[:p₁=>p_val])` +and then solving the problem and store it in `jdsol_re`. + +In the layout below, `mean_zero_counts` while contain the final mean values of the averaged numbers of zeros from a 1000 simulations using a specific $p$ value, `zero_counts_p_val` will contain the actual number of zeros for a 1000 simulations using a specific $p$ value. + +Use the layout below to fill in `mean_zero_counts`. +""" + +# ╔═╡ 682e9120-0e1c-4dfa-9ec6-66bb0a3f4374 +begin + p_values = 0.0:0.1:1.0 # different p-values + mean_zero_counts = [] # vector to store the corresponding mean zero values + for p_val = p_values # p_val will be each of the p_values + zero_counts_p_val = [] # vector to store the zeros for the 1000 simulations + for i = 1:1000 # do a 1000 simulation + # take a deepcopy and remake the problem for the specific p-value + jdprob_re = remake(deepcopy(jdprob); p=[:p₁=>p_val]) + # solve the problem + jdsol_re = solve(jdprob_re, SSAStepper()); + # append the number of zeros to zero_counts_p_val + append!(zero_counts_p_val, count(jdsol_re[:O] .== 0)) + end + # append the mean number of zeros to mean_zero_counts + append!(mean_zero_counts, mean(zero_counts_p_val)) + end +end + +# ╔═╡ 705d3fcb-20b6-4481-a304-1d3ccd623674 +md""" +Have a look at the mean zero counts by typing `mean_zero_counts`: +""" + +# ╔═╡ 5968317a-6c07-4655-8137-6702656bb3b4 +mean_zero_counts + +# ╔═╡ ff9370d8-3395-4382-9f51-afa11748319e +md""" +Plot the mean zero counts as a function of the $p$-values. +""" + +# ╔═╡ 48be49d0-0b60-44f3-8152-1ca917a4232e +plot(p_values, mean_zero_counts) + +# ╔═╡ d6452915-bdf0-48f0-8c7d-3df83c7bce72 +md""" +!!! question "Question" + - From what value of $p$ do the empty number of bike racks at Olin clearly begin to rise? + - Reflect on this, does this make sense? Hint: change the value of $p_2$ and observe what happens. +""" + +# ╔═╡ Cell order: +# ╠═6b342f14-e7d5-11ef-1ea0-77ceb0d78f32 +# ╠═7bfcc024-7d7f-4c0b-b918-8f7626b10974 +# ╠═309035dd-5653-48a6-a53d-817e743279fa +# ╠═71140c81-af29-4857-8020-4f94c8bd64b3 +# ╠═284f5847-9c15-41f3-a595-1e12a22df69f +# ╟─1f975552-b0b8-4830-8dcc-214574d4fc38 +# ╟─d2f32eab-0b35-4794-9219-5bcbb4c069c5 +# ╟─016842c9-9479-4061-a27e-9dc006121f23 +# ╠═6c97bf81-ef32-45a4-aa7c-c8c26ba2d2c3 +# ╟─7227a95a-ba0c-44dc-b0b8-18d6bbf362e8 +# ╟─9c7ab7fb-7380-41a3-85ea-714478ade218 +# ╠═1536fe23-0f8d-4b86-98d2-076248b35954 +# ╟─e6e2ff5c-38eb-4ba3-b430-c9031483a0a5 +# ╠═ab6af765-1cde-4da8-bbc1-a5fab391db54 +# ╟─378878a0-5c09-4eb0-ac43-1031014ff12a +# ╠═3ae98e83-7beb-4597-89be-80c813d4349b +# ╟─988f79c0-9c7b-4752-a7f2-d4473ad73ce6 +# ╠═0d8f53f8-0a14-4ac6-bd0c-2190d4db0909 +# ╟─08d43ac8-a973-4d7b-baf7-4c37e54cfe24 +# ╠═e20e4dd8-bdbb-4005-af68-6bf7e4ec130e +# ╟─238e1120-34af-4d57-8efa-aa80ab28a874 +# ╠═d4c45709-70c9-4ba0-8fb8-6b600473723d +# ╟─d06fb076-76e4-4248-a940-96804ea68833 +# ╠═7644adf4-d992-48b1-b40a-12fdf30f6cb5 +# ╟─74708270-b1ec-48c7-af32-3b970b92c706 +# ╠═2b00df5d-994e-47a1-8068-c93ce3f1a618 +# ╟─9d06c31e-3525-4889-a1de-3fe02413c7d8 +# ╠═9a90f800-3669-4831-b50b-c5405bbb9a03 +# ╟─a554fd16-aa3d-48ca-8de6-5582725c27d8 +# ╟─d6872046-b5ef-4c2d-a9bb-2418f57f715d +# ╟─747e20c4-b06b-4e78-a09a-55053cf42bf4 +# ╟─92181028-60fc-4830-afba-2380ac91455d +# ╠═f8942b10-773a-4b22-baad-8004fba8bd34 +# ╟─43d41284-053d-4dfe-8d5b-96be70c0495c +# ╠═a999ae2a-7567-41e7-9c0c-e94fad6f5d46 +# ╟─9ebb5b44-04d7-4b89-acdb-e40a245703d2 +# ╠═049de8d5-b221-452b-b2c4-9bc1e0c17f48 +# ╟─a73a2853-1f48-4179-9771-083794d3f137 +# ╠═682e9120-0e1c-4dfa-9ec6-66bb0a3f4374 +# ╟─705d3fcb-20b6-4481-a304-1d3ccd623674 +# ╠═5968317a-6c07-4655-8137-6702656bb3b4 +# ╟─ff9370d8-3395-4382-9f51-afa11748319e +# ╠═48be49d0-0b60-44f3-8152-1ca917a4232e +# ╟─d6452915-bdf0-48f0-8c7d-3df83c7bce72 diff --git a/exercises/ssa_model_catalyst_intro.jl b/exercises/ssa_model_catalyst_intro.jl index 3edabf86..26b17fe7 100644 --- a/exercises/ssa_model_catalyst_intro.jl +++ b/exercises/ssa_model_catalyst_intro.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ e5f8c320-eda0-11ee-37d0-458bdbd94f15 @@ -28,7 +28,7 @@ using DifferentialEquations, Plots # ╔═╡ 62b185be-e327-4ef3-af39-819732d107bf md""" -# Introduction to Catalyst (SSA) +# Solving discrete jump problems with Catalyst """ # ╔═╡ f5f32d5d-0c13-4865-8024-ca47208c9b8e @@ -247,7 +247,7 @@ We create a DiscreteProblem by calling the `DiscreteProblem` function. Applying """ # ╔═╡ e2f215e7-8d20-4e72-9e0b-cc0ce150e55b -dprob = DiscreteProblem(infection_model, u0, tspan, params) +dprob = DiscreteProblem(infection_model, u0, tspan, params); # ╔═╡ d061c4e2-8fbb-4ac5-95cf-c37d2916e669 md""" diff --git a/exercises/ssa_model_foxes_rabbits.jl b/exercises/ssa_model_foxes_rabbits.jl index 422c6dc0..e33b0907 100644 --- a/exercises/ssa_model_foxes_rabbits.jl +++ b/exercises/ssa_model_foxes_rabbits.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 9b9d35c4-9136-11ef-284a-d5964e231d9e @@ -36,21 +36,21 @@ md""" md""" Rabbits live on some secluded territory. Their maximum growth rate coefficient is $r$ $[year^{-1}]$, and their population capacity is $R_m$ $[\#rabbits]$. The rabbits die of old age or sickness with a dying rate coefficient $d$ $[year^{-1}]$. -At $t=0$, foxes intrude the territory and stay there. The foxes exclusively feed themselves with the rabbits. They hunt the rabbits at a rate proportional to the number of foxes (proportionality factor is $h$ $[year^{-1} \#foxes^{-1}]$). The population of foxes grows at a rate proportional to the number of rabbits (proportionality factor is $g$ $[year^{-1} \#rabbits^{-1}]$). The foxes die of old age or sickness with a dying rate coefficient $\delta$ $[year^{-1}]$. +At $t=0$, foxes intrude the territory and stay there. The foxes exclusively feed themselves with the rabbits. They hunt the rabbits at a rate proportional to the number of foxes (proportionality factor is $h$ $[year^{-1} \#foxes^{-1}]$). Thereby, the yield factor for the foxes is $Y$ $[\#foxes\,(\#rabbits)^{-1}]$. The foxes die of old age or sickness with a dying rate coefficient $\delta$ $[year^{-1}]$. -The initial number of rabbits on the territory is 89, the initial number of -foxes intruding the territory is 2. +The initial number of rabbits on the territory is $89$, the initial number of +foxes intruding the territory is $2$. """ # ╔═╡ 91e77fb0-cab3-4da7-8bc9-6f657df2497c md""" **Exercises:** -1. Make simulations of the evolution of rabbits and foxes as a ODE problem in the time interval $[0, 10]\;years$. +1. Make simulations of the evolution of rabbits and foxes as a ODE problem in the time interval $[0, 15]\;years$. -2. Make simulations of the evolution of rabbits and foxes as a discrete (jump) problem in the time interval $[0, 10]\;years$. +2. Make simulations of the evolution of rabbits and foxes as a discrete (jump) problem in the time interval $[0, 15]\;years$. -Assume the following parameter values: $r = 18.4\;year^{-1}$, $R_m = 120\;(\#rabbits)$, $d = 2.0\;year^{-1}$, $h = 1.4\;year^{-1}(\#foxes)^{-1}$, $g = 0.05\;year^{-1}(\#rabbits)^{-1}$ and $\delta = 1.0\;year^{-1}$. +Assume the following parameter values: $r = 18.4\;year^{-1}$, $R_m = 120\;(\#rabbits)$, $d = 2.0\;year^{-1}$, $h = 1.4\;year^{-1}(\#foxes)^{-1}$, $Y=0.036\;\#foxes\,(\#rabbits)^{-1}$ and $\delta = 1.0\;year^{-1}$. """ # ╔═╡ d11b4e97-df16-4641-9e32-c7f2a098ffb7 @@ -59,7 +59,7 @@ Create a *reaction network object* model for the aforementioned problem. Name it Hints: - Use the variable names `R` and `F` for the rabbits and foxes respectively. -- Use the variable names `r`, `Rm`, `d`, `h`, `g` and `δ` for the parameters. +- Use the variable names `r`, `Rm`, `d`, `h`, `Y` and `δ` for the parameters. """ # ╔═╡ 6d49c334-76e0-4210-890b-e3e79097222d @@ -70,7 +70,6 @@ Hints: # missing # natural population growth of the rabbits # missing # deaths by age or sickness of the rabbits # missing # hunting of rabbits by the foxes -# missing # gaining of foxes by hinting rabbits # missing # deaths by age or sickness of the foxes # end @@ -100,11 +99,11 @@ Set the timespan for the simulation: # ╔═╡ 1a835253-3677-4698-9347-d59937f9e7c0 md""" -Initialize a vector `params` with the parameter values: +Initialize a vector `parms` with the parameter values: """ # ╔═╡ 2bd4dd93-1be0-427b-b372-88cb9849a124 -# params = missing # Uncomment and complete the instruction +# parms = missing # Uncomment and complete the instruction # ╔═╡ 4953f436-afed-4363-b840-956440fddc25 md""" @@ -117,7 +116,7 @@ Create the ODE problem and store it in `oprob`: """ # ╔═╡ 629126b3-0b6b-43f0-9142-2d4d7d6270d9 -# oprob = missing # Uncomment and complete the instruction +# oprob = missing; # Uncomment and complete the instruction # ╔═╡ 3c071a33-5092-42f7-80b2-63066bdf3f22 md""" @@ -146,7 +145,7 @@ Create a DiscreteProblem and store it in `dprob`: """ # ╔═╡ 581a5b6e-04a7-4fd1-9f69-a9cf8655a06c -# dprob = missing # Uncomment and complete the instruction +# dprob = missing; # Uncomment and complete the instruction # ╔═╡ 497fe4e8-b451-4dd7-b961-6e7968c6cb3d md""" @@ -154,7 +153,7 @@ Create a JumpProblem and store it in `jdprob`. Use the simulation method `Direct """ # ╔═╡ 74e91495-998e-48a0-b14a-9d7be2c6410d -# jdprob = missing # Uncomment and complete the instruction +# jdprob = missing; # Uncomment and complete the instruction # ╔═╡ 9c9f097b-2a84-4383-843c-0cdc1b40e061 md""" @@ -200,7 +199,7 @@ Write a piece of code that solves the problem a $1000$ times and stores the time # ╔═╡ 2eb41790-23ef-43fc-8b69-7dd9dbb9f820 md""" -Make a histogram so that you can have an idea of the distribution when the rabbits die out. Use `bins=range(0, 10, length=121)`. +Make a histogram so that you can have an idea of the distribution when the rabbits die out. Use `bins=range(0, 15, length=151)` or `bins=0:0.1:15`. """ # ╔═╡ 1c8188de-e8b8-44ae-b0b6-7d490f3a15e8 diff --git a/exercises/ssa_model_foxes_rabbits_sol.jl b/exercises/ssa_model_foxes_rabbits_sol.jl index 2d00d280..013f2aba 100644 --- a/exercises/ssa_model_foxes_rabbits_sol.jl +++ b/exercises/ssa_model_foxes_rabbits_sol.jl @@ -8,7 +8,7 @@ using InteractiveUtils begin # add this cell if you want the notebook to use the environment from where the Pluto server is launched using Pkg - Pkg.activate(".") + Pkg.activate("..") end # ╔═╡ 9b9d35c4-9136-11ef-284a-d5964e231d9e @@ -23,6 +23,9 @@ using Catalyst # ╔═╡ 92c50b0a-d9f1-45a9-9c8a-ced71a6ee967 using DifferentialEquations, Plots +# ╔═╡ e773ce20-2b91-4db4-8baa-aee131333f4e +using Distributions + # ╔═╡ 2a129f80-f4c2-4429-85e8-98d946fb3f36 using PlutoUI; TableOfContents() @@ -36,7 +39,7 @@ md""" md""" Rabbits live on some secluded territory. Their maximum growth rate coefficient is $r$ $[year^{-1}]$, and their population capacity is $R_m$ $[\#rabbits]$. The rabbits die of old age or sickness with a dying rate coefficient $d$ $[year^{-1}]$. -At $t=0$, foxes intrude the territory and stay there. The foxes exclusively feed themselves with the rabbits. They hunt the rabbits at a rate proportional to the number of foxes (proportionality factor is $h$ $[year^{-1} \#foxes^{-1}]$). The population of foxes grows at a rate proportional to the number of rabbits (proportionality factor is $g$ $[year^{-1} \#rabbits^{-1}]$). The foxes die of old age or sickness with a dying rate coefficient $\delta$ $[year^{-1}]$. +At $t=0$, foxes intrude the territory and stay there. The foxes exclusively feed themselves with the rabbits. They hunt the rabbits at a rate proportional to the number of foxes (proportionality factor is $h$ $[year^{-1} \#foxes^{-1}]$). Thereby, the yield factor for the foxes is $Y$ $[\#foxes\,(\#rabbits)^{-1}]$. The foxes die of old age or sickness with a dying rate coefficient $\delta$ $[year^{-1}]$. The initial number of rabbits on the territory is 89, the initial number of foxes intruding the territory is 2. @@ -46,11 +49,11 @@ foxes intruding the territory is 2. md""" **Exercises:** -1. Make simulations of the evolution of rabbits and foxes as a ODE problem in the time interval $[0, 10]\;years$. +1. Make simulations of the evolution of rabbits and foxes as a ODE problem in the time interval $[0, 15]\;years$. -2. Make simulations of the evolution of rabbits and foxes as a discrete (jump) problem in the time interval $[0, 10]\;years$. +2. Make simulations of the evolution of rabbits and foxes as a discrete (jump) problem in the time interval $[0, 15]\;years$. -Assume the following parameter values: $r = 18.4\;year^{-1}$, $R_m = 120\;(\#rabbits)$, $d = 2.0\;year^{-1}$, $h = 1.4\;year^{-1}(\#foxes)^{-1}$, $g = 0.05\;year^{-1}(\#rabbits)^{-1}$ and $\delta = 1.0\;year^{-1}$. +Assume the following parameter values: $r =$ 18.4$\;year^{-1}$, $R_m =$ 120$\;(\#rabbits)$, $d =$ 2.0$\;year^{-1}$, $h =$ 1.4$\;year^{-1}(\#foxes)^{-1}$, $Y=$0.036$\;\#foxes\,(\#rabbits)^{-1}$ and $\delta =$ 1.0$\;year^{-1}$. """ # ╔═╡ d11b4e97-df16-4641-9e32-c7f2a098ffb7 @@ -59,27 +62,16 @@ Create a *reaction network object* model for the aforementioned problem. Name it Hitns: - Use the variable names `R` and `F` for the rabbits and foxes respectively. -- Use the variable names `r`, `Rm`, `d`, `h`, `g` and `δ` for the parameters. +- Use the variable names `r`, `Rm`, `d`, `h`, `Y` and `δ` for the parameters. """ # ╔═╡ 6d49c334-76e0-4210-890b-e3e79097222d -# Uncomment and complete the instruction -# foxes_rabbits_rn = @reaction_network begin -# @species missing -# @parameters missing -# missing # natural population growth of the rabbits -# missing # deaths by age or sickness of the rabbits -# missing # hunting of rabbits by the foxes -# missing # gaining of foxes by hinting rabbits -# missing # deaths by age or sickness of the foxes -# end foxes_rabbits_rn = @reaction_network begin @species R(t)=89 F(t)=2 - @parameters r=18.4 Rm=120 d=2.0 h=1.4 g=0.05 δ=1.0 + @parameters r=18.4 Rm=120 d=2.0 h=1.4 Y=0.036 δ=1.0 r*(1 - R/Rm), R --> 2R # natural population growth of the rabbits d, R --> 0 # deaths by age or sickness of the rabbits - h*F, R --> 0 # hunting of rabbits by the foxes - g*R, F --> 2F # gaining of foxes by hinting rabbits + h, F+R --> (1+Y)*F # hunting of rabbits by the foxes δ, F --> 0 # deaths by age or sickness of the foxes end @@ -89,7 +81,6 @@ Convert the system to a symbolic differential equation model and verify, by anal """ # ╔═╡ 3ffbec86-a33a-4a71-9c8c-9f895a3a1f26 -# osys = missing # Uncomment and complete the instruction osys = convert(ODESystem, foxes_rabbits_rn) # ╔═╡ 577ae94c-543c-4717-981b-ce90c02d1828 @@ -98,7 +89,6 @@ Initialize a vector `u0` with the initial conditions: """ # ╔═╡ 55c208e5-f123-4c4e-8b03-c3e3d3eda605 -# u0 = missing # Uncomment and complete the instruction u0 = [:R => 89, :F => 2] # ╔═╡ 5270da4a-7d14-44cd-8672-9e481888704a @@ -107,17 +97,15 @@ Set the timespan for the simulation: """ # ╔═╡ 10f878d8-d2da-4701-b190-7a2feaa0c009 -# tspan = missing # Uncomment and complete the instruction -tspan = (0.0, 10.0) +tspan = (0.0, 15.0) # ╔═╡ 1a835253-3677-4698-9347-d59937f9e7c0 md""" -Initialize a vector `params` with the parameter values: +Initialize a vector `parms` with the parameter values: """ # ╔═╡ 2bd4dd93-1be0-427b-b372-88cb9849a124 -# params = missing # Uncomment and complete the instruction -params = [:r=>18.4, :Rm=>120, :d=>2.0, :h=>1.4, :g=>0.05, :δ=>1.0] +parms = [:r=>18.4, :Rm=>120, :d=>2.0, :h=>1.4, :Y=>0.036, :δ=>1.0] # ╔═╡ 4953f436-afed-4363-b840-956440fddc25 md""" @@ -130,8 +118,7 @@ Create the ODE problem and store it in `oprob`: """ # ╔═╡ 629126b3-0b6b-43f0-9142-2d4d7d6270d9 -# oprob = missing # Uncomment and complete the instruction -oprob = ODEProblem(foxes_rabbits_rn, u0, tspan, params) +oprob = ODEProblem(foxes_rabbits_rn, u0, tspan, parms); # ╔═╡ 3c071a33-5092-42f7-80b2-63066bdf3f22 md""" @@ -139,7 +126,6 @@ Solve the ODE problem. Use `Tsit5()` and `saveat=0.05`. Store the solution in `o """ # ╔═╡ 0f17c44c-a2e6-4b4a-be9c-e2e9763a3374 -# osol = missing # Uncomment and complete the instruction osol = solve(oprob, Tsit5(), saveat=0.05) # ╔═╡ e4bf9eca-ffee-4dca-8318-74875c636245 @@ -148,7 +134,6 @@ Plot the solution. """ # ╔═╡ a35eccae-7890-41a1-82a0-6cf98488d8a7 -# missing # Uncomment and complete the instruction plot(osol) # ╔═╡ c9ca9a36-784a-4560-93bf-4381812f41ac @@ -162,8 +147,7 @@ Create a DiscreteProblem and store it in `dprob`: """ # ╔═╡ 581a5b6e-04a7-4fd1-9f69-a9cf8655a06c -# dprob = missing # Uncomment and complete the instruction -dprob = DiscreteProblem(foxes_rabbits_rn, u0, tspan, params) +dprob = DiscreteProblem(foxes_rabbits_rn, u0, tspan, parms); # ╔═╡ 497fe4e8-b451-4dd7-b961-6e7968c6cb3d md""" @@ -171,8 +155,7 @@ Create a JumpProblem and store it in `jdprob`. Use the simulation method `Direct """ # ╔═╡ 74e91495-998e-48a0-b14a-9d7be2c6410d -# jdprob = missing # Uncomment and complete the instruction -jdprob = JumpProblem(foxes_rabbits_rn, dprob, Direct()) +jdprob = JumpProblem(foxes_rabbits_rn, dprob, Direct()); # ╔═╡ 9c9f097b-2a84-4383-843c-0cdc1b40e061 md""" @@ -180,7 +163,6 @@ Solve the problem and store it in `jdsol`. Use the `SSAStepper()` stepping algor """ # ╔═╡ c80337e8-6dbe-4c78-a793-d3a1e968c319 -# jdsol = missing # Uncomment and complete the instruction jdsol = solve(jdprob, SSAStepper()) # ╔═╡ a743af00-cce6-4e6e-b426-107ad04960d8 @@ -189,7 +171,6 @@ Plot the solution. """ # ╔═╡ 46610efe-927a-4c5f-bd6a-fa8001949aa7 -# missing # Uncomment and complete the instruction plot(jdsol) # ╔═╡ 969bc08d-0709-4941-8fa8-3be707c5b0ed @@ -214,12 +195,6 @@ Write a piece of code that solves the problem a $1000$ times and stores the time """ # ╔═╡ a6bc48a8-3bbc-4abc-918b-da70eab39017 -# Uncomment and complete the instruction -# begin -# times = [] # make empty vector -# # missing -# # ... -# end begin times = [] # make empty vector while length(times) < 1000 # while statement @@ -233,13 +208,18 @@ end # ╔═╡ 2eb41790-23ef-43fc-8b69-7dd9dbb9f820 md""" -Make a histogram so that you can have an idea of the distribution when the rabbits die out. Use `bins=range(0, 10, length=121)`. +Make a histogram so that you can have an idea of the distribution when the rabbits die out. Use `bins=range(0, 15, length=151)` or `bins=0:0.1:15`. """ # ╔═╡ 1c8188de-e8b8-44ae-b0b6-7d490f3a15e8 -# missing # Uncomment and complete the instruction -# histogram(times, bins=range(0, 10, length=121)) -histogram(times, bins=range(0, 10, length=121), normalize=:pdf) +histogram(times, bins=0:0.1:15) +# histogram(times, bins=range(0, 15, length=151), normalize=:pdf) + +# ╔═╡ c544ec5f-e0cd-45e3-b32b-cd35152f2346 +mean(times) + +# ╔═╡ 2e498d7c-f3e3-4cfe-83dd-41e2cd3e4ced +std(times) # ╔═╡ Cell order: # ╠═9b9d35c4-9136-11ef-284a-d5964e231d9e @@ -247,6 +227,7 @@ histogram(times, bins=range(0, 10, length=121), normalize=:pdf) # ╠═e8dd4f61-4f51-4255-9193-62ea1368240b # ╠═c7c12802-f3e7-4e42-be3f-f91eabe432d8 # ╠═92c50b0a-d9f1-45a9-9c8a-ced71a6ee967 +# ╠═e773ce20-2b91-4db4-8baa-aee131333f4e # ╠═2a129f80-f4c2-4429-85e8-98d946fb3f36 # ╟─3a1a01f6-7f6e-411d-958b-0dce35b791ff # ╟─92a0efee-1e40-4080-aee2-831d98312176 @@ -284,3 +265,5 @@ histogram(times, bins=range(0, 10, length=121), normalize=:pdf) # ╠═a6bc48a8-3bbc-4abc-918b-da70eab39017 # ╟─2eb41790-23ef-43fc-8b69-7dd9dbb9f820 # ╠═1c8188de-e8b8-44ae-b0b6-7d490f3a15e8 +# ╠═c544ec5f-e0cd-45e3-b32b-cd35152f2346 +# ╠═2e498d7c-f3e3-4cfe-83dd-41e2cd3e4ced diff --git a/slides/slides_ode/JMBeamIVPV.sty b/slides/slides_ode/JMBeamIVPV.sty new file mode 100755 index 00000000..fbee4611 --- /dev/null +++ b/slides/slides_ode/JMBeamIVPV.sty @@ -0,0 +1,156 @@ +%\ProvidesPackage{beamerthemesplit}[2003/10/29 ver 0.92] +\NeedsTeXFormat{LaTeX2e}[1995/12/01] + +% Copyright 2003 by Till Tantau . +% +% This program can be redistributed and/or modified under the terms +% of the LaTeX Project Public License Distributed from CTAN +% archives in directory macros/latex/base/lppl.txt. + +\mode % or \mode
for handouts + +\newcommand{\conference} +{\text{IVPV}} +\newcommand{\authorshort} +{\text{Joris FA Meys}} +\newcommand{\email} +{\text{e-mail: joris.meys@UGent.be}} + +\beamertemplatelargetitlepage +\beamertemplatelargepartpage +\beamertemplatelargeframetitle +\beamertemplateplaintoc +\beamertemplatelargeblocks +%\beamertemplatenavigationsymbolsempty +%\usealerttemplate{\color{beamerstructure}}{} %set alert color equal to beamerstructure color +\usenavigationsymbolstemplate{\vbox{% +% \hbox{\insertslidenavigationsymbol} + \hbox{\insertframenavigationsymbol} + %\hbox{\insertsubsectionnavigationsymbol} + %\hbox{\insertsectionnavigationsymbol} + %\hbox{\insertdocnavigationsymbol} + %\hbox{\insertbackfindforwardnavigationsymbol} + }} + +\usesectionheadtemplate + {\hfill\color{white}\tiny\textbf{\insertsectionhead}} + {\hfill\color{white!50!black}\tiny\textbf{\insertsectionhead}} + +\usesubsectionheadtemplate + {\color{white}\tiny\textbf{\insertsubsectionhead}} + {\color{white!50!structure}\tiny\textbf{\insertsubsectionhead}} + + % Head +\ifbeamer@compress +\useheadtemplate{% + \vbox{% + \tiny% + \setbox\beamer@linebox=\hbox to\paperwidth{% + \insertsectionnavigationhorizontal{.5\paperwidth}{\hskip0pt plus1filll}{}% + \insertsubsectionnavigationhorizontal{.5\paperwidth}{}{\hskip0pt plus1filll}\hfil}% + \ht\beamer@linebox=2.625ex + \dp\beamer@linebox=0pt + \setbox\beamer@linebox=\vbox{\box\beamer@linebox\vskip1.125ex}% + \hbox to\textwidth{% + {\color{black}\hskip-\Gm@lmargin\vrule width.5\paperwidth height\ht\beamer@linebox + \color{structure}\vrule width.5\paperwidth height\ht\beamer@linebox\hskip-\paperwidth\hskip\Gm@lmargin}% + \hskip-\Gm@lmargin\box\beamer@linebox\hfill\hskip-\Gm@rmargin + }% + }% +} +\else +\useheadtemplate{% + \vbox{% + \tiny% + \beamer@tempdim=2.4375ex% + \ifnum\beamer@subsectionmax<\beamer@sectionmax% + \multiply\beamer@tempdim by\beamer@sectionmax% + \else% + \multiply\beamer@tempdim by\beamer@subsectionmax% + \fi% + \advance\beamer@tempdim by 1.125ex% + \setbox\beamer@linebox=\hbox to\paperwidth{% + \vbox to \beamer@tempdim{\vfil\insertsectionnavigation{.5\paperwidth}\vfil}% + \vbox to \beamer@tempdim{\vfil\insertsubsectionnavigation{.5\paperwidth}\vfil}\hfill}% + %\vbox to \beamer@tempdim{\vfil\hyperlinkslideprev{\insertreturnsymbol}\vfil}\hfill}% + \hbox to\textwidth{% + {\color{black}\hskip-\Gm@lmargin\vrule width.5\paperwidth + height\ht\beamer@linebox\color{structure}\vrule width.5\paperwidth + height\ht\beamer@linebox\hskip-\paperwidth\hskip\Gm@lmargin}% + \hskip-\Gm@lmargin\box\beamer@linebox\hfill\hskip-\Gm@rmargin% + }% + }% +} +\fi + + +\usefoottemplate{% + \vbox{\tiny% + \hbox{% + \setbox\beamer@linebox=\hbox to\paperwidth{% + \hyperlinkslideprev{\hbox to.5\paperwidth{\hfill\tiny\color{white}\vspace{1.7cm}\textbf{\conference}\hskip.3cm}}% + \hyperlinkslidenext{\hbox to.5\paperwidth{\hskip.3cm\tiny\color{white}\textbf{\authorshort \hfill\hfill \hfill \hfill \hfill \hfill \insertframenumber/\inserttotalframenumber}\hfill}}\hfill}% + \ht\beamer@linebox=2.625ex% + \dp\beamer@linebox=0pt% + \setbox\beamer@linebox=\vbox{\box\beamer@linebox\vskip1.125ex}% + \color{black}\hskip-\Gm@lmargin\vrule width.5\paperwidth + height\ht\beamer@linebox\color{structure}\vrule width.5\paperwidth + height\ht\beamer@linebox\hskip-\paperwidth% + \hbox{\box\beamer@linebox\hfill}\hfill\hskip-\Gm@rmargin}}} + +\usetitlepagetemplate{ + \vbox{% + \tiny% + \beamer@tempdim=2.4375ex% + \ifnum\beamer@subsectionmax<\beamer@sectionmax% + \multiply\beamer@tempdim by\beamer@sectionmax% + \else% + \multiply\beamer@tempdim by\beamer@subsectionmax% + \fi% + \advance\beamer@tempdim by 1.125ex% + \setbox\beamer@linebox=\hbox to\paperwidth{% + \vbox to \beamer@tempdim{\vfil}% + \vbox to \beamer@tempdim{\vfil}\hfill}% + %\vbox to \beamer@tempdim{\vfil\hyperlinkslideprev{\insertreturnsymbol}\vfil}\hfill}% + \hbox to\textwidth{% + {\color{black}\hskip-\Gm@lmargin\vrule width.5\paperwidth + height\ht\beamer@linebox\color{structure}\vrule width.5\paperwidth + height\ht\beamer@linebox\hskip-\paperwidth\hskip\Gm@lmargin}% + \hskip-\Gm@lmargin\box\beamer@linebox\hfill\hskip-\Gm@rmargin% + }% + }% + +% +\beamerline{\hspace{1cm}\parbox[l][3cm][c]{0.5\paperwidth}{\includegraphics[height=1.5cm]{ruglogo.png}} +\parbox[r][3cm][c]{.5\textwidth}{\flushright{{\begin{center}\bf BIOMATH\\\tiny Department of Applied Mathematics,\\Biometrics and Process Control\end{center}}}}} + \vskip0pt plus 1filll + + \begin{center} + \Large{\color{beamerstructure}{\inserttitle}}\\ + \vspace{0.3cm} + \small \insertauthor\\ + \vspace{0.6cm} + \insertsubtitle\\ + \vspace{0.15cm} + \insertdate + \end{center} + \vskip0pt plus 1filll + + \vbox{\tiny% + \hbox{% + \setbox\beamer@linebox=\hbox to\paperwidth{% + \hyperlinkslideprev{\hbox to.5\paperwidth{\hfill\tiny\color{white}\vspace{1.7cm}\textbf{BIOMATH, Coupure Links 653, 9000 Gent,Belgium}\hskip.3cm}}% + \hyperlinkslidenext{\hbox to.5\paperwidth{\hskip.3cm\tiny\color{white}\textbf{\email}\hfill}}\hfill}% + \ht\beamer@linebox=2.625ex% + \dp\beamer@linebox=0pt% + \setbox\beamer@linebox=\vbox{\box\beamer@linebox\vskip1.125ex}% + \color{black}\hskip-\Gm@lmargin\vrule width.5\paperwidth + height\ht\beamer@linebox\color{structure}\vrule width.5\paperwidth + height\ht\beamer@linebox\hskip-\paperwidth% + \hbox{\box\beamer@linebox\hfill}\hfill\hskip-\Gm@rmargin}} + +%gepruts kan nuttig zijn om uit te leren: vb colorbox paperwidth hyperlink kleur:beamerstructure +%\beamerline{\colorbox{black}{\parbox[b][.18cm][c]{.5\paperwidth}{\hbox to.484\paperwidth{\hfill\tiny\bf\color{white}BIOMATH, Coupure Links 653, 9000 Gent,Belgium\hskip.3cm}}}\hyperlinkslidenext{\colorbox{beamerstructure}{\parbox[b][0.18cm][c]{.5\paperwidth}{\hbox to.5\paperwidth{\hskip.3cm\tiny\bf\color{white}e-mail: joris.meys@biomath.ugent.be\hfill}}}}} +} +\mode + diff --git a/slides/slides_ode/P01-ODE1.tex b/slides/slides_ode/P01-ODE1.tex new file mode 100644 index 00000000..fdaad184 --- /dev/null +++ b/slides/slides_ode/P01-ODE1.tex @@ -0,0 +1,621 @@ +%\documentclass[handout]{beamer} +\documentclass{beamer} + +\usepackage[english]{babel} +\usepackage[latin1]{inputenc} +\usepackage{textpos} +\usepackage{epstopdf} +\epstopdfsetup{update} +%\usepackage{pgfpages} +%\pgfpagesuselayout{resize to}[letterpaper,landscape] +%\usepackage{epstopdf} +%\epstopdfsetup{update} +\usepackage{pgfplots} +\usepackage{pgfbaseimage} +\usepackage{amsmath} %More mathematical +\usepackage{multirow} +%\usepackage[absolute,overlay]{textpos} +%\usepackage[tikz]{bclogo} +%\usepackage{etoolbox} +% listings for matlab code: +\usepackage{listings} +%\usepackage[autolinebreaks, useliterate]{mcode} +\lstset{backgroundcolor=\color[gray]{0.9}} + +\usepackage{chemplants} +\usepackage{cancel} +\usepackage{graphicx} +\usetikzlibrary{math} +\usepackage{wasysym} +\usepackage{marvosym} + +\usetikzlibrary{shapes.arrows} +\tikzset{My Arrow Style/.style={single arrow, draw=green!40!gray, very thick, fill=green!20!gray!10, anchor=base, align=center,text width=2cm,text=green!40!gray,rotate=-90,minimum width=0.5cm, inner sep=1mm, minimum height=0.5cm}} +\newcommand{\MyArrow}[2][]{\tikz[baseline] \node [My Arrow Style,#1] {#2};} + +%------------------------------------------------- +% FOOTER +% +% Choose your footer style, by commenting other options: +% +%% - Clean: no footer, except of page number +\mode{\usetheme{presentationTemplateBiomathFClean}} +%% - Info: a fixed footer with basic presenter information +%\mode{\usetheme{presentationTemplateBiomathFInfo}} +%% - Section: Provide the sections and current section in the footer +%\mode{\usetheme{presentationTemplateBiomathFSection}} +%------------------------------------------------- + + +%voor de hand-outs +%\usepackage{pgfpages} +%\pgfpagesuselayout{2 on 1}[a4paper,border shrink=5mm] + +\title{\LARGE Modelling and Simulation \normalsize of Biosystems} +\title{Modelling and Simulation of Biosystems} +\author[Daniel Illana]{Daniel Illana Gonz\'alez} %(daniel.illanagonzalez@ugent.be)} +\subtitle{Practicum 1: Modelling with ODEs} +\date{Academic year 2024-2025} + + +\newcommand{\mtx}[2] + {\left[\begin{array}{#1}#2\end{array}\right]} +\newcommand{\eqset}[1] + {\left\{\begin{array}{rcl}#1\end{array}\right.} +\newcommand{\rbar}[2] + {\left.#1\right|_{#2}} +\newcommand{\atwp}[1] + {\rbar{#1}{\overline{X},\overline{U}}} + +\usepackage{mdframed} + +\newenvironment{opgave}[2][]{% + \mdfsetup{% + frametitle={% + \tikz[baseline=(current bounding box.east),outer sep=0pt] + \node[anchor=east,rectangle,fill=gray!40] + {\strut #1};}% + } + \mdfsetup{% + innertopmargin=10pt,linecolor=white!30,% + linewidth=0pt,topline=true,% + frametitleaboveskip=\dimexpr-\ht\strutbox\relax% + } + + \begin{mdframed}[]\relax}{% +\end{mdframed}} + + + +% Table of contents at the beginning of each section +%\AtBeginSection[] +%{ +% \begin{frame} +% \frametitle{Outline} +% \tableofcontents[currentsection] +% \end{frame} +%} + +% Title page customisation +\titlegraphic{} + +\begin{document} + +\frame[plain]{\titlepage} + + +\frame{ + \frametitle{Practical information} + + \begin{itemize} + \item PC-exercises: Pluto notebooks (via Ufora); BYOD! + \item Group 1: Monday, 8.30-11.30, PC E-1.1 \\ + \hspace{1em}{\color{ugent-la} Cel- en genbiotechnologie; Landbouwkunde } + \item Group 2: Tuesday, 16.00-19.00, PC E-1.1 \\ + \hspace{1em}{\color{ugent-la} Bos \& Natuur, Chemie \& Voeding, Land, Water \& Klimaat, Milieutechnologie (rest of bachelor majors) } + \item Exceptions: see \textbf{agenda} in Ufora + \vfill %\pause + \item Notebooks, slides, solutions: Ufora \medskip + \item Questions: \textbf{forum}, during sessions $\rightarrow$ work in groups encouraged ! \medskip + \item Solutions: only notebook-code in html will be provided, questions can be discussed during class + \end{itemize} +} + +\frame{ +\frametitle{Today} +\Large +\begin{itemize} + \item Short introduction \bigskip % \vfill + \item Example exercise + \begin{itemize} + \large + \item Introduction to Catalyst (ODE) with the infection model \bigskip + \end{itemize} + \item Exercises to do \medskip + \begin{enumerate} + \large + \item Infection model + \begin{itemize} + \item Influence of parameter $\alpha$ + \item Administration of medicinal products + \item Adding vaccination to the model + \end{itemize} + \item Simple birth-death model for mice + \item Irrigation experiment \bigskip + \item (Extra) Fermenter - First order kinetics + \item (Extra) Fermenter - Monod kinetics + \item (Extra) Soil contamination with plant uptake + \item (Extra) Water evaporation and infiltration + \item (Extra) Anaerobic fermentation + \end{enumerate} +\end{itemize} +} + +\frame{ +\frametitle{Your environment} +\begin{enumerate} +\item[1.] Create a folder for the course (e.g., \texttt{modsim}) in a suitable location (e.g., \texttt{Documents}) +\begin{itemize} \medskip +\item In principle this can be any location, choose an easily accessible one \smallskip +\item Preferably don't choose the \texttt{Downloads} folder... +\end{itemize} \medskip +\item[2.] Go to your created folder (cf. \texttt{modsim}) with a \textit{File Explorer} \medskip +\item[3.] Now create a new folder \texttt{P1\_ODEs1} (under the folder \texttt{modsim}) \medskip +\item[4.] From the Ufora module \textbf{Exercises} $>$ \textbf{Important files}, download: +\begin{itemize} +\item \texttt{Project.toml} +\item \texttt{launch\_pluto.jl} +\end{itemize} +\medskip +Place these two files in your \texttt{modsim} folder. +\end{enumerate} +} + +\frame{ +\frametitle{Your environment} +\begin{enumerate} +\item[5.] Next, from the Ufora module \textbf{Exercises} $>$ \textbf{P1: ODEs 1}, download all the Pluto notebook files +\begin{itemize} +\item \texttt{ode\_model\_catalyst\_intro.jl} +\item \texttt{ode\_model\_infection.jl} +\item etc. +\end{itemize} +Place all these files in the folder \texttt{P1\_ODEs1}.\medskip +\item[6.] Go back to your \texttt{modsim} folder with a \textit{File Explorer}, then open in this location in the \textit{Terminal} or command line interface (CLI), e.g., right click on your mouse and choose \texttt{Open in Terminal}. \medskip +\item[7.] Type {\color{ugent-la} \texttt{julia launch\_pluto.jl}} and then click [\textit{Enter}] +\begin{itemize} +\item Packages will be installed, this might take a few minutes... +\item When installation in complete, you will be able to open the notebooks in the folder \texttt{P1\_ODEs1} by using the Pluto interface +\end{itemize} + +\end{enumerate} +} + +%\frame{ +%\frametitle{Installing packages} +%\begin{enumerate} +%\item Create a folder (e.g., \texttt{modsim}) in a suitable location (e.g., \texttt{Documents}) where you will place all your Pluto notebooks +%\begin{itemize} \medskip +%\item In principle this can be any location, choose an easily accessible one \smallskip +%\item Preferably don't choose the \texttt{Downloads} folder... +%\end{itemize} \bigskip +%\item Go to your created folder (cf. \texttt{modsim}) with a \textit{File Explorer}, then open this location in the \textit{Terminal} or command line interface (CLI), e.g., right click on your mouse and choose \texttt{Open in Terminal}. \bigskip +%\item Run Julia with the command \texttt{julia}. \bigskip +%\item Activate your ``environment'' (cf. in the \texttt{modsim} folder) and start to install/add new packages.\\ \medskip +%There are two equivalent possibilities, we will show both. +%\end{enumerate} +%} + + +%\frame{ +%\frametitle{Installing packages} +%\textbf{Possibility 1} +%\begin{itemize} +%\item Enter the package manager by pressing {\color{ugent-la}\texttt{]}} +%\item Type: {\color{ugent-la}\texttt{activate .}} +%\item Now, to install/add packages you need to write \texttt{add} followed by a comma separated list of package names. You don't need to include all packages on one line, you can subdivide. E.g., you could type:\\ +%{\color{ugent-la} +%\texttt{add Pluto, PlutoUI}\\ +%\texttt{add Markdown, InteractiveUtils}\\ +%\texttt{add Catalyst, DifferentialEquations, Plots}\\ +%\texttt{add Distributions}} \medskip +%\item Make sure you added all aforementioned packages. You will need them in Practicum 1 and 2. \medskip +%\item Leave the package manager after installation is done by pressing \texttt{}. +%\end{itemize} +%} +% +% +%\frame{ +%\frametitle{Installing packages} +%\textbf{Possibility 2} +%\begin{itemize} +%\item Still in the \texttt{julia} prompt, type {\color{ugent-la}\texttt{using Pkg}} \medskip +%\item Type: {\color{ugent-la}\texttt{Pkg.activate(".")}} \medskip +%\item Now, to install/add packages you can do that as follow:\\ +%{\color{ugent-la} +%\texttt{Pkg.add(["Pluto", "PlutoUI"])}\\ +%\texttt{Pkg.add(["Markdown", "InteractiveUtils"])}\\ +%\texttt{Pkg.add(["Catalyst", "DifferentialEquations", "Plots"])}\\ +%\texttt{Pkg.add("Distributions")}} \medskip +%\item Make sure you added all aforementioned packages. You will need them in Practicum 1 and 2. +%\end{itemize} +%} + +\frame{ +\frametitle{What is modelling?} +\begin{definition} +Modelling is the translation of a system from reality into a set of mathematical expressions, also called a model. +\end{definition} +} + +\frame{ + + \begin{figure} + \includegraphics[width=0.2\textwidth]{figs/reality.png} + \end{figure} + +%\pause + +\begin{center} +\begin{tikzpicture}[every node/.style={single arrow, draw=none, rotate=-90}] +\node [draw=green!40!gray,fill=green!20!gray!10,text=green!40!gray,font=\footnotesize] {Assumptions}; +\end{tikzpicture} +\end{center} + + +\usetikzlibrary{shapes,arrows} +\tikzstyle{block} = [draw, rectangle, minimum height=3em, minimum width=6em] +\tikzstyle{input} = [coordinate] +\tikzstyle{output} = [coordinate] + +\begin{figure} +\centering +\begin{tikzpicture}[auto, node distance=4cm, >=latex, very thick] + \node [input, name=input] {}; + \node [block, right of=input, text width=2cm] (system) {\begin{center} SYSTEM\\\medskip production \end{center} }; + \node [output, right of=system] (output) {}; + \draw [->] (input) -- node[above] {incoming} (system) {}; + \draw [->] (system) -- node[above] {outgoing} (output) {}; +\end{tikzpicture} +\end{figure} + +%\pause + \color{ugent-la} + \begin{equation*} + \left[ + \frac{accumulation}{time} + \right]= + \left[ + \frac{production}{time} + \right] + + + \underbrace{ + \left[ + \frac{incoming}{time} + \right]-\left[ + \frac{outgoing}{time} + \right]}_{transport} + \label{eq:massconsdyn} + \end{equation*} + +} + +\frame{ + + \begin{figure} + \begin{minipage}[b]{0.23\linewidth} + \centering + \includegraphics[height=2.5cm]{figs/bos} + \begin{tikzpicture}[every node/.style={single arrow, draw=none, rotate=-90}] + \node [draw=green!40!gray,fill=green!20!gray!10,text=green!40!gray,font=\tiny] {Assumptions}; + \end{tikzpicture} + \includegraphics[height=2.5cm]{figs/foodweb} + \color{ugent-la}{\begin{equation*} + \frac{d v}{d t} + \end{equation*}} + \end{minipage} + \hspace{0.05cm} + \begin{minipage}[b]{0.23\linewidth} + \centering + \includegraphics[height=2.5cm]{figs/reactorBio} + \begin{tikzpicture}[every node/.style={single arrow, draw=none, rotate=-90}] + \node [draw=green!40!gray,fill=green!20!gray!10,text=green!40!gray,font=\tiny] {Assumptions}; + \end{tikzpicture} + \includegraphics[height=2.5cm]{figs/reactorBioM} + \color{ugent-la}{\begin{equation*} + \frac{d[X]}{d t} + \end{equation*}} + \end{minipage} + \hspace{0.05cm} + \begin{minipage}[b]{0.23\linewidth} + \centering + \includegraphics[height=2.5cm]{figs/reactorVuur} + \begin{tikzpicture}[every node/.style={single arrow, draw=none, rotate=-90}] + \node [draw=green!40!gray,fill=green!20!gray!10,text=green!40!gray,font=\tiny] {Assumptions}; + \end{tikzpicture} + \includegraphics[height=2.5cm]{figs/reactorVuurM} + \color{ugent-la}{\begin{equation*} + \frac{d T}{d t} + \end{equation*}} + \end{minipage} + \hspace{0.05cm} + \begin{minipage}[b]{0.23\linewidth} + \centering + \includegraphics[height=2.5cm]{figs/osc} + \begin{tikzpicture}[every node/.style={single arrow, draw=none, rotate=-90}] + \node [draw=green!40!gray,fill=green!20!gray!10,text=green!40!gray,font=\tiny] {Assumptions}; + \end{tikzpicture} + + \includegraphics[height=2.5cm]{figs/oscM} + \color{ugent-la}{\begin{equation*} + \frac{d^2 x}{d t^2} + \end{equation*}} + \end{minipage} + \end{figure} + +} + +\frame{ + \frametitle{Goal of this practicum} + \Large + \color{beamerstructure} + {\begin{enumerate} + \item Implementing \textit{reaction systems} using Catalyst + \vfill %\pause + \item Understanding the relation with balance equations + \vfill %\pause + \item Simulation of systems as ODE-problems + \vfill %\pause + \item Influence of parameters + \vfill %\pause + \item Implementing \textbf{discrete events} + \vfill %\pause + \item Implementing \textbf{continuous events} + \end{enumerate} + } +} + +\frame{ +\frametitle{Introduction to Catalyst} +\Large +\begin{itemize} +\item Symbolic modelling package for construction, analysis and high performance simulation of chemical reaction networks. +\vfill +\item Catalyst defines symbolic ReactionSystems, created using Catalyst's \textbf{D}omain \textbf{S}pecific \textbf{L}anguage (DSL). +\vfill +\end{itemize} +} + +\frame{ +\frametitle{Introduction to Catalyst} +\Large + +The infection model \bigskip + +\begin{figure} + \includegraphics[width=0.6\textwidth]{figs/infection_model.png} +\end{figure} +} + + +\frame{ +\frametitle{Introduction to Catalyst} +\Large + +The infection model - \textit{reaction network system} + +$$S + I \xrightarrow[]{\alpha \beta} 2I$$ +$$I \xrightarrow[]{mr} D$$ +$$I \xrightarrow[]{(1-m)r} R$$ + +Implementation + +\begin{figure} + \includegraphics[width=0.7\textwidth]{figs/infection_model_catalyst_implementation.png} +\end{figure} + +$S$, $I$, $D$ and $R$ are called species, unknowns or states\\ +$\alpha$, $\beta$, $m$, $r$ are called parameters +} + + +\frame{ +\frametitle{Introduction to Catalyst} +\Large + +The infection model - corresponding \textit{system of ODEs} + +\begin{eqnarray*} +\cfrac{dS}{dt} &=& -\alpha \beta S I \\ +\cfrac{dI}{dt} &=& \alpha \beta S I - r I \\ +\cfrac{dD}{dt} &=& m r I \\ +\cfrac{dR}{dt} &=& (1-m) r I +\end{eqnarray*} + +} + + +\frame{ +\frametitle{Introduction to Catalyst} +\Large +For a given problem it is: \medskip +\begin{itemize} +\item Sometimes easier to immediately write down the \textbf{reaction network} (reaction kinetics), e.g., for chemistry, biological, population and epidemiological related problems. \medskip +\item Sometimes easier to write down the \textbf{system of ODEs}, e.g., for environmental and physics related problems. In the latter case you will need to ``translate'' it into a reaction network. +\end{itemize} +} + + +%\frame{ +%\frametitle{Pluto notebooks} +%\large \bigskip +%All exercises will be in the form of Pluto notebooks. You will find them on Ufora in a submodule of the module \textbf{Exercises}. \medskip +%\begin{itemize} +%\item For this practicum, go to the Ufora submodule\\ \textbf{P1: ODEs 1 $>$ files} \medskip +%\item Download the Julia script \texttt{launch\_pluto.jl} and all the Pluto notebooks (\texttt{e.g., ode\_model\_catalyst\_intro.jl}, etc.) into your dedicated \texttt{modsim} folder. \medskip +%\begin{itemize} +%\item \texttt{launch\_pluto.jl} is a small script to activate your environment and to be able to use the packages you installed in your environment. \medskip +%\end{itemize} +%\item Go to your dedicated folder (cf. \texttt{modsim}) with a \textit{File Explorer}, then in this location right click on your mouse and choose \texttt{Open in Terminal} (or something alike). \medskip +%\item Type {\color{ugent-la} \texttt{julia launch\_pluto.jl}} and then click [\textit{Enter}] \medskip +%\item The Pluto notebook of you choice will open in your browser. +%\end{itemize} +%} + + +\frame{ +\frametitle{Practicum 1: ODEs 1} +\large +The following notebooks are the subjects for today: +\begin{itemize} +\item \texttt{ode\_model\_catalyst\_intro.jl} (introduction) \vspace*{2mm} +\item \texttt{ode\_model\_infection.jl} +\item \texttt{ode\_model\_birth\_death.jl} +\item \texttt{ode\_model\_irrigation.jl} \vspace*{2mm} +\item \texttt{ode\_model\_fermenter\_firstorder.jl} (extra) +\item \texttt{ode\_model\_fermenter\_monod.jl} (extra) +\item \texttt{ode\_model\_soil\_cont\_plant\_uptake.jl} (extra) +\item \texttt{ode\_model\_water\_evap\_infil.jl} (extra) +\item \texttt{ode\_model\_anaerobic\_fermentation.jl} (extra) +\end{itemize} +} + + + +\frame{ +\frametitle{Intro to Catalyst - ODEs} +\large +We will use the infection model to illustrate the following: \medskip +\begin{itemize} +\item Implementation of the system as a \textit{reaction network} object using Catalyst's DSL \medskip +\item Simulation of the system as an ODE-problem \medskip +\item Some advanced examples: +\begin{itemize} +\item How to analyse the \textit{influence of a parameter} \smallskip +\item Introduce a \textit{discrete event} in time \smallskip +\item Introduce a \textit{continuous event} +\end{itemize} +\end{itemize} +} + + +\frame{ +\frametitle{Intro to Catalyst - ODEs} +\Large \bigskip + +Notebook: {\color{ugent-la} \texttt{ode\_model\_catalyst\_intro.jl}} + +\medskip +The infection model: \medskip + +\begin{figure} + \includegraphics[width=0.6\textwidth]{figs/infection_model.png} +\end{figure} +} + +\frame{ +\frametitle{Exercise 1} +\Large +\textbf{The infection model}\\ \medskip +Notebook: {\color{ugent-la}\texttt{ode\_model\_infection.jl}} + +\begin{itemize} +\item Contains the code from the introduction notebook (minimal explanatory text) \medskip +\item Influence of parameter $\alpha$ \medskip +\item Administration of medicinal products \medskip +\item Adding vaccination to the model +\end{itemize} +} + + +\frame{ +\frametitle{Exercise 2} +\Large +\textbf{Simple birth-death model for mice}\\ \medskip +Notebook: {\color{ugent-la}\texttt{ode\_model\_birth\_death.jl}} + +\vspace*{2mm} +Part 1 + +\begin{figure} + \includegraphics[width=0.8\textwidth]{figs/mice_model_part1.png} +\end{figure} +} + + +\frame{ +\frametitle{Exercise 2} +\Large \medskip +\textbf{Simple birth-death model for mice}\\ \medskip +Notebook: {\color{ugent-la}\texttt{ode\_model\_birth\_death.jl}} + +\vspace*{2mm} +Part 2 + +\begin{figure} + \includegraphics[width=0.8\textwidth]{figs/mice_model_part2.png} +\end{figure} +} + + +\frame{ +\frametitle{Exercise 3} +\Large +\textbf{Irrigation experiment}\\ \medskip +Notebook: {\color{ugent-la}\texttt{ode\_model\_irrigation.jl}} + +\begin{figure} + \includegraphics[width=0.8\textwidth]{figs/irrigation_model.png} +\end{figure} +} + + +\frame{ +\frametitle{Extra exercises 4 and 5} +\Large +\textbf{Fermenter}\\ \medskip +Notebooks: {\color{ugent-la}\texttt{ode\_model\_fermenter\_firstorder.jl}} and {\color{ugent-la}\texttt{ode\_model\_fermenter\_monod.jl}} + +\begin{figure} + \includegraphics[width=0.5\textwidth]{figs/fermenter_model.png} +\end{figure} +} + + +\frame{ +\frametitle{Extra exercise 6} +\Large \medskip +\textbf{Soil contamination with plant uptake}\\ \medskip +Notebook: {\color{ugent-la}\texttt{ode\_model\_soil\_cont\_plant\_uptake.jl}} + +\begin{figure} + \includegraphics[width=0.7\textwidth]{figs/soil_plant_cont_model.png} +\end{figure} +} + + +\frame{ +\frametitle{Extra exercise 7} +\Large \medskip +\textbf{Water evaporation and infiltration}\\ \medskip +Notebook: {\color{ugent-la}\texttt{ode\_model\_water\_evap\_infil.jl}} + +\begin{figure} + \includegraphics[width=0.7\textwidth]{figs/water_evap_infil_model.png} +\end{figure} +} + +\frame{ +\frametitle{Extra exercise 8} +\Large +\textbf{Anaerobic fermentation}\\ \medskip +Notebook: {\color{ugent-la}\texttt{ode\_model\_anaerobic\_fermentation.jl}} + +\begin{figure} + \includegraphics[width=0.7\textwidth]{figs/anaerobic_fermentation.png} +\end{figure} +} + + +\end{document} + diff --git a/slides/slides_ode/P02-ODE2.tex b/slides/slides_ode/P02-ODE2.tex new file mode 100644 index 00000000..9f8d5a4f --- /dev/null +++ b/slides/slides_ode/P02-ODE2.tex @@ -0,0 +1,449 @@ +%\documentclass[handout]{beamer} +\documentclass{beamer} + +\usepackage[english]{babel} +\usepackage[latin1]{inputenc} +\usepackage{textpos} +\usepackage{epstopdf} +\epstopdfsetup{update} +%\usepackage{pgfpages} +%\pgfpagesuselayout{resize to}[letterpaper,landscape] +%\usepackage{epstopdf} +%\epstopdfsetup{update} +\usepackage{pgfplots} +\usepackage{pgfbaseimage} +\usepackage{amsmath} %More mathematical +\usepackage{multirow} +%\usepackage[absolute,overlay]{textpos} +%\usepackage[tikz]{bclogo} +%\usepackage{etoolbox} +% listings for matlab code: +\usepackage{listings} +%\usepackage[autolinebreaks, useliterate]{mcode} +\lstset{backgroundcolor=\color[gray]{0.9}} + +\usepackage{chemplants} +\usepackage{cancel} +\usepackage{graphicx} +\usetikzlibrary{math} +\usepackage{wasysym} +\usepackage{marvosym} + +\usepackage{animate} + +\usetikzlibrary{shapes.arrows} +\tikzset{My Arrow Style/.style={single arrow, draw=green!40!gray, very thick, fill=green!20!gray!10, anchor=base, align=center,text width=2cm,text=green!40!gray,rotate=-90,minimum width=0.5cm, inner sep=1mm, minimum height=0.5cm}} +\newcommand{\MyArrow}[2][]{\tikz[baseline] \node [My Arrow Style,#1] {#2};} + +%------------------------------------------------- +% FOOTER +% +% Choose your footer style, by commenting other options: +% +%% - Clean: no footer, except of page number +\mode{\usetheme{presentationTemplateBiomathFClean}} +%% - Info: a fixed footer with basic presenter information +%\mode{\usetheme{presentationTemplateBiomathFInfo}} +%% - Section: Provide the sections and current section in the footer +%\mode{\usetheme{presentationTemplateBiomathFSection}} +%------------------------------------------------- + + +%voor de hand-outs +%\usepackage{pgfpages} +%\pgfpagesuselayout{2 on 1}[a4paper,border shrink=5mm] + +\title{\LARGE Modelling and Simulation \normalsize of Biosystems} +\title{Modelling and Simulation of Biosystems} +\author[Daniel Illana]{Daniel Illana Gonz\'alez} %(daniel.illanagonzalez@ugent.be)} +\subtitle{Practicum 2: Modelling with ODEs} +\date{Academic year 2024-2025} + + +\newcommand{\mtx}[2] + {\left[\begin{array}{#1}#2\end{array}\right]} +\newcommand{\eqset}[1] + {\left\{\begin{array}{rcl}#1\end{array}\right.} +\newcommand{\rbar}[2] + {\left.#1\right|_{#2}} +\newcommand{\atwp}[1] + {\rbar{#1}{\overline{X},\overline{U}}} + +\usepackage{mdframed} + +\newenvironment{opgave}[2][]{% + \mdfsetup{% + frametitle={% + \tikz[baseline=(current bounding box.east),outer sep=0pt] + \node[anchor=east,rectangle,fill=gray!40] + {\strut #1};}% + } + \mdfsetup{% + innertopmargin=10pt,linecolor=white!30,% + linewidth=0pt,topline=true,% + frametitleaboveskip=\dimexpr-\ht\strutbox\relax% + } + + \begin{mdframed}[]\relax}{% +\end{mdframed}} + + + +% Table of contents at the beginning of each section +%\AtBeginSection[] +%{ +% \begin{frame} +% \frametitle{Outline} +% \tableofcontents[currentsection] +% \end{frame} +%} + +% Title page customisation +\titlegraphic{} + +\begin{document} + +\frame[plain]{\titlepage} + + +\frame{ +\frametitle{Today} +\Large +\begin{itemize} + \item Short introduction %\bigskip % \vfill + \begin{itemize} + \item Stochastic Differential Equations (SDE) + \item Discrete Jump Equations (DJE) \bigskip + \end{itemize} + \item Example exercises (infection model) + \begin{itemize} + \large + \item Solving SDE problems with Catalyst + \item Solving DJE problems with Catalyst \bigskip + \end{itemize} + \item Exercises to do %\bigskip + \begin{enumerate} + \large + \item Fermenter - Second order kinetics (SDE) + \item Aging and saturated repair (SDE) + \item Foxes and rabbits (DJE) + \item A simple bike sharing system (DJE) + \end{enumerate} +\end{itemize} +} + +\frame{ +\frametitle{Stochastic differential equations} +\large +ODEs vs SDEs +\begin{itemize} +\item ODEs: model dynamics of \textbf{deterministic} system +\item SDEs: model dynamics of a system with a \textbf{noisy component} +\end{itemize} +\vfill +SDEs can generate trends with \textbf{random fluctuations}, e.g., in: +\begin{itemize} +\item stock markets +\item population of animals or humans +\item (bio)chemical processes +\end{itemize} +\vfill +Suitable for temperature, pressure, price, very large number of species. +} + + + +\frame{ +\frametitle{Stochastic differential equations} +\Large + +\begin{figure} + \includegraphics[width=0.8\textwidth]{figs/bel20.jpeg} +\end{figure} + +} + + +\frame{ +\frametitle{Stochastic differential equations} +\Large \medskip +In many natural systems, the noisiness originates from \textbf{Brownian motion}: + +\begin{figure} + \includegraphics[width=0.5\textwidth]{figs/single_brownian_motion.png} +\end{figure} + +$\blacktriangleright$ Motion is the result of random collisions with surrounding particles. + +} + + +\frame{ +\frametitle{Stochastic differential equations} +\large \medskip +Brownian motion can be modelled by a \textbf{Wiener process}.\\ \smallskip +{\small $\blacktriangleright$ A stochastic process representing a stochastic variable $W(t)$ through time:} +$$ +W(t + \tau) - W(t) \sim N(0, \sqrt{\tau}) +$$ + +\begin{figure} + \includegraphics[width=0.6\textwidth]{figs/brownian_motions_graph.png} +\end{figure} + +Generates continuous functions and $W(t)$ is a real value (${\rm I\!R}$). + +} + + +\frame{ +\frametitle{Stochastic differential equations} +\Large + +A stochastic differential equation contains two parts: +\begin{itemize} + \item a deterministic part (ODE) + \item a stochastic part (Wiener process) +\end{itemize} +\vfill +$$ +d Y(t) = \mu(Y(t), t)dt + \sigma(Y(t), t)dW_t +$$ +\vfill +In the numerical integration, the variable $Y(t)$ changes in small steps. At every step, two terms are added: +\begin{enumerate} +\item $\mu(Y(t), t)dt$ is added to the previous step, +\item some noise $dW_t$ proportional to $\sigma(Y(t), t)$. +\end{enumerate} + + +} + + +\frame{ +\frametitle{Discrete Jump Equations} +\Large +Many phenomena involve discrete variables, e.g.: +\begin{itemize} +\item small population of animals +\item reactions involving a limited number of species +\item traffic monitoring +\item standing in a queue +\end{itemize} + +\bigskip + +Variables are represented by natural numbers (${\rm I\!N}$). + +} + + +\frame{ +\frametitle{Discrete Jump Equations} +\Large +\begin{figure} + \includegraphics[width=0.8\textwidth]{figs/discrete_jump_SIR.png} +\end{figure} +} + + +\frame{ +\frametitle{Discrete Jump Equations} +\large +\textbf{The Gillespie algorithm} \medskip +\begin{itemize} +\item This method is a way to simulate the \textit{random}, \textit{discrete events} in a system that evolves through \textbf{jumps} (or reactions). +\item It is widely used in chemical kinetics and population dynamics when modeling systems where \textbf{changes happen at random times} rather than continuously. +\item Since the process is stochastic (random), the time to the next event is not fixed but follows an \textbf{exponential distribution}. +\item Each reaction has a certain likelihood of occurring, depending on its rate which also depends on the number of reactants. +\end{itemize} + +} + + +\frame{ + \frametitle{Goals of this practicum} + \Large + \color{beamerstructure} + {\begin{enumerate} + \item Simulating systems as SDE-problems + \vfill %\pause + \item Creating an ensemble problem\\ + \vfill %\pause + \item Simulating systems as discrete jump problems + \vfill %\pause + \item Plotting distributions/histograms + \end{enumerate} + } +} + + +\frame{ +\frametitle{Pluto notebooks} +\large + +Download the exercise notebooks for today. \vfill + +\begin{itemize} +\item For this practicum, go to the Ufora submodule\\ \textbf{P2: ODEs 2 $>$ files} \vfill +\item Download the Pluto notebooks and put them into your dedicated \texttt{modsim\_practica/P2\_ODE2} folder. \vfill +\item Go to your dedicated folder (cf. \texttt{modsim\_practica}) with a \textit{File Explorer}, then in this location either \vfill +\begin{itemize} +\item right click on your mouse and choose \texttt{Open in Terminal} (or something alike), or +\item write the command \texttt{cmd} in the address bar and click [\textit{Enter}]. +\end{itemize} \vfill +\item Execute \texttt{julia launch\_pluto.jl} \vfill +\item Now you will be able to open and run the Pluto notebook of you choice. \vfill +\end{itemize} +} + + +\frame{ +\frametitle{Practicum 2: ODEs 2} +\large +The following notebooks are the subjects for today:\vspace*{2mm} +\begin{itemize} +\item \texttt{sde\_model\_catalyst\_intro.jl} (introduction) \vspace*{2mm} +\item \texttt{sde\_model\_fermenter\_secondorder.jl} +\item \texttt{sde\_model\_aging.jl} \vspace*{2mm} \bigskip +\item \texttt{ssa\_model\_catalyst\_intro.jl} (introduction) \vspace*{2mm} +\item \texttt{ssa\_model\_foxes\_rabbits} +\item \texttt{ssa\_model\_bike\_sharing.jl} +\end{itemize} +} + + + +\frame{ +\frametitle{SDEs problems} +\large +We will use the infection model to illustrate the following: +\begin{itemize} +\item Implementation of the system as a \textit{reaction network} object including a \textit{noise scaling} parameter +\item Simulation of the system as an SDE-problem +\item Simulating the system as an \textit{ensemble problem} +\item Introducing a \textit{discrete callback} function +\item Analysing the results from an ensemble problem +\end{itemize} +} + + +\frame{ +\frametitle{SDEs problems} +\Large + +Notebook: \texttt{sde\_model\_catalyst\_intro.jl} + +The infection model: + +\begin{figure} +\includegraphics[width=0.6\textwidth]{figs/infection_model.png} +\end{figure} +} + +\frame{ +\frametitle{Exercise 1} +\Large + +\textbf{Fermenter}\\ +Notebook: \texttt{ode\_model\_fermenter\_secondorder.jl} + +\begin{figure} +\centering +\includegraphics[width=0.5\textwidth]{figs/fermenter_model_2nd.png} +\end{figure} + +} + + + +\frame{ +\frametitle{Exercise 2} +\Large +\textbf{Aging and saturated repair}\\ +Notebook: \texttt{sde\_model\_aging.jl} +\vfill +{\small +$\bullet$ More senescent cells with age\\ +$\bullet$ Senescent cells are being cleaned up by NK-cells\\ +$\bullet$ Remaining senescent cells cause inflammation\\ +} + +\begin{figure} + \includegraphics[width=0.7\textwidth]{figs/nk_cells_senescent_cells.png} +\end{figure} +} + + +\frame{ +\frametitle{Exercise 2} +\Large +\textbf{Aging and saturated repair}\\ +\vfill +$X$ = number of senescent cells in a human body +\vfill +Our simple model has two features: +\begin{enumerate} +\item production of damage that rises linearly with age +\item the saturating removal of damage +\end{enumerate} + +$$ +\cfrac{dX}{dt} = \mu t - \beta \cfrac{X}{X + \kappa} +$$ +} + + +\frame{ +\frametitle{Discrete Jump Problems} +\large +We will use the infection model to illustrate the following: +\begin{itemize} +\item Simulation of the system as an Discrete Jump problem +\item Extracting information from multiple simulations +\end{itemize} +} + + +\frame{ +\frametitle{Discrete jump problems} +\Large + +Notebook: \texttt{ssa\_model\_catalyst\_intro.jl} + +The infection model: + +\begin{figure} + \includegraphics[width=0.6\textwidth]{figs/infection_model.png} +\end{figure} +} + + +\frame{ +\frametitle{Exercise 3} +\Large +\textbf{Foxes and rabbits}\\ +Notebook: \texttt{ssa\_model\_foxes\_rabbits} + +\vspace*{2mm} + +\begin{figure} + \includegraphics[width=0.7\textwidth]{figs/foxes_rabbits_model.png} +\end{figure} +} + + +\frame{ +\frametitle{Exercise 4} +\Large +\textbf{Bike sharing}\\ +Notebook: \texttt{ssa\_model\_bike\_sharing.jl} + +\begin{figure} + \includegraphics[width=0.8\textwidth]{figs/bike_sharing_model.png} +\end{figure} +} + + +\end{document} + diff --git a/slides/slides_ode/beamercolorthemeUniversiteitGent.sty b/slides/slides_ode/beamercolorthemeUniversiteitGent.sty new file mode 100755 index 00000000..d1671486 --- /dev/null +++ b/slides/slides_ode/beamercolorthemeUniversiteitGent.sty @@ -0,0 +1,52 @@ +% Copyright 2012 Pieter Belmans +% https://github.com/pbelmans/ugent-beamer +% +% Based on Nico Schlömer's ua-beamer (https://github.com/nschloe/ua-beamer) +% +% This file may be distributed and/or modified +% +% 1. under the LaTeX Project Public License and/or +% 2. under the GNU Public License. + +\RequirePackage{ifthen} + +\mode + +\input{colors} + +\ifbeamer@faculty\colorlet{ugent-faculty}{ugent-\beamer@facultyvalue}\fi + +% switch between the generic yellow use of highlights or faculty specific colors +\ifthenelse{ \boolean{beamer@faculty} \AND \boolean{beamer@usefacultycolors} } +{ + \colorlet{ugentalert} {ugent-faculty} + \colorlet{ugentexample}{ugentblue} +} +{ + \colorlet{ugentalert} {ugentyellow} + \colorlet{ugentexample}{ugentblue} +} + + +% general colors +\setbeamercolor{structure} {fg = ugentblue}% +\setbeamercolor{normal text} {fg = ugentblue}% +\setbeamercolor{frametitle} {fg = ugentblue}% +\setbeamercolor{frame number in foot}{fg = ugentblue}% +\setbeamercolor{subtitle} {fg = ugentyellow}% +\setbeamercolor{author} {fg = ugentblue}% + +% alert color +\setbeamercolor{alerted text}{fg=ugentalert} + +% blocks +\setbeamercolor{block title}{use=structure,fg=white,bg=ugentblue} +\setbeamercolor{block title alerted}{use=alerted text,fg=white,bg=ugentalert} +\setbeamercolor{block title example}{use=example text,fg=white,bg=ugentexample} + +\setbeamercolor{block body} {fg=ugentblue,use=block title,bg=ugentblue!10!white} +\setbeamercolor{block body alerted}{fg=ugentblue,use=block title alerted,bg=ugentalert!10!white} +\setbeamercolor{block body example}{fg=ugentblue,use=block title example,bg=ugentexample!10!white} + +\mode + diff --git a/slides/slides_ode/beamerfontthemeUniversiteitGent.sty b/slides/slides_ode/beamerfontthemeUniversiteitGent.sty new file mode 100755 index 00000000..d7aaac0b --- /dev/null +++ b/slides/slides_ode/beamerfontthemeUniversiteitGent.sty @@ -0,0 +1,23 @@ +% Copyright 2012 Pieter Belmans +% https://github.com/pbelmans/ugent-beamer +% +% Based on Nico Schlömer's ua-beamer (https://github.com/nschloe/ua-beamer) +% +% This file may be distributed and/or modified +% +% 1. under the LaTeX Project Public License and/or +% 2. under the GNU Public License. + +\mode + +\setbeamerfont{title} {size=\huge} +\setbeamerfont{subtitle} {size=\Large} +\setbeamerfont{frametitle}{size=\LARGE} + +\setbeamerfont{author}{size=\normalsize} + +\setbeamerfont{frame number in head}{size=\scriptsize} +\setbeamerfont{frame number in foot}{size=\scriptsize} + +\mode + diff --git a/slides/slides_ode/beamerinnerthemeUniversiteitGent.sty b/slides/slides_ode/beamerinnerthemeUniversiteitGent.sty new file mode 100755 index 00000000..b9ef934b --- /dev/null +++ b/slides/slides_ode/beamerinnerthemeUniversiteitGent.sty @@ -0,0 +1,46 @@ +% Copyright 2012 Pieter Belmans +% https://github.com/pbelmans/ugent-beamer +% +% Based on Nico Schlömer's ua-beamer (https://github.com/nschloe/ua-beamer) +% +% This file may be distributed and/or modified +% +% 1. under the LaTeX Project Public License and/or +% 2. under the GNU Public License. + +\mode + +\defbeamertemplate*{title page}{ugent theme} +{ + \begin{center} + %\pgfuseimage{logo}% + %\vskip1cm + \usebeamerfont{title}\usebeamercolor[fg]{title}\inserttitle% + \ifx\insertsubtitle\@empty% + \else% + \vskip2ex% + \usebeamerfont{subtitle}\usebeamercolor[fg]{subtitle}\insertsubtitle% + \fi% + \ifx\insertauthor\@empty% + \else% + \vskip2ex% + \usebeamerfont{author}\usebeamercolor[fg]{author}\insertauthor% + \fi% + \ifx\insertinstitution\@empty% + \else% + \vskip2ex% + \usebeamerfont{author}\usebeamercolor[fg]{author}\insertinstitute% + \fi% + \ifx\insertdate\@empty% + \else% + \vskip4ex% + \usebeamerfont{author}\usebeamercolor[fg]{author}\insertdate% + \fi% + \end{center} + \vfill% +} + +\setbeamertemplate{blocks}[rounded] + +\mode + diff --git a/slides/slides_ode/beamerouterthemeUniversiteitGent.sty b/slides/slides_ode/beamerouterthemeUniversiteitGent.sty new file mode 100755 index 00000000..a27622ee --- /dev/null +++ b/slides/slides_ode/beamerouterthemeUniversiteitGent.sty @@ -0,0 +1,95 @@ +% Copyright 2012 Pieter Belmans +% https://github.com/pbelmans/ugent-beamer +% +% Based on Nico Schlömer's ua-beamer (https://github.com/nschloe/ua-beamer) +% +% This file may be distributed and/or modified +% +% 1. under the LaTeX Project Public License and/or +% 2. under the GNU Public License. + +% UGent page geometry +% \geometry{paperheight=7.5in,paperwidth=10.0in} +% ... Hang on! As suggested in the manual, don't mess around with beamer's +% assumed page dimensions (128mm x 96mm). Fonts, for example, do no get +% automatically scaled and will look tiny if the above is executed. +% Instead, define a multiplier 12.8/(10.0*2.54) = 64/127 and adjust all +% respective lengths. + +\RequirePackage{ifthen} + +\mode + +% lengths +\newlength\margin +\setlength\margin{0.43cm}% 0.85cm * 64/127 + +\newlength\bannerwidth +\setlength\bannerwidth{11.94cm}% (10in - 2*0.85cm) * 64/127 + +\newlength\bannertopmargin% +\setlength\bannertopmargin{0.43cm}% 0.85cm * 64/127 + + +% images +\pgfdeclareimage[width=3cm]{logo}{logo} + +\ifbeamer@faculty + \pgfdeclareimage[width=\bannerwidth]{banner}{\beamer@facultyvalue-\beamer@languagevalue} +\else + \pgfdeclareimage[width=\bannerwidth]{banner}{banner} +\fi + + +% headline +\defbeamertemplate*{headline}{ugent theme}% +{% + \vskip\bannertopmargin% + \hskip\margin% + \pgfuseimage{banner}% +} + +% frametitle +\defbeamertemplate*{frametitle}{ugent theme} +{% + \begin{beamercolorbox}[right]{frame title}% + \insertframetitle% + \end{beamercolorbox}% + \vspace{-.2cm} +} + +% footline +\defbeamertemplate*{footline}{ugent theme} +{% + \ifbeamer@footline + \ifnum\pdf@strcmp{\beamer@footlinevalue}{sections}=0 + \pgftext[bottom, left, at = \pgfpoint{0.02\paperwidth}{0.02\paperwidth}]{\insertsectionhead}% + \else + \pgftext[bottom, left, at = \pgfpoint{0.02\paperwidth}{0.02\paperwidth}]{\insertinstitute}% + \fi + \pgftext[bottom, at = \pgfpoint{0.5\paperwidth}{0.02\paperwidth}]{\insertauthor}% + \fi + \ifbeamer@framenumber% + \ifnum\c@framenumber=1\else + \pgftext[bottom, right, at = \pgfpoint{0.96\paperwidth}{0.02\paperwidth}]{% + \usebeamerfont{frame number in foot}% + \usebeamercolor[fg]{frame number in foot}\insertframenumber{}% + \ifbeamer@totalframenumber% + /\inserttotalframenumber% + \fi + }% + \fi + \fi% +}% + +% margins +\setbeamersize{text margin left=2\margin,% + text margin right=2\margin} + +% background +\defbeamertemplate*{background canvas}{ugent theme} +{% +} + +\mode + diff --git a/slides/slides_ode/beamerthemeUniversiteitGent.sty b/slides/slides_ode/beamerthemeUniversiteitGent.sty new file mode 100755 index 00000000..b3fcc3f5 --- /dev/null +++ b/slides/slides_ode/beamerthemeUniversiteitGent.sty @@ -0,0 +1,49 @@ +% Copyright 2012 Pieter Belmans +% https://github.com/pbelmans/ugent-beamer +% +% Based on Nico Schlömer's ua-beamer (https://github.com/nschloe/ua-beamer) +% +% This file may be distributed and/or modified +% +% 1. under the LaTeX Project Public License and/or +% 2. under the GNU Public License. + + +% introduce options +\newif\ifbeamer@faculty +\beamer@facultyfalse +\newcommand\beamer@facultyvalue{} +\DeclareOptionBeamer{faculty}{\beamer@facultytrue\renewcommand\beamer@facultyvalue{#1}} + +\newif\ifbeamer@usefacultycolors\beamer@usefacultycolorsfalse +\DeclareOptionBeamer{usecolors}{\beamer@usefacultycolorstrue} + +\newif\ifbeamer@footline +\beamer@footlinefalse +\newcommand\beamer@footlinevalue{} +\DeclareOptionBeamer{footline}{\beamer@footlinetrue\renewcommand\beamer@footlinevalue{#1}} + +\newcommand\beamer@languagevalue{dutch} +\DeclareOptionBeamer{language}{\renewcommand\beamer@languagevalue{#1}} + +\newif\ifbeamer@framenumber\beamer@framenumberfalse +\DeclareOptionBeamer{framenumber}{\beamer@framenumbertrue} + +\newif\ifbeamer@totalframenumber\beamer@totalframenumberfalse +\DeclareOptionBeamer{totalframenumber}{\beamer@totalframenumbertrue} + +\ProcessOptionsBeamer + +% actual configuration +\mode + +\useinnertheme{UniversiteitGent} +\usefonttheme {UniversiteitGent} +\usecolortheme{UniversiteitGent} +\useoutertheme{UniversiteitGent} + +% I don't like navigational symbols, neither should you +\beamertemplatenavigationsymbolsempty + +\mode + diff --git a/slides/slides_ode/beamerthemepresentationTemplateBiomathFClean.sty b/slides/slides_ode/beamerthemepresentationTemplateBiomathFClean.sty new file mode 100755 index 00000000..41a42848 --- /dev/null +++ b/slides/slides_ode/beamerthemepresentationTemplateBiomathFClean.sty @@ -0,0 +1,139 @@ +\ProvidesPackage{beamerthemepresentationTemplateBiomathFClean} + +\mode + +\newlength\margin +\setlength\margin{0.05\beamer@paperwidth} +\newlength\bannerwidth +\setlength\bannerwidth{0.99\beamer@paperwidth} +\newlength\bannertopmargin +\setlength\bannertopmargin{0.05\beamer@paperheight} + +\setbeamersize{text margin left=1.5em,text margin right=1.5em} +\beamertemplatenavigationsymbolsempty + +%Definition of new colors +\definecolor{red}{RGB}{254,0,0} +\definecolor{ugentblue}{RGB}{30,100,200} % Pantone 534: global +\definecolor{ugentyellow}{RGB}{255,210,0} % Pantone 130: generic colour + +\definecolor{ugentwhite}{RGB}{255,255,255} + +%\definecolor{ugentblue}{RGB}{36,71,127} +\definecolor{ugentyellowOUD}{RGB}{250,178,10} + +\definecolor{ugent-la}{RGB}{39,171,173} % Pantone 3262c: Faculty of Bioscience Engineering +\definecolor{ugent-fw}{RGB}{190,81,144} % Pantone purple: Faculty of Pharmaceutical Sciences +\colorlet{ugentalert}{red} +\colorlet{ugentexample}{ugentblue} +%Colors of different items +\setbeamercolor{structure}{fg=ugentblue, bg = ugentblue} +\setbeamercolor{normal text}{fg=ugentblue} +\setbeamercolor{frametitle}{fg=ugentblue} +\setbeamercolor{frame number in foot}{fg=ugentblue} +\setbeamercolor{title}{fg=ugentwhite} +\setbeamercolor{subtitle}{fg=ugentwhite} +\setbeamercolor{author}{fg=ugentwhite} +\setbeamercolor{alerted text}{fg=ugentalert} +\setbeamercolor{block title}{use=structure,fg=white,bg=ugentblue} +\setbeamercolor{block title alerted}{use=alerted text,fg=white,bg=ugentalert} +\setbeamercolor{block title example}{use=example text,fg=white,bg=ugentexample} +\setbeamercolor{block body}{fg=ugentblue,use=block title,bg=ugentblue!10!white} +\setbeamercolor{block body alerted}{fg=ugentblue,use=block title alerted,bg=ugentalert!10!white} +\setbeamercolor{block body example}{fg=ugentblue,use=block title example,bg=ugentexample!10!white} +\setbeamercolor{title in head/foot}{fg=ugentblue, bg=white} +\setbeamercolor{author in head/foot}{fg=ugentblue, bg=white} +%Fontsize of different items +\setbeamerfont{title}{size=\huge} +\setbeamerfont{subtitle}{size=\Large} +\setbeamerfont{frametitle}{size=\LARGE} +\setbeamerfont{author}{size=\normalsize} +\setbeamerfont{frame number in foot}{size=\scriptsize} +%Images +\pgfdeclareimage[width=\bannerwidth]{banner}{la-english.pdf} +\pgfdeclareimage[width=\bannerwidth]{banner2}{la-english2.pdf} +\pgfdeclareimage[width=0.1\bannerwidth]{logoBio}{logo_biomath} + +\setbeamercolor{title1}{bg=ugentblue} + +%Templates +\setbeamertemplate{blocks}[rounded] + +\newcommand{\biomathlogo}{ + \setlength{\TPHorizModule}{1pt} + \setlength{\TPVertModule}{1pt} + \begin{textblock}{1}(10,259) + \includegraphics[width=48pt,height=8pt]{logo_biomath} + \end{textblock} + } + +\setbeamertemplate{title page} +{ + \begin{picture}(320,250)(0,0) + \put(-21.5,208.5){\includegraphics[scale = 0.7]{icoon_UGent_BW_NL_RGB_2400_kleur.png}} + \put(-9.5,122){ + \begin{minipage}{\paperwidth} + + \begin{beamercolorbox}[ht =59mm, sep = 3ex]{title} + + \usebeamerfont{title}\textbf{\inserttitle}\par + \usebeamerfont{subtitle}\insertsubtitle\par + + \bigskip + + + \bigskip + + \usebeamerfont{institute}\insertauthor\par + \usebeamerfont{date}\insertdate\par + + \end{beamercolorbox}% + \end{minipage}% + } + \put(-21.5,-19){\includegraphics[scale = 0.7]{logo_UGent_NL_RGB_2400_kleur.png}} + \end{picture} +} + +\setbeamertemplate{headline}{} + +\setbeamertemplate{frametitle} +{ + \begin{beamercolorbox}[right]{frame title} + \insertframetitle + \end{beamercolorbox} + \vspace{-.2cm} +} + +\setbeamertemplate{footline}{ + \hbox{ + \begin{beamercolorbox}[wd=0.95\beamer@paperwidth,ht=4ex,dp=3ex,right]{date in head/foot} + \insertframenumber{}/\inserttotalframenumber + \end{beamercolorbox} + } +} + +%Special features for boxes +\newcommand{\info}[2]{ +\begin{bclogo}[couleur=ugentblue!30,arrondi=0.2,ombre=false,couleurBarre=ugentblue!60!black!50, logo=\bcinfo,noborder=true]{#1}#2 +\end{bclogo} +} +\newcommand{\question}[2]{ +\begin{bclogo}[couleur=ugent-la!30,arrondi=0.2,ombre=false,couleurBarre=ugent-la!60!black!50,logo=\bcquestion,noborder=true]{#1}#2 +\end{bclogo} +} +\newcommand{\important}[2]{ +\begin{bclogo}[couleur = orange!30, arrondi = 0.2,ombre=false, couleurBarre=orange!60!black!50,logo=\bcattention,noborder=true]{#1}#2 +\end{bclogo} +} +\newcommand{\actions}[2]{ +\begin{bclogo}[couleur=ugentyellow!50!white,arrondi=0.2,ombre=false,couleurBarre=ugentyellow!60!black!50,logo=\bccrayon,noborder=true]{#1}#2 +\end{bclogo} +} + +%\AtBeginDocument{ +%\begin{frame}[plain] +% \maketitle +%\end{frame} +%} + +\mode diff --git a/slides/slides_ode/biomath.sty b/slides/slides_ode/biomath.sty new file mode 100755 index 00000000..46857626 --- /dev/null +++ b/slides/slides_ode/biomath.sty @@ -0,0 +1,149 @@ +%\ProvidesPackage{beamerthemesplit}[2003/10/29 ver 0.92] +\NeedsTeXFormat{LaTeX2e}[1995/12/01] + +% Copyright 2003 by Till Tantau . +% +% This program can be redistributed and/or modified under the terms +% of the LaTeX Project Public License Distributed from CTAN +% archives in directory macros/latex/base/lppl.txt. + +\mode + +\beamertemplatelargetitlepage +\beamertemplatelargepartpage +\beamertemplatelargeframetitle +\beamertemplateplaintoc +\beamertemplatelargeblocks +%\beamertemplatenavigationsymbolsempty +%\usealerttemplate{\color{beamerstructure}}{} %set alert color equal to beamerstructure color +\usenavigationsymbolstemplate{\vbox{% +% \hbox{\insertslidenavigationsymbol} + \hbox{\insertframenavigationsymbol} + %\hbox{\insertsubsectionnavigationsymbol} + %\hbox{\insertsectionnavigationsymbol} + %\hbox{\insertdocnavigationsymbol} + %\hbox{\insertbackfindforwardnavigationsymbol} + }} + +\usesectionheadtemplate + {\hfill\color{white}\tiny\textbf{\insertsectionhead}} + {\hfill\color{white!50!black}\tiny\textbf{\insertsectionhead}} + +\usesubsectionheadtemplate + {\color{white}\tiny\textbf{\insertsubsectionhead}} + {\color{white!50!structure}\tiny\textbf{\insertsubsectionhead}} + + % Head +\ifbeamer@compress +\useheadtemplate{% + \vbox{% + \tiny% + \setbox\beamer@linebox=\hbox to\paperwidth{% + \insertsectionnavigationhorizontal{.5\paperwidth}{\hskip0pt plus1filll}{}% + \insertsubsectionnavigationhorizontal{.5\paperwidth}{}{\hskip0pt plus1filll}\hfil}% + \ht\beamer@linebox=2.625ex + \dp\beamer@linebox=0pt + \setbox\beamer@linebox=\vbox{\box\beamer@linebox\vskip1.125ex}% + \hbox to\textwidth{% + {\color{black}\hskip-\Gm@lmargin\vrule width.5\paperwidth height\ht\beamer@linebox + \color{structure}\vrule width.5\paperwidth height\ht\beamer@linebox\hskip-\paperwidth\hskip\Gm@lmargin}% + \hskip-\Gm@lmargin\box\beamer@linebox\hfill\hskip-\Gm@rmargin + }% + }% +} +\else +\useheadtemplate{% + \vbox{% + \tiny% + \beamer@tempdim=2.4375ex% + \ifnum\beamer@subsectionmax<\beamer@sectionmax% + \multiply\beamer@tempdim by\beamer@sectionmax% + \else% + \multiply\beamer@tempdim by\beamer@subsectionmax% + \fi% + \advance\beamer@tempdim by 1.125ex% + \setbox\beamer@linebox=\hbox to\paperwidth{% + \vbox to \beamer@tempdim{\vfil\insertsectionnavigation{.5\paperwidth}\vfil}% + \vbox to \beamer@tempdim{\vfil\insertsubsectionnavigation{.5\paperwidth}\vfil}\hfill}% + %\vbox to \beamer@tempdim{\vfil\hyperlinkslideprev{\insertreturnsymbol}\vfil}\hfill}% + \hbox to\textwidth{% + {\color{black}\hskip-\Gm@lmargin\vrule width.5\paperwidth + height\ht\beamer@linebox\color{structure}\vrule width.5\paperwidth + height\ht\beamer@linebox\hskip-\paperwidth\hskip\Gm@lmargin}% + \hskip-\Gm@lmargin\box\beamer@linebox\hfill\hskip-\Gm@rmargin% + }% + }% +} +\fi + + +\usefoottemplate{% + \vbox{\tiny% + \hbox{% + \setbox\beamer@linebox=\hbox to\paperwidth{% + \hyperlinkslideprev{\hbox to.5\paperwidth{\hfill\tiny\color{white}\vspace{1.7cm}\textbf{BIOMATH, Coupure Links 653, 9000 Gent,Belgium}\hskip.3cm}}% + \hyperlinkslidenext{\hbox to.5\paperwidth{\hskip.3cm\tiny\color{white}\textbf{Elena Torfs\hfill\hfill \hfill \hfill \hfill \hfill \insertpagenumber/\insertpresentationendpage}\hfill}}\hfill}% + \ht\beamer@linebox=2.625ex% + \dp\beamer@linebox=0pt% + \setbox\beamer@linebox=\vbox{\box\beamer@linebox\vskip1.125ex}% + \color{black}\hskip-\Gm@lmargin\vrule width.5\paperwidth + height\ht\beamer@linebox\color{structure}\vrule width.5\paperwidth + height\ht\beamer@linebox\hskip-\paperwidth% + \hbox{\box\beamer@linebox\hfill}\hfill\hskip-\Gm@rmargin}}} + +\usetitlepagetemplate{ + \vbox{% + \tiny% + \beamer@tempdim=2.4375ex% + \ifnum\beamer@subsectionmax<\beamer@sectionmax% + \multiply\beamer@tempdim by\beamer@sectionmax% + \else% + \multiply\beamer@tempdim by\beamer@subsectionmax% + \fi% + \advance\beamer@tempdim by 1.125ex% + \setbox\beamer@linebox=\hbox to\paperwidth{% + \vbox to \beamer@tempdim{\vfil}% + \vbox to \beamer@tempdim{\vfil}\hfill}% + %\vbox to \beamer@tempdim{\vfil\hyperlinkslideprev{\insertreturnsymbol}\vfil}\hfill}% + \hbox to\textwidth{% + {\color{black}\hskip-\Gm@lmargin\vrule width.5\paperwidth + height\ht\beamer@linebox\color{structure}\vrule width.5\paperwidth + height\ht\beamer@linebox\hskip-\paperwidth\hskip\Gm@lmargin}% + \hskip-\Gm@lmargin\box\beamer@linebox\hfill\hskip-\Gm@rmargin% + }% + }% + +% +\beamerline{\hspace{1cm}\parbox[l][3cm][c]{0.5\paperwidth}{\includegraphics[height=1.5cm]{logo.png}} +\parbox[r][3cm][c]{.5\textwidth}{\flushright{{\begin{center}\bf BIOMATH\\\tiny Toegepaste Wiskunde\\Biometrie and Procesregeling\end{center}}}}} + \vskip0pt plus 1filll + + \begin{center} + {\bf \Large{\color{beamerstructure}{\inserttitle}}}\\ + \vspace{0.3cm} + \small \insertauthor\\ + \vspace{1cm} + \insertsubtitle\\ + \vspace{.15cm} + \insertdate + \end{center} + \vskip0pt plus 1filll + + \vbox{\tiny% + \hbox{% + \setbox\beamer@linebox=\hbox to\paperwidth{% + \hyperlinkslideprev{\hbox to.5\paperwidth{\hfill\tiny\color{white}\vspace{1.7cm}\textbf{BIOMATH, Coupure Links 653, 9000 Gent,Belgium}\hskip.3cm}}% + \hyperlinkslidenext{\hbox to.5\paperwidth{\hskip.3cm\tiny\color{white}\textbf{e-mail: elena.torfs@ugent.be}\hfill}}\hfill}% + \ht\beamer@linebox=2.625ex% + \dp\beamer@linebox=0pt% + \setbox\beamer@linebox=\vbox{\box\beamer@linebox\vskip1.125ex}% + \color{black}\hskip-\Gm@lmargin\vrule width.5\paperwidth + height\ht\beamer@linebox\color{structure}\vrule width.5\paperwidth + height\ht\beamer@linebox\hskip-\paperwidth% + \hbox{\box\beamer@linebox\hfill}\hfill\hskip-\Gm@rmargin}} + +%gepruts kan nuttig zijn om uit te leren: vb colorbox paperwidth hyperlink kleur:beamerstructure +%\beamerline{\colorbox{black}{\parbox[b][.18cm][c]{.5\paperwidth}{\hbox to.484\paperwidth{\hfill\tiny\bf\color{white}BIOSTAT, Coupure Links 653, 9000 Gent,Belgium\hskip.3cm}}}\hyperlinkslidenext{\colorbox{beamerstructure}{\parbox[b][0.18cm][c]{.5\paperwidth}{\hbox to.5\paperwidth{\hskip.3cm\tiny\bf\color{white}e-mail: lieven.clement@BIOSTAT.ugent.be\hfill}}}}} +} +\mode + diff --git a/slides/slides_ode/bw-nl.png b/slides/slides_ode/bw-nl.png new file mode 100755 index 00000000..04f06016 Binary files /dev/null and b/slides/slides_ode/bw-nl.png differ diff --git a/slides/slides_ode/chemplants.sty b/slides/slides_ode/chemplants.sty new file mode 100755 index 00000000..460078dd --- /dev/null +++ b/slides/slides_ode/chemplants.sty @@ -0,0 +1,1758 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% chemplants.sty +%% Copyright 2018-2019 Elia Arnese Feffin +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3c +% of this license or (at your option) any later version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3c or later is part of all distributions of LaTeX +% version 2005/12/01 or later. +% +% This work has the LPPL maintenance status "maintained". +% +% The Current Maintainer of this work is Elia Arnese Feffin. +% The Current Maintainer can be reached at the e-mail: elia24913@me.com. +% +% This work consists of the files chemplants.sty, chemplants-doc.tex +% and chemplants-changes.tex, together with the derived files +% chemplants-doc.pdf and chemplants-changes.pdf. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%:File chemplants.sty +\NeedsTeXFormat{LaTeX2e} +\def\chpversion{0.9.8} +\def\chpdate{2019/11/19} +\ProvidesPackage{chemplants}[% + 2019/11/19 v0.9.8 Symbology to draw chemical plants with TikZ% +] + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%: Packages Loading + +\RequirePackage{ifthen} % If-Then Logic +\RequirePackage{tikz} % The Mother of Them All + \usetikzlibrary{decorations.markings} % Patch Patterns + \usetikzlibrary{hobby} % Hobby's Algorithm + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%: Definitions, Parameters and Commands + +%: Default Parameters +\def\chp@StreamTip{stealth} % Stream Tip +\def\chp@MainStreamThickness{semithick} % Main Stream Thickness +\def\chp@SecondaryStreamThickness{thin} % Secondary Stream Thickness +\def\chp@UtilityStreamThickness{very thin} % Utility Stream Thickness +\def\chp@UnitThickness{thick} % Unit Thickness +\def\chp@UnitScale{1} % Unit Scale +\def\chp@SignalThickness{very thin} % Signal Thickness +\def\chp@HiddenStreamStyle{dashed} % Hidden Stream +\def\chp@HiddenComponentStyle{densely dotted} % Hidden Component +\def\chp@MeasureColor{gray} % Measure Color +\def\chp@MeasureTip{|} % Measure Tip +\def\chp@MeasureThickness{thin} % Measure Thickness +\def\chp@MeasureFontSize{\footnotesize} % Measure Font Size +\def\chp@InstrumentThickness{thin} % Instrument Thickness +\def\chp@InstrumentScale{1} % Instrument Scale +\def\chp@InstrumentFontSize{\footnotesize} % Instrument Font Size +\def\chp@BlockThickness{thick} % Block Thickness +\def\chp@BlockScale{1} % Block Scale +\def\chp@BlockFontSize{\footnotesize} % Block Font Size + +%: Commands to Set Parameters +\newcommand*{\setchpstreamtip}[1]{% % Stream Tip + \gdef\chp@StreamTip{#1}% +} +\newcommand*{\setchpmainstreamthickness}[1]{% % Main Stream Thickness + \gdef\chp@MainStreamThickness{#1}% +} +\newcommand*{\setchpsecondarystreamthickness}[1]{% % Secondary Stream Thickness + \gdef\chp@MainStreamThickness{#1}% +} +\newcommand*{\setchputilitystreamthickness}[1]{% % Utility Stream Thickness + \gdef\chp@UtilityStreamThickness{#1}% +} +\newcommand*{\setchpunitthickness}[1]{% % Unit Thickness + \gdef\chp@UnitThickness{#1}% +} +\newcommand*{\setchpunitscale}[1]{% % Unit Scale + \gdef\chp@UnitScale{#1}% +} +\newcommand*{\setchpsignalthickness}[1]{% % Signal Thickness + \gdef\chp@SignalThickness{#1}% +} +\newcommand*{\setchphiddenstreamstyle}[1]{% % Hidden Stream Style + \gdef\chp@HiddenStreamStyle{#1}% +} +\newcommand*{\setchphiddencomponentstyle}[1]{% % Hidden Component Style + \gdef\chp@HiddenComponentStyle{#1}% +} +\newcommand*{\setchpmeasurecolor}[1]{% % Measure Color + \gdef\chp@MeasureColor{#1}% +} +\newcommand*{\setchpmeasuretip}[1]{% % Measure Tip + \gdef\chp@MeasureTip{#1}% +} +\newcommand*{\setchpmeasurethickness}[1]{% % Measure Thickness + \gdef\chp@MeasureThickness{#1}% +} +\newcommand*{\setchpmeasurefontsize}[1]{% % Measure + \gdef\chp@MeasureFontSize{#1}% +} +\newcommand*{\setchpinstrumentthickness}[1]{% % Instrument Thickness + \gdef\chp@InstrumentThickness{#1}% +} +\newcommand*{\setchpinstrumentscale}[1]{% % Instrument Scale + \gdef\chp@InstrumentScale{#1}% +} +\newcommand*{\setchpinstrumentfontsize}[1]{% % Instrument Font Size + \gdef\chp@InstrumentFontSize{#1}% +} +\newcommand*{\setchpblockthickness}[1]{% % Block Thickness + \gdef\chp@BlockThickness{#1}% +} +\newcommand*{\setchpblockscale}[1]{% % Block Scale + \gdef\chp@BlockScale{#1}% +} +\newcommand*{\setchpblockfontsize}[1]{% % Block Font Size + \gdef\chp@BlockFontSize{#1}% +} + +%: Measure Command +\newcommand*{\measure}[4][below]{% + \draw [chpmeasure] #2 -- #3 + node [pos=0.5,sloped,#1,font=\chp@MeasureFontSize] {#4};% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%: Styles for Streams, Units and Signals + +%: Main Stream +\tikzset{main stream/.style=% + {% + -\chp@StreamTip,% + \chp@MainStreamThickness,% + }% +} + +%: Secondary Stream +\tikzset{secondary stream/.style=% + {% + -\chp@StreamTip,% + \chp@SecondaryStreamThickness,% + }% +} + +%: Utility Stream +\tikzset{utility stream/.style=% + {% + -\chp@StreamTip,% + \chp@UtilityStreamThickness, + }% +} + +%: Process Unit +\tikzset{chpunitstyle/.style=% + {% + \chp@UnitThickness,% + scale=\chp@UnitScale% + }% +} + +%: Signal +\tikzset{signal/.style=% + {% + \chp@SignalThickness,% + decoration={% + markings, mark=between positions 5mm and (1-5mm) step 5mm with{% + \draw [\chp@SignalThickness] (-2pt,2pt) -- (2pt,-2pt); + \draw [\chp@SignalThickness] (-1pt,2pt) -- (3pt,-2pt); + }% + }, postaction={decorate}% + }% +} + +%: Short Signal +\tikzset{short signal/.style=% + {% + \chp@SignalThickness,% + decoration={% + markings, mark=at position 0.5 with{% + \draw [\chp@SignalThickness] (-2pt,2pt) -- (2pt,-2pt); + \draw [\chp@SignalThickness] (-1pt,2pt) -- (3pt,-2pt);% + }% + }, postaction={decorate}% + }% +} + +%: Hidden Stream +\tikzset{hidden stream/.style=% + {% + \chp@HiddenStreamStyle% + }% +} + +%: Hidden Component +\tikzset{hidden component/.style=% + {% + \chp@HiddenComponentStyle% + }% +} + +%: Measure +\tikzset{chpmeasure/.style=% + {% + draw=\chp@MeasureColor,% + \chp@MeasureTip-\chp@MeasureTip,% + \chp@MeasureThickness% + }% +} + +%: Instrument +\tikzset{chpinstrumentstyle/.style=% + {% + \chp@InstrumentThickness,% + scale=\chp@InstrumentScale% + }% +} + +%: Block +\tikzset{chpblockstyle/.style=% + {% + \chp@BlockThickness,% + scale=\chp@BlockScale% + }% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%: Process Units + +%: Fluids and Solids Storage +%: Tank +\tikzset{tank/.pic=% + {% + \draw [chpunitstyle] + (-1,-0.915) to [out=270,in=270] + (1,-0.915) -- + (1,0.915) to [out=90,in=90] + (-1,0.915) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-1,0); + \coordinate (-bottom left) at (-1,-0.915); + \coordinate (-bottom) at (0,-1.5); + \coordinate (-bottom right) at (1,-0.915); + \coordinate (-right) at (1,0); + \coordinate (-top right) at (1,0.915); + \coordinate (-top) at (0,1.5); + \coordinate (-top left) at (-1,0.915); + \end{scope} + }% +} +%: Cone Tank +\tikzset{cone tank/.pic=% + {% + \draw [chpunitstyle] + (-1.5,-1.5) -- + (1.5,-1.5) -- + (1.5,1.1) -- + (0,1.5) -- + (-1.5,1.1) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-1.5,0); + \coordinate (-bottom left) at (-1.5,-1.4); + \coordinate (-bottom) at (0,-1.5); + \coordinate (-bottom right) at (1.5,-1.4); + \coordinate (-right) at (1.5,0); + \coordinate (-top right) at (1.5,1.1); + \coordinate (-top) at (0,1.5); + \coordinate (-top left) at (-1.5,1.1); + \end{scope} + }% +} +%: Dome Tank +\tikzset{dome tank/.pic=% + {% + \draw [chpunitstyle] + (-1.5,-1.5) -- + (1.5,-1.5) -- + (1.5,0.7) to [out=90,in=0] + (0,1.5) to [out=180,in=90] + (-1.5,0.7) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-1.5,0); + \coordinate (-bottom left) at (-1.5,-1.4); + \coordinate (-bottom) at (0,-1.5); + \coordinate (-bottom right) at (1.5,-1.4); + \coordinate (-right) at (1.5,0); + \coordinate (-top right) at (1.5,0.7); + \coordinate (-top) at (0,1.5); + \coordinate (-top left) at (-1.5,0.7); + \end{scope} + }% +} +%: Floating Roof Tank +\tikzset{floating roof tank/.pic=% + {% + \draw [chpunitstyle] + (-1.5,1.5) -- + (-1.5,-1.5) -- + (1.5,-1.5) -- + (1.5,1.5); + \draw [chpunitstyle] + (-1.45,1.4) circle (0.05) + (1.45,1.4) circle (0.05) + (-1.4,1.3) rectangle (1.4,1.5); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-1.5,0); + \coordinate (-bottom left) at (-1.5,-1.4); + \coordinate (-bottom) at (0,-1.5); + \coordinate (-bottom right) at (1.5,-1.4); + \coordinate (-right) at (1.5,0); + \coordinate (-top right) at (1.5,1.2); + \coordinate (-top) at (0,1.5); + \coordinate (-top left) at (-1.5,1.2); + \end{scope} + }% +} +%: Bell Gasholder +\tikzset{bell gasholder/.pic=% + {% + \draw [chpunitstyle] + (-1.5,0.5) -- + (-1.5,-1.5) -- + (1.5,-1.5) -- + (1.5,0.5); + \draw [chpunitstyle] + (1.45,-0.5) -- + (1.45,0.7) to [out=90,in=0] + (0,1.45) to [out=180,in=90] + (-1.45,0.7) -- (-1.45,-0.50); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-1.5,0); + \coordinate (-bottom left) at (-1.5,-1.4); + \coordinate (-bottom) at (0,-1.5); + \coordinate (-bottom right) at (1.5,-1.4); + \coordinate (-right) at (1.5,0); + \coordinate (-top right) at (1.45,0.7); + \coordinate (-top) at (0,1.5); + \coordinate (-top left) at (-1.45,0.7); + \end{scope} + }% +} +%: Dry Gasholder +\tikzset{dry gasholder/.pic=% + {% + \draw [chpunitstyle] + (1.5,-1.0) arc + (0:180:1.5) -- cycle; + \draw [chpunitstyle] + (1.5,-1.0) -- + (1.5,1.0) -- + (-1.5,1.0) -- + (-1.5,-1.0); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-1.5,0); + \coordinate (-bottom left) at (-1.5,-0.9); + \coordinate (-bottom) at (0,-1.0); + \coordinate (-bottom right) at (1.5,-0.9); + \coordinate (-right) at (1.5,0); + \coordinate (-top right) at (1.5,1); + \coordinate (-top) at (0,1); + \coordinate (-top left) at (-1.5,1); + \coordinate (-dome top) at (0,0.5); + \end{scope} + }% +} + +%: Fluids Handling +%: Centrifugal Pump +\tikzset{centrifugal pump/.pic=% + {% + \draw [chpunitstyle] + (0,0) circle (0.4) circle (0.05); + \draw [chpunitstyle] + (230.19:0.4) -- + ++(230.19:0.377) -- + ++(1,0) -- ++(129.81:0.377); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.4,0); + \coordinate (-bottom) at (0,-0.6); + \coordinate (-right) at (0.4,0); + \coordinate (-top) at (0,0.4); + \end{scope} + }% +} +%: Rotary Pump +\tikzset{rotary pump/.pic=% + {% + \draw [chpunitstyle] + (-0.4,0) arc + (180:360:0.4) -- + (0.4,0.5) arc + (0:180:0.4) -- cycle + (0,0) circle (0.225) + (0,0.5) circle (0.225); + \draw [chpunitstyle] + (230.19:0.4) -- + ++(230.19:0.377) -- + ++(1,0) -- ++(129.81:0.377); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.4,0.25); + \coordinate (-bottom) at (0,-0.6); + \coordinate (-right) at (0.4,0.25); + \coordinate (-top) at (0,0.9); + \end{scope} + }% +} +%: Liquid Ring Pump +\tikzset{liquid ring pump/.pic=% + {% + \draw [chpunitstyle] + (0,0) circle (0.4) circle (0.325); + \draw [chpunitstyle] + (230.19:0.4) -- + ++(230.19:0.377) -- + ++(1,0) -- ++(129.81:0.377); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.4,0); + \coordinate (-bottom) at (0,-0.6); + \coordinate (-right) at (0.4,0); + \coordinate (-top) at (0,0.4); + \end{scope} + }% +} +%: Reciprocating Pump +\tikzset{reciprocating pump/.pic=% + {% + \draw [chpunitstyle] + (-0.4,-0.4) rectangle (0.4,0.4); + \draw [chpunitstyle] + (-0.3,-0.4) -- (-0.3,-0.6) + (0.3,-0.4) -- (0.3,-0.6) + (-0.5,-0.6) -- (0.5,-0.6); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.4,0); + \coordinate (-bottom) at (0,-0.6); + \coordinate (-right) at (0.4,0); + \coordinate (-top) at (0,0.4); + \end{scope} + }% +} +%: Fan +\tikzset{fan/.pic=% + {% + \draw [chpunitstyle] + (0.4,0.4) -- + (0,0.4) arc + (90:360:0.4) -- cycle + (0,0) circle (0.15); + \draw [chpunitstyle] + (230.19:0.4) -- + ++(230.19:0.377) -- + ++(1,0) -- ++(129.81:0.377); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.4,0); + \coordinate (-bottom) at (0,-0.6); + \coordinate (-right) at (0.4,0); + \coordinate (-top) at (0,0.4); + \coordinate (-outlet) at (0.4,0.4); + \end{scope} + }% +} +%: Centrifugal Compressor +\tikzset{centrifugal compressor/.pic=% + {% + \draw [chpunitstyle] + (-0.9,-0.4) -- + (0.9,-0.2) -- + (0.9,0.2) -- + (-0.9,0.4) -- cycle; + \draw [chpunitstyle] + (-0.8,-0.39) -- (-0.8,-0.6) + (0.8,-0.21) -- (0.8,-0.6) + (-1.0,-0.6) -- (1.0,-0.6); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.9,0); + \coordinate (-bottom) at (0,-0.6); + \coordinate (-right) at (0.9,0); + \coordinate (-inlet bottom) at (-0.9,-0.4); + \coordinate (-outlet bottom) at (0.9,-0.2); + \coordinate (-outlet top) at (0.9,0.2); + \coordinate (-inlet top) at (-0.9,0.4); + \end{scope} + }% +} +%: Rotary Compressor +\tikzset{rotary compressor/.pic=% + {% + \draw [chpunitstyle] + (-0.4,0) arc + (180:360:0.4) -- + (0.4,0.5) arc + (0:180:0.4) -- cycle + (0.325,0.5) arc + (0:180:0.325) to [out=270,in=90] + (0.325,0) arc (360:180:0.325); + \draw [chpunitstyle] + (230.19:0.4) -- + ++(230.19:0.377) -- + ++(1,0) -- ++(129.81:0.377); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.4,0.25); + \coordinate (-bottom) at (0,-0.6); + \coordinate (-right) at (0.4,0.25); + \coordinate (-top) at (0,0.9); + \end{scope} + }% +} +%: Reciprocating Compressor +\tikzset{reciprocating compressor/.pic=% + {% + \draw [chpunitstyle] + (0,0) circle (0.4) + (0.2,-0.346) -- + (1.4,-0.346) -- + (1.4,0.346) -- + (0.2,0.346); + \draw [chpunitstyle] + (0.2,-0.346) -- (0.2,-0.6) + (-0.2,-0.346) -- (-0.2,-0.6) + (1.3,-0.346) -- (1.3,-0.6) + (-0.5,-0.6) -- (1.5,-0.6); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.4,0); + \coordinate (-bottom) at (0.5,-0.6); + \coordinate (-top) at (0,0.4); + \coordinate (-inlet bottom) at (0.8,-0.346); + \coordinate (-outlet) at (1.4,0); + \coordinate (-inlet top) at (0.8,0.346); + \end{scope} + }% +} +%: MultiStage Compressor +\tikzset{multistage compressor/.pic=% + {% + \draw [chpunitstyle] + (0,0) circle (0.4) + (0.2,-0.346) -- + (0.7,-0.346) -- + (0.7,0.346) -- (0.2,0.346) + (0.7,-0.231) -- + (1.1,-0.231) -- + (1.1,0.231) -- (0.7,0.231) + (1.1,-0.116) -- + (1.4,-0.116) -- + (1.4,0.116) -- (1.1,0.116); + \draw [chpunitstyle] + (0.2,-0.346) -- (0.2,-0.6) + (-0.2,-0.346) -- (-0.2,-0.6) + (1.3,-0.116) -- (1.3,-0.6) + (-0.5,-0.6) -- (1.5,-0.6); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.4,0); + \coordinate (-bottom) at (0.5,-0.6); + \coordinate (-top) at (0,0.4); + \coordinate (-first bottom) at (0.45,-0.346); + \coordinate (-second bottom) at (0.9,-0.231); + \coordinate (-third bottom) at (1.25,-0.116); + \coordinate (-outlet) at (1.4,0); + \coordinate (-third top) at (1.25,0.116); + \coordinate (-second top) at (0.9,0.231); + \coordinate (-first top) at (0.45,0.346); + \end{scope} + }% +} +%: Ejector +\tikzset{ejector/.pic=% + {% + \draw [chpunitstyle] + (0.25,-0.1) -- + (0.25,-0.25) -- + (-0.25,-0.25) -- + (-0.25,0.25) -- + (0.25,0.25) -- + (0.25,0.1) -- + (1.25,0.25) -- + (1.25,-0.25) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-main inlet) at (-0.25,0); + \coordinate (-suck inlet bottom) at (0,-0.25); + \coordinate (-outlet) at (1.25,0); + \coordinate (-suck inlet top) at (0,0.25); + \end{scope} + }% +} + +%: Heat Exchangers +%: Heat Exchanger +\tikzset{heat exchanger/.pic=% + {% + \draw [chpunitstyle] + (0,0) circle (0.5) + (-0.5,0) -- + (-0.25,0) -- + (-0.25,0.3) -- + (0.25,-0.3) -- + (0.25,0) -- (0.5,0); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-shell bottom) at (0,-0.5); + \coordinate (-shell top) at (0,0.5); + \coordinate (-pipes left) at (-0.5,0); + \coordinate (-pipes right) at (0.5,0); + \end{scope} + }% +} +%: Two-Phases Heat Exchanger +\tikzset{heat exchanger biphase/.pic=% + {% + \draw [chpunitstyle] + (0,0) circle (0.5) + (30:0.5) -- + ++(-0.6,0) -- + ++(0.3,-0.25) -- + ++(-0.3,-0.25) -- ++(0.6,0); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-shell left) at (-0.5,0); + \coordinate (-shell bottom) at (0,-0.5); + \coordinate (-shell right) at (0.5,0); + \coordinate (-shell top) at (0,0.5); + \coordinate (-pipes bottom) at (-30:0.5); + \coordinate (-pipes top) at (30:0.5); + \end{scope} + }% +} +%: Boiler +\tikzset{boiler/.pic=% + {% + \draw [chpunitstyle] + (0,0) circle (0.5); + \draw [chpunitstyle, -\chp@StreamTip] + (-0.7,0.5) -- + (-0.5,0.5) -- + (0.5,-0.5) -- (0.7,-0.5); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.5,0); + \coordinate (-bottom) at (0,-0.5); + \coordinate (-right) at (0.5,0); + \coordinate (-top) at (0,0.5); + \coordinate (-pipes inlet) at (-0.7,0.5); + \coordinate (-pipes outlet) at (0.7,-0.5); + \end{scope} + }% +} +%: Condenser +\tikzset{condenser/.pic=% + {% + \draw [chpunitstyle] + (0,0) circle (0.5); + \draw [chpunitstyle, -\chp@StreamTip] + (-0.7,-0.5) -- + (-0.5,-0.5) -- + (0.5,0.5) -- + (0.7,0.5); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.5,0); + \coordinate (-bottom) at (0,-0.5); + \coordinate (-right) at (0.5,0); + \coordinate (-top) at (0,0.5); + \coordinate (-pipes inlet) at (-0.7,-0.5); + \coordinate (-pipes outlet) at (0.7,0.5); + \end{scope} + }% +} +%: Air Heat Exchanger +\tikzset{air heat exchanger/.pic=% + {% + \draw [chpunitstyle] + (-0.5,-0.5) rectangle (0.5,0.5) + (0,0) circle (0.4) + (-0.3,0) -- + (-0.3,-0.15) -- + (0.3,0.15) -- + (0.3,0) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.5,0); + \coordinate (-bottom) at (0,-0.5); + \coordinate (-right) at (0.5,0); + \coordinate (-top) at (0,0.5); + \end{scope} + }% +} +%: Tube Bundle Heat Exchanger +\tikzset{tube bundle heat exchanger/.pic=% + {% + \draw [chpunitstyle] + (-1.0,-0.3) -- + (0.7,-0.3) arc + (270:450:0.3) -- + (-1.0,0.3) -- cycle; + \foreach \i in {1, 2, ...,10} {% + \draw [chpunitstyle] + (-0.6,-0.3 + 0.06*\i) -- ++(1.2,0); + } + \draw [chpunitstyle] + (-1.0,-0.35) -- (-1.0,-0.3) + (-1.0,0.35) -- (-1.0,0.3) + (-0.6,-0.35) -- (-0.6,0.35) + (0.6,-0.35) -- (0.6,0.35); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-1.0,0); + \coordinate (-right) at (1.0,0); + \coordinate (-head bottom) at (-0.8,-0.3); + \coordinate (-head top) at (-0.8,0.3); + \coordinate (-shell bottom left) at (-0.5,-0.3); + \coordinate (-shell bottom) at (0,-0.3); + \coordinate (-shell bottom right) at (0.5,-0.3); + \coordinate (-shell top right) at (0.5,0.3); + \coordinate (-shell top) at (0,0.3); + \coordinate (-shell top left) at (-0.5,0.3); + \end{scope} + }% +} +%: Plate Heat Exchanger +\tikzset{plate heat exchanger/.pic=% + {% + \draw [chpunitstyle] + (-0.5,-0.7) rectangle + (0.5,0.7); + \foreach \i in {1, 2, ..., 4} {% + \draw [chpunitstyle] + (-0.5 + 0.2*\i,-0.7) -- ++(0,1.4); + } + \draw [chpunitstyle] + (-0.5,-0.6) -- (0.5,0.6); + \draw [chpunitstyle] + (-0.5,-0.75) -- (-0.5,-0.7) + (-0.5,0.7) -- (-0.5,0.75) + (0.5,-0.75) -- (0.5,-0.7) + (0.5,0.7) -- (0.5,0.75); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.5,0); + \coordinate (-bottom) at (0,-0.7); + \coordinate (-right) at (0.5,0); + \coordinate (-top) at (0,0.7); + \coordinate (-inner left) at (-0.5,-0.6); + \coordinate (-inner right) at (0.5,0.6); + \coordinate (-outer left) at (-0.5,0.6); + \coordinate (-outer right) at (0.5,-0.6); + \end{scope} + }% +} +%: Spiral Heat Exchanger +\tikzset{spiral heat exchanger/.pic=% + {% + \draw [chpunitstyle] + (0,0) circle (0.7); + \draw [chpunitstyle] + (-0.7,0) -- (0.001,0); + \draw [chpunitstyle] + plot [variable=\t, domain=0:720, hobby] + (\t:\t*0.7/720); + \draw [chpunitstyle, dashed] + (0,0) -- (0,0.7); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-inner center) at (-0.7,0); + \coordinate (-inner edge) at (0.7,0); + \coordinate (-outer center) at (0,0.7); + \coordinate (-outer edge) at (0,-0.7); + \end{scope} + }% +} +%: Pipe Furnace +\tikzset{pipe furnace/.pic=% + {% + \draw [chpunitstyle] + (-1.0,-0.5) -- + (1.0,-0.5) -- + (1.0,0.5) -- + (0.2,0.75) -- + (0.2,1.5) -- + (-0.2,1.5) -- + (-0.2,0.75) -- + (-1.0,0.5) -- cycle; + \draw [chpunitstyle] + (-1.0,0) -- + (-0.75,0) -- + (-0.6,-0.4) -- + (-0.3,0.4) -- + (0,-0.4) -- + (0.3,0.4) -- + (0.6,-0.4) -- + (0.75,0) -- (1.0,0); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-bottom) at (0,-0.5); + \coordinate (-top) at (0,1.5); + \coordinate (-pipes left) at (-1.0,0); + \coordinate (-pipes right) at (1.0,0); + \end{scope} + }% +} + +%: Separators +%: Steam Trap +\tikzset{steam trap/.pic=% + {% + \draw [chpunitstyle] + (45:0.15) arc (45:225:0.15); + \draw [chpunitstyle, fill] + (225:0.15) arc (225:405:0.15) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.15,0); + \coordinate (-bottom) at (0,-0.15); + \coordinate (-right) at (0.15,0); + \coordinate (-top) at (0,0.15); + \end{scope} + }% +} +%: Gas-Liquid Separator +\tikzset{gas-liquid separator/.pic=% + {% + \draw [chpunitstyle] + (-0.8,-1.032) to [out=270,in=270] + (0.8,-1.032) -- + (0.8,1.032) to [out=90,in=90] + (-0.8,1.032) -- cycle; + \draw [chpunitstyle, densely dotted] + (-0.755,1.2) -- (0.755,1.2); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-bottom left) at (-0.8,-1.032); + \coordinate (-bottom right) at (0.8,-1.032); + \coordinate (-top right) at (0.8,1.032); + \coordinate (-top left) at (-0.8,1.032); + \coordinate (-stirrer) at (0.5,1.5); + \coordinate (-anchor) at (0,0); + \coordinate (-inlet left) at (-0.8,0); + \coordinate (-inlet right) at (0.8,0); + \coordinate (-gas outlet) at (0,1.5); + \coordinate (-liquid outlet) at (0,-1.5); + \end{scope} + }% +} +%: Cyclone +\tikzset{cyclone/.pic=% + {% + \draw [chpunitstyle] + (-0.3,0.25) rectangle + (0.3,0) -- + (0,-1.0) -- (-0.3,0); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-inlet left) at (-0.3,0.125); + \coordinate (-inlet right) at (0.3,0.125); + \coordinate (-gas outlet) at (0,0.25); + \coordinate (-solid outlet) at (0,-1.0); + \end{scope} + }% +} +%: Stratifier +\tikzset{stratifier/.pic=% + {% + \draw [chpunitstyle] + (1.032,-0.8) to [out=0,in=0] + (1.032,0.8) -- + (-1.032,0.8) to [out=180,in=180] + (-1.032,-0.8) -- cycle; + \draw [chpunitstyle] + (-0.9,-0.85) -- (-0.9,0.3) + (0.9,-0.85) -- (0.9,0) + (0.6,0.85) -- (0.6,0.7) + (0.6,0.6) -- (0.6,-0.6); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-1.5,0); + \coordinate (-bottom) at (0,-0.8); + \coordinate (-right) at (1.5,0); + \coordinate (-top right) at (1.032,0.8); + \coordinate (-top left) at (-1.032,0.8); + \coordinate (-inlet) at (0,0.8); + \coordinate (-light outlet) at (-1.032,-0.8); + \coordinate (-heavy outlet) at (1.032,-0.8); + \end{scope} + }% +} +%: Settler +\tikzset{settler/.pic=% + {% + \draw [chpunitstyle] + (-1.5,-0.2) -- + (0,-0.8) -- + (1.5,-0.2) -- + (1.5,0.8) -- + (-1.5,0.8) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-inlet left) at (-1.5,-0.2); + \coordinate (-inlet right) at (1.5,-0.2); + \coordinate (-inlet top) at (0,0.8); + \coordinate (-liquid outlet left) at (-1.5,0.8); + \coordinate (-liquid outlet right) at (1.5,0.8); + \coordinate (-solid outlet) at (0,-0.8); + \end{scope} + }% +} +%: Scrubber +\tikzset{scrubber/.pic=% + {% + \draw [chpunitstyle] + (-0.3,-0.25) -- + (0,-0.75) -- + (0.3,-0.25) -- + (0.3,0.55) to [out=90,in=0] + (0,0.75) to [out=180,in=90] + (-0.3,0.55) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-gas inlet left) at (-0.3,-0.25); + \coordinate (-gas inlet right) at (0.3,-0.25); + \coordinate (-liquid inlet left) at (-0.3,0.55); + \coordinate (-liquid inlet right) at (0.3,0.55); + \coordinate (-gas outlet) at (0,0.75); + \coordinate (-liquid outlet) at (0,-0.75); + \end{scope} + }% +} +%: Kettle Bolier +\tikzset{kettle boiler/.pic=% + {% + \draw [chpunitstyle] + (-1.0,-0.3) -- + (0.7,-0.3) to [out=0,in=270] + (1.0,0.2) to [out=90,in=0] + (0.7,0.7) -- + (-0.3,0.7) -- + (-0.6,0.3) -- + (-1.0,0.3) -- cycle; + \draw [chpunitstyle] + (-1.0,-0.35) -- (-1.0,-0.3) + (-1.0,0.35) -- (-1.0,0.3) + (-0.6,-0.35) -- (-0.6,0.35) + (0.6,-0.35) -- (0.6,0.35); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-1.0,0); + \coordinate (-right) at (1.0,0.2); + \coordinate (-inlet) at (0,-0.3); + \coordinate (-gas outlet) at (0.2,0.7); + \coordinate (-liquid outlet) at (0.7,-0.3); + \coordinate (-head bottom) at (-0.8,-0.3); + \coordinate (-head top) at (-0.8,0.3); + \end{scope} + }% +} +%: Tube Bundle Evaporator +\tikzset{tube bundle evaporator/.pic=% + {% + \draw [chpunitstyle] + (-0.8,-1.032) to [out=270,in=270] + (0.8,-1.032) -- + (0.8,1.032) to [out=90,in=90] + (-0.8,1.032) -- cycle; + \foreach \i in {0, 1, ..., 10} {% + \draw [chpunitstyle] + (-0.85,-0.9 + 0.08*\i) -- ++(1.7,0); + } + \draw [chpunitstyle] + (-0.85,-0.95) -- (-0.85,-0.05) + (0.85,-0.95) -- (0.85,-0.05); + \draw [chpunitstyle, densely dotted] + (-0.755,1.2) -- (0.755,1.2); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-bottom left) at (-0.8,-1.032); + \coordinate (-bottom right) at (0.8,-1.032); + \coordinate (-top right) at (0.8,1.032); + \coordinate (-top left) at (-0.8,1.032); + \coordinate (-inlet left) at (-0.8,0); + \coordinate (-inlet right) at (0.8,0); + \coordinate (-gas outlet) at (0,1.5); + \coordinate (-liquid outlet) at (0,-1.5); + \coordinate (-pipes left) at (-0.85,-0.5); + \coordinate (-pipes right) at (0.85,-0.5); + \end{scope} + }% +} +%: Basket Evaporator +\tikzset{basket evaporator/.pic=% + {% + \draw [chpunitstyle] + (-0.8,-1.032) to [out=270,in=270] + (0.8,-1.032) -- + (0.8,1.032) to [out=90,in=90] + (-0.8,1.032) -- cycle; + \foreach \i in {1, 2, ...,19} {% + \draw [chpunitstyle] + (-0.8 + 0.08*\i,-0.9) -- ++(0,0.8); + } + \draw [chpunitstyle] + (-0.85,-0.9) -- (0.85,-0.9) + (-0.85,-0.1) -- (0.85,-0.1); + \draw [chpunitstyle, densely dotted] + (-0.755,1.2) -- (0.755,1.2); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-bottom left) at (-0.8,-1.032); + \coordinate (-bottom right) at (0.8,-1.032); + \coordinate (-top right) at (0.8,1.032); + \coordinate (-top left) at (-0.8,1.032); + \coordinate (-inlet left) at (-0.8,0); + \coordinate (-inlet right) at (0.8,0); + \coordinate (-gas outlet) at (0,1.5); + \coordinate (-liquid outlet) at (0,-1.5); + \coordinate (-shell top left) at (-0.8,-0.2); + \coordinate (-shell left) at (-0.8,-0.5); + \coordinate (-shell bottom left) at (-0.8,-0.8); + \coordinate (-shell bottom right) at (0.8,-0.8); + \coordinate (-shell right) at (0.8,-0.5); + \coordinate (-shell top right) at (0.8,-0.2); + \end{scope} + }% +} +%: Climbing Film Evaporator +\tikzset{climbing film evaporator/.pic=% + {% + \draw [chpunitstyle] + (-0.4,0.4) -- + (-0.4,-1.2) to [out=270,in=180] + (0,-1.5) to [out=0,in=270] + (0.4,-1.2) -- (0.4,0.4) + (0.4,0.3) -- + (0.8,0.6) -- + (0.8,1.032) to [out=90,in=90] + (-0.8,1.032) -- + (-0.8,0.6) -- (-0.4,0.3); + \foreach \i in {1, 2, ...,10} {% + \draw [chpunitstyle] + (-0.4 + 0.08*\i,-1.2) -- ++(0,1.5); + } + \draw [chpunitstyle] + (-0.45,0.3) -- (0.45,0.3) + (-0.45,-1.2) -- (0.45,-1.2); + \draw [chpunitstyle, -\chp@StreamTip] + (-0.5,0.37) -- + (-0.6,0.23) -- + (-0.6,-1.35) -- (-0.35,-1.35); + \draw [chpunitstyle, densely dotted] + (-0.755,1.2) -- (0.755,1.2); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-top right) at (0.8,1.032); + \coordinate (-top left) at (-0.8,1.032); + \coordinate (-inlet left) at (-0.8,0.6); + \coordinate (-inlet right) at (0.8,0.6); + \coordinate (-gas outlet) at (0,1.5); + \coordinate (-liquid outlet) at (0,-1.5); + \coordinate (-shell top left) at (-0.4,0.2); + \coordinate (-shell left) at (-0.4,-0.45); + \coordinate (-shell bottom left) at (-0.4,-1.1); + \coordinate (-shell bottom right) at (0.4,-1.1); + \coordinate (-shell right) at (0.4,-0.45); + \coordinate (-shell top right) at (0.4,0.2); + \end{scope} + }% +} +%: Tube Bundle Crystallizer +\tikzset{tube bundle crystallizer/.pic=% + {% + \draw [chpunitstyle] + (-0.8,-1.032) -- + (0,-1.5) -- + (0.8,-1.032) -- + (0.8,1.032) to [out=90,in=90] + (-0.8,1.032) -- cycle; + \foreach \i in {0, 1, ..., 10} {% + \draw [chpunitstyle] + (-0.85,-0.9 + 0.08*\i) -- ++(1.7,0); + } + \draw [chpunitstyle] + (-0.85,-0.95) -- (-0.85,-0.05) + (0.85,-0.95) -- (0.85,-0.05); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-bottom left) at (-0.8,-1.032); + \coordinate (-bottom right) at (0.8,-1.032); + \coordinate (-top right) at (0.8,1.032); + \coordinate (-top left) at (-0.8,1.032); + \coordinate (-inlet left) at (-0.8,0); + \coordinate (-inlet right) at (0.8,0); + \coordinate (-liquid outlet) at (0,1.5); + \coordinate (-solid outlet) at (0,-1.5); + \coordinate (-pipes left) at (-0.85,-0.5); + \coordinate (-pipes right) at (0.85,-0.5); + \end{scope} + }% +} +%: Stirred Crystallizer +\tikzset{stirred crystallizer/.pic=% + {% + \draw [chpunitstyle] + (-0.8,-1.032) -- + (0,-1.5) -- + (0.8,-1.032) -- + (0.8,1.032) to [out=90,in=90] + (-0.8,1.032) -- cycle; + \draw [chpunitstyle, yshift=-0.25cm, xslant=0.285] + (0,1.75) -- + (0,0) to [out=150,in=90] + (-0.5,0) to [out=270,in=210] + (0,0) to [out=30,in=90] + (0.5,0) to [out=270,in=330] (0,0); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-bottom left) at (-0.8,-1.032); + \coordinate (-bottom right) at (0.8,-1.032); + \coordinate (-top right) at (0.8,1.032); + \coordinate (-top left) at (-0.8,1.032); + \coordinate (-inlet left) at (-0.8,0); + \coordinate (-inlet right) at (0.8,0); + \coordinate (-liquid outlet) at (0,1.5); + \coordinate (-solid outlet) at (0,-1.5); + \coordinate (-shaft) at (0.5,1.5); + \end{scope} + }% +} + +%: Columns +%: Column +\tikzset{pics/column/.style=% + {% + code=% + {% + \draw [chpunitstyle] + (-0.5,-2.7) to [out=270,in=270] + (0.5,-2.7) -- + (0.5,2.7) to [out=90,in=90] + (-0.5,2.7) -- cycle; + \ifthenelse{\equal{#1}{empty}}{% + \relax% + }% + {% + \relax% + } + \ifthenelse{\equal{#1}{trayed}}{% + \foreach \i in {0, 1, ..., 24} {% + \draw [chpunitstyle] + (-0.5,-2.4 + 0.2*\i) -- (0.5,-2.4 + 0.2*\i); + }% + }% + {% + \relax% + } + \ifthenelse{\equal{#1}{packed}}{% + \draw [chpunitstyle, join=bevel] + (-0.5,-2.4) -- + (0.5,2.4) -- + (-0.5,2.4) -- + (0.5,-2.4) -- cycle; + }% + {% + \relax% + } + \ifthenelse{\equal{#1}{packed double}}{% + \draw [chpunitstyle, join=bevel] + (-0.5,-2.4) -- + (0.5,-0.2) -- + (-0.5,-0.2) -- + (0.5,-2.4) -- cycle; + \draw [chpunitstyle, join=bevel] + (-0.5,2.4) -- + (0.5,0.2) -- + (-0.5,0.2) -- + (0.5,2.4) -- cycle; + }% + {% + \relax% + } + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.5,0); + \coordinate (-bottom left) at (-0.5,-2.6); + \coordinate (-bottom) at (0,-3); + \coordinate (-bottom right) at (0.5,-2.6); + \coordinate (-right) at (0.5,0); + \coordinate (-top right) at (0.5,2.6); + \coordinate (-top) at (0,3); + \coordinate (-top left) at (-0.5,2.6); + \end{scope} + }% + }% +} + +%: Reactors +%: Stirred Reactor +\tikzset{stirred reactor/.pic=% + {% + \draw [chpunitstyle] + (-0.8,-0.732) to [out=270,in=270] + (0.8,-0.732) -- + (0.8,0.732) to [out=90,in=90] + (-0.8,0.732) -- cycle; + \draw [chpunitstyle, yshift=-0.25cm, xslant=0.285] + (0,1.75) -- + (0,0) to [out=150,in=90] + (-0.5,0) to [out=270,in=210] + (0,0) to [out=30,in=90] + (0.5,0) to [out=270,in=330] (0,0); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.8,0); + \coordinate (-bottom left) at (-0.8,-0.732); + \coordinate (-bottom) at (0,-1.2); + \coordinate (-bottom right) at (0.8,-0.732); + \coordinate (-right) at (0.8,0); + \coordinate (-top right) at (0.8,0.732); + \coordinate (-top) at (0,1.2); + \coordinate (-top left) at (-0.8,0.732); + \coordinate (-shaft) at (0.5,1.5); + \end{scope} + }% +} +%: Packed Bed Reactor +\tikzset{packed bed reactor/.pic=% + {% + \draw [chpunitstyle] + (-1.0,-0.4) rectangle (1.0,0.4) + (-1.0,-0.45) -- (-1.0,0.45) + (1.0,-0.45) -- (1.0,0.45); + \draw [chpunitstyle, join=bevel] + (-0.8,0.4) -- + (0.8,-0.4) -- + (0.8,0.4) -- + (-0.8,-0.4) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-1,0); + \coordinate (-bottom) at (0,-0.4); + \coordinate (-right) at (1,0); + \coordinate (-top) at (0,0.4); + \coordinate (-utility bottom left) at (-0.9,-0.4); + \coordinate (-utility bottom right) at (0.9,-0.4); + \coordinate (-utility top right) at (0.9,0.4); + \coordinate (-utility top left) at (-0.9,0.4); + \end{scope} + }% +} +%: Fluidized Bed Reactor +\tikzset{fluidized bed reactor/.pic=% + {% + \draw [chpunitstyle] + (-0.8,-0.4) -- + (-0.2,-0.8) -- + (-0.2,-1.2) -- + (0.2,-1.2) -- + (0.2,-0.8) -- + (0.8,-0.4) -- + (0.8,0.732) to [out=90,in=90] + (-0.8,0.732) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.8,0); + \coordinate (-bottom left) at (-0.8,-0.4); + \coordinate (-bottom) at (0,-1.2); + \coordinate (-bottom right) at (0.8,-0.4); + \coordinate (-right) at (0.8,0); + \coordinate (-top right) at (0.8,0.732); + \coordinate (-top) at (0,1.2); + \coordinate (-top left) at (-0.8,0.732); + \end{scope} + }% +} +%: Tube Bundle Reactor +\tikzset{tube bundle reactor/.pic=% + {% + \draw [chpunitstyle] + (-0.8,-0.732) to [out=270,in=270] + (0.8,-0.732) -- + (0.8,0.732) to [out=90,in=90] + (-0.8,0.732) -- cycle; + \foreach \i in {1, 2, ...,19} {% + \draw [chpunitstyle] + (-0.8 + 0.08*\i,-0.65) -- ++(0,1.3); + } + \draw [chpunitstyle] + (-0.85,-0.65) -- (0.85,-0.65) + (-0.85,0.65) -- (0.85,0.65); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.8,0); + \coordinate (-bottom left) at (-0.8,-0.732); + \coordinate (-bottom) at (0,-1.2); + \coordinate (-bottom right) at (0.8,-0.732); + \coordinate (-right) at (0.8,0); + \coordinate (-top right) at (0.8,0.732); + \coordinate (-top) at (0,1.2); + \coordinate (-top left) at (-0.8,0.732); + \end{scope} + }% +} +%: Associative Pics for Reactors +%: Tank Reactor +\tikzset{tank reactor/.pic=% + {% + \draw [chpunitstyle] + (-0.8,-0.732) to [out=270,in=270] + (0.8,-0.732) -- + (0.8,0.732) to [out=90,in=90] + (-0.8,0.732) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.8,0); + \coordinate (-bottom left) at (-0.8,-0.732); + \coordinate (-bottom) at (0,-1.2); + \coordinate (-bottom right) at (0.8,-0.732); + \coordinate (-right) at (0.8,0); + \coordinate (-top right) at (0.8,0.732); + \coordinate (-top) at (0,1.2); + \coordinate (-top left) at (-0.8,0.732); + \end{scope} + }% +} +%: Jacket +\tikzset{jacket/.pic=% + {% + \draw [chpunitstyle] + (-0.8,0.7) -- + (-1.0,0.5) -- + (-1.0,-0.732) to [out=270,in=180] + (-0.15,-1.3) -- (-0.1,-1.2) + (0.8,0.7) -- + (1.0,0.5) -- + (1.0,-0.732) to [out=270,in=0] + (0.15,-1.3) -- (0.1,-1.2); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-1.0,0); + \coordinate (-bottom left) at (-0.15,-1.3); + \coordinate (-bottom right) at (0.15,-1.3); + \coordinate (-right) at (1.0,0); + \coordinate (-top right) at (1.0,0.5); + \coordinate (-top left) at (-1.0,0.5); + \end{scope} + }% +} +%: Stirrer +\tikzset{stirrer/.pic=% + {% + \draw [chpunitstyle, yshift=-0.25cm, xslant=0.285] + (0,1.75) -- + (0,0) to [out=150,in=90] + (-0.5,0) to [out=270,in=210] + (0,0) to [out=30,in=90] + (0.5,0) to [out=270,in=330] (0,0); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-shaft) at (0.5,1.5); + \end{scope} + }% +} +%: Coil +\tikzset{coil/.pic=% + {% + \draw [chpunitstyle, join=bevel] + (1.0,0.7) -- + (-0.7,0.7) -- + (0.7,0.467) -- + (-0.7,0.233) -- + (0.7,0) -- + (-0.7,-0.233) -- + (0.7,-0.467) -- + (-0.7,-0.7) -- (1.0,-0.7); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-bottom) at (1.0,-0.7); + \coordinate (-top) at (1.0,0.7); + \end{scope} + }% +} +%: Sprayer +\tikzset{sprayer/.pic=% + {% + \draw [chpunitstyle] + (0,0) -- + (1.4,0) -- ++(0.1,-0.1) + (0.2,0) -- ++(-0.1,-0.1) + (0.2,0) -- ++(0.1,-0.1) + (0.6,0) -- ++(-0.1,-0.1) + (0.6,0) -- ++(0.1,-0.1) + (1.0,0) -- ++(-0.1,-0.1) + (1.0,0) -- ++(0.1,-0.1) + (1.4,0) -- ++(-0.1,-0.1); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \end{scope} + }% +} +%: Bubbler +\tikzset{bubbler/.pic=% + {% + \draw [chpunitstyle] + (0,0) -- + (1.4,0) -- ++(0.1,0.1) + (0.2,0) -- ++(-0.1,0.1) + (0.2,0) -- ++(0.1,0.1) + (0.6,0) -- ++(-0.1,0.1) + (0.6,0) -- ++(0.1,0.1) + (1.0,0) -- ++(-0.1,0.1) + (1.0,0) -- ++(0.1,0.1) + (1.4,0) -- ++(-0.1,0.1); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \end{scope} + }% +} +%: Packing +\tikzset{packing/.pic=% + {% + \draw [chpunitstyle, join=bevel] + (-0.8,-0.7) -- + (0.8,0.7) -- + (-0.8,0.7) -- + (0.8,-0.7) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \end{scope} + }% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%: Process Utilities + +%: Valves +%: Lamination Valve +\tikzset{lamination valve/.pic=% + {% + \draw [chpunitstyle] + (-0.2,-0.1) rectangle (0.2,0.1) + (-0.2,0.1) -- (0.2,0) + (-0.2,-0.1) -- (0.2,0); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-inlet) at (-0.2,0); + \coordinate (-outlet) at (0.2,0); + \end{scope} + }% +} +%: Valve +\tikzset{pics/valve/.style=% + {% + code=% + {% + \ifthenelse{\equal{#1}{main}}{% + \let\chp@ValveThickness\chp@MainStreamThickness% + }% + {% + \relax% + } + \ifthenelse{\equal{#1}{secondary}}{% + \let\chp@ValveThickness\chp@SecondaryStreamThickness% + }% + {% + \relax% + } + \ifthenelse{\equal{#1}{utility}}{% + \let\chp@ValveThickness\chp@UtilityStreamThickness% + }% + {% + \relax% + } + \draw [\chp@ValveThickness, scale=\chp@UnitScale] + (-0.2,-0.1) -- + (-0.2,0.1) -- + (0.2,-0.1) -- + (0.2,0.1) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.2,0); + \coordinate (-right) at (0.2,0); + \end{scope} + }% + }% +} +%: Three-Way Valve +\tikzset{pics/valve triple/.style=% + {% + code=% + {% + \ifthenelse{\equal{#1}{main}}{% + \let\chp@ValveThickness\chp@MainStreamThickness% + }% + {% + \relax% + } + \ifthenelse{\equal{#1}{secondary}}{% + \let\chp@ValveThickness\chp@SecondaryStreamThickness% + }% + {% + \relax% + } + \ifthenelse{\equal{#1}{utility}}{% + \let\chp@ValveThickness\chp@UtilityStreamThickness% + }% + {% + \relax% + } + \draw [\chp@ValveThickness, scale=\chp@UnitScale] + (0,0) -- + (-0.2,-0.1) -- + (-0.2,0.1) -- + (0,0) -- + (-0.1,0.2) -- + (0.1,0.2) -- + (0,0) -- + (0.2,-0.1) -- + (0.2,0.1) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.2,0); + \coordinate (-right) at (0.2,0); + \coordinate (-top) at (0,0.2); + \end{scope} + }% + }% +} +%: Four-Way Valve +\tikzset{pics/valve quadruple/.style=% + {% + code=% + {% + \ifthenelse{\equal{#1}{main}}{% + \let\chp@ValveThickness\chp@MainStreamThickness% + }% + {% + \relax% + } + \ifthenelse{\equal{#1}{secondary}}{% + \let\chp@ValveThickness\chp@SecondaryStreamThickness% + }% + {% + \relax% + } + \ifthenelse{\equal{#1}{utility}}{% + \let\chp@ValveThickness\chp@UtilityStreamThickness% + }% + {% + \relax% + } + \draw [\chp@ValveThickness, scale=\chp@UnitScale] + (-0.2,-0.1) -- + (-0.2,0.1) -- + (0.2,-0.1) -- + (0.2,0.1) -- cycle + (-0.1,0.2) -- + (0.1,0.2) -- + (-0.1,-0.2) -- + (0.1,-0.2) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.2,0); + \coordinate (-bottom) at (0,-0.2); + \coordinate (-right) at (0.2,0); + \coordinate (-top) at (0,0.2); + \end{scope} + }% + }% +} +%: Safety Valve +\tikzset{pics/safety valve/.style=% + {% + code=% + {% + \ifthenelse{\equal{#1}{main}}{% + \let\chp@ValveThickness\chp@MainStreamThickness% + }% + {% + \relax% + } + \ifthenelse{\equal{#1}{utility}}{% + \let\chp@ValveThickness\chp@UtilityStreamThickness% + }% + {% + \relax% + } + \draw [\chp@ValveThickness, scale=\chp@UnitScale] + (0,0) -- + (-0.1,-0.2) -- + (0.1,-0.2) -- cycle + (0,0) -- + (0.2,-0.1) -- + (0.2,0.1) -- cycle; + \draw [\chp@ValveThickness, scale=\chp@UnitScale, fill] + (0,0) circle (0.025); + \draw [\chp@ValveThickness, scale=\chp@UnitScale] + (0,0) -- (0,0.3) + (-0.05,0.26) -- (0.05,0.24) + (-0.05,0.21) -- (0.05,0.19) + (-0.05,0.16) -- (0.05,0.14); + \draw [\chp@ValveThickness, scale=\chp@UnitScale] + (0.2,0) -- (0.4,0) + (0.35,0.1) -- (0.45,-0.1); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-inlet) at (0,-0.2); + \coordinate (-outlet) at (0.4,0); + \end{scope} + }% + }% +} + +%: Process Streams +%: Inlet +\tikzset{inlet/.pic=% + {% + \draw [chpunitstyle] + (0,0) circle (0.25); + \draw [chpunitstyle, fill] + (0.25,0) -- (150:0.25) + (0.25,0) -- (-150:0.25) arc (210:150:0.25); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.25,0); + \coordinate (-bottom) at (0,-0.25); + \coordinate (-stream) at (0.25,0); + \coordinate (-top) at (0,0.25); + \end{scope} + }% +} +%: Outlet +\tikzset{outlet/.pic=% + {% + \draw [chpunitstyle] + (0,0) circle (0.25) + (0.25,0) -- (150:0.25) + (0.25,0) -- (-150:0.25); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-stream) at (-0.25,0); + \coordinate (-bottom) at (0,-0.25); + \coordinate (-right) at (0.25,0); + \coordinate (-top) at (0,0.25); + \end{scope} + }% +} + +%: Instrumentation +%: Instrument +\tikzset{pics/instrument/.style=% + {% + code=% + {% + \draw [chpinstrumentstyle] + (0,0) circle (0.5); + \node [font=\chp@InstrumentFontSize] at (0,0) {#1}; + \begin{scope} [scale=\chp@InstrumentScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.5,0); + \coordinate (-bottom) at (0,-0.5); + \coordinate (-right) at (0.5,0); + \coordinate (-top) at (0,0.5); + \end{scope} + }% + }% +} +%: Controller +\tikzset{pics/controller/.style=% + {% + code=% + {% + \draw [chpinstrumentstyle] + (-0.5,-0.5) rectangle (0.5,0.5); + \node [font=\chp@InstrumentFontSize] at (0,0) {#1}; + \begin{scope} [scale=\chp@InstrumentScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-0.5,0); + \coordinate (-bottom) at (0,-0.5); + \coordinate (-right) at (0.5,0); + \coordinate (-top) at (0,0.5); + \end{scope} + }% + }% +} +%: Actuator +\tikzset{actuator/.pic=% + {% + \draw [\chp@InstrumentThickness, scale=\chp@UnitScale] + (0,0) -- (0,0.2) + (0.1,0.2) arc (0:180:0.1) -- cycle; + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \coordinate (-top) at (0,0.3); + \end{scope} + }% +} + +%: Nozzles +%: Input +\tikzset{input/.pic=% + {% + \draw [chpunitstyle] + (0,0) circle (0.05); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \end{scope} + }% +} +%: Output +\tikzset{output/.pic=% + {% + \draw [chpunitstyle, fill] + (0,0) circle (0.05); + \begin{scope} [scale=\chp@UnitScale] + \coordinate (-anchor) at (0,0); + \end{scope} + }% +} + +%: Blocks +%: Block +\tikzset{pics/block/.style=% + {% + code=% + {% + \draw [chpblockstyle] + (-1.5,-0.75) rectangle (1.5,0.75); + \node [align=center, font=\chp@BlockFontSize] at (0,0) {#1}; + \begin{scope} [scale=\chp@BlockScale] + \coordinate (-anchor) at (0,0); + \coordinate (-left) at (-1.5,0); + \coordinate (-bottom) at (0,-0.75); + \coordinate (-right) at (1.5,0); + \coordinate (-top) at (0,0.75); + \end{scope} + }% + }% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\endinput % End of the Package \ No newline at end of file diff --git a/slides/slides_ode/colors.tex b/slides/slides_ode/colors.tex new file mode 100755 index 00000000..b9c81b31 --- /dev/null +++ b/slides/slides_ode/colors.tex @@ -0,0 +1,28 @@ +% Pantone 534: global +\definecolor{ugentblue}{RGB}{36,71,127} +% Pantone 130: generic colour +\definecolor{ugentyellow}{RGB}{250,178,10} + + +% Pantone 103c: Faculty of Literature & Philosophy +\definecolor{ugent-lw}{RGB}{214,198,0} +% Pantone 485c: Faculty of Law +\definecolor{ugent-re}{RGB}{238,39,34} +% Pantone 292c: Faculty of Science +\definecolor{ugent-we}{RGB}{131,194,236} +% Pantone 702: Faculty of Medicine and Health Sciences +\definecolor{ugent-ge}{RGB}{232,80,118} +% Pantone 272c: Faculty of Engineering and Architecture +\definecolor{ugent-tw}{RGB}{116,121,197} +% Pantone 556c: Faculty of Economics and Business Administration +\definecolor{ugent-eb}{RGB}{113,165,136} +% Pantone 2583c: Faculty of Veterinary Medicine +\definecolor{ugent-di}{RGB}{145,94,182} +% Pantone 1655c: Faculty of Psychology and Educational Sciences +\definecolor{ugent-pp}{RGB}{244,106,37} +% Pantone 3262c: Faculty of Bioscience Engineering +\definecolor{ugent-la}{RGB}{74,194,182} +% Pantone purple: Faculty of Pharmaceutical Sciences +\definecolor{ugent-fw}{RGB}{163,43,155} +% Pantone 375c: Faculty of Political and Social Sciences +\definecolor{ugent-ps}{RGB}{159,217,93} diff --git a/slides/slides_ode/figs/anaerobic_fermentation.png b/slides/slides_ode/figs/anaerobic_fermentation.png new file mode 100644 index 00000000..ff794b47 Binary files /dev/null and b/slides/slides_ode/figs/anaerobic_fermentation.png differ diff --git a/slides/slides_ode/figs/bel20.jpeg b/slides/slides_ode/figs/bel20.jpeg new file mode 100644 index 00000000..efa1ae5a Binary files /dev/null and b/slides/slides_ode/figs/bel20.jpeg differ diff --git a/slides/slides_ode/figs/bike_sharing_model.png b/slides/slides_ode/figs/bike_sharing_model.png new file mode 100644 index 00000000..b2d132a3 Binary files /dev/null and b/slides/slides_ode/figs/bike_sharing_model.png differ diff --git a/slides/slides_ode/figs/bos.png b/slides/slides_ode/figs/bos.png new file mode 100755 index 00000000..482a5795 Binary files /dev/null and b/slides/slides_ode/figs/bos.png differ diff --git a/slides/slides_ode/figs/brownian_motions_graph.png b/slides/slides_ode/figs/brownian_motions_graph.png new file mode 100644 index 00000000..90e2bd71 Binary files /dev/null and b/slides/slides_ode/figs/brownian_motions_graph.png differ diff --git a/slides/slides_ode/figs/discrete_jump_SIR.png b/slides/slides_ode/figs/discrete_jump_SIR.png new file mode 100644 index 00000000..a68a04fc Binary files /dev/null and b/slides/slides_ode/figs/discrete_jump_SIR.png differ diff --git a/slides/slides_ode/figs/fermenter_model.png b/slides/slides_ode/figs/fermenter_model.png new file mode 100755 index 00000000..4efdfd47 Binary files /dev/null and b/slides/slides_ode/figs/fermenter_model.png differ diff --git a/slides/slides_ode/figs/fermenter_model_2nd.png b/slides/slides_ode/figs/fermenter_model_2nd.png new file mode 100644 index 00000000..4efdfd47 Binary files /dev/null and b/slides/slides_ode/figs/fermenter_model_2nd.png differ diff --git a/slides/slides_ode/figs/foodweb.png b/slides/slides_ode/figs/foodweb.png new file mode 100755 index 00000000..b8cccfdf Binary files /dev/null and b/slides/slides_ode/figs/foodweb.png differ diff --git a/slides/slides_ode/figs/foxes_and_rabbits_1.png b/slides/slides_ode/figs/foxes_and_rabbits_1.png new file mode 100644 index 00000000..70cb3c73 Binary files /dev/null and b/slides/slides_ode/figs/foxes_and_rabbits_1.png differ diff --git a/slides/slides_ode/figs/foxes_rabbits_model.png b/slides/slides_ode/figs/foxes_rabbits_model.png new file mode 100644 index 00000000..011cec6d Binary files /dev/null and b/slides/slides_ode/figs/foxes_rabbits_model.png differ diff --git a/slides/slides_ode/figs/infection_model.png b/slides/slides_ode/figs/infection_model.png new file mode 100755 index 00000000..879e1168 Binary files /dev/null and b/slides/slides_ode/figs/infection_model.png differ diff --git a/slides/slides_ode/figs/infection_model_catalyst_implementation.png b/slides/slides_ode/figs/infection_model_catalyst_implementation.png new file mode 100755 index 00000000..10d6eaba Binary files /dev/null and b/slides/slides_ode/figs/infection_model_catalyst_implementation.png differ diff --git a/slides/slides_ode/figs/irrigation_model.png b/slides/slides_ode/figs/irrigation_model.png new file mode 100755 index 00000000..ffa72931 Binary files /dev/null and b/slides/slides_ode/figs/irrigation_model.png differ diff --git a/slides/slides_ode/figs/mice_model_part1.png b/slides/slides_ode/figs/mice_model_part1.png new file mode 100755 index 00000000..e5130de4 Binary files /dev/null and b/slides/slides_ode/figs/mice_model_part1.png differ diff --git a/slides/slides_ode/figs/mice_model_part2.png b/slides/slides_ode/figs/mice_model_part2.png new file mode 100755 index 00000000..5c685e6a Binary files /dev/null and b/slides/slides_ode/figs/mice_model_part2.png differ diff --git a/slides/slides_ode/figs/nk_cells_senescent_cells.png b/slides/slides_ode/figs/nk_cells_senescent_cells.png new file mode 100644 index 00000000..f9c9570e Binary files /dev/null and b/slides/slides_ode/figs/nk_cells_senescent_cells.png differ diff --git a/slides/slides_ode/figs/osc.png b/slides/slides_ode/figs/osc.png new file mode 100755 index 00000000..5baec450 Binary files /dev/null and b/slides/slides_ode/figs/osc.png differ diff --git a/slides/slides_ode/figs/oscM.png b/slides/slides_ode/figs/oscM.png new file mode 100755 index 00000000..330a6186 Binary files /dev/null and b/slides/slides_ode/figs/oscM.png differ diff --git a/slides/slides_ode/figs/reactorBio.png b/slides/slides_ode/figs/reactorBio.png new file mode 100755 index 00000000..bcc1ee31 Binary files /dev/null and b/slides/slides_ode/figs/reactorBio.png differ diff --git a/slides/slides_ode/figs/reactorBioM.png b/slides/slides_ode/figs/reactorBioM.png new file mode 100755 index 00000000..6d508fc3 Binary files /dev/null and b/slides/slides_ode/figs/reactorBioM.png differ diff --git a/slides/slides_ode/figs/reactorVuur.png b/slides/slides_ode/figs/reactorVuur.png new file mode 100755 index 00000000..998193d9 Binary files /dev/null and b/slides/slides_ode/figs/reactorVuur.png differ diff --git a/slides/slides_ode/figs/reactorVuurM.png b/slides/slides_ode/figs/reactorVuurM.png new file mode 100755 index 00000000..a2fe74d1 Binary files /dev/null and b/slides/slides_ode/figs/reactorVuurM.png differ diff --git a/slides/slides_ode/figs/reality.png b/slides/slides_ode/figs/reality.png new file mode 100755 index 00000000..362b377f Binary files /dev/null and b/slides/slides_ode/figs/reality.png differ diff --git a/slides/slides_ode/figs/single_brownian_motion.png b/slides/slides_ode/figs/single_brownian_motion.png new file mode 100644 index 00000000..0dce9de5 Binary files /dev/null and b/slides/slides_ode/figs/single_brownian_motion.png differ diff --git a/slides/slides_ode/figs/soil_plant_cont_model.png b/slides/slides_ode/figs/soil_plant_cont_model.png new file mode 100755 index 00000000..f1a1ea65 Binary files /dev/null and b/slides/slides_ode/figs/soil_plant_cont_model.png differ diff --git a/slides/slides_ode/figs/treactor_seat_puzzle_a.png b/slides/slides_ode/figs/treactor_seat_puzzle_a.png new file mode 100755 index 00000000..42d9c736 Binary files /dev/null and b/slides/slides_ode/figs/treactor_seat_puzzle_a.png differ diff --git a/slides/slides_ode/figs/treactor_seat_puzzle_b.png b/slides/slides_ode/figs/treactor_seat_puzzle_b.png new file mode 100755 index 00000000..dce9ed63 Binary files /dev/null and b/slides/slides_ode/figs/treactor_seat_puzzle_b.png differ diff --git a/slides/slides_ode/figs/water_evap_infil_model.png b/slides/slides_ode/figs/water_evap_infil_model.png new file mode 100755 index 00000000..db94b254 Binary files /dev/null and b/slides/slides_ode/figs/water_evap_infil_model.png differ diff --git a/slides/slides_ode/icoon_UGent_BW_NL_RGB_2400_kleur.png b/slides/slides_ode/icoon_UGent_BW_NL_RGB_2400_kleur.png new file mode 100755 index 00000000..a2baf94a Binary files /dev/null and b/slides/slides_ode/icoon_UGent_BW_NL_RGB_2400_kleur.png differ diff --git a/slides/slides_ode/logo_UGent_NL_RGB_2400_kleur.png b/slides/slides_ode/logo_UGent_NL_RGB_2400_kleur.png new file mode 100755 index 00000000..a13203be Binary files /dev/null and b/slides/slides_ode/logo_UGent_NL_RGB_2400_kleur.png differ diff --git a/slides/slides_ode/mathemfig.nb b/slides/slides_ode/mathemfig.nb new file mode 100755 index 00000000..871cf3e3 --- /dev/null +++ b/slides/slides_ode/mathemfig.nb @@ -0,0 +1,1866 @@ +(* Content-type: application/vnd.wolfram.mathematica *) + +(*** Wolfram Notebook File ***) +(* http://www.wolfram.com/nb *) + +(* CreatedBy='Mathematica 10.2' *) + +(*CacheID: 234*) +(* Internal cache information: +NotebookFileLineBreakTest +NotebookFileLineBreakTest +NotebookDataPosition[ 158, 7] +NotebookDataLength[ 98797, 1857] +NotebookOptionsPosition[ 98120, 1830] +NotebookOutlinePosition[ 98463, 1845] +CellTagsIndexPosition[ 98420, 1842] +WindowFrame->Normal*) + +(* Beginning of Notebook Content *) +Notebook[{ + +Cell[CellGroupData[{ +Cell[BoxData[{ + RowBox[{ + RowBox[{"rho", "=", "1000"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"g", "=", "9.81"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"a", "=", "100"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"qin", "=", "5"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"r", "=", "20"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"tend", "=", "10000"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"s", "=", + RowBox[{"NDSolve", "[", + RowBox[{ + RowBox[{"{", + RowBox[{ + RowBox[{ + RowBox[{"D", "[", + RowBox[{ + RowBox[{"p", "[", "t", "]"}], ",", "t"}], "]"}], "\[Equal]", + RowBox[{ + RowBox[{"rho", "*", + RowBox[{ + RowBox[{"g", "/", "a"}], "/", + RowBox[{"10", "^", "5"}]}], "*", "qin"}], "-", + RowBox[{ + RowBox[{ + RowBox[{"p", "[", "t", "]"}], "/", "a"}], "/", "r"}]}]}], ",", + RowBox[{ + RowBox[{"p", "[", "0", "]"}], "==", "1"}]}], "}"}], ",", "p", ",", + RowBox[{"{", + RowBox[{"t", ",", "0", ",", "tend"}], "}"}]}], "]"}]}], + ";"}], "\[IndentingNewLine]", + RowBox[{"Plot", "[", + RowBox[{ + RowBox[{"Evaluate", "[", + RowBox[{ + RowBox[{"p", "[", "t", "]"}], "/.", "s"}], "]"}], ",", + RowBox[{"{", + RowBox[{"t", ",", "0", ",", "tend"}], "}"}], ",", + RowBox[{"PlotRange", "\[Rule]", "All"}]}], "]"}]}], "Input", + CellChangeTimes->{{3.696656602997286*^9, 3.696656675330431*^9}, { + 3.696656715162595*^9, 3.696656862185568*^9}, {3.6966573484889545`*^9, + 3.696657355431864*^9}}], + +Cell[BoxData[ + GraphicsBox[{{}, {}, + {RGBColor[0.368417, 0.506779, 0.709798], AbsoluteThickness[1.6], Opacity[ + 1.], LineBox[CompressedData[" +1:eJwVzHk4lAkAx3HH9rg6HZHJMO+7jtyVduRofolYUutOpcjSsY6eVbvlHku8 +UipFWqXLZIlJjsE0DO+mbTvo0Daonad6pFqPcYylwr77x+/5PZ9/vpzdiYEx +aioqKv7M/n+Bg5v8r3ZrnlpMwKiKioKX2ZPvcJbShGe7cNcmroKnubhfuIsy +wlKDFeysBAXvgYO6wpOywlBNRfWNAQWvlmd4kks5Iy7J7+OsaJRX7s2RO1I+ +KHVcnl6+f5xX4meRZ0dtxVKyBTrSSV7RQ6sBG2ovrl4z2xliN8NbHfDaLfTU +EWzoGVlbqDUPb2gnVdfZLKSUOMq9DmsjxL7qTJk+hUXP3Y+N+S2CUWsKrScs +hELG4mSr62JK+Sw04p/TeKH3aaJdVR8FpudLXTcUYxXPZb90wgCNjs0NWfml +KHEcl8XVGGLoTHZNVGkZosPj/3hqtgy/a80l+X0ox/yw1C6qwBi9Q3oFsfzL +uG6haq9sY6FIGvxn/7yrEH1u3u7dvRwVl+ISQ6uvQWCesiqgzwRuVdvVLzgJ +0PfE/vhWMRuWtzmzQ6+uY2QkcV9eiSkG1uvH7OP/hvDzNgXqdmYwHH3Z2qhR +DUpfmPA53QyCyvSfNYQ3YCpr8/frNkMrNUmYu9Qi+WzXsFKXAyLJa43PoBDe +M3WL2SEcWO+Vy7bcuQlJTSQ/r5CDnGrqZBRVh94tMUG0lAPtpIuflBG3kFxo +s06p4CCwm73jwNf1cJ3K9yxcRiAjpnH8q3f1MDnRyr3qTuB5hmjd8tYGVLrp +sFSjCCjszfnLMhqR+6U46lE6Aafdsz+VBjeB3/PEWvkrgYju4SurLUQo/Dyt +09BI4NvHPl3170VYLAty23OfwK6wRReaJM24KLF0qZQT4P64/ofyX1qwcEln +/skxAhNdVOIVr1YkHeT3JquRGCh3t7QyEqOeKzMx1CVxdEHE86IBMboDOi+u +MyWxbe6dc1bdbUz1uOSxbUmM5rw6HXpYgonBzI7Jb0jEb/xIeLm2gZW7MrcU +JPSORcc2LWzHmP3hDm1fEqnfe19e8KwdERmPy+YCSGhE3b87HixFgQbX5244 +Cdp2VjYskUJZ+4gtiCQh7xx812fagf0vA/cciCWhy8rZopXfAd/rN2WsOBIC +d9kt6+EOmBDRZa8PkLBNc14ZvrkThhtqPDmHSNxN99e6J+rEh/jCWt8jTN/X +6KWNMQ3dCXnqg1QS0hWU3RsWDfOWksh+xm2an9LOm9A4+P6O+wfGzV39bC0O +jdVU0VuNNBI3PMojBy1pzK/HWw/GZ1ws3l5aw/RMfWtFjGOtnT4aBNAQdwdn +lqWTiNaqcH0YSMNC7HeuinHkkEFBdjANvZklVc2Mtwn+tR0PoyHnG4qfMd5M +iBN6dtIwTgsqmp9BgmvsMZYfR2OmcpKdwthp+paHRwKN/lrb3jzGq16QRdOJ +NF6p7MwpZmxbPM9pbxKNtqOSp3WMzXTvHfJKpkFrSKyGGJuMru36kkKjeoex +UMnYuKdqaUMajWNTeQ7qmST0TxSICD6Nc2oVbDbjJfEzGn1ZNFJGwo7bMF64 +KWHrqWwaEjPLSWfGOjZ/V/ocpdESYhC+kbGm9nfTc7k07vmbNwUx/g/3YS0h + + "]]}}, + AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948], + Axes->{True, True}, + AxesLabel->{None, None}, + AxesOrigin->{0, 1.}, + DisplayFunction->Identity, + Frame->{{False, False}, {False, False}}, + FrameLabel->{{None, None}, {None, None}}, + FrameTicks->{{Automatic, Automatic}, {Automatic, Automatic}}, + GridLines->{None, None}, + GridLinesStyle->Directive[ + GrayLevel[0.5, 0.4]], + Method->{ + "DefaultBoundaryStyle" -> Automatic, "DefaultMeshStyle" -> + AbsolutePointSize[6], "ScalingFunctions" -> None}, + PlotRange->{All, All}, + PlotRangeClipping->True, + PlotRangePadding->{{ + Scaled[0.02], + Scaled[0.02]}, { + Scaled[0.05], + Scaled[0.05]}}, + Ticks->{Automatic, Automatic}]], "Output", + CellChangeTimes->{{3.6966567238237185`*^9, 3.696656787208536*^9}, { + 3.6966568211815577`*^9, 3.696656862665907*^9}, {3.696657349009306*^9, + 3.696657355872157*^9}}] +}, Open ]], + +Cell[BoxData[{ + RowBox[{ + RowBox[{ + "SetDirectory", "[", + "\"\\"", "]"}], + ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"Export", "[", + RowBox[{"\"\\"", ",", + RowBox[{"Transpose", "[", + RowBox[{"{", + RowBox[{ + RowBox[{"Table", "[", + RowBox[{"i", ",", + RowBox[{"{", + RowBox[{"i", ",", "0", ",", "tend", ",", "10"}], "}"}]}], "]"}], + ",", + RowBox[{"Flatten", "[", + RowBox[{"Map", "[", + RowBox[{ + RowBox[{ + RowBox[{"Evaluate", "[", + RowBox[{ + RowBox[{"p", "[", "#", "]"}], "/.", "s"}], "]"}], "&"}], ",", + RowBox[{"Table", "[", + RowBox[{"i", ",", + RowBox[{"{", + RowBox[{"i", ",", "0", ",", "tend", ",", "10"}], "}"}]}], + "]"}]}], "]"}], "]"}]}], "}"}], "]"}]}], "]"}], ";"}]}], "Input", + CellChangeTimes->{{3.696656921897328*^9, 3.696656956569823*^9}}], + +Cell[CellGroupData[{ + +Cell[BoxData[{ + RowBox[{ + RowBox[{"m", "=", "80"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"k", "=", "3000"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"l", "=", "0.4"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"b", "=", "200"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"fe", "=", "0"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"g", "=", "9.81"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{ + RowBox[{"tend", "=", "10"}], ";"}], + "\[IndentingNewLine]"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"s2", "=", + RowBox[{"NDSolve", "[", + RowBox[{ + RowBox[{"{", + RowBox[{ + RowBox[{ + RowBox[{"m", "*", + RowBox[{"D", "[", + RowBox[{ + RowBox[{"x", "[", "t", "]"}], ",", "t", ",", "t"}], "]"}]}], + "\[Equal]", + RowBox[{"fe", "-", + RowBox[{"m", "*", "g"}], "+", + RowBox[{"k", "*", + RowBox[{"(", + RowBox[{"l", "-", + RowBox[{"x", "[", "t", "]"}]}], ")"}]}], "-", + RowBox[{"b", "*", + RowBox[{"D", "[", + RowBox[{ + RowBox[{"x", "[", "t", "]"}], ",", "t"}], "]"}]}]}]}], ",", + RowBox[{ + RowBox[{"x", "[", "0", "]"}], "==", "0.1"}], ",", + RowBox[{ + RowBox[{ + RowBox[{"x", "'"}], "[", "0", "]"}], "\[Equal]", "0"}]}], "}"}], ",", + "x", ",", + RowBox[{"{", + RowBox[{"t", ",", "0", ",", "tend"}], "}"}]}], "]"}]}], + ";"}], "\[IndentingNewLine]", + RowBox[{"Plot", "[", + RowBox[{ + RowBox[{"Evaluate", "[", + RowBox[{ + RowBox[{"x", "[", "t", "]"}], "/.", "s2"}], "]"}], ",", + RowBox[{"{", + RowBox[{"t", ",", "0", ",", "tend"}], "}"}], ",", + RowBox[{"PlotRange", "\[Rule]", "All"}]}], "]"}]}], "Input", + CellChangeTimes->{{3.69666079033793*^9, 3.6966608120753174`*^9}, { + 3.69666085537992*^9, 3.6966610149307504`*^9}, {3.696661050915177*^9, + 3.696661062475351*^9}, {3.696661521265508*^9, 3.696661524553834*^9}, { + 3.696661731065503*^9, 3.6966618254962716`*^9}}], + +Cell[BoxData[ + GraphicsBox[{{}, {}, + {RGBColor[0.368417, 0.506779, 0.709798], AbsoluteThickness[1.6], Opacity[ + 1.], LineBox[CompressedData[" +1:eJwc2nk4VV0XAHDzlHmeiqQUEpIhshcyjymleJMxMxWhSBISUSElIcmYISEk +3EsSJUOhUOaQeZ7i2+d7/3mf33Pu3eectddaZ52r3XZe5o5UFBQUEnQUFMT/ +n92wo5NziFLXTX+C/6tAKecmj54RdUG9VI+4diRVoB/Gdy+LigYgptM/hv57 +WoHklb6+YOq+hSrcrE7df1aB/HTPstKKRqIo/6LAtLQKVHVmyH/7YiySazF3 +is6oQJQlZXObXQ/RULkYk3lOBRKv2ti3vpGAJG/Pm80UVCCderBeEXmCmqnT +2exKK5Dz57AHi1rJSLiigyO7qgJFfWtqmLuYitJj93LX1FegM9P0N1a0n6Nd +j/TIGV/w5y/n8i93pSPVfI2q010VKGDZ6M2iSwbSN0mIax+oQHevzRgvbLxE +Fzgam3imKlD+LYXQWZEcRDfyR3KMthJV03XtnHmdi5T0dQQvc1Wi1rsB5VNa +r5BxgMBm+e5KNP+wemriYiGqq+t6fhkq0a0o2frFwCL0yqfj02+zSnT3SwjH +ovZrFLQd+XbLthIlnxB/Nd9VjOpUHI/rhFeijDjftbm0N6isXnvR+Uklyv/e +oDPnUoIqntAmyuXj8591GZjZKEWZTJPB2Z2VaMC2gHdKpAI9zja88F32HZp4 +sW0/OVaBxF5uhLTqvUPzI2av/76uRBND7acsbd8hGtcFwwmtKuRcVztDEf8O +7busHPLnYg0SX/mdYLn9DilqDCzNdpHR5QMfOvf/rUJHByOTvdXqkOLhiKpz +TO+Reqi81mxaHQqpbPw4eOA90v0Qen/GpR5pqH+3/uPyHlnq75Oa3viAjgV8 +97sw9R5dP+F24a/IJ5T6seUW7XY12gpVFPgd/QnZ3Pc3HxevQTfLKNvb1z6h +SmvXz7MGNei20GOtyo4mFHyjMvZsYg2KGanfFxnxGdnKCV29x1+L0gJ2Te2b ++Yo8Ir5m/ldcizg6F81ZZFpR8mTm90sfapG517lDEQ6tqDn/pYhfdy36/nzv +2LW2VuR4bzDQeKsW/aSrOmuX14ZsDj5hWNYjoaHWMTU5mw6Uasp6rKibhMRd +TQTyEjpQgKnkacoJEnKiLlkS/9yBVDZ1rfZvkNDYkeACfpVvSKjR0GJemIwm +k3hEKbi+o+cHWRdNzpPRQYXrmwH635Ggrf3u/Z5k5Pmlv3sh+Ds63CJy4XMQ +Gc1t5z34M/kd1X2tO3YpmYyWHTSpvzZ0InO9kpvMOO5KW1m/9f51okjvIvpd +I2Tkn8hSRT7chXrLMtvn5slo41O3T1laF1qS+OLdy1KHKA55jT671o0sJWxP +voQ6pNH4jcz3uhupHlXTLjKqQ7dsj6Y++NONfNKVv121rEM08bSWYad+oI/v +4wUVvOoQ49rTT+4yP9HWBvfl80/qkHLEj2sGtj8R6+ftu/fT65AzD5/0/vif +KJJmeU9oXh1qkHsYM7T2EznxWEVkV9Wh5ZqviCTdg3iTzCp/1tehvSYscyk2 +PeiS3wP1z5/r0G3XOyfPfehBNxw0T0321KGS1Q80yqs9KKr98i3BoTo0FE5d +xiPVi+6b7lCln6hDmi9u8Lfd70UKXe8+Ca3UoctyVZ8K6nqRVImel9a/OvS8 +Zu1a9HIvCqBuOnaAuh5R9Pr06Vr3oZ/XDiofYq1Hsq7FMXtj+1DCmIWDKVc9 +slmdQdTkPtTl7VJ5kL8exYQfnOtf7EM9UXQGTcL1qJrbLb1a4hdijs/fv3d3 +PZpKzz6ZfO4XupMcfUl9bz0SlhuluXbvF3p0I0ib90A9um5se/HIwi/0q/vj +ISrZepTbk8LPte83ql7Ve8l7uB79dOn9NGv5G02P19pPHKlHjKsC11uifqPy +t87ZQcr1SDn8jPSr6t+I7+Z4aevReuTMndAXOfcbCY1GfhtSq0dGJ1w+Hubs +R4L0tOZv1euRAz9DWrpUP7L2OxNiCPj8vzP9ObT70Sn96Mo0jXr0MFP7xM3z +/eh8z7NzbzXx9XgMH5jx60dJb7PrYrXqEVkhlOr8g36kuzRjLXkcX9/G7p7P +uf1oRKzgYQT2PLn2jWp9P/LwGP6ehc141yY6t68feTVJJkdhi57YchBY6UeU +qtk2h7GV+Z8du8M+gHYHHktNxeub/VblXTkwgBS83X614vM7Z/6cdtQaQGGK +e19+xNd30yPg4zfrAZRzJD34Nr7+RAX+NK2rA8gjWG6LHtWjgo0y/+LYAfTm +gUqp+bF61EC2OLE7ZwBVpFsfc1StR78iFw/cJw8gkfDzh0GlHi2bxVFt9wyg +x0xbSsOK9YiVX77HY2kAPTjdMnNCoR7t+936ppd1EP04zk59V64eqWd6RRvu +H0SmpKid92TqkYUHq2OlxiBiZrs2bSVVj9wV8o8dsBpEfHzf969I1KPbG4a8 +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 + "]]}}, + AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948], + Axes->{True, True}, + AxesLabel->{None, None}, + AxesOrigin->{0, 0.098}, + DisplayFunction->Identity, + Frame->{{False, False}, {False, False}}, + FrameLabel->{{None, None}, {None, None}}, + FrameTicks->{{Automatic, Automatic}, {Automatic, Automatic}}, + GridLines->{None, None}, + GridLinesStyle->Directive[ + GrayLevel[0.5, 0.4]], + ImageSize->{585., Automatic}, + Method->{ + "DefaultBoundaryStyle" -> Automatic, "DefaultMeshStyle" -> + AbsolutePointSize[6], "ScalingFunctions" -> None}, + PlotRange->{All, All}, + PlotRangeClipping->True, + PlotRangePadding->{{ + Scaled[0.02], + Scaled[0.02]}, { + Scaled[0.05], + Scaled[0.05]}}, + Ticks->{Automatic, Automatic}]], "Output", + CellChangeTimes->{{3.696660953460269*^9, 3.696661015350047*^9}, { + 3.6966610531597815`*^9, 3.6966610629626956`*^9}, {3.6966615217758703`*^9, + 3.696661524926097*^9}, {3.69666173157086*^9, 3.696661825968623*^9}}] +}, Open ]], + +Cell[BoxData[ + RowBox[{ + RowBox[{"Export", "[", + RowBox[{"\"\\"", ",", + RowBox[{"Transpose", "[", + RowBox[{"{", + RowBox[{ + RowBox[{"Table", "[", + RowBox[{"i", ",", + RowBox[{"{", + RowBox[{"i", ",", "0", ",", "tend", ",", "0.02"}], "}"}]}], "]"}], + ",", + RowBox[{"Flatten", "[", + RowBox[{"Map", "[", + RowBox[{ + RowBox[{ + RowBox[{"Evaluate", "[", + RowBox[{ + RowBox[{"x", "[", "#", "]"}], "/.", "s2"}], "]"}], "&"}], ",", + RowBox[{"Table", "[", + RowBox[{"i", ",", + RowBox[{"{", + RowBox[{"i", ",", "0", ",", "tend", ",", "0.02"}], "}"}]}], + "]"}]}], "]"}], "]"}]}], "}"}], "]"}]}], "]"}], ";"}]], "Input", + CellChangeTimes->{{3.6966618423682013`*^9, 3.696661851872922*^9}, { + 3.696661986087821*^9, 3.6966619884885197`*^9}}], + +Cell[CellGroupData[{ + +Cell[BoxData[ + RowBox[{"\[IndentingNewLine]", + RowBox[{ + RowBox[{"Clear", "[", + RowBox[{"s", ",", "r"}], "]"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"n", "=", "10000000"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"I0", "=", "1000"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"beta", "=", + RowBox[{"10", "^", + RowBox[{"(", + RowBox[{"-", "6"}], ")"}]}]}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"alpha", "=", "0.05"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"m", "=", "0.6"}], ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"rp", "=", "0.2"}], ";"}], "\[IndentingNewLine]", + "\[IndentingNewLine]", + RowBox[{ + RowBox[{"tend", "=", "100"}], ";"}], "\[IndentingNewLine]", + "\[IndentingNewLine]", "\[IndentingNewLine]", + RowBox[{ + RowBox[{"s3", "=", + RowBox[{"NDSolve", "[", + RowBox[{ + RowBox[{"{", + RowBox[{ + RowBox[{ + RowBox[{"D", "[", + RowBox[{ + RowBox[{"s", "[", "t", "]"}], ",", "t"}], "]"}], "\[Equal]", + RowBox[{ + RowBox[{"-", "alpha"}], "*", "beta", "*", + RowBox[{"i", "[", "t", "]"}], "*", + RowBox[{"s", "[", "t", "]"}]}]}], ",", + RowBox[{ + RowBox[{"D", "[", + RowBox[{ + RowBox[{"i", "[", "t", "]"}], ",", "t"}], "]"}], "==", + RowBox[{ + RowBox[{"alpha", "*", "beta", "*", + RowBox[{"i", "[", "t", "]"}], "*", + RowBox[{"s", "[", "t", "]"}]}], "-", + RowBox[{"rp", "*", + RowBox[{"i", "[", "t", "]"}]}]}]}], ",", + RowBox[{ + RowBox[{"D", "[", + RowBox[{ + RowBox[{"d", "[", "t", "]"}], ",", "t"}], "]"}], "\[Equal]", + RowBox[{"m", "*", "rp", "*", + RowBox[{"i", "[", "t", "]"}]}]}], ",", + RowBox[{ + RowBox[{"D", "[", + RowBox[{ + RowBox[{"r", "[", "t", "]"}], ",", "t"}], "]"}], "\[Equal]", + RowBox[{ + RowBox[{"(", + RowBox[{"1", "-", "m"}], ")"}], "*", "rp", "*", + RowBox[{"i", "[", "t", "]"}]}]}], ",", + RowBox[{ + RowBox[{"s", "[", "0", "]"}], "==", + RowBox[{"n", "-", "I0"}]}], ",", + RowBox[{ + RowBox[{"i", "[", "0", "]"}], "==", "I0"}], ",", + RowBox[{ + RowBox[{"r", "[", "0", "]"}], "==", "0"}], ",", + RowBox[{ + RowBox[{"d", "[", "0", "]"}], "\[Equal]", "0"}]}], "}"}], ",", + RowBox[{"{", + RowBox[{"s", ",", "i", ",", "r", ",", "d"}], "}"}], ",", + RowBox[{"{", + RowBox[{"t", ",", "0", ",", "tend"}], "}"}]}], "]"}]}], ";"}], + "\[IndentingNewLine]", "\[IndentingNewLine]", + RowBox[{"Plot", "[", + RowBox[{ + RowBox[{"Evaluate", "[", + RowBox[{ + RowBox[{"{", + RowBox[{ + RowBox[{"s", "[", "t", "]"}], ",", + RowBox[{"i", "[", "t", "]"}], ",", + RowBox[{"r", "[", "t", "]"}], ",", + RowBox[{"d", "[", "t", "]"}]}], "}"}], "/.", "s3"}], "]"}], ",", + RowBox[{"{", + RowBox[{"t", ",", "0", ",", "tend"}], "}"}], ",", + RowBox[{"PlotRange", "\[Rule]", "All"}]}], "]"}], "\[IndentingNewLine]", + "\[IndentingNewLine]"}]}]], "Input", + CellChangeTimes->{{3.6966655426889067`*^9, 3.6966658157867994`*^9}}], + +Cell[BoxData[ + GraphicsBox[{{}, {}, + {RGBColor[0.368417, 0.506779, 0.709798], AbsoluteThickness[1.6], Opacity[ + 1.], LineBox[CompressedData[" +1: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 + "]]}, + {RGBColor[0.880722, 0.611041, 0.142051], AbsoluteThickness[1.6], Opacity[ + 1.], LineBox[CompressedData[" +1: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 +/A+XRZPH + "]]}, + {RGBColor[0.560181, 0.691569, 0.194885], AbsoluteThickness[1.6], Opacity[ + 1.], LineBox[CompressedData[" +1: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 + "]]}, + {RGBColor[0.922526, 0.385626, 0.209179], AbsoluteThickness[1.6], Opacity[ + 1.], LineBox[CompressedData[" +1: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 +VQ6O76oNLZGZjKYscvo+NBnDgUeD9h5cZDRTeHCUe8MYTCnBHd6yZBTuVSC8 +TmMCxy/YbeuWI6OdSgLOI3QmkLLrWJOSAhnJN+78r5jVBC4pXW2dVyIjvw/z +3zX4TUC+Y6+YgzoZLWw+njimZQKHRjiS5nXJaIWqP5cTYoL31XcPsNmSkWqw +f92XCyag3XKo7jiVjALScqN2R5lAmdP+hjI7Mlr8uM4Zfc0EJH/fFDe0J6M5 +0iMN1wwT8I2deeTqREaT5hLRMo0m8CnNRM/Rk4wGgZGrjsYU4ogvyiCcjPgc +1Ybn6UwhSL/4j3MEGR2NOFV8gMkUanjvzkVHklFfY4tm5m5T8Bkd6H8WRUaf +NENORIiYAu9UU4/sFTLqUpkqNtA3hSch0XntiWTUKvVGq+eKKaivHZ9nzSUj +McmM7tbrplBds+i9gn1Z3MOtJtEUagU+jH29S0YmIow3U9JMIdOtr7ssn4ze +8+lP2RSZwu366VLtIjIa3tmQPtBmCl6Wx11ky8lofal0+Tu9GdAtPGA5+pSM +HBZDr39kMoP4eDU+8QYyapk3EW5jMwO/i6NGs9jRM+PmRXvNIMU3ZT2yiYyY +J0QL3MVx/xGJ2dvPyIhnIIM0o28GsrtsOvPacb6fXa9YjTYDHqbydK4PZGS4 +j/2ddqwZvPL0+/IR2+ZMyvTFODPgzByWT+klo2DhLGnWW2ZgqKJ/YOcnMqq/ +WJ4vVGgGiavBHqtfyAh0u9NMOsyApS3gT85XMjJ/zhWZwWoOl7lpXQmTZHSc +LyN7hN0cRndZpi5h+5zd3yi+1xxSvR3/pU2RUaKo1J8KAXO4Lu8aMviTjHqi +NQJeyJkDe+lPZfsZMqLq25/+RTCHAc/4qEOLZHTy5V2Czi1zoL9EaTm5TkZt +ocGhfrfN4ZXfJfYZbCkFq4K7WebwmT2yPmiDjKbvrK9uLzSHeYt2wav/cH35 +2eZ01JrDriGrwwU0FBTDxzZD/GIOR236gxroKKjwTPD1U3wWUOv0b0coKwUx +Slo9urXfAsIN3q7PYXsMig+3iVqA3JCWsxsbBckZfVCSlrEANmLCRdJOCnrM +L9f/S9sCBE6LiomwU1BH+39SQQ4W4HBk/GrRHgqaErBqu3rXAnYwBRKteCnI +t7qtwf+eBSTSbq8rx14yPFJz7L4F2EnteMTGR0EbvrK5slUW4Oph5PUam72V +JbS7xQKcCi58PyJAQWquHbL7RiwgYZefM6cQBV0sR7eKBS3hlXFOU4A4BTHo +1V2/IWIJKQc7Utqxr31WiAqVsAT7865svBIUlEIj5GsuZwlJDFnjjdiFpH/G +c4ctwYpT3IxWioLerNSvHzpuCSadWlJBByiIR0flVHuGJaQb124Iy1OQuazT +f3S5lsCw882SL3YEX4KzboElnJA0jGvEHlsdd2wss4TzzXLZtgoU9Kgy43hN +oyWwuRscvaJIQSSR7bY5w5Yw1SSZ9lGZguLoe0yCRK1AuE5JQUGdgloW/3U8 +lLSCNp9fLGexF0cPGi8ctIK3DbG3HmEfbbpk6K1iBbs6f9VoaFCQdJCG3kkD +K+i0MpU6oklBbRO52lZuVuC+vNtQXZuCaN/4ykuWWsHe3zSLizoURL19OIy/ +wgpWL0cGSQMFlbuytO+usYL02etNDthHaYsc1uutYE7sxK0O7Gq1r/Hdr63g +9VSB921EQafumk+HTVnBRw1+BgU97KcplAlOAvhsMpcqGVLQrrywP9+4CGA2 +QKVzwq6Pdc4d4iGArpGjVCI2u43CdA8/AcY4krqnsBvnOqMbxQhAQxSuyDGi +IC6J7TXJKgRgkgp5s2mM6ynpzO7DFAJI7oySyDCjIP5C2kZZGwL0RipGtGL7 +Pb1xWpBKANaFiNJJbO6xqubNYwQIsXgWccicgly1FrxbTxKgwtqUvxubfsz/ +tdFZAgxx7SOuW1CQrlZANCmZACehek2ZQEGpBDp5vRQC7At8L2KDPeWS0q+c +SgCWeQeJYOwbSQ8V994hgA1fSP1T7JEfS8Of7xIgtpXKh4i4HpICtY9XEUAw +P+SHPomCGn6cW3Z7T4CSCGqLIoWCxoucfkT1EKDH9OoMEZvDw/xjVi8BulLM +l89gu88IP/rwhQCBH43jq7C5Vt8E6IwSoOOo2bScNZ4vo+gS1wIBhGn2JInY +UJD4wa6Fl3uIIO0qWD1jS0GEX3XfRvYSoXje3ZyZSkHnKwp6/nITARS/vhDH +7lEOrVbkJ4Lyv+8Ee+xIbXH/LDEiBEpP9rVj91uEzQeoEmEirfZDuh0FJfhJ +zonaEuEfbVaY6DEKMs1zbuO1I4KEhcRNDewdvVmZu48RYfG9yw0r7MhDnCab +DkTIuhOqG4bt/48mr9+VCAzDQqHd2LZx/eQb54iw6h9PDbGnIKHi+Mf/bhFh +r9P1lMfHKWiwryN+OY0ITa0Mda+xb7PQnZq+TYSRrNT2IWwO31D2/iwieOy0 +zd/ugJ+nmpv7o3tEiP69m2qJPfUc+LweEYF/U+rNMHbN8GJ4Xy8RdEjqsYsn +KMi46ertP5+IcKFcN4reEY+Xuf8hXx8RHBr/unBj0x01mzw+RISqPeNTmtiU +3jzytx9EkLmS/SsSe6mDKPVzBcfzwHeG0YmCVKorutd5SNDcaJDG5LxVrwbT +AnwkKD1b/ocH2953gEFHgASvIv6YSmHHyOzQvihMgpXHd6oNsXsLHQrpD5Ag +PjAhNwo7MIMtbKcWCdJu9LGsYtfGeIoJHSfBRf7Ypp6TON4eorjACRKU2TSz +DGPTCqtL8DqRYC2l0vQntnkjnRSnCwmGFLZnbz9FQaPLWQcZvUlg6XEoUxmb +1e290tx5EhB2EOhvYDubqKKWTBLcFDj5G7lQUGwan25jNglE7AczzbEf/KDV +q88lwebCurIt9trFd/oPC0jQI+R92As7vt7NuLiMBNI66U23sJ8cvGOV1ECC +P+mJl8ew2XZuHnccJEFcm398hCuO/1rCKfJXEsiz3k6OxS7ZIehpOEKCIxfC +4m9gG9IeDpb5ToJ/kvmn8rHDl0KT136S4GXcs9tt2DP9K21Jf0kg9dtOmsWN +gt4Vzcg/4yUDbeeSTDx2pli42kN+MrT3xmymYHvcZTtcJEiGRy9kX2ViM2TI +mMaLkGFNYwGVYR9J8Dhld4AM18rtX7/GrggYS5/XIMOVk2d0GE5TUBL6Siti +RwaLeY3Nc9hqnh3mOsfI4Dl152g49kBKdZr9cTIcMxwvu4QtMXFZNs2JDNsZ +fNRSsBsS5O1YPchwt9n1ayX2xEBk5UooGXKWs65PYMM50ROdmWQI17pUSHTH +348ctpKJbDKoBxxYssW+/mp1if4uGXwid2g6YH/if3MN7pHh6LeEcg9sr+cB +tY8ekCEzcEArGjudvY0tt4kMjOJVs9XYcyWnGwJGyJBX8HWd1YOCJPXzf3l/ +w/m6fXIHB7bD0JCg23cy/Gbcx8qN3bmLfNFuggz+X+TphLELAw4bHpkjw1h2 +W4UK9vEjHO930FDgLOepP0exX3c//e/OfgpkZRRfy8em9VzhTBGmgKlmx3gR +tjqdomG8KAUuHhjRKcO+p1ZYHCFJgfZ3u0YfYkdmJHmfkqeAWjfbxEvsQy4u +q7I6FKjdHcU2jl2wtpPlmQMFnAUTh8Q98ffoSEHkd0cKZGQYLUtjt8RorOw4 +SQGZsv92yGEPsZ8atXSjwPLFYQE1bC7puseDvhS43p/CZogda3fy1Fokvs7h +TeuC7VX/uFE+nwKH6ZpdcrBDaSyUyfcowPm8/UfeVnvDb8XninB70zNOhdj3 +elhTGkspcEGlwewB9tcpJw+zhxTY/aN9uh6bwMfK7faSAjO+Hi4fsVXPO/pl +j1NgQP+69Q4vCpqey/75eJICAtKTBszYeS5Drt0/KWCiXabEhs1udfQ43RwF +dvmdpd2z1V6YYuqxRgHe5MgAQeyCdiMxNSZruDTm/lAFm3OP/Je3B6whKPlg +nQN25xVv8riMNSxk+h5xwo5aL31HI28NIiKZLSex535IvVRWtobtZY1PT2O/ +eSJSfVvLGqKl4+L9sWMcuOJczK3BVDov7xL24v0NnQ1va2COFiq7j62dEHd3 +wRdfP+VfWbrV3p9v+8QZa+giB1Y/2IpHS6OtJ9AanL+lV1Rhq70JMC++YA2v +HXIT6rCDZ35SyfHWUDK0MdqBva7Uf+Z+GR6//PXsD2x9bvcP2eXWMBinXDGO +Hfd3VSWl0hqm7TO9JrEFXuxdC39oDfTD50ansY9YE8MpDdYw9SKhZhE7Mqjj +2manNXT/0P9L443X84bafOuf1iAbYi7Fiy1mkWsS+Msa0l+kv+HD1v96dTZl +1ho8cgd8BLCjaY5r9S5aw9kVywdC2NsMtn8grVuDVboihyQ2zTurbQQ2G+C6 +xRGujL0+POFoKm8DUvf0Zk2x+c/0MHgo2oBQHpetObb2toayq8o28FHqYKMF +dphY4lrHIRvoOi4cQ8D+c1o1yQhswEUufMMae23+YrM+0Qb0HnzOccRe3M4n +qHPWBuxe3awKwC6gsy7RDLSBna8OdQdi29AnqqkF2QDTxYTZc9hPGLZbyYbZ +QCfnUakQ7PNMPyP4om2AUnzz2oWtfOx6OrqabAPqrsMcl7E5eY/dq6y2Ab5p +5sOp2C95bymWPbQByew+1TTsc3xdjUW1NhDPHCubjv2FX+9Tdr0NyKpf3XcH +O3P/wR3xrTbAPAvfs7byK/73tHuPDfSzFRrcw1ZVyJARWbCBz2V8qAY74UR4 +054lG1iz4uV8iD2R4ESgX8HzsZAe23LmL8mAid820Hjx/JXarfyXPnxaTmsL +GWx7m+uw34u/M9XabQt8Z9e2tWB78dG6UxRsQep20/dO7DbT738MlGzBT6gt +4w22UGh73CEVWyC92yC+xf7wJb6SV90WKlRpG95ha6byro3o2IKt3ZnL3diM +u1WueFvZwn2pluVP2PkMbvcu+9ji+djoj2L3fisIy/OzBc64xLktMzR/Izb5 +43hmlzK+YZ8Ocvi3fM4WUm2M5v7DlpmwtnWJsIUUgkTiGHbtK30m/SRboOcr +KfyJ/SpOxJu22hY6Mwv0lv9fD456Ag9tIeLXkc9bljHI3qdRawuvfUQ9Vrby +t7Gvza/eFuzd38WvYpN8du8fabWFL0wv3vzGHrSi6W76gMcnT0v/w57l+Kpy +ftkWFlf2uDH44PXTwWv+7Kot7HETHdpyQMmfB56/bWEbXylpB/ZvxC15bMMW ++srFtRmxt58h7NOkp8LhA18YmbG5u1o3VjmpYJ7w+Cobts71orazKlQ4Kx4p +y4m97bNqtKcaFTIcnt7c8guRFzon1alQvufi7y2b1I88IWlTwX7jwfO92OTJ +faWK+lRQFs4kcWO7GcUlzpKp0HxY+xgvduL2M1TPs1Sw6+HjE8LW3/arJCuQ +ChSR8QtbXqNx3+gKogL/U+WRLTv+c8xTOU8FCU1yvjC20m/C9EYMFVpvNoiK +Yn+aUYhMSqXC2ugzNglswf65okd1VIgq6712ELvni9ef8adUeNC99HXLVz5P +mPM2UeEv430lGey53pH58FYqDH7q+rLl1q73WsadVHjJJiEkh+36srKrf5AK +9yS9MxSweV/IiLAN4/tn75zccldrMd7PU0EvxlxNEVu9JXdfwQ8q7EjK6doy +89Okk94zVOgiVm4oYTfVsdbmzOF4J3SNlbHPPoll7FmggtqnwOQtDz6KfKC2 +SoX4wiZxFeykh+ubp3/j5xH90WfLBjXBpIy/VGAoSXi85T9VSwVvN6ggnza1 +ueXySr/VzU0q9LZPGqli/w8j52JN + "]]}}, + AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948], + Axes->{True, True}, + AxesLabel->{None, None}, + AxesOrigin->{0, 0}, + DisplayFunction->Identity, + Frame->{{False, False}, {False, False}}, + FrameLabel->{{None, None}, {None, None}}, + FrameTicks->{{Automatic, Automatic}, {Automatic, Automatic}}, + GridLines->{None, None}, + GridLinesStyle->Directive[ + GrayLevel[0.5, 0.4]], + Method->{ + "DefaultBoundaryStyle" -> Automatic, "DefaultMeshStyle" -> + AbsolutePointSize[6], "ScalingFunctions" -> None}, + PlotRange->{All, All}, + PlotRangeClipping->True, + PlotRangePadding->{{ + Scaled[0.02], + Scaled[0.02]}, { + Scaled[0.05], + Scaled[0.05]}}, + Ticks->{Automatic, Automatic}]], "Output", + CellChangeTimes->{ + 3.696665697503615*^9, {3.696665757350455*^9, 3.696665766799118*^9}, { + 3.6966658082134438`*^9, 3.696665816605879*^9}, 3.6966660046630397`*^9}] +}, Open ]], + +Cell[BoxData[{ + RowBox[{ + RowBox[{"Export", "[", + RowBox[{"\"\\"", ",", + RowBox[{"Transpose", "[", + RowBox[{"{", + RowBox[{ + RowBox[{"Table", "[", + RowBox[{"i", ",", + RowBox[{"{", + RowBox[{"i", ",", "0", ",", "tend", ",", "0.5"}], "}"}]}], "]"}], + ",", + RowBox[{"Flatten", "[", + RowBox[{"Map", "[", + RowBox[{ + RowBox[{ + RowBox[{"Evaluate", "[", + RowBox[{ + RowBox[{"s", "[", "#", "]"}], "/.", "s3"}], "]"}], "&"}], ",", + RowBox[{"Table", "[", + RowBox[{"i", ",", + RowBox[{"{", + RowBox[{"i", ",", "0", ",", "tend", ",", "0.5"}], "}"}]}], + "]"}]}], "]"}], "]"}]}], "}"}], "]"}]}], "]"}], + ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"Export", "[", + RowBox[{"\"\\"", ",", + RowBox[{"Transpose", "[", + RowBox[{"{", + RowBox[{ + RowBox[{"Table", "[", + RowBox[{"i", ",", + RowBox[{"{", + RowBox[{"i", ",", "0", ",", "tend", ",", "0.5"}], "}"}]}], "]"}], + ",", + RowBox[{"Flatten", "[", + RowBox[{"Map", "[", + RowBox[{ + RowBox[{ + RowBox[{"Evaluate", "[", + RowBox[{ + RowBox[{"i", "[", "#", "]"}], "/.", "s3"}], "]"}], "&"}], ",", + RowBox[{"Table", "[", + RowBox[{"i", ",", + RowBox[{"{", + RowBox[{"i", ",", "0", ",", "tend", ",", "0.5"}], "}"}]}], + "]"}]}], "]"}], "]"}]}], "}"}], "]"}]}], "]"}], + ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"Export", "[", + RowBox[{"\"\\"", ",", + RowBox[{"Transpose", "[", + RowBox[{"{", + RowBox[{ + RowBox[{"Table", "[", + RowBox[{"i", ",", + RowBox[{"{", + RowBox[{"i", ",", "0", ",", "tend", ",", "0.5"}], "}"}]}], "]"}], + ",", + RowBox[{"Flatten", "[", + RowBox[{"Map", "[", + RowBox[{ + RowBox[{ + RowBox[{"Evaluate", "[", + RowBox[{ + RowBox[{"d", "[", "#", "]"}], "/.", "s3"}], "]"}], "&"}], ",", + RowBox[{"Table", "[", + RowBox[{"i", ",", + RowBox[{"{", + RowBox[{"i", ",", "0", ",", "tend", ",", "0.5"}], "}"}]}], + "]"}]}], "]"}], "]"}]}], "}"}], "]"}]}], "]"}], + ";"}], "\[IndentingNewLine]", + RowBox[{ + RowBox[{"Export", "[", + RowBox[{"\"\\"", ",", + RowBox[{"Transpose", "[", + RowBox[{"{", + RowBox[{ + RowBox[{"Table", "[", + RowBox[{"i", ",", + RowBox[{"{", + RowBox[{"i", ",", "0", ",", "tend", ",", "0.5"}], "}"}]}], "]"}], + ",", + RowBox[{"Flatten", "[", + RowBox[{"Map", "[", + RowBox[{ + RowBox[{ + RowBox[{"Evaluate", "[", + RowBox[{ + RowBox[{"r", "[", "#", "]"}], "/.", "s3"}], "]"}], "&"}], ",", + RowBox[{"Table", "[", + RowBox[{"i", ",", + RowBox[{"{", + RowBox[{"i", ",", "0", ",", "tend", ",", "0.5"}], "}"}]}], + "]"}]}], "]"}], "]"}]}], "}"}], "]"}]}], "]"}], ";"}]}], "Input", + CellChangeTimes->{{3.69666586986604*^9, 3.6966659033382072`*^9}, { + 3.696665992482427*^9, 3.696665996393693*^9}}] +}, +WindowSize->{759, 833}, +WindowMargins->{{125, Automatic}, {Automatic, 70}}, +FrontEndVersion->"10.2 for Microsoft Windows (64-bit) (July 29, 2015)", +StyleDefinitions->"Default.nb" +] +(* End of Notebook Content *) + +(* Internal cache information *) +(*CellTagsOutline +CellTagsIndex->{} +*) +(*CellTagsIndex +CellTagsIndex->{} +*) +(*NotebookFileOutline +Notebook[{ +Cell[CellGroupData[{ +Cell[580, 22, 1606, 46, 192, "Input"], +Cell[2189, 70, 2705, 57, 234, "Output"] +}, Open ]], +Cell[4909, 130, 1085, 30, 112, "Input"], +Cell[CellGroupData[{ +Cell[6019, 164, 2052, 59, 232, "Input"], +Cell[8074, 225, 31078, 521, 370, "Output"] +}, Open ]], +Cell[39167, 749, 915, 25, 72, "Input"], +Cell[CellGroupData[{ +Cell[40107, 778, 3359, 90, 412, "Input"], +Cell[43469, 870, 51330, 858, 224, "Output"] +}, Open ]], +Cell[94814, 1731, 3302, 97, 252, "Input"] +} +] +*) + +(* End of internal cache information *) diff --git a/slides/slides_ode/mcode.sty b/slides/slides_ode/mcode.sty new file mode 100755 index 00000000..2384bb4f --- /dev/null +++ b/slides/slides_ode/mcode.sty @@ -0,0 +1,291 @@ +%% +%% This is file `mcode.sty' +%% +%% It is supposed to help you easily include MATLAB source code +%% into LaTeX document, but have it nicely highlighted, using +%% the great listings package. +%% +%% PLEASE NOTE that this package does nothing but save you from +%% figuring out some configurations in setting up the LISTINGS +%% package. ALL the work is done by that package! Thus, please +%% refer your questions to the listings package documentation. +%% +%% Usage: You have three ways of including your MATLAB code. As +%% environment, as inline object and directly from an external +%% file. +%% +%% 1) Environment: +%% +%% \begin{lstlisting} +%% YOUR CODE HERE +%% \end{lstlisting} +%% +%% +%% 2) Inline object*: +%% +%% Bla bla \mcode{CODEFRAGMENT} bla bla. +%% +%% +%% 3) Include external file (in environment form) +%% +%% \lstinputlisting{YOUR-FILE.m} +%% +%% +%% For your convenience this package has the following options: +%% +%% - bw if you intend to print the document (highlighting done +%% via text formatting (bold, italic) and shades of gray) +%% +%% - numbered if you want line numbers +%% +%% - autolinebreaks if you want the package to automatically +%% wrap your code. This is buggy as it may well break +%% break syntax and it doesn't work well with comments. +%% You REALLY should wrap your code manually. +%% +%% - useliterate if you want some characters / relations in +%% your code to be replace with something more readable. +%% Example: ~= becomes $\neq$, >= becomes $\geq$, delta +%% becomes $\delta$ and so on. +%% +%% - framed if you want a frame around the source code blocks +%% +%% - final if you have ``gloablly'' set the draft option, the +%% listings package will not output the code at all. to +%% force it to do so anyway, load this package with the +%% final option (passes the ``final'' on to listings). +%% +%% For example, you may use \usepackage[numbered,framed]{mcode} +%% in your document preamble. +%% +%% * If you want to place some inline code in a footnote, use +%% \mcodefn{} instead (this will reduce the font size a bit). +%% +%% Note: Inside code blocks you can escape to LaTeX text mode +%% using §...§. For ex. §text and some math: $x^2$§, which is +%% especially useful in comments for putting nicely typeset +%% equations etc. To get the same colour/style as in the rest +%% of the comment use \mcommentfont, i.e. §\mcommentfont $x^2$§ +%% +%% To change the font used, edit the first line in the "custo- +%% mise below" section. And feel free to edit other things as +%% well. Refer to the documentation of the listings package to +%% see what else you could do. If an extra small font is re- +%% quired, use {\fontfamily{pcr}\fontsize{3}{4.6}\selectfont} +%% in the definition of \lstbasicfont. +%% +%% Author: +%% Florian Knorn | florian@knorn.org | www.florian-knorn.com +%% +%% Version history: +%% 2.5 -- Renamed internal variables (thx S. Kranenbarg!) +%% 2.4 -- Added \mcodefn{} command (thx Tony Almeida!) +%% 2.3 -- More keywords (thx Dominik Wild!) +%% 2.2 -- Bugfix (thx Willi Gerbig!) +%% 2.1 -- Finally automatic detection between end and end +%% 2.0 -- New options for line breaking and literate prog. +%% 1.8 -- Fixed typo in documentation regarding §...§ +%% 1.7 -- Added MATLAB block comment syntax %{ ...... %} +%% 1.6 -- Added some infos, dealing with keyword ``end'' +%% 1.5 -- Tweaked check to see wether textcomp is loaded +%% 1.4 -- Fixed misconfig (mathescape now set to false) +%% 1.3 -- Purely cosmetic (tabs replaced by spaces) +%% 1.2 -- Added \lstset{showstringspaces=false} +%% 1.1 -- Added \mcode command and [final] option +%% 1.0 -- Release + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% D O N ' T T O U C H T H I S % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\fileversion{2.5} +\def\filedate{2014/03/06} + +\typeout{-- Package: `mcode' \fileversion\space <\filedate> --} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{mcode}[\filedate\space\fileversion] + +% for bw-option +\newif\ifmcode@bw +\DeclareOption{bw}{\mcode@bwtrue} + +% numbered option +\newif\ifmcode@numbered +\DeclareOption{numbered}{\mcode@numberedtrue} + +% final option +\newif\ifmcode@final +\DeclareOption{final}{\mcode@finaltrue} + +% autolinebreaks option +\newif\ifmcode@autolinebreaks +\DeclareOption{autolinebreaks}{\mcode@autolinebreakstrue} + +% literate programming (replace certain characters/relations +\newif\ifmcode@useliterate +\DeclareOption{useliterate}{\mcode@useliteratetrue} + +% framed option +\newif\ifmcode@framed +\DeclareOption{framed}{\mcode@framedtrue} + +\DeclareOption*{% default + \PackageWarning{mcode}{Unknown option `\CurrentOption' !}% +} +\ProcessOptions + +\ifmcode@bw\typeout{ - settings optimized for printing (bw formating)} +\else\typeout{ - settings optimized for display (colour formating)}\fi +\ifmcode@numbered\typeout{ - line numbering enabled}\else\fi +\ifmcode@useliterate\typeout{ - literate programming (character replacements) enabled}\else\fi +\ifmcode@autolinebreaks\typeout{ - automatic line breaking enabled (careful, buggy!)}\else\fi +\ifmcode@framed\typeout{ - framed listings}\else\fi + +% This command allows you to typeset syntax highlighted Matlab +% code ``inline''. The font size \small seems to look best... +\newcommand{\mcode}[1]{\lstinline[basicstyle=\lstbasicfont\small]|#1|} + +% Same, but for footnotes +\newcommand{\mcodefn}[1]{\lstinline[basicstyle=\lstbasicfont\footnotesize]|#1|} + +% check if color command exists +\ifx\color\undefined% + \RequirePackage{xcolor}% +\fi + +% check if listings has been loaded +\ifx\lstset\undefined% + \ifmcode@final + \RequirePackage[final]{listings} + \else + \RequirePackage{listings} + \fi +\fi + +% Check if textcomp has been loaded (this package is needed for +% upright quotes '' (instead of typographic ones `´)... +\ifx\textquotesingle\undefined% + \RequirePackage{textcomp}% +\fi + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% C U S T O M I S E B E L O W % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% --------------------------------------------------------------------------------- +% default font +\def\lstbasicfont{\fontfamily{pcr}\selectfont\footnotesize} + +% --------------------------------------------------------------------------------- +% matlat languate definition +\lstdefinelanguage{matlabfloz}{% + alsoletter={...},% + morekeywords={% % keywords + break,case,catch,continue,elseif,else,end,% + for,function,global,if,otherwise,persistent,% + return,switch,try,while,methods,properties,% + events,classdef,...},% + comment=[l]\%, % comments + morecomment=[l]..., % comments + morecomment=[s]{\%\{}{\%\}}, % block comments + morestring=[m]' % strings +}[keywords,comments,strings]% + +% --------------------------------------------------------------------------------- +% general definitions +\lstset{% + basicstyle={\lstbasicfont}, % set font + showstringspaces=false, % do not emphasize spaces in strings + tabsize=4, % number of spaces of a TAB + mathescape=false,escapechar=§, % escape to latex with §...§ + upquote=true, % upright quotes + aboveskip={1.5\baselineskip}, % a bit of space above listings + columns=fixed % nice spacing +} + +% --------------------------------------------------------------------------------- +% define colours and styles +\ifmcode@bw % use font formating and gray 'colors' + \def\mcommentfont{\color[gray]{.75}\itshape} %comments light gray and italic + \lstset{language=matlabfloz, % use our version of highlighting + keywordstyle=\bfseries, % keywords in bold + commentstyle=\mcommentfont, % comments + stringstyle=\color[gray]{0.5} % strings darker gray + } +\else% notbw => use colors : ) + \def\mcommentfont{\color[rgb]{.133,.545,.133}} %comments in green + \lstset{language=matlabfloz, % use our version of highlighting + keywordstyle=\color[rgb]{0,0,1}, % keywords in blue + commentstyle=\mcommentfont, % comments + stringstyle=\color[rgb]{.627,.126,.941} % strings in purple + } +\fi%bw + +% --------------------------------------------------------------------------------- +% automatic line breaking --- warning, this is buggy and +% doesn't break comments correctly! +\ifmcode@autolinebreaks + \newsavebox{\lbreakdots}\sbox{\lbreakdots}{\lstbasicfont\mcommentfont...} + \lstset{breaklines=true,breakatwhitespace=true,prebreak=\usebox{\lbreakdots}} +\fi + +% --------------------------------------------------------------------------------- +% literate replacements +% the following is for replacing some matlab relations like >= or ~= +% by the corresponding LaTeX symbols, which are much easier to read ... +\ifmcode@useliterate + \lstset{% + literate=% + {~}{{$\neg$}}1 % \neg + {<=}{{\tiny$\leq$}}1 % \leq + {>=}{{\tiny$\geq$}}1 % \geq + {~=}{{\tiny$\neq$}}1 % \neq + {delta}{{\tiny$\Delta$}}1 % \Delta + {(end)}{\lstbasicfont (end)}{5} % black ``end'' when indexing last vector element + {({ }end)}{\lstbasicfont ({ }end)}{6} + {(end{ })}{\lstbasicfont (end{ })}{6} + {({ }end{ })}{\lstbasicfont ({ }end{ })}{7} + {:end}{\lstbasicfont :end}{4} + {:{ }end}{\lstbasicfont :{ }end}{5} + {end:}{\lstbasicfont end:}{4} + {end{ }:}{\lstbasicfont end{ }:}{5} + {,end}{\lstbasicfont ,end}{4} + {,{ }end}{\lstbasicfont ,{ }end}{5} + } +\else + \lstset{% + literate=% + {(end)}{\lstbasicfont (end)}{5} % black ``end'' when indexing last vector element + {({ }end)}{\lstbasicfont ({ }end)}{6} + {(end{ })}{\lstbasicfont (end{ })}{6} + {({ }end{ })}{\lstbasicfont ({ }end{ })}{7} + {:end}{\lstbasicfont :end}{4} + {:{ }end}{\lstbasicfont :{ }end}{5} + {end:}{\lstbasicfont end:}{4} + {end{ }:}{\lstbasicfont end{ }:}{5} + {,end}{\lstbasicfont ,end}{4} + {,{ }end}{\lstbasicfont ,{ }end}{5} + } +\fi%literates + +% --------------------------------------------------------------------------------- +% line numbering +\ifmcode@numbered% numbered option + \lstset{% + numbersep=3mm, numbers=left, numberstyle=\tiny, % number style + } +\fi + +\ifmcode@framed% framed option + \lstset{% + frame=single, % frame + } + \ifmcode@numbered% + \lstset{% + framexleftmargin=6mm, xleftmargin=6mm % tweak margins + } + \fi +\fi + +\endinput +%% End of file `mcode.sty'. \ No newline at end of file diff --git a/slides/slides_ode/ugent-nl.png b/slides/slides_ode/ugent-nl.png new file mode 100755 index 00000000..615eb1ab Binary files /dev/null and b/slides/slides_ode/ugent-nl.png differ