-
Notifications
You must be signed in to change notification settings - Fork 1
/
oscillator.html
144 lines (126 loc) · 4.93 KB
/
oscillator.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://api.fonts.coollabs.io">
<title>Oscillators</title>
<meta name="description" content="Numerical simulations of Oscillator in JavaScript">
<link rel="stylesheet" href="css/ode.css">
<link rel="stylesheet" href="https://api.fonts.coollabs.io/css2?family=Raleway:wght@300;400;600&display=swap">
<link rel="preload" href="css/uplot.min.css" as="style">
<link rel="preload" href="scripts/ode.js" as="script">
<link rel="preload" href="scripts/uplot.min.js" as="script">
</head>
<body>
<a class="homeLink" href="./"><svg width="40" height="40" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M11.9481 14.8285L10.5339 16.2427L6.29126 12L10.5339 7.7574L11.9481 9.17161L10.1197 11H17.6568V13H10.1197L11.9481 14.8285Z"
fill="currentColor" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M23 19C23 21.2091 21.2091 23 19 23H5C2.79086 23 1 21.2091 1 19V5C1 2.79086 2.79086 1 5 1H19C21.2091 1 23 2.79086 23 5V19ZM19 21H5C3.89543 21 3 20.1046 3 19V5C3 3.89543 3.89543 3 5 3H19C20.1046 3 21 3.89543 21 5V19C21 20.1046 20.1046 21 19 21Z"
fill="currentColor" />
</svg></a>
<h1>Oscillators</h1>
<p>
Harmonic oscillators are used to describe a variety of systems in physics, like pendulums, electronic circuits and
even <a href="https://en.wikipedia.org/wiki/Quantum_harmonic_oscillator">quantum particles</a> in a potential well.
The underlying equation is the following second order ODE
</p>
<object style="width: 100%; max-height: 1.8em;" data="images/oszi.svg" type="image/svg+xml">harmonic oscillator
ode</object>
<p>
The parameter gamma is an optional dampening factor. In the demo Below, different numerical methods are used to
solve this popular differential equation. As you can see, the simpler methods diverge quickly and only produce
accurate results when the simulation step size is significantly smaller than the oszillation frequency, while the
higher order Runge Kutta Method produces useful results, even at a low resolution.
</p>
<div style="display: flex; justify-content: space-between;">
<div class="sliderscont">
<input type="range" oninput="updateSim()" min="3" max="14" value="8" name="resolution slider" id="alphaSlid">
<label for="alphaSlid">resolution</label>
<input type="range" oninput="updateInitialValues()" value="2" min="-10" max="10" step="any" name="amplitude"
id="betaSlid">
<label for="betaSlid">initial amplitude</label>
</div>
<div class="sliderscont">
<input type="range" oninput="updateInitialValues()" value="5" min="0.1" max="10" step="any"
name="resonance slider" id="deltaSlid">
<label for="deltaSlid">resonance frequency</label>
<input type="range" oninput="updateInitialValues()" value="0.1" min="0" max="1" step="any" name="dampening slider"
id="gammaSlid">
<label for="gammaSlid">dampening</label>
</div>
</div>
<noscript>
<p>
Please enable JavaScript for a live demo. I promise it's not for tracking.
</p>
</noscript>
<div id="plot"></div>
</body>
<link rel="stylesheet" href="css/uplot.min.css">
<script src="scripts/uplot.min.js"></script>
<script src="scripts/ode.js"></script>
<script>
var plotElem = document.getElementById("plot")
var dampening = 0.1
var resonance = 5
function getSliderValue(id) {
return parseFloat(document.getElementById(id).value)
}
var Oscillator = (t, y) => {
dampening = getSliderValue("gammaSlid")
resonance = getSliderValue("deltaSlid")
return [y[1], -resonance * y[0] - y[1] * dampening]
}
var solver = new ODEsolver(Oscillator, [2, 0], 0, 20)
function updateInitialValues() {
solver.y0[0] = getSliderValue("betaSlid")
updateSim()
}
function updateSim() {
u.setData(calcOde(Math.pow(2, document.getElementById("alphaSlid").value)))
}
const opts = {
width: 900,
height: 900,
title: "Oscillator",
scales: {
x: { time: false },
y: { range: [-10, 10] }
},
series: [
{ label: "t" },
{
label: "Euler",
stroke: "#D32F2F",
},
{
label: "Midpoint",
stroke: "#ff8000",
},
{
label: "RK4",
stroke: "#12B02F",
},
],
}
function calcOde(resolution) {
const eres = solver.euler(~~resolution)
data = [
eres.ts,
eres.ys.map((t) => t[0]),
solver.midpoint(~~resolution).ys.map((t) => t[0]),
solver.rk4(~~resolution).ys.map((t) => t[0]),
]
return data
}
var u = new uPlot(opts, calcOde(2 ** 8), plotElem)
u.setSize({ width: plotElem.clientWidth, height: plotElem.clientWidth })
window.addEventListener("resize", e => {
u.setSize({ width: plotElem.clientWidth, height: plotElem.clientWidth })
})
</script>
</html>