-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
122 lines (111 loc) · 3.81 KB
/
index.html
File metadata and controls
122 lines (111 loc) · 3.81 KB
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Upwind Footprint (Interactive)</title>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body style="font-family: sans-serif; margin: 20px;">
<h2>Interactive Upwind Footprint</h2>
<div>
<label>Sensor height (m): <span id="heightVal">20</span></label>
<input type="range" id="height" min="2" max="100" step="1" value="20">
</div>
<div>
<label>Wind speed (m/s): <span id="windVal">5</span></label>
<input type="range" id="wind" min="0.5" max="15" step="0.5" value="5">
</div>
<div>
<label>Stability: </label>
<select id="stability">
<option value="unstable">Unstable</option>
<option value="neutral" selected>Neutral</option>
<option value="stable">Stable</option>
</select>
</div>
<div id="plot" style="width: 800px; height: 500px;"></div>
<script>
// Gamma PDF function
function gammaPDF(x, k, theta) {
if (x <= 0) return 0;
return Math.pow(x, k-1) * Math.exp(-x/theta) / (Math.pow(theta, k) * gammaFunc(k));
}
// Approximate Gamma function (Lanczos approximation)
function gammaFunc(z) {
const g = 7;
const p = [
0.99999999999980993, 676.5203681218851,
-1259.1392167224028, 771.32342877765313,
-176.61502916214059, 12.507343278686905,
-0.13857109526572012, 9.9843695780195716e-6,
1.5056327351493116e-7
];
if(z < 0.5) {
return Math.PI / (Math.sin(Math.PI*z) * gammaFunc(1-z));
}
z -= 1;
let x = p[0];
for(let i = 1; i < g+2; i++) {
x += p[i] / (z + i);
}
let t = z + g + 0.5;
return Math.sqrt(2*Math.PI) * Math.pow(t, z+0.5) * Math.exp(-t) * x;
}
function footprint(z, U, stability) {
const kMap = {unstable: 1.8, neutral: 2.2, stable: 3.0};
const sMap = {unstable: 0.6, neutral: 1.0, stable: 1.8};
let k = kMap[stability];
let baseScale = z * (10.0 / Math.max(U, 0.1));
let theta = baseScale * sMap[stability];
let x = [];
let f = [];
let xmax = Math.max(300, 12*baseScale);
let n = 800;
for (let i=0; i<n; i++) {
let xi = i * xmax / (n-1);
x.push(xi);
f.push(gammaPDF(xi, k, theta));
}
// Normalize numerically
let area = 0;
for (let i=1; i<n; i++) {
area += 0.5*(f[i]+f[i-1])*(x[i]-x[i-1]);
}
f = f.map(v => v/area);
return {x:x, f:f, k:k, theta:theta};
}
function updatePlot() {
let z = parseFloat(document.getElementById("height").value);
let U = parseFloat(document.getElementById("wind").value);
let stability = document.getElementById("stability").value;
document.getElementById("heightVal").innerText = z;
document.getElementById("windVal").innerText = U;
let data = footprint(z,U,stability);
let xPeak = Math.max(0,(data.k-1)*data.theta);
Plotly.newPlot('plot', [{
x: data.x,
y: data.f,
type: 'scatter',
mode: 'lines',
line: {color:'blue'},
name: 'Footprint'
},{
x:[xPeak,xPeak],
y:[0,Math.max(...data.f)],
mode:'lines',
line:{dash:'dot',color:'black'},
name: 'Peak value'
}], {
title: `Upwind Footprint<br>Height=${z} m, Windspeed=${U} m/s, Stability=${stability}`,
xaxis:{title:'Upwind distance x (m)'},
yaxis:{title:'Footprint footprint f(x) (1/m)'}
});
}
document.getElementById("height").oninput = updatePlot;
document.getElementById("wind").oninput = updatePlot;
document.getElementById("stability").onchange = updatePlot;
// Initial plot
updatePlot();
</script>
</body>
</html>