Skip to content

Instantly share code, notes, and snippets.

@globalpolicy
Created June 7, 2019 19:19
Show Gist options
  • Save globalpolicy/2d191e85ef2954c7b2c4b9fa2c27adaf to your computer and use it in GitHub Desktop.
Save globalpolicy/2d191e85ef2954c7b2c4b9fa2c27adaf to your computer and use it in GitHub Desktop.
Dam-break problem simulator
<html>
<head>
<title>Dam break simulation</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0/dist/Chart.min.js"></script>
</head>
<body>
<div id="chartDiv">
<canvas id="chart" width="500" height="400" style="border:1px solid">
</canvas>
</div>
<div>
<div>
<label for="xRange">X_max (m)</label>
<input type="range" min=1 max=100000 value=100 class="slider" id="xRange"
oninput='document.getElementById("xRangeVal").innerHTML=this.value'>
<label id="xRangeVal">100</label>
</div>
<div>
<label for="delX">delX (m)</label>
<input type="range" min=0.1 max=10000 value=2 step=0.1 class="slider" id="delX"
oninput='document.getElementById("delXVal").innerHTML=this.value'>
<label id="delXVal">2</label>
</div>
<div>
<label for="maxT">Simulation time (s)</label>
<input type="range" min=1 max=100000 value=100 class="slider" id="maxT"
oninput='document.getElementById("maxTVal").innerHTML=this.value'>
<label id="maxTVal">100</label>
</div>
<div>
<label for="delT">delT (s)</label>
<input type="range" min=0.0001 max=1000 value=0.01 step=0.0001 class="slider" id="delT"
oninput='document.getElementById("delTVal").innerHTML=this.value'>
<label id="delTVal">0.01</label>
</div>
<div>
<label for="y0">Reservoir water depth (m)</label>
<input type="range" min=0 max=1000 value=10 class="slider" id="y0"
oninput='document.getElementById("y0Val").innerHTML=this.value'>
<label id="y0Val">10</label>
</div>
<div>
<label for="delayMs">Delay between subsequent graphs (ms)</label>
<input type="range" min=10 max=1000 value=10 class="slider" id="delayMs"
oninput='document.getElementById("delayMsVal").innerHTML=this.value'>
<label id="delayMsVal">10</label>
</div>
<div>
<input type="button" value="Calculate" id="calculate" onClick="updateGraph()">
</div>
</div>
<script src="main.js"></script>
</body>
</html>
//s0ft
//Dam break simulation - Advanced Hydraulics
//MSc Water Resource Engineering
//June 8th, 2019
//12:17AM
let chart, worker;
function drawChart(output, y0) {
var ctx = document.getElementById('chart').getContext('2d');
if (chart != undefined) {
chart.destroy();
}
chart = new Chart(ctx, {
type: 'line',
data: {
labels: output.x,
datasets: [{
label: 'Depth (m)',
data: output.y,
borderColor: ['rgba(255, 99, 132, 1)'],
borderWidth: 1,
fill: false,
pointRadius: 1
}]
},
options: {
animation: {
duration: 0
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
max: y0
},
scaleLabel:{
display:true,
labelString:'Depth y (m)'
}
}],
xAxes: [{
ticks: {
autoSkip: true
},
scaleLabel: {
display: true,
labelString: 'x (m)'
}
}]
},
title: {
display: true,
text: output.t + " s"
},
maintainAspectRatio: false,
responsive: true
}
});
}
function updateGraph(e) {
if (worker != undefined) {
worker.terminate();
}
var delT = document.getElementById("delT").valueAsNumber;
var delX = document.getElementById("delX").valueAsNumber;
var xRange = document.getElementById("xRange").valueAsNumber;
var maxT = document.getElementById("maxT").valueAsNumber;
var y0 = document.getElementById("y0").valueAsNumber;
var delayMs = document.getElementById("delayMs").valueAsNumber;
if(2*xRange/delX>100){
alert("Please increase delX. Current value gives too many data points.\nKeep delX ~ 1/50 of xRange");
return;
}
worker = new Worker("worker.js");
worker.postMessage({
y0,
delT,
delX,
xRange,
maxT,
delayMs
});
worker.onmessage = (event) => {
var data = event.data;
drawChart(data, y0);
}
}
updateGraph();
//s0ft
//Dam break simulation - Advanced Hydraulics
//MSc Water Resource Engineering
//June 8th, 2019
//12:17AM
let t;
function calculateSurfaceProfile(y0, delT, delX, xRange, maxT, delayMs) {
if (t == undefined) {
t = 0.00001;
}
if (t > maxT) {
return;
}
var X = [];
var Y = [];
for (var x = -xRange; x <= xRange; x += delX) {
X.push(x);
var c0 = Math.pow((9.81 * y0), 0.5);
if (x <= 0) {
if (Math.abs(x) <= c0 * t) {
Y.push(Math.pow((2 * c0 - x / t), 2) / (9 * 9.81));
} else {
Y.push(y0);
}
} else {
if (x < 2 * c0 * t) {
Y.push(Math.pow((2 * c0 - x / t), 2) / (9 * 9.81));
} else {
Y.push(0);
}
}
}
postMessage({
x: X,
y: Y,
t: t
});
t += delT;
setTimeout(() => {
calculateSurfaceProfile(y0, delT, delX, xRange, maxT, delayMs);
}, delayMs);
}
onmessage = function (ev) {
var y0 = ev.data.y0;
var delT = ev.data.delT;
var delX = ev.data.delX;
var xRange = ev.data.xRange;
var maxT = ev.data.maxT;
var delayMs = ev.data.delayMs;
calculateSurfaceProfile(y0, delT, delX, xRange, maxT, delayMs);
}
onerror = function (error) {
var error = error.message;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment