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:
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 {