Skip to content
Snippets Groups Projects
Commit 9f3e5054 authored by Thom Groen's avatar Thom Groen
Browse files

Merge branch 'graph-interactivity' into 'main'

Added interactivity to Fig 3.3 of Chapter 3

See merge request !1
parents 273a7f35 db2b8ff9
No related branches found
No related tags found
1 merge request!1Added interactivity to Fig 3.3 of Chapter 3
......@@ -246,6 +246,99 @@ glue("dampedoscillations", fig, display=False)
Position as function of time for four types of oscillation: undamped ($\zeta = 0$, blue), underdamped ($0 < \zeta < 1$, orange), critically damped ($\zeta = 1$, green) and overdamped ($\zeta > 1$, red). In all cases the initial conditions are $x(0) = 1$ and $v(0) = 0$.
```
```{code-cell} ipython3
:tags: ["remove-input"]
import numpy as np
import plotly.graph_objects as go
# Define parameters for the slider
zeta_values = np.linspace(0, 2, 21)
fig = go.Figure()
# Function to determine color based on zeta value
def get_color(zeta):
if zeta == 0:
return '#0f63a3'
elif 0 < zeta < 1:
return 'orange'
elif zeta == 1:
return 'green'
else: # zeta > 1
return 'red'
# Function to determine damping condition based on zeta value
def get_damping_condition(zeta):
if zeta == 0:
return 'Undamped'
elif 0 < zeta < 1:
return 'Underdamped'
elif zeta == 1:
return 'Critically damped'
else: # zeta > 1
return 'Overdamped'
# Add traces for each zeta value
for zeta in zeta_values:
t = np.linspace(0, 4*np.pi, 400)
if zeta == 0:
y = np.cos(t)
elif zeta < 1:
y = np.exp(-zeta*t) * np.cos(np.sqrt(1-zeta**2) * t)
elif zeta == 1:
y = (1 + t) * np.exp(-t)
else: # zeta > 1
Omega = np.sqrt(zeta**2 - 1)
A = 0.5 + 1/(2*Omega)
B = 0.5 - 1/(2*Omega)
y = (A*np.exp((Omega - zeta) * t) + B*np.exp((-Omega - zeta) * t))
color = get_color(zeta)
damping_condition = get_damping_condition(zeta)
fig.add_trace(go.Scatter(x=t, y=y, visible=False, name=f'ζ = {zeta:.2f} ({damping_condition})', line=dict(color=color)))
# Make the first trace visible
fig.data[0].visible = True
# Create and add slider
steps = []
for i, zeta in enumerate(zeta_values):
damping_condition = get_damping_condition(zeta)
step = dict(
method="update",
args=[{"visible": [False] * len(zeta_values)},
{"title": f"Position as function of time for oscillation type: {damping_condition}"}],
label=f"{zeta:.2f}")
step["args"][0]["visible"][i] = True
steps.append(step)
sliders = [dict(
active=0,
currentvalue={"prefix": "\u03B6 = "},
pad={"t": 50},
steps=steps
)]
fig.update_layout(
sliders=sliders,
title=f"Position as function of time for oscillation type: {get_damping_condition(zeta_values[0])}",
yaxis=dict(range=[-1, 1]),
xaxis=dict(
tickmode='array',
tickvals=[0, np.pi, 2*np.pi, 3*np.pi, 4*np.pi],
ticktext=['0', '\u03C0', '2\u03C0', '3\u03C0', '4\u03C0']
),
xaxis_title='t',
yaxis_title='x(t)'
)
fig.show()
```
## Driven harmonic oscillator
```{index} harmonic oscillator ; driven
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment