Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
M
Mechanica
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Open textbooks
Mechanica
Commits
2798ec5d
Commit
2798ec5d
authored
1 month ago
by
Minouk Noordsij
Browse files
Options
Downloads
Plain Diff
Merge branch 'Interactive_Ch3' into 'main'
add interactive plot See merge request
!1
parents
36deac60
fc513db6
No related branches found
No related tags found
1 merge request
!1
add interactive plot
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
content/Ch3_AnalyticalOrNumerical.md
+110
-85
110 additions, 85 deletions
content/Ch3_AnalyticalOrNumerical.md
with
110 additions
and
85 deletions
content/Ch3_AnalyticalOrNumerical.md
+
110
−
85
View file @
2798ec5d
...
...
@@ -137,48 +137,40 @@ Note, that for $Re<1$ the friction force tends to $F_f \propto -v$ as we had in
### Simulation of a falling hail stone: friction versus no friction with the surrounding air ###
```
{
code-cell
}
ipython3
:tags
:
[
hide-input
,
remove-output
]
:tags
:
[
hide-input
]
#
, remove-output]
%
config InlineBackend.figure_formats = ['svg']
import plotly.graph_objects as go
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams.update({'font.size'
:
12})
from matplotlib.widgets import Button, Slider
from myst_nb import glue
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#"""
#Created on Wed Oct 30 11:39:43 2024
#
#@author: rmudde
#"""
rho_p =
915
################ Code used for physics ################
# Define constants
rho_p =
915
rho_air =
1.2
mu_air = 1.8e-5
D = 2.5e-3
H = 1e3
g =
9.813
v0 =
0
z0 = H
m = np.pi/6 * D**3 * rho_p
A = np.pi/4 * D**2
mu_air
= 1.8e-5
D
= 2.5e-3
H
= 1e3
g
=
9.813
v0
=
0
z0
= H
m
= np.pi/6 * D**3 * rho_p
A
= np.pi/4 * D**2
Vol = np.pi/6 * D**3
dt = 1e-2
dt
= 1e-2
Ndata =
501
# Update D values
def recalc(D)
:
D = D
m = np.pi/6 * D**3 * rho_p
A = np.pi/4 * D**2
'
'
'
Function
to
recompute
all
values
that
depend
on
D'
'
'
D = D
m = np.pi/6 * D**3 * rho_p
A = np.pi/4 * D**2
Vol = np.pi/6 * D**3
return D, m, A, Vol
def CD(v,D)
:
#
compute drag coefficient
'
'
'
Function
to
compute
the
drag
coefficient
'
'
'
Re = rho_air * np.abs(v) * D / mu_air
if Re < 1e-6
:
Re = 1e-6
...
...
@@ -186,16 +178,17 @@ def CD(v,D):
return CD
def force(v,D,m,Vol,A)
:
'
'
'
Function
to
compute
the
force'
'
'
f = -m*g + rho_air*Vol*g - CD(v,D)*A*1/2*rho_air*np.abs(v)*v
return f
# The parametrized function to be plotted
def velo(D)
:
'
'
'
Parametrized
function
to
determine
t,
v
and
v
without
friction
used
in
plotting'
'
'
recalc(D)
v
=
[]
v
=
[]
v_nofriction = []
z
=
[]
t
=
[]
z
=
[]
t
=
[]
v.append(v0)
v_nofriction.append(v0)
z.append(z0)
...
...
@@ -209,68 +202,100 @@ def velo(D):
v.append(v_new)
z.append(z_new)
v_nofriction.append(-g*teller*dt)
return t,v,v_nofriction
return t,
v,
v_nofriction
# Compute initial values
[
t
,
v
,
v_nofriction
]
= velo(D)
################ Code used for Interactive Plot ################
line_red = '#e96868'
# red line
line_blue = '#68a0e9'
# blue line
fig = go.Figure()
fig, ax = plt.subplots(figsize=(6,4))
line, = ax.plot(t[0:Ndata], v[0:Ndata], '-r')
line2, = ax.plot(t[0:Ndata], v_nofriction[0:Ndata], '-b')
ax.axhline(y = 0, color = 'k', linestyle = ':')
ax.set_xlim(0,t[Ndata])
ax.set_ylim(2.0*v[Ndata],0)
ax.set_xlabel('$t$')
ax.set_ylabel('$v(t)$')
plt.title('velocity of a hail stone')
plt.grid()
plt.legend(['friction','no-friction'])
# adjust the main plot to make room for the sliders
fig.subplots_adjust(left=0.25, bottom=0.25)
# Make a horizontal slider to control the frequency.
axdia = fig.add_axes([0.25, 0.1, 0.65, 0.03])
dia_slider = Slider(
ax=axdia,
label='diameter [mm]',
valmin=0.1,
valmax=5.0,
valinit=2.5,
)
# Define the steps for the slider and an empty array of the minimum values used later for setting the y-axis range
slider_steps = np.arange(0.1,5,0.1)
vmin = np.zeros_like(slider_steps)
# The function to be called anytime a slider's value changes
def upda
te
(
val
)
:
D =
dia_slider.
val * 1e-3
for ind,val in enumerate(slider_steps)
:
# Rescale D to meters and compu
te
val
ues
D = val * 1e-3
recalc(D)
[t,v,v_nofriction] = velo(D)
line.set_ydata(v[0:Ndata])
ax.set_ylim(2.0*v[Ndata],0)
fig.canvas.draw_idle()
# register the update function with each slider
dia_slider.on_changed(update)
# Create a `matplotlib.widgets.Button` to reset the sliders to initial values.
resetax = fig.add_axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', hovercolor='0.975')
vmin[ind] = min(v)
# Add the trace with friction
fig.add_trace(
go.Scatter(
visible=False,
x = t,
y = v,
line = dict(color=line_red),
mode = 'lines',
name = 'friction'))
# Add the trace without friction
fig.add_trace(
go.Scatter(
visible=False,
x = t,
y = v_nofriction,
line = dict(color=line_blue),
mode = 'lines',
name = 'no friction'))
# Update the y-axis range
fig.update_yaxes(range=[2 * v[-1], 0], title_text=r'v(t)')
base_traces = 0
traces_per_step =
2
# Number of traces per value of a
# Show the traces for one value of a when loading the plot (initial setup)
active_index = slider_steps.shape[0]//2
# Set the traces for the active value of D to visible
for i in range(traces_per_step)
:
current_index = int(base_traces + active_index*traces_per_step + i)
fig.data[current_index].visible = True
steps = []
for i in range(0, slider_steps.shape[0])
:
# Make only the traces for the current value of a visible
visarray = [False] * len(fig.data)
visarray[0:base_traces] = [True] * base_traces
current_index = int(base_traces + i * traces_per_step)
next_idx = int(base_traces + (i+1) * traces_per_step)
visarray[current_index:next_idx] = [True] * traces_per_step
# Define content of the slider step
step = dict(
method="update",
args=[
{"visible"
:
visarray},
{"yaxis.range"
:
[
2 * vmin
[
i
],
0
]
},
{
"
yaxis.titletext"
:
r'v(t)'
}
],
label=str(round(slider_steps[i], 1))
)
steps.append(step)
sliders = [dict(
active = active_index,
currentvalue = {"prefix"
:
"
diameter:
"
,
"
suffix"
:
"
mm"
,
"
font"
:
{
"
size"
:
20
}
},
steps = steps
)]
def reset(event)
:
dia_
slider
.reset()
button.on_clicked(reset
)
fig.update_layout(
slider
s=sliders,
legend_title="Legend"
)
plt.show(
)
fig.update_xaxes(title_text=r't [s]', range=[0, 5]
)
#
Save graph to load in figure later (special Jupyter Book feature)
glue("HailStone", fig, display=True)
#
Update yaxis properties
fig
```
```
{
glue
:
figure
}
HailStone
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment