physics-simulations

A collection of physics simulations
git clone https://git.ashermorgan.net/physics-simulations/
Log | Files | Refs | README

commit d92e2c070fa9d57c675f6a18a431a041904dbc10
parent e1aef44d3f38eba8d8fb0912fe5cccf364498ecd
Author: AsherMorgan <59518073+AsherMorgan@users.noreply.github.com>
Date:   Sun, 28 Feb 2021 14:05:14 -0800

Add atwood machine simulation

Diffstat:
Mindex.html | 1+
Asimulations/atwood-machine.html | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asimulations/atwood-machine.js | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msimulations/circular-motion.html | 2+-
Msimulations/styles.css | 2+-
5 files changed, 152 insertions(+), 2 deletions(-)

diff --git a/index.html b/index.html @@ -15,6 +15,7 @@ <p>A collection of physics simulations</p> <ul> + <li><a href="simulations/atwood-machine.html">Atwood Machine Simulation</a></li> <li><a href="simulations/circular-motion.html">Circular Motion Simulation</a></li> </ul> </body> diff --git a/simulations/atwood-machine.html b/simulations/atwood-machine.html @@ -0,0 +1,66 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8"> + <title>Atwood Machine Simulation</title> + <meta name="Description" content="Atwood machine physics simulation and calculator"> + <meta name="viewport" content="width=device-width"> + <script src="https://cdn.jsdelivr.net/npm/vue@3.0.6"></script> + <link rel="stylesheet" href="styles.css"> + <script src="atwood-machine.js"></script> + </head> + <body onload="createApp()"> + <div id="app"> + <header> + <h1>Atwood Machine Simulation</h1> + </header> + + <noscript> + <p>This simulation requires JavaScript</p> + </noscript> + + <div id="input" hidden> + <section> + <label for="mass1Input"><b>Mass 1:</b> {{ mass1.toFixed(1) }} Kg</label> + <input type="range" min="1" max="10" step="0.1" v-model.number="mass1" @input="reset" :disabled="active" id="mass1Input"> + </section> + <section> + <label for="mass2Input"><b>Mass 2:</b> {{ mass2.toFixed(1) }} Kg</label> + <input type="range" min="1" max="10" step="0.1" v-model.number="mass2" @input="reset" :disabled="active" id="mass2Input"> + </section> + <section> + <label for="gravityInput"><b>Gravity:</b> {{ gravity.toFixed(1) }} m/s<sup>2</sup></label> + <input type="range" min="1" max="10" step="0.1" v-model.number="gravity" @input="reset" :disabled="active" id="gravityInput"> + </section> + <button @click="toggle" class="icon" :title="active ? 'Pause' : (time === 0 ? 'Start' : 'Resume')"> + <img alt="" :src="active ? '../images/pause.svg' : '../images/play.svg'"> + </button> + <button @click="reset" class="icon" title="Reset"> + <img alt="" src="../images/reset.svg"> + </button> + </div> + + <div id="output" hidden> + <svg width="200px" viewBox="0 0 4 8"> + <!-- Pulley --> + <circle cx="2" cy="1.1" r="1" stroke-width="0.1" stroke="#808080" fill="#404040"></circle> + + <!-- 1st weight --> + <line x1="1" y1="1.1" x2="1" :y2="4.1 + positions[0]" stroke-width="0.1" stroke="#808080"></line> + <circle cx="1" :cy="4.1 + positions[0]" :r="0.03*mass1+0.2" fill="#ff0000"></circle> + + <!-- 2nd weight --> + <line x1="3" y1="1.1" x2="3" :y2="4.1 + positions[1]" stroke-width="0.1" stroke="#808080"></line> + <circle cx="3" :cy="4.1 + positions[1]" :r="0.03*mass2+0.2" fill="#0000ff"></circle> + </svg> + </div> + + <div id="data" hidden> + <label><b>Time:</b> {{ time.toFixed(2) }} s</label> + <label><b>Displacement:</b> {{ Math.abs(positions[0]).toFixed(2) }} m</label> + <label><b>Speed:</b> {{ Math.abs(velocity).toFixed(2) }} m/s</label> + <label><b>Acceleration:</b> {{ Math.abs(acceleration).toFixed(2) }} m/s<sup>2</sup></label> + </div> + </div> + </body> +</html> diff --git a/simulations/atwood-machine.js b/simulations/atwood-machine.js @@ -0,0 +1,83 @@ +const App = { + data: function() { + return { + mass1: 1, // The mass of the 1st weight (Kg) + mass2: 10, // The mass of the 2nd weight (Kg) + gravity: 9.8, // The acceleration due to gravity (m/s/s) + time: 0, // The time (s) + active: false, // Whether the simulation is active + refreshRate: 0.01, // The simulation refresh rate (s) + intervalId: null, // The value returned by setInterval + } + }, + computed: { + /** + * The net force on the 1st weight + */ + netForce: function() { + return (this.mass1 * this.gravity) - (this.mass2 * this.gravity); + }, + + /** + * The acceleration of the 1st weight + */ + acceleration: function() { + return this.netForce / (this.mass1 + this.mass2); + }, + + /** + * The velocity of the 1st weight + */ + velocity: function() { + return this.acceleration * this.time; + }, + + /** + * The heights of the weights + */ + positions: function() { + let position = 0.5 * this.acceleration * this.time * this.time; + if (position > 3) position = 3; + if (position < -3) position = -3; + if (Math.abs(position) === 3) this.toggle(); + return [position, -position]; + }, + }, + methods: { + /** + * Toggle whether the simulation is active + */ + toggle: function() { + this.active = !this.active; + if (this.active) this.intervalID = setInterval(this.update, this.refreshRate * 1000); + else clearInterval(this.intervalID); + }, + + /** + * Reset the simulation + */ + reset: function() { + this.time = 0; + }, + + /** + * Update the simulation output + */ + update: function() { + this.time += this.refreshRate; + }, + }, +} + + + +// Create Vue app +function createApp() { + // Create app + Vue.createApp(App).mount("#app"); + + // Unhide app divs + document.getElementById("input").hidden = false; + document.getElementById("output").hidden = false; + document.getElementById("data").hidden = false; +} diff --git a/simulations/circular-motion.html b/simulations/circular-motion.html @@ -41,7 +41,7 @@ </div> <div id="output" hidden> - <svg viewBox="-1.5 -1.5 3 3"> + <svg width="400px" viewBox="-1.5 -1.5 3 3"> <!-- Circle outline --> <circle cx="0" cy="0" :r="radius" stroke="#808080" stroke-width="0.01" fill="none" stroke-dasharray="0.05,0.05"/> <circle cx="0" cy="0" r="0.025" fill="#000000"></circle> diff --git a/simulations/styles.css b/simulations/styles.css @@ -57,7 +57,7 @@ noscript { } #output svg { - width: 400px; + padding: 10px; } @media only screen and (max-width: 800px) { #output svg {