Skip to content

Instantly share code, notes, and snippets.

@globalpolicy
Created May 30, 2019 04:34
Show Gist options
  • Save globalpolicy/a431dc0b9bf0b82c052acca25822b63a to your computer and use it in GitHub Desktop.
Save globalpolicy/a431dc0b9bf0b82c052acca25822b63a to your computer and use it in GitHub Desktop.
Mein and Larson infiltration model with finite time steps
<html>
<head>
<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="600" height="600" style="border:1px solid">
</canvas>
</div>
<script src="run.js"></script>
</body>
</html>
//s0ft
function getRainfallIntensity(time) {
if (time <= 1) {
return 1.5;
} else if (time > 1 && time <= 4) {
return 0.1;
} else if (time > 4 && time <= 6) {
return 0.5;
} else if (time > 6) {
return 0;
}
}
function run(targetT, delT, startF_p, startf, t_p) {
const numIterations = (targetT - 0) / delT;
var t = 0;
var F = startF_p;
var f = startf;
var I_avg = 0,
f = 0,
delP = 0,
S = 0,
delS = 0,
RO = 0,
delF = 0,
Q = 0;
var output = {
t: [],
f: [],
F: [],
Q: [],
S: []
};
for (var i = 1; i <= numIterations; i++) {
if(t<t_p){
output.t.push(t);
output.f.push(getRainfallIntensity(t));
output.F.push(getRainfallIntensity(t)*t);
output.Q.push(0);
output.S.push(0);
t+=delT;
continue;
}
I_avg = (getRainfallIntensity(t) + getRainfallIntensity(t+delT)) / 2;
delF = f * delT;
F += delF;
delP = I_avg * delT;
delS = delP - delF;
S += delS;
if (S > 0.5) {
RO = S - 0.5;
S = 0.5;
} else {
RO = 0;
}
if (S < 0) { //infiltration is greater than precipitation and so soil desaturation is taking place
S = 0; //storage remains at zero
}
Q = RO / delT;
f = K_s * (1 + (s*IMD) / F);
output.t.push(t);
output.f.push(f);
output.F.push(F);
output.Q.push(Q);
output.S.push(S);
t += delT;
console.log("t=" + t + ";I_avg=" + I_avg + ";F=" + F + ";f=" + f + ";S=" + S + ";RO=" + RO + ";Q=" + Q);
}
return output;
}
function drawChart(output) {
var ctx = document.getElementById('chart').getContext('2d');
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: output.t,
datasets: [{
label: 'Infiltration rate f (cm/hr)',
data: output.f,
borderColor: ['rgba(255, 99, 132, 1)'],
borderWidth: 1,
fill: false,
pointRadius: 1
},
{
label: 'Total infiltration F (cm)',
data: output.F,
borderColor: ['rgba(11,200,50,1)'],
borderWidth: 1,
fill: false,
pointRadius: 1
},
{
label: 'Runoff (cm/hr)',
data: output.Q,
borderColor: ['rgba(11,50,230,1)'],
borderWidth: 1,
fill: false,
pointRadius: 1
},
{
label: 'Storage (cm)',
data: output.S,
borderColor: ['rgba(111,50,30,1)'],
borderWidth: 1,
fill: false,
pointRadius: 1
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
ticks: {
autoSkip: true,
autoSkipPadding: 30
},
scaleLabel: {
display: true,
labelString: 'Time (hr)'
}
}]
},
maintainAspectRatio: false,
responsive: true
}
});
}
function pruneOutput(output, skipNum) {
var prunedOutput = {
t: [],
f: [],
F: [],
Q: [],
S: []
};
for (var i = 0; i < output.t.length; i++) {
if (i % (skipNum + 1) == 0) {
prunedOutput.t.push(output.t[i].toFixed(2));
prunedOutput.f.push(output.f[i]);
prunedOutput.F.push(output.F[i]);
prunedOutput.Q.push(output.Q[i]);
prunedOutput.S.push(output.S[i]);
}
}
return prunedOutput;
}
const s = 22.4,
IMD = 0.25,
K_s = 0.044;
let F_p = (s * IMD) / (getRainfallIntensity(0) / K_s - 1);
let t_p = F_p / getRainfallIntensity(0);
output = run(10, 0.01, F_p, getRainfallIntensity(t_p), t_p);
prunedOutput = pruneOutput(output, 8); //skip eight numbers between picks
drawChart(prunedOutput);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment