Skip to content

Commit 1942f90

Browse files
committed
Update blog post
1 parent 6a7e555 commit 1942f90

File tree

5 files changed

+169
-32
lines changed

5 files changed

+169
-32
lines changed

_posts/guides/interactive-blog/2025-02-13-interactive-julia-plotting.md

Lines changed: 120 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,17 @@ order of rendering, since new dependencies get included in the session that firs
7878
that dependency.
7979
{% endalert %}
8080

81-
## A DifferentialEquations.jl example
81+
## A second example
82+
83+
To render multiple plots we need to use a `Subsession`, which skips uploading similar
84+
assets/data and setup. The sub session can be created by calling `Session(session)` with
85+
the parent session as an argument.
86+
87+
{% include_code file="_posts/guides/interactive-blog/plots.jl" lang="julia" start="30" end="34" %}
88+
89+
{% include_relative volume.html %}
90+
91+
## (Bonus) A DifferentialEquations.jl example
8292

8393
Now for a more exciting example, we will use the
8494
[DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/stable/) package to calculate
@@ -88,7 +98,7 @@ to visualize the resulting trajectory.
8898
We will start from a physical description of the problem. This description is derived
8999
from Newton's second law of motion, which states that the acceleration of an object is
90100
directly proportional to the net forces acting on it. An excellent summary of the
91-
physics involved can be found in a series of blog posts by Hugo, namely [Bend it like Newton: curves in football](http://chalkdustmagazine.com/blog/bend-it-like-newton-curves-in-football/) and [The maths behind a chip goal](https://chalkdustmagazine.com/blog/the-maths-behind-a-chip-goal/).
101+
physics involved can be found in a series of blog posts by Hugo, namely [Bend it like Newton: curves in football](http://chalkdustmagazine.com/blog/bend-it-like-newton-curves-in-football/), [The maths behind a chip goal](https://chalkdustmagazine.com/blog/the-maths-behind-a-chip-goal/) and [Football free-kicks… taken by Newton](https://chalkdustmagazine.com/blog/free-kicks/).
92102

93103
<div style="margin-top: 20px; margin-bottom: -100px;"><center>
94104
<svg viewBox="0 0 250 250">
@@ -99,20 +109,125 @@ physics involved can be found in a series of blog posts by Hugo, namely [Bend it
99109
### The trajectory of a soccer ball
100110

101111
The position of a soccer ball in three dimensions can be described by a vector
102-
$\vec{x} = [x, y, z]^T$.
112+
$\vec{x} = [x, y, z]^T$, its velocity by $\vec{v} = [v_x, v_y, v_z]^T $. The
113+
initial position of the ball is $\vec{p}_0$, and the initial velocity is $\vec{v}_0$.
103114

104115
Newton's second law of motion relates the acceleration of the ball to the forces acting
105116
on it. Mathematically, this can be written as:
106117

107118
$$
108119
\begin{equation}
109-
m \frac{d^2 \vec{x}}{dt^2} = \vec{F_G} + \vec{F_D} + \vec{F_L}
120+
m \cdot \vec{a} = m \frac{d^2}{dt^2}\vec{x} = \vec{F_G} + \vec{F_D} + \vec{F_L}
110121
\end{equation}
111122
$$
112123

113124
Where we consider the gravitational force $\vec{F_G}$, the drag force $\vec{F_D}$ and the
114125
lift force $\vec{F_L}$. We are interested in solving this equation for $\vec{x}$ because
115-
that will give us the position of the ball at any given time. $m$ is the mass of the ball.
126+
that will give us the position of the ball (with mass $m$) at any given time $t$.
127+
128+
We will refer to the <i>trajectory</i> of the ball as the time-dependent position vector
129+
$\vec{x}(t)$.
130+
</div>
131+
132+
There are a bunch of interesting questions we can ask in this general problem context.
133+
A few that come to mind are:
134+
- How does the trajectory of the ball change when we change the initial velocity $\vec{v}_0$?
135+
- Given some initial velocity $\vec{v}_0$, what is the maximum horizontal distance the ball can travel?
136+
- Given (noisy) observations of a ball's trajectory, can we estimate what the initial
137+
position $\vec{p}_0$ and velocity $\vec{v}_0$ were? Or even more interesting, can we
138+
predict where the ball will land while it is still in the air?
139+
140+
<div class="theorem-box" markdown="1">
141+
### Forces affecting a ball’s trajectory
142+
143+
The gravitational force $\vec{F_G}$ is given by:
144+
145+
$$
146+
\begin{equation}
147+
\vec{F_G} = -m \vec{g}
148+
\end{equation}
149+
$$
150+
151+
Where $\vec{g} = [0, 0, 9.81]^T$ is the downward acceleration due to gravity. The drag
152+
force $\vec{F_D}$ is the aerodynamic force that opposes the motion of the ball due to air
153+
resistance. It is given by:
154+
155+
$$
156+
\begin{equation}
157+
\vec{F_D} = -\frac{1}{2} \rho A C_D \left| \vec{v} \right| \cdot \vec{v}
158+
\end{equation}
159+
$$
160+
161+
Where $\rho$ is the air density, $A$ is the cross-sectional area of the ball,
162+
$C_D$ is the drag coefficient, $v$ is the velocity of the ball and
163+
$\left| \vec{v} \right| = \sqrt{v_x^2 + v_y^2 + v_z^2}$ is the magnitude of the velocity.
164+
165+
The lift force $\vec{F_L}$, or Magnus force, is the force that causes the ball to curve
166+
in flight and is perpendicular to the velocity vector of the ball $\vec{v}$. It is given
167+
by:
168+
169+
$$
170+
\begin{equation}
171+
\vec{F_L} = \frac{1}{2} \rho A C_L \left| \vec{v} \right| \cdot \vec{v} \cdot f(\theta)
172+
\end{equation}
173+
$$
174+
175+
Where $C_L$ is the lift coefficient, $\theta$ is the angle of attack and $f(\theta)$ is a
176+
function that depends on the spin angle of the ball. Let's assume that the ball is spinning
177+
around the $z$-axis, then $f(\theta) = [-1, 1, 0]^T$ where we assume that the dependence
178+
on the angular velocity $\omega$ is already included in $C_L$.
179+
</div>
180+
181+
We are now almost there. We have a physical description of the problem, but this
182+
description is only solvable analytically in specific, simplified cases. We need to
183+
write out the equations in a form that can be solved numerically, so that we can then
184+
use the `DifferentialEquations.jl` package to integrate the equations of motion which
185+
will give us the trajectory of the ball.
186+
187+
<div class="theorem-box" markdown="1">
188+
### System of differential equations
189+
190+
To make it easier to write out the equations of motion, we will introduce the
191+
constant $H = \frac{\rho A}{2m}$, which will simplify the equations.
192+
193+
Using the fact that $\frac{dx}{dt} = v_x, \frac{dy}{dt} = v_y, \frac{dz}{dt} = v_z$ the
194+
system of differential equations can then be written as:
195+
196+
<!-- $$
197+
\begin{align}
198+
H &= \frac{\rho A}{2m} \\
199+
\left| \vec{v} \right| &= \sqrt{v_x^2 + v_y^2 + v_z^2}
200+
% C_L &= \left| \vec{v} \right|^{-1} \omega r \\ % C_L &= \frac{\omega r}{\left| \vec{v} \right|}\\
201+
% \omega &= \omega_0 \cdot \exp\left(-\frac{t}{\tau}\right)
202+
\end{align}
203+
$$ -->
204+
205+
$$
206+
\begin{align}
207+
\vec{a} &= -\left | \vec{v}\right | H
208+
\begin{bmatrix}
209+
C_D \cdot v_x + C_L \cdot v_y \\
210+
C_D \cdot v_y - C_L \cdot v_x \\
211+
C_D \cdot v_z - g
212+
\end{bmatrix}
213+
\end{align}
214+
$$
215+
216+
The value of $C_L$ is usually derived from experiments and depends on the speed and
217+
angular velocity of the ball. We will assume that $C_L$ takes the following form:
218+
219+
$$
220+
\begin{align}
221+
C_L &= \frac{\omega r}{\left| \vec{v} \right|}\\
222+
\omega &= \omega_0 \cdot \exp\left(-\frac{t}{\tau}\right)
223+
\end{align}
224+
$$
225+
226+
Where $\omega_0$ is the initial angular velocity and $\tau$ is the time constant. We
227+
will solve this system numerically to get the trajectory of the ball.
116228
</div>
117229

230+
Now we can finally start writing code! Which should be a breeze after because we have
231+
access to [DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/stable/).
118232

233+
{% include_code file="_posts/guides/interactive-blog/plots.jl" lang="julia" start="30" end="50" %}

_posts/guides/interactive-blog/plots.jl

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using Bonito, WGLMakie
22

3-
output_file = "_posts/examples/diffeqviz/sinc_surface.html"
3+
output_folder = "_posts/guides/interactive-blog/"
44

55
function as_html(io, session, app)
66
dom = Bonito.session_dom(session, app)
@@ -10,14 +10,14 @@ end
1010
session = Session(NoConnection(); asset_server=NoServer())
1111

1212
# plot 1 - random scatter plot
13-
open("_posts/guides/interactive-blog/scatter.html", "w") do io
13+
open(output_folder * "scatter.html", "w") do io
1414
println(io, """<center>""")
1515
app = App() do
16-
markersize = Bonito.Slider(range(0.01, stop=0.11, length=6))
16+
markersize = Bonito.Slider(range(0.01, stop=0.11, length=6), value=0.07)
1717
scale_value = DOM.div("\\(s = \\)", markersize.value)
1818

1919
# Create a scatter plot
20-
fig, ax = meshscatter(rand(3, 100), markersize=markersize, figure=(; size=(550, 550)))
20+
fig, ax = meshscatter(rand(3, 100), markersize=markersize, figure=(; size=(500, 500)))
2121

2222
# Return the plot and the slider
2323
return Bonito.record_states(session, DOM.div(fig, scale_value, markersize))
@@ -26,27 +26,36 @@ open("_posts/guides/interactive-blog/scatter.html", "w") do io
2626
println(io, """</center>""")
2727
end
2828

29-
using DifferentialEquations
30-
31-
# struct to hold problem constants
32-
struct SoccerConst
33-
m::Float64 # mass of the ball
34-
g::Float64 # acceleration due to gravity
35-
r::Float64 # radius of the ball
36-
ρ::Float64 # density of the air
37-
C_L::Float64 # lift coefficient
38-
C_D::Float64 # drag coefficient
29+
# plot 2 - volume plot
30+
open(output_folder * "volume.html", "w") do io
31+
sub = Session(session)
32+
app = App(volume(rand(10, 10, 10), figure=(; size=(500, 500))))
33+
as_html(io, sub, app)
3934
end
4035

41-
# inital conditions
42-
struct SoccerIC
43-
x::Float64 # initial x position
44-
y::Float64 # initial y position
45-
z::Float64 # initial z position
46-
v_x::Float64 # initial x velocity
47-
v_y::Float64 # initial y velocity
48-
v_z::Float64 # initial z velocity
49-
end
36+
# plot 3 - differential equation
37+
38+
# using DifferentialEquations
39+
40+
# # struct to hold problem constants
41+
# struct SoccerConst
42+
# m::Float64 # mass of the ball
43+
# g::Float64 # acceleration due to gravity
44+
# r::Float64 # radius of the ball
45+
# ρ::Float64 # density of the air
46+
# C_L::Float64 # lift coefficient
47+
# C_D::Float64 # drag coefficient
48+
# end
49+
50+
# # inital conditions
51+
# struct SoccerIC
52+
# x::Float64 # initial x position
53+
# y::Float64 # initial y position
54+
# z::Float64 # initial z position
55+
# v_x::Float64 # initial x velocity
56+
# v_y::Float64 # initial y velocity
57+
# v_z::Float64 # initial z velocity
58+
# end
5059

5160
# open("_posts/examples/diffeqviz/contour.html", "w") do io
5261
# app = App() do

_posts/guides/interactive-blog/scatter.html

Lines changed: 4 additions & 4 deletions
Large diffs are not rendered by default.

_posts/guides/interactive-blog/volume.html

Lines changed: 12 additions & 0 deletions
Large diffs are not rendered by default.

assets/css/theorem.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
border: 2px solid rgba(50, 50, 53, 0.5);
77
padding: 20px;
88
border-radius: 5px;
9+
margin-bottom: 50px;
910
}
1011

1112
.theorem-box h3 {

0 commit comments

Comments
 (0)