zero2geospatial3d-sdk 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zero2geospatial3d/__init__.py +105 -0
- zero2geospatial3d/acoustics.py +284 -0
- zero2geospatial3d/classify.py +379 -0
- zero2geospatial3d/cli.py +367 -0
- zero2geospatial3d/comfort.py +687 -0
- zero2geospatial3d/data/epw_stations.json.gz +0 -0
- zero2geospatial3d/daylight.py +337 -0
- zero2geospatial3d/dispersion.py +249 -0
- zero2geospatial3d/epw.py +162 -0
- zero2geospatial3d/geo.py +138 -0
- zero2geospatial3d/grid.py +119 -0
- zero2geospatial3d/microclimate.py +388 -0
- zero2geospatial3d/morphology.py +283 -0
- zero2geospatial3d/nsga2.py +315 -0
- zero2geospatial3d/osm.py +450 -0
- zero2geospatial3d/osm_tags.py +180 -0
- zero2geospatial3d/py.typed +0 -0
- zero2geospatial3d/results.py +231 -0
- zero2geospatial3d/road_sources.py +141 -0
- zero2geospatial3d/scene.py +555 -0
- zero2geospatial3d/server.py +332 -0
- zero2geospatial3d/shading.py +443 -0
- zero2geospatial3d/solar.py +207 -0
- zero2geospatial3d/terrain.py +610 -0
- zero2geospatial3d/urban_form.py +326 -0
- zero2geospatial3d/walkability.py +380 -0
- zero2geospatial3d/weather.py +373 -0
- zero2geospatial3d/web/index.html +50 -0
- zero2geospatial3d/web/src/analysis/climate.js +278 -0
- zero2geospatial3d/web/src/analysis/compliance.js +345 -0
- zero2geospatial3d/web/src/analysis/gpu.js +431 -0
- zero2geospatial3d/web/src/analysis/optimize.js +208 -0
- zero2geospatial3d/web/src/analysis/runners.js +1644 -0
- zero2geospatial3d/web/src/analysis/terrain_results.js +145 -0
- zero2geospatial3d/web/src/app.js +630 -0
- zero2geospatial3d/web/src/core/acoustics.js +341 -0
- zero2geospatial3d/web/src/core/classify.js +158 -0
- zero2geospatial3d/web/src/core/comfort.js +686 -0
- zero2geospatial3d/web/src/core/daylight_rule.js +199 -0
- zero2geospatial3d/web/src/core/dispersion.js +264 -0
- zero2geospatial3d/web/src/core/microclimate.js +372 -0
- zero2geospatial3d/web/src/core/morphology.js +153 -0
- zero2geospatial3d/web/src/core/nsga2.js +181 -0
- zero2geospatial3d/web/src/core/party_walls.js +60 -0
- zero2geospatial3d/web/src/core/road_sources.js +127 -0
- zero2geospatial3d/web/src/core/solar.js +112 -0
- zero2geospatial3d/web/src/core/terrain_analysis.js +267 -0
- zero2geospatial3d/web/src/core/terrain_math.js +279 -0
- zero2geospatial3d/web/src/core/urban_form.js +405 -0
- zero2geospatial3d/web/src/core/walkability.js +316 -0
- zero2geospatial3d/web/src/core/weather.js +225 -0
- zero2geospatial3d/web/src/core/wind.js +131 -0
- zero2geospatial3d/web/src/export/check_pdf.js +74 -0
- zero2geospatial3d/web/src/export/exporters.js +556 -0
- zero2geospatial3d/web/src/export/pdf.js +149 -0
- zero2geospatial3d/web/src/export/snapshot.js +234 -0
- zero2geospatial3d/web/src/export/snapshot_scene.js +150 -0
- zero2geospatial3d/web/src/main.js +75 -0
- zero2geospatial3d/web/src/scene/objects.js +645 -0
- zero2geospatial3d/web/src/scene/overlay.js +145 -0
- zero2geospatial3d/web/src/scene/terrain.js +546 -0
- zero2geospatial3d/web/src/scene/viewer.js +275 -0
- zero2geospatial3d/web/src/scene/wind_streamlines.js +336 -0
- zero2geospatial3d/web/src/style.css +225 -0
- zero2geospatial3d/web/src/ui/building_report.js +404 -0
- zero2geospatial3d/web/src/ui/charts.js +441 -0
- zero2geospatial3d/web/src/ui/colorize.js +101 -0
- zero2geospatial3d/web/src/ui/compare.js +362 -0
- zero2geospatial3d/web/src/ui/dom.js +104 -0
- zero2geospatial3d/web/src/ui/panel_analyze.js +742 -0
- zero2geospatial3d/web/src/ui/panel_compare.js +294 -0
- zero2geospatial3d/web/src/ui/panel_layers.js +172 -0
- zero2geospatial3d/web/src/ui/panel_terrain.js +277 -0
- zero2geospatial3d/web/src/ui/qgis_link.js +127 -0
- zero2geospatial3d/web/src/ui/sunclock.js +45 -0
- zero2geospatial3d/web/src/ui/tools.js +197 -0
- zero2geospatial3d/web/src/ui/viewtools.js +173 -0
- zero2geospatial3d/web/vendor/three/addons/controls/OrbitControls.js +1417 -0
- zero2geospatial3d/web/vendor/three/addons/exporters/GLTFExporter.js +3309 -0
- zero2geospatial3d/web/vendor/three/addons/utils/TextureUtils.js +98 -0
- zero2geospatial3d/web/vendor/three/three.module.js +53044 -0
- zero2geospatial3d/wind.py +178 -0
- zero2geospatial3d_sdk-0.1.0.dist-info/METADATA +219 -0
- zero2geospatial3d_sdk-0.1.0.dist-info/RECORD +89 -0
- zero2geospatial3d_sdk-0.1.0.dist-info/WHEEL +5 -0
- zero2geospatial3d_sdk-0.1.0.dist-info/entry_points.txt +2 -0
- zero2geospatial3d_sdk-0.1.0.dist-info/licenses/LICENSE +21 -0
- zero2geospatial3d_sdk-0.1.0.dist-info/licenses/THIRD_PARTY_NOTICES.md +52 -0
- zero2geospatial3d_sdk-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
// Outdoor thermal comfort: UTCI and mean radiant temperature.
|
|
3
|
+
//
|
|
4
|
+
// UTCI: the 6th-order polynomial approximation of Broede et al. (2012),
|
|
5
|
+
// "Deriving the operational procedure for the Universal Thermal Climate
|
|
6
|
+
// Index (UTCI)", Int J Biometeorol 56:481-494, doi:10.1007/s00484-011-0454-1.
|
|
7
|
+
// The polynomial and the saturation vapour pressure function are transcribed
|
|
8
|
+
// from pythermalcomfort (models/utci.py), MIT License, Copyright (c) 2019
|
|
9
|
+
// Federico Tartarini, and checked against its documented values
|
|
10
|
+
// (utci(25, 25, 1.0, 50) = 24.6; utci(40, 25, 1.0, 50) = 40.4).
|
|
11
|
+
//
|
|
12
|
+
// MRT: longwave exchange with sky and surroundings plus the SolarCal
|
|
13
|
+
// short-wave increment (Arens et al. 2015, "Modeling the comfort effects of
|
|
14
|
+
// short-wave solar radiation indoors", Building and Environment 88:3-9,
|
|
15
|
+
// doi:10.1016/j.buildenv.2014.09.004; ANSI/ASHRAE Standard 55, Appendix C).
|
|
16
|
+
// Surrounding surfaces are taken at air temperature: a screening model, not
|
|
17
|
+
// a surface energy balance.
|
|
18
|
+
|
|
19
|
+
const SIGMA = 5.67e-8;
|
|
20
|
+
|
|
21
|
+
/** Saturation vapour pressure over water, hPa (as used by the UTCI reference code). */
|
|
22
|
+
export function saturationVapourPressure(tdb) {
|
|
23
|
+
const g = [-2836.5744, -6028.076559, 19.54263612, -0.02737830188, 0.000016261698, 7.0229056e-10, -1.8680009e-13];
|
|
24
|
+
const tk = tdb + 273.15;
|
|
25
|
+
let es = 2.7150305 * Math.log(tk);
|
|
26
|
+
for (let i = 0; i < g.length; i++) es += g[i] * Math.pow(tk, i - 2);
|
|
27
|
+
return Math.exp(es) * 0.01;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* UTCI equivalent temperature, degrees C.
|
|
32
|
+
* @param {number} tdb air temperature, C
|
|
33
|
+
* @param {number} tr mean radiant temperature, C
|
|
34
|
+
* @param {number} v wind speed at 10 m, m/s
|
|
35
|
+
* @param {number} rh relative humidity, %
|
|
36
|
+
* @param {{ limit?: boolean }} [opts] limit: NaN outside the model's validity range
|
|
37
|
+
*/
|
|
38
|
+
export function utci(tdb, tr, v, rh, { limit = false } = {}) {
|
|
39
|
+
if (limit && (tdb < -50 || tdb > 50 || tr - tdb < -30 || tr - tdb > 70 || v < 0.5 || v > 17)) return NaN;
|
|
40
|
+
const pa = saturationVapourPressure(tdb) * (rh / 100) / 10; // kPa
|
|
41
|
+
const delta_t_tr = tr - tdb;
|
|
42
|
+
return (
|
|
43
|
+
tdb
|
|
44
|
+
+ 0.607562052
|
|
45
|
+
+ (-0.0227712343) * tdb
|
|
46
|
+
+ (8.06470249 * (10 ** (-4))) * tdb * tdb
|
|
47
|
+
+ (-1.54271372 * (10 ** (-4))) * tdb * tdb * tdb
|
|
48
|
+
+ (-3.24651735 * (10 ** (-6))) * tdb * tdb * tdb * tdb
|
|
49
|
+
+ (7.32602852 * (10 ** (-8))) * tdb * tdb * tdb * tdb * tdb
|
|
50
|
+
+ (1.35959073 * (10 ** (-9))) * tdb * tdb * tdb * tdb * tdb * tdb
|
|
51
|
+
+ (-2.25836520) * v
|
|
52
|
+
+ 0.0880326035 * tdb * v
|
|
53
|
+
+ 0.00216844454 * tdb * tdb * v
|
|
54
|
+
+ (-1.53347087 * (10 ** (-5))) * tdb * tdb * tdb * v
|
|
55
|
+
+ (-5.72983704 * (10 ** (-7))) * tdb * tdb * tdb * tdb * v
|
|
56
|
+
+ (-2.55090145 * (10 ** (-9))) * tdb * tdb * tdb * tdb * tdb * v
|
|
57
|
+
+ (-0.751269505) * v * v
|
|
58
|
+
+ (-0.00408350271) * tdb * v * v
|
|
59
|
+
+ (-5.21670675 * (10 ** (-5))) * tdb * tdb * v * v
|
|
60
|
+
+ (1.94544667 * (10 ** (-6))) * tdb * tdb * tdb * v * v
|
|
61
|
+
+ (1.14099531 * (10 ** (-8))) * tdb * tdb * tdb * tdb * v * v
|
|
62
|
+
+ 0.158137256 * v * v * v
|
|
63
|
+
+ (-6.57263143 * (10 ** (-5))) * tdb * v * v * v
|
|
64
|
+
+ (2.22697524 * (10 ** (-7))) * tdb * tdb * v * v * v
|
|
65
|
+
+ (-4.16117031 * (10 ** (-8))) * tdb * tdb * tdb * v * v * v
|
|
66
|
+
+ (-0.0127762753) * v * v * v * v
|
|
67
|
+
+ (9.66891875 * (10 ** (-6))) * tdb * v * v * v * v
|
|
68
|
+
+ (2.52785852 * (10 ** (-9))) * tdb * tdb * v * v * v * v
|
|
69
|
+
+ (4.56306672 * (10 ** (-4))) * v * v * v * v * v
|
|
70
|
+
+ (-1.74202546 * (10 ** (-7))) * tdb * v * v * v * v * v
|
|
71
|
+
+ (-5.91491269 * (10 ** (-6))) * v * v * v * v * v * v
|
|
72
|
+
+ 0.398374029 * delta_t_tr
|
|
73
|
+
+ (1.83945314 * (10 ** (-4))) * tdb * delta_t_tr
|
|
74
|
+
+ (-1.73754510 * (10 ** (-4))) * tdb * tdb * delta_t_tr
|
|
75
|
+
+ (-7.60781159 * (10 ** (-7))) * tdb * tdb * tdb * delta_t_tr
|
|
76
|
+
+ (3.77830287 * (10 ** (-8))) * tdb * tdb * tdb * tdb * delta_t_tr
|
|
77
|
+
+ (5.43079673 * (10 ** (-10))) * tdb * tdb * tdb * tdb * tdb * delta_t_tr
|
|
78
|
+
+ (-0.0200518269) * v * delta_t_tr
|
|
79
|
+
+ (8.92859837 * (10 ** (-4))) * tdb * v * delta_t_tr
|
|
80
|
+
+ (3.45433048 * (10 ** (-6))) * tdb * tdb * v * delta_t_tr
|
|
81
|
+
+ (-3.77925774 * (10 ** (-7))) * tdb * tdb * tdb * v * delta_t_tr
|
|
82
|
+
+ (-1.69699377 * (10 ** (-9))) * tdb * tdb * tdb * tdb * v * delta_t_tr
|
|
83
|
+
+ (1.69992415 * (10 ** (-4))) * v * v * delta_t_tr
|
|
84
|
+
+ (-4.99204314 * (10 ** (-5))) * tdb * v * v * delta_t_tr
|
|
85
|
+
+ (2.47417178 * (10 ** (-7))) * tdb * tdb * v * v * delta_t_tr
|
|
86
|
+
+ (1.07596466 * (10 ** (-8))) * tdb * tdb * tdb * v * v * delta_t_tr
|
|
87
|
+
+ (8.49242932 * (10 ** (-5))) * v * v * v * delta_t_tr
|
|
88
|
+
+ (1.35191328 * (10 ** (-6))) * tdb * v * v * v * delta_t_tr
|
|
89
|
+
+ (-6.21531254 * (10 ** (-9))) * tdb * tdb * v * v * v * delta_t_tr
|
|
90
|
+
+ (-4.99410301 * (10 ** (-6))) * v * v * v * v * delta_t_tr
|
|
91
|
+
+ (-1.89489258 * (10 ** (-8))) * tdb * v * v * v * v * delta_t_tr
|
|
92
|
+
+ (8.15300114 * (10 ** (-8))) * v * v * v * v * v * delta_t_tr
|
|
93
|
+
+ (7.55043090 * (10 ** (-4))) * delta_t_tr * delta_t_tr
|
|
94
|
+
+ (-5.65095215 * (10 ** (-5))) * tdb * delta_t_tr * delta_t_tr
|
|
95
|
+
+ (-4.52166564 * (10 ** (-7))) * tdb * tdb * delta_t_tr * delta_t_tr
|
|
96
|
+
+ (2.46688878 * (10 ** (-8))) * tdb * tdb * tdb * delta_t_tr * delta_t_tr
|
|
97
|
+
+ (2.42674348 * (10 ** (-10))) * tdb * tdb * tdb * tdb * delta_t_tr * delta_t_tr
|
|
98
|
+
+ (1.54547250 * (10 ** (-4))) * v * delta_t_tr * delta_t_tr
|
|
99
|
+
+ (5.24110970 * (10 ** (-6))) * tdb * v * delta_t_tr * delta_t_tr
|
|
100
|
+
+ (-8.75874982 * (10 ** (-8))) * tdb * tdb * v * delta_t_tr * delta_t_tr
|
|
101
|
+
+ (-1.50743064 * (10 ** (-9))) * tdb * tdb * tdb * v * delta_t_tr * delta_t_tr
|
|
102
|
+
+ (-1.56236307 * (10 ** (-5))) * v * v * delta_t_tr * delta_t_tr
|
|
103
|
+
+ (-1.33895614 * (10 ** (-7))) * tdb * v * v * delta_t_tr * delta_t_tr
|
|
104
|
+
+ (2.49709824 * (10 ** (-9))) * tdb * tdb * v * v * delta_t_tr * delta_t_tr
|
|
105
|
+
+ (6.51711721 * (10 ** (-7))) * v * v * v * delta_t_tr * delta_t_tr
|
|
106
|
+
+ (1.94960053 * (10 ** (-9))) * tdb * v * v * v * delta_t_tr * delta_t_tr
|
|
107
|
+
+ (-1.00361113 * (10 ** (-8))) * v * v * v * v * delta_t_tr * delta_t_tr
|
|
108
|
+
+ (-1.21206673 * (10 ** (-5))) * delta_t_tr * delta_t_tr * delta_t_tr
|
|
109
|
+
+ (-2.18203660 * (10 ** (-7))) * tdb * delta_t_tr * delta_t_tr * delta_t_tr
|
|
110
|
+
+ (7.51269482 * (10 ** (-9))) * tdb * tdb * delta_t_tr * delta_t_tr * delta_t_tr
|
|
111
|
+
+ (9.79063848 * (10 ** (-11)))
|
|
112
|
+
* tdb
|
|
113
|
+
* tdb
|
|
114
|
+
* tdb
|
|
115
|
+
* delta_t_tr
|
|
116
|
+
* delta_t_tr
|
|
117
|
+
* delta_t_tr
|
|
118
|
+
+ (1.25006734 * (10 ** (-6))) * v * delta_t_tr * delta_t_tr * delta_t_tr
|
|
119
|
+
+ (-1.81584736 * (10 ** (-9))) * tdb * v * delta_t_tr * delta_t_tr * delta_t_tr
|
|
120
|
+
+ (-3.52197671 * (10 ** (-10)))
|
|
121
|
+
* tdb
|
|
122
|
+
* tdb
|
|
123
|
+
* v
|
|
124
|
+
* delta_t_tr
|
|
125
|
+
* delta_t_tr
|
|
126
|
+
* delta_t_tr
|
|
127
|
+
+ (-3.36514630 * (10 ** (-8))) * v * v * delta_t_tr * delta_t_tr * delta_t_tr
|
|
128
|
+
+ (1.35908359 * (10 ** (-10)))
|
|
129
|
+
* tdb
|
|
130
|
+
* v
|
|
131
|
+
* v
|
|
132
|
+
* delta_t_tr
|
|
133
|
+
* delta_t_tr
|
|
134
|
+
* delta_t_tr
|
|
135
|
+
+ (4.17032620 * (10 ** (-10)))
|
|
136
|
+
* v
|
|
137
|
+
* v
|
|
138
|
+
* v
|
|
139
|
+
* delta_t_tr
|
|
140
|
+
* delta_t_tr
|
|
141
|
+
* delta_t_tr
|
|
142
|
+
+ (-1.30369025 * (10 ** (-9)))
|
|
143
|
+
* delta_t_tr
|
|
144
|
+
* delta_t_tr
|
|
145
|
+
* delta_t_tr
|
|
146
|
+
* delta_t_tr
|
|
147
|
+
+ (4.13908461 * (10 ** (-10)))
|
|
148
|
+
* tdb
|
|
149
|
+
* delta_t_tr
|
|
150
|
+
* delta_t_tr
|
|
151
|
+
* delta_t_tr
|
|
152
|
+
* delta_t_tr
|
|
153
|
+
+ (9.22652254 * (10 ** (-12)))
|
|
154
|
+
* tdb
|
|
155
|
+
* tdb
|
|
156
|
+
* delta_t_tr
|
|
157
|
+
* delta_t_tr
|
|
158
|
+
* delta_t_tr
|
|
159
|
+
* delta_t_tr
|
|
160
|
+
+ (-5.08220384 * (10 ** (-9)))
|
|
161
|
+
* v
|
|
162
|
+
* delta_t_tr
|
|
163
|
+
* delta_t_tr
|
|
164
|
+
* delta_t_tr
|
|
165
|
+
* delta_t_tr
|
|
166
|
+
+ (-2.24730961 * (10 ** (-11)))
|
|
167
|
+
* tdb
|
|
168
|
+
* v
|
|
169
|
+
* delta_t_tr
|
|
170
|
+
* delta_t_tr
|
|
171
|
+
* delta_t_tr
|
|
172
|
+
* delta_t_tr
|
|
173
|
+
+ (1.17139133 * (10 ** (-10)))
|
|
174
|
+
* v
|
|
175
|
+
* v
|
|
176
|
+
* delta_t_tr
|
|
177
|
+
* delta_t_tr
|
|
178
|
+
* delta_t_tr
|
|
179
|
+
* delta_t_tr
|
|
180
|
+
+ (6.62154879 * (10 ** (-10)))
|
|
181
|
+
* delta_t_tr
|
|
182
|
+
* delta_t_tr
|
|
183
|
+
* delta_t_tr
|
|
184
|
+
* delta_t_tr
|
|
185
|
+
* delta_t_tr
|
|
186
|
+
+ (4.03863260 * (10 ** (-13)))
|
|
187
|
+
* tdb
|
|
188
|
+
* delta_t_tr
|
|
189
|
+
* delta_t_tr
|
|
190
|
+
* delta_t_tr
|
|
191
|
+
* delta_t_tr
|
|
192
|
+
* delta_t_tr
|
|
193
|
+
+ (1.95087203 * (10 ** (-12)))
|
|
194
|
+
* v
|
|
195
|
+
* delta_t_tr
|
|
196
|
+
* delta_t_tr
|
|
197
|
+
* delta_t_tr
|
|
198
|
+
* delta_t_tr
|
|
199
|
+
* delta_t_tr
|
|
200
|
+
+ (-4.73602469 * (10 ** (-12)))
|
|
201
|
+
* delta_t_tr
|
|
202
|
+
* delta_t_tr
|
|
203
|
+
* delta_t_tr
|
|
204
|
+
* delta_t_tr
|
|
205
|
+
* delta_t_tr
|
|
206
|
+
* delta_t_tr
|
|
207
|
+
+ 5.12733497 * pa
|
|
208
|
+
+ (-0.312788561) * tdb * pa
|
|
209
|
+
+ (-0.0196701861) * tdb * tdb * pa
|
|
210
|
+
+ (9.99690870 * (10 ** (-4))) * tdb * tdb * tdb * pa
|
|
211
|
+
+ (9.51738512 * (10 ** (-6))) * tdb * tdb * tdb * tdb * pa
|
|
212
|
+
+ (-4.66426341 * (10 ** (-7))) * tdb * tdb * tdb * tdb * tdb * pa
|
|
213
|
+
+ 0.548050612 * v * pa
|
|
214
|
+
+ (-0.00330552823) * tdb * v * pa
|
|
215
|
+
+ (-0.00164119440) * tdb * tdb * v * pa
|
|
216
|
+
+ (-5.16670694 * (10 ** (-6))) * tdb * tdb * tdb * v * pa
|
|
217
|
+
+ (9.52692432 * (10 ** (-7))) * tdb * tdb * tdb * tdb * v * pa
|
|
218
|
+
+ (-0.0429223622) * v * v * pa
|
|
219
|
+
+ 0.00500845667 * tdb * v * v * pa
|
|
220
|
+
+ (1.00601257 * (10 ** (-6))) * tdb * tdb * v * v * pa
|
|
221
|
+
+ (-1.81748644 * (10 ** (-6))) * tdb * tdb * tdb * v * v * pa
|
|
222
|
+
+ (-1.25813502 * (10 ** (-3))) * v * v * v * pa
|
|
223
|
+
+ (-1.79330391 * (10 ** (-4))) * tdb * v * v * v * pa
|
|
224
|
+
+ (2.34994441 * (10 ** (-6))) * tdb * tdb * v * v * v * pa
|
|
225
|
+
+ (1.29735808 * (10 ** (-4))) * v * v * v * v * pa
|
|
226
|
+
+ (1.29064870 * (10 ** (-6))) * tdb * v * v * v * v * pa
|
|
227
|
+
+ (-2.28558686 * (10 ** (-6))) * v * v * v * v * v * pa
|
|
228
|
+
+ (-0.0369476348) * delta_t_tr * pa
|
|
229
|
+
+ 0.00162325322 * tdb * delta_t_tr * pa
|
|
230
|
+
+ (-3.14279680 * (10 ** (-5))) * tdb * tdb * delta_t_tr * pa
|
|
231
|
+
+ (2.59835559 * (10 ** (-6))) * tdb * tdb * tdb * delta_t_tr * pa
|
|
232
|
+
+ (-4.77136523 * (10 ** (-8))) * tdb * tdb * tdb * tdb * delta_t_tr * pa
|
|
233
|
+
+ (8.64203390 * (10 ** (-3))) * v * delta_t_tr * pa
|
|
234
|
+
+ (-6.87405181 * (10 ** (-4))) * tdb * v * delta_t_tr * pa
|
|
235
|
+
+ (-9.13863872 * (10 ** (-6))) * tdb * tdb * v * delta_t_tr * pa
|
|
236
|
+
+ (5.15916806 * (10 ** (-7))) * tdb * tdb * tdb * v * delta_t_tr * pa
|
|
237
|
+
+ (-3.59217476 * (10 ** (-5))) * v * v * delta_t_tr * pa
|
|
238
|
+
+ (3.28696511 * (10 ** (-5))) * tdb * v * v * delta_t_tr * pa
|
|
239
|
+
+ (-7.10542454 * (10 ** (-7))) * tdb * tdb * v * v * delta_t_tr * pa
|
|
240
|
+
+ (-1.24382300 * (10 ** (-5))) * v * v * v * delta_t_tr * pa
|
|
241
|
+
+ (-7.38584400 * (10 ** (-9))) * tdb * v * v * v * delta_t_tr * pa
|
|
242
|
+
+ (2.20609296 * (10 ** (-7))) * v * v * v * v * delta_t_tr * pa
|
|
243
|
+
+ (-7.32469180 * (10 ** (-4))) * delta_t_tr * delta_t_tr * pa
|
|
244
|
+
+ (-1.87381964 * (10 ** (-5))) * tdb * delta_t_tr * delta_t_tr * pa
|
|
245
|
+
+ (4.80925239 * (10 ** (-6))) * tdb * tdb * delta_t_tr * delta_t_tr * pa
|
|
246
|
+
+ (-8.75492040 * (10 ** (-8))) * tdb * tdb * tdb * delta_t_tr * delta_t_tr * pa
|
|
247
|
+
+ (2.77862930 * (10 ** (-5))) * v * delta_t_tr * delta_t_tr * pa
|
|
248
|
+
+ (-5.06004592 * (10 ** (-6))) * tdb * v * delta_t_tr * delta_t_tr * pa
|
|
249
|
+
+ (1.14325367 * (10 ** (-7))) * tdb * tdb * v * delta_t_tr * delta_t_tr * pa
|
|
250
|
+
+ (2.53016723 * (10 ** (-6))) * v * v * delta_t_tr * delta_t_tr * pa
|
|
251
|
+
+ (-1.72857035 * (10 ** (-8))) * tdb * v * v * delta_t_tr * delta_t_tr * pa
|
|
252
|
+
+ (-3.95079398 * (10 ** (-8))) * v * v * v * delta_t_tr * delta_t_tr * pa
|
|
253
|
+
+ (-3.59413173 * (10 ** (-7))) * delta_t_tr * delta_t_tr * delta_t_tr * pa
|
|
254
|
+
+ (7.04388046 * (10 ** (-7))) * tdb * delta_t_tr * delta_t_tr * delta_t_tr * pa
|
|
255
|
+
+ (-1.89309167 * (10 ** (-8)))
|
|
256
|
+
* tdb
|
|
257
|
+
* tdb
|
|
258
|
+
* delta_t_tr
|
|
259
|
+
* delta_t_tr
|
|
260
|
+
* delta_t_tr
|
|
261
|
+
* pa
|
|
262
|
+
+ (-4.79768731 * (10 ** (-7))) * v * delta_t_tr * delta_t_tr * delta_t_tr * pa
|
|
263
|
+
+ (7.96079978 * (10 ** (-9)))
|
|
264
|
+
* tdb
|
|
265
|
+
* v
|
|
266
|
+
* delta_t_tr
|
|
267
|
+
* delta_t_tr
|
|
268
|
+
* delta_t_tr
|
|
269
|
+
* pa
|
|
270
|
+
+ (1.62897058 * (10 ** (-9)))
|
|
271
|
+
* v
|
|
272
|
+
* v
|
|
273
|
+
* delta_t_tr
|
|
274
|
+
* delta_t_tr
|
|
275
|
+
* delta_t_tr
|
|
276
|
+
* pa
|
|
277
|
+
+ (3.94367674 * (10 ** (-8)))
|
|
278
|
+
* delta_t_tr
|
|
279
|
+
* delta_t_tr
|
|
280
|
+
* delta_t_tr
|
|
281
|
+
* delta_t_tr
|
|
282
|
+
* pa
|
|
283
|
+
+ (-1.18566247 * (10 ** (-9)))
|
|
284
|
+
* tdb
|
|
285
|
+
* delta_t_tr
|
|
286
|
+
* delta_t_tr
|
|
287
|
+
* delta_t_tr
|
|
288
|
+
* delta_t_tr
|
|
289
|
+
* pa
|
|
290
|
+
+ (3.34678041 * (10 ** (-10)))
|
|
291
|
+
* v
|
|
292
|
+
* delta_t_tr
|
|
293
|
+
* delta_t_tr
|
|
294
|
+
* delta_t_tr
|
|
295
|
+
* delta_t_tr
|
|
296
|
+
* pa
|
|
297
|
+
+ (-1.15606447 * (10 ** (-10)))
|
|
298
|
+
* delta_t_tr
|
|
299
|
+
* delta_t_tr
|
|
300
|
+
* delta_t_tr
|
|
301
|
+
* delta_t_tr
|
|
302
|
+
* delta_t_tr
|
|
303
|
+
* pa
|
|
304
|
+
+ (-2.80626406) * pa * pa
|
|
305
|
+
+ 0.548712484 * tdb * pa * pa
|
|
306
|
+
+ (-0.00399428410) * tdb * tdb * pa * pa
|
|
307
|
+
+ (-9.54009191 * (10 ** (-4))) * tdb * tdb * tdb * pa * pa
|
|
308
|
+
+ (1.93090978 * (10 ** (-5))) * tdb * tdb * tdb * tdb * pa * pa
|
|
309
|
+
+ (-0.308806365) * v * pa * pa
|
|
310
|
+
+ 0.0116952364 * tdb * v * pa * pa
|
|
311
|
+
+ (4.95271903 * (10 ** (-4))) * tdb * tdb * v * pa * pa
|
|
312
|
+
+ (-1.90710882 * (10 ** (-5))) * tdb * tdb * tdb * v * pa * pa
|
|
313
|
+
+ 0.00210787756 * v * v * pa * pa
|
|
314
|
+
+ (-6.98445738 * (10 ** (-4))) * tdb * v * v * pa * pa
|
|
315
|
+
+ (2.30109073 * (10 ** (-5))) * tdb * tdb * v * v * pa * pa
|
|
316
|
+
+ (4.17856590 * (10 ** (-4))) * v * v * v * pa * pa
|
|
317
|
+
+ (-1.27043871 * (10 ** (-5))) * tdb * v * v * v * pa * pa
|
|
318
|
+
+ (-3.04620472 * (10 ** (-6))) * v * v * v * v * pa * pa
|
|
319
|
+
+ 0.0514507424 * delta_t_tr * pa * pa
|
|
320
|
+
+ (-0.00432510997) * tdb * delta_t_tr * pa * pa
|
|
321
|
+
+ (8.99281156 * (10 ** (-5))) * tdb * tdb * delta_t_tr * pa * pa
|
|
322
|
+
+ (-7.14663943 * (10 ** (-7))) * tdb * tdb * tdb * delta_t_tr * pa * pa
|
|
323
|
+
+ (-2.66016305 * (10 ** (-4))) * v * delta_t_tr * pa * pa
|
|
324
|
+
+ (2.63789586 * (10 ** (-4))) * tdb * v * delta_t_tr * pa * pa
|
|
325
|
+
+ (-7.01199003 * (10 ** (-6))) * tdb * tdb * v * delta_t_tr * pa * pa
|
|
326
|
+
+ (-1.06823306 * (10 ** (-4))) * v * v * delta_t_tr * pa * pa
|
|
327
|
+
+ (3.61341136 * (10 ** (-6))) * tdb * v * v * delta_t_tr * pa * pa
|
|
328
|
+
+ (2.29748967 * (10 ** (-7))) * v * v * v * delta_t_tr * pa * pa
|
|
329
|
+
+ (3.04788893 * (10 ** (-4))) * delta_t_tr * delta_t_tr * pa * pa
|
|
330
|
+
+ (-6.42070836 * (10 ** (-5))) * tdb * delta_t_tr * delta_t_tr * pa * pa
|
|
331
|
+
+ (1.16257971 * (10 ** (-6))) * tdb * tdb * delta_t_tr * delta_t_tr * pa * pa
|
|
332
|
+
+ (7.68023384 * (10 ** (-6))) * v * delta_t_tr * delta_t_tr * pa * pa
|
|
333
|
+
+ (-5.47446896 * (10 ** (-7))) * tdb * v * delta_t_tr * delta_t_tr * pa * pa
|
|
334
|
+
+ (-3.59937910 * (10 ** (-8))) * v * v * delta_t_tr * delta_t_tr * pa * pa
|
|
335
|
+
+ (-4.36497725 * (10 ** (-6))) * delta_t_tr * delta_t_tr * delta_t_tr * pa * pa
|
|
336
|
+
+ (1.68737969 * (10 ** (-7)))
|
|
337
|
+
* tdb
|
|
338
|
+
* delta_t_tr
|
|
339
|
+
* delta_t_tr
|
|
340
|
+
* delta_t_tr
|
|
341
|
+
* pa
|
|
342
|
+
* pa
|
|
343
|
+
+ (2.67489271 * (10 ** (-8)))
|
|
344
|
+
* v
|
|
345
|
+
* delta_t_tr
|
|
346
|
+
* delta_t_tr
|
|
347
|
+
* delta_t_tr
|
|
348
|
+
* pa
|
|
349
|
+
* pa
|
|
350
|
+
+ (3.23926897 * (10 ** (-9)))
|
|
351
|
+
* delta_t_tr
|
|
352
|
+
* delta_t_tr
|
|
353
|
+
* delta_t_tr
|
|
354
|
+
* delta_t_tr
|
|
355
|
+
* pa
|
|
356
|
+
* pa
|
|
357
|
+
+ (-0.0353874123) * pa * pa * pa
|
|
358
|
+
+ (-0.221201190) * tdb * pa * pa * pa
|
|
359
|
+
+ 0.0155126038 * tdb * tdb * pa * pa * pa
|
|
360
|
+
+ (-2.63917279 * (10 ** (-4))) * tdb * tdb * tdb * pa * pa * pa
|
|
361
|
+
+ 0.0453433455 * v * pa * pa * pa
|
|
362
|
+
+ (-0.00432943862) * tdb * v * pa * pa * pa
|
|
363
|
+
+ (1.45389826 * (10 ** (-4))) * tdb * tdb * v * pa * pa * pa
|
|
364
|
+
+ (2.17508610 * (10 ** (-4))) * v * v * pa * pa * pa
|
|
365
|
+
+ (-6.66724702 * (10 ** (-5))) * tdb * v * v * pa * pa * pa
|
|
366
|
+
+ (3.33217140 * (10 ** (-5))) * v * v * v * pa * pa * pa
|
|
367
|
+
+ (-0.00226921615) * delta_t_tr * pa * pa * pa
|
|
368
|
+
+ (3.80261982 * (10 ** (-4))) * tdb * delta_t_tr * pa * pa * pa
|
|
369
|
+
+ (-5.45314314 * (10 ** (-9))) * tdb * tdb * delta_t_tr * pa * pa * pa
|
|
370
|
+
+ (-7.96355448 * (10 ** (-4))) * v * delta_t_tr * pa * pa * pa
|
|
371
|
+
+ (2.53458034 * (10 ** (-5))) * tdb * v * delta_t_tr * pa * pa * pa
|
|
372
|
+
+ (-6.31223658 * (10 ** (-6))) * v * v * delta_t_tr * pa * pa * pa
|
|
373
|
+
+ (3.02122035 * (10 ** (-4))) * delta_t_tr * delta_t_tr * pa * pa * pa
|
|
374
|
+
+ (-4.77403547 * (10 ** (-6))) * tdb * delta_t_tr * delta_t_tr * pa * pa * pa
|
|
375
|
+
+ (1.73825715 * (10 ** (-6))) * v * delta_t_tr * delta_t_tr * pa * pa * pa
|
|
376
|
+
+ (-4.09087898 * (10 ** (-7)))
|
|
377
|
+
* delta_t_tr
|
|
378
|
+
* delta_t_tr
|
|
379
|
+
* delta_t_tr
|
|
380
|
+
* pa
|
|
381
|
+
* pa
|
|
382
|
+
* pa
|
|
383
|
+
+ 0.614155345 * pa * pa * pa * pa
|
|
384
|
+
+ (-0.0616755931) * tdb * pa * pa * pa * pa
|
|
385
|
+
+ 0.00133374846 * tdb * tdb * pa * pa * pa * pa
|
|
386
|
+
+ 0.00355375387 * v * pa * pa * pa * pa
|
|
387
|
+
+ (-5.13027851 * (10 ** (-4))) * tdb * v * pa * pa * pa * pa
|
|
388
|
+
+ (1.02449757 * (10 ** (-4))) * v * v * pa * pa * pa * pa
|
|
389
|
+
+ (-0.00148526421) * delta_t_tr * pa * pa * pa * pa
|
|
390
|
+
+ (-4.11469183 * (10 ** (-5))) * tdb * delta_t_tr * pa * pa * pa * pa
|
|
391
|
+
+ (-6.80434415 * (10 ** (-6))) * v * delta_t_tr * pa * pa * pa * pa
|
|
392
|
+
+ (-9.77675906 * (10 ** (-6))) * delta_t_tr * delta_t_tr * pa * pa * pa * pa
|
|
393
|
+
+ 0.0882773108 * pa * pa * pa * pa * pa
|
|
394
|
+
+ (-0.00301859306) * tdb * pa * pa * pa * pa * pa
|
|
395
|
+
+ 0.00104452989 * v * pa * pa * pa * pa * pa
|
|
396
|
+
+ (2.47090539 * (10 ** (-4))) * delta_t_tr * pa * pa * pa * pa * pa
|
|
397
|
+
+ 0.00148348065 * pa * pa * pa * pa * pa * pa
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export const UTCI_CATEGORIES = [
|
|
402
|
+
{ max: -40, label: 'Extreme cold stress', color: '#08306b' },
|
|
403
|
+
{ max: -27, label: 'Very strong cold stress', color: '#08519c' },
|
|
404
|
+
{ max: -13, label: 'Strong cold stress', color: '#2171b5' },
|
|
405
|
+
{ max: 0, label: 'Moderate cold stress', color: '#6baed6' },
|
|
406
|
+
{ max: 9, label: 'Slight cold stress', color: '#c6dbef' },
|
|
407
|
+
{ max: 26, label: 'No thermal stress', color: '#a1d99b' },
|
|
408
|
+
{ max: 32, label: 'Moderate heat stress', color: '#fdd0a2' },
|
|
409
|
+
{ max: 38, label: 'Strong heat stress', color: '#fd8d3c' },
|
|
410
|
+
{ max: 46, label: 'Very strong heat stress', color: '#d94801' },
|
|
411
|
+
{ max: Infinity, label: 'Extreme heat stress', color: '#7f2704' }
|
|
412
|
+
];
|
|
413
|
+
|
|
414
|
+
export function utciCategory(value) {
|
|
415
|
+
if (!Number.isFinite(value)) return null;
|
|
416
|
+
return UTCI_CATEGORIES.find((c) => value < c.max) || UTCI_CATEGORIES[UTCI_CATEGORIES.length - 1];
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Projected area factor of a standing person for a sun elevation in degrees
|
|
421
|
+
* (Underwood and Ward 1966, as used by SOLWEIG): projected area over the
|
|
422
|
+
* effective radiating area.
|
|
423
|
+
*/
|
|
424
|
+
export function projectedAreaFactor(elevationDeg) {
|
|
425
|
+
const b = Math.max(0, Math.min(90, elevationDeg));
|
|
426
|
+
return 0.308 * Math.cos((b * (0.998 - (b * b) / 50000)) * Math.PI / 180);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/** Sky temperature (C) from EPW horizontal infrared, or Swinbank (1963) when missing. */
|
|
430
|
+
export function skyTemperature(airTemp, horizontalIr) {
|
|
431
|
+
if (Number.isFinite(horizontalIr) && horizontalIr > 50) return Math.pow(horizontalIr / SIGMA, 0.25) - 273.15;
|
|
432
|
+
const ta = airTemp + 273.15;
|
|
433
|
+
return 0.0552 * Math.pow(ta, 1.5) - 273.15;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Mean radiant temperature of a standing person outdoors, C.
|
|
438
|
+
* @param {object} p
|
|
439
|
+
* @param {number} p.airTemp C
|
|
440
|
+
* @param {number} p.skyTemp C
|
|
441
|
+
* @param {number} p.svf sky view factor of the spot (0..1)
|
|
442
|
+
* @param {boolean|number} p.sunlit 1 if the person is in the sun (fraction allowed)
|
|
443
|
+
* @param {number} p.dni direct normal irradiance, W/m2
|
|
444
|
+
* @param {number} p.dhi diffuse horizontal irradiance, W/m2
|
|
445
|
+
* @param {number} p.ghi global horizontal irradiance, W/m2
|
|
446
|
+
* @param {number} p.elevationDeg sun elevation, degrees
|
|
447
|
+
* @param {number} [p.albedo] ground reflectance
|
|
448
|
+
* @param {number} [p.absorptivity] clothing/skin short-wave absorptivity
|
|
449
|
+
* @param {number} [p.groundTemp] ground surface temperature, C
|
|
450
|
+
* @param {number} [p.wallTemp] surrounding wall temperature, C
|
|
451
|
+
*/
|
|
452
|
+
export function meanRadiantTemperature({
|
|
453
|
+
airTemp,
|
|
454
|
+
skyTemp,
|
|
455
|
+
svf,
|
|
456
|
+
sunlit,
|
|
457
|
+
dni,
|
|
458
|
+
dhi,
|
|
459
|
+
ghi,
|
|
460
|
+
elevationDeg,
|
|
461
|
+
albedo = 0.2,
|
|
462
|
+
absorptivity = 0.7,
|
|
463
|
+
groundTemp = NaN,
|
|
464
|
+
wallTemp = NaN
|
|
465
|
+
}) {
|
|
466
|
+
const fEff = 0.725; // standing person
|
|
467
|
+
const hr = 6.012; // W/m2K
|
|
468
|
+
const emissivity = 0.95; // long-wave absorptivity
|
|
469
|
+
const s = Math.max(0, Math.min(1, svf));
|
|
470
|
+
const tSky = skyTemp + 273.15;
|
|
471
|
+
const tAir = airTemp + 273.15;
|
|
472
|
+
|
|
473
|
+
let tLw;
|
|
474
|
+
if (!Number.isFinite(groundTemp) && !Number.isFinite(wallTemp)) {
|
|
475
|
+
// Exact backward-compatible formula when surface temperatures are omitted
|
|
476
|
+
const fSky = 0.5 * s;
|
|
477
|
+
tLw = Math.pow(fSky * Math.pow(tSky, 4) + (1 - fSky) * Math.pow(tAir, 4), 0.25) - 273.15;
|
|
478
|
+
} else {
|
|
479
|
+
// Surface-aware longwave exchange:
|
|
480
|
+
// Upper hemisphere (weight 0.5) has svf sky at tSky and (1 - svf) walls at tWall.
|
|
481
|
+
// Lower hemisphere (weight 0.5) is ground at tGnd.
|
|
482
|
+
const tWall = (Number.isFinite(wallTemp) ? wallTemp : airTemp) + 273.15;
|
|
483
|
+
const tGnd = (Number.isFinite(groundTemp) ? groundTemp : airTemp) + 273.15;
|
|
484
|
+
tLw = Math.pow(0.5 * s * Math.pow(tSky, 4) + 0.5 * (1 - s) * Math.pow(tWall, 4) + 0.5 * Math.pow(tGnd, 4), 0.25) - 273.15;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (!(elevationDeg > 0) || !(ghi > 0)) return tLw;
|
|
488
|
+
const fBes = Math.max(0, Math.min(1, Number(sunlit)));
|
|
489
|
+
const apOverAd = projectedAreaFactor(elevationDeg) * fEff;
|
|
490
|
+
const eDiff = 0.5 * fEff * s * (dhi + ghi * albedo);
|
|
491
|
+
const eDir = apOverAd * fBes * dni;
|
|
492
|
+
const erf = (eDiff + eDir) * (absorptivity / emissivity);
|
|
493
|
+
return tLw + erf / (fEff * hr);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
export const PET_CATEGORIES = [
|
|
497
|
+
{ max: 4, label: 'Extreme cold stress', color: '#08306b' },
|
|
498
|
+
{ max: 8, label: 'Strong cold stress', color: '#2171b5' },
|
|
499
|
+
{ max: 13, label: 'Moderate cold stress', color: '#6baed6' },
|
|
500
|
+
{ max: 18, label: 'Slight cold stress', color: '#c6dbef' },
|
|
501
|
+
{ max: 23, label: 'Comfortable', color: '#a1d99b' },
|
|
502
|
+
{ max: 29, label: 'Slight heat stress', color: '#fdd0a2' },
|
|
503
|
+
{ max: 35, label: 'Moderate heat stress', color: '#fd8d3c' },
|
|
504
|
+
{ max: 41, label: 'Strong heat stress', color: '#d94801' },
|
|
505
|
+
{ max: Infinity, label: 'Extreme heat stress', color: '#7f2704' }
|
|
506
|
+
];
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Return thermal stress category for a PET value (°C).
|
|
510
|
+
* @param {number} value
|
|
511
|
+
* @returns {{ max: number, label: string, color: string } | null}
|
|
512
|
+
*/
|
|
513
|
+
export function petCategory(value) {
|
|
514
|
+
if (!Number.isFinite(value)) return null;
|
|
515
|
+
return PET_CATEGORIES.find((c) => value < c.max) || PET_CATEGORIES[PET_CATEGORIES.length - 1];
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Physiological Equivalent Temperature (PET) following Höppe (1999) / Walther & Goestchel (2018) MEMI.
|
|
520
|
+
* @param {number} tdb dry-bulb air temperature, C
|
|
521
|
+
* @param {number} tr mean radiant temperature, C
|
|
522
|
+
* @param {number} v wind speed, m/s
|
|
523
|
+
* @param {number} rh relative humidity, %
|
|
524
|
+
* @param {{ met?: number, clo?: number }} [opts] met in W (default 80), clo (default 0.9)
|
|
525
|
+
* @returns {number} PET in degrees C
|
|
526
|
+
*/
|
|
527
|
+
export function pet(tdb, tr, v, rh, { met = 80, clo = 0.9 } = {}) {
|
|
528
|
+
if (!Number.isFinite(tdb) || !Number.isFinite(tr)) return NaN;
|
|
529
|
+
const va = Math.max(0.1, Math.min(20, Number.isFinite(v) ? v : 0.5));
|
|
530
|
+
const rhClamped = Math.max(0, Math.min(100, Number.isFinite(rh) ? rh : 50));
|
|
531
|
+
const Ta = tdb;
|
|
532
|
+
const Tmrt = tr;
|
|
533
|
+
const vpa = saturationVapourPressure(Ta) * (rhClamped / 100);
|
|
534
|
+
|
|
535
|
+
const age = 35;
|
|
536
|
+
const ht = 1.8;
|
|
537
|
+
const mbody = 75.0;
|
|
538
|
+
const p = 1013.25;
|
|
539
|
+
const cb = 3640.0;
|
|
540
|
+
const cair = 1010.0;
|
|
541
|
+
const emsk = 0.99;
|
|
542
|
+
const emcl = 0.95;
|
|
543
|
+
const Lvap = 2.42e6;
|
|
544
|
+
const sigm = 5.67e-8;
|
|
545
|
+
const eta = 0.0;
|
|
546
|
+
const tc_set = 36.6;
|
|
547
|
+
const tsk_set = 34.0;
|
|
548
|
+
const tbody_set = 0.1 * tsk_set + 0.9 * tc_set;
|
|
549
|
+
|
|
550
|
+
const Adu = 0.203 * Math.pow(mbody, 0.425) * Math.pow(ht, 0.725);
|
|
551
|
+
const feff = 0.725;
|
|
552
|
+
const fcl = 1.0 + 0.31 * clo;
|
|
553
|
+
const facl = Math.max(0, Math.min(1, (173.51 * clo - 2.36 - 100.76 * clo * clo + 19.28 * Math.pow(clo, 3)) / 100));
|
|
554
|
+
const Aclo = Adu * facl + Adu * (fcl - 1.0);
|
|
555
|
+
const Aeffr = Adu * feff;
|
|
556
|
+
|
|
557
|
+
const hc = 2.67 + 6.5 * Math.pow(va, 0.67);
|
|
558
|
+
const metab_male = 3.45 * Math.pow(mbody, 0.75) * (1.0 + 0.004 * (30.0 - age) + 0.01 * (ht * 100.0 / Math.pow(mbody, 1.0 / 3.0) - 43.4));
|
|
559
|
+
const he = (met + metab_male) / Adu;
|
|
560
|
+
const h = he * (1.0 - eta);
|
|
561
|
+
|
|
562
|
+
const texp = 0.47 * Ta + 21.0;
|
|
563
|
+
const dventpulm = he * 1.44e-6;
|
|
564
|
+
const eres = cair * (Ta - texp) * dventpulm;
|
|
565
|
+
const vpexp = 6.11 * Math.pow(10.0, 7.45 * texp / (235.0 + texp));
|
|
566
|
+
const erel = 0.623 * (Lvap / p) * (vpa - vpexp) * dventpulm;
|
|
567
|
+
const ere = eres + erel;
|
|
568
|
+
|
|
569
|
+
const rcl = clo > 0.01 ? clo / 6.45 : 0.001;
|
|
570
|
+
const y = (ht - 0.2) / ht;
|
|
571
|
+
const r2 = Adu * (fcl - 1.0 + facl) / (6.28 * ht * y);
|
|
572
|
+
const r1 = facl * Adu / (6.28 * ht * y);
|
|
573
|
+
const di = r2 - r1;
|
|
574
|
+
const htcl = clo > 0.01 ? (6.28 * ht * y * di) / (rcl * Math.log(r2 / r1) * Aclo) : 1e5;
|
|
575
|
+
|
|
576
|
+
const Lw = 1.67;
|
|
577
|
+
const he_diff = hc * Lw;
|
|
578
|
+
const fecl = 1.0 / (1.0 + 0.92 * hc * rcl);
|
|
579
|
+
const R_ecl = (1.0 / (fcl * hc) + rcl) / (Lw * 0.38);
|
|
580
|
+
|
|
581
|
+
function syst3(T) {
|
|
582
|
+
const Tcr = T[0], Tsk = T[1], Tcl = T[2];
|
|
583
|
+
const sig_skin = Math.max(0, tsk_set - Tsk);
|
|
584
|
+
const sig_core = Math.max(0, Tcr - tc_set);
|
|
585
|
+
const qmblood = Math.min(90.0, (6.3 + 75.0 * sig_core) / (1.0 + 0.5 * sig_skin));
|
|
586
|
+
const alpha = 0.1;
|
|
587
|
+
|
|
588
|
+
const tbody = alpha * Tsk + (1.0 - alpha) * Tcr;
|
|
589
|
+
const sig_body = Math.max(0, tbody - tbody_set);
|
|
590
|
+
const qmsw = Math.min(500.0, 304.94e-3 * sig_body * 1000.0);
|
|
591
|
+
const esw = (Lvap / 1000.0) * (qmsw / 3600.0);
|
|
592
|
+
|
|
593
|
+
const Pvsk = 6.105 * Math.exp((17.27 * (Tsk + 273.15) - 4717.03) / (237.7 + Tsk));
|
|
594
|
+
const emax = he_diff * fecl * (Pvsk - vpa);
|
|
595
|
+
const w = emax > 0 ? Math.min(1.0, Math.max(0, esw / emax)) : 1.0;
|
|
596
|
+
const ediff = (1.0 - w) * (Pvsk - vpa) / R_ecl;
|
|
597
|
+
const evap = -(ediff + esw);
|
|
598
|
+
|
|
599
|
+
const rbare = Aeffr * (1.0 - facl) * emsk * sigm * (Math.pow(Tmrt + 273.15, 4) - Math.pow(Tsk + 273.15, 4)) / Adu;
|
|
600
|
+
const rclo = feff * Aclo * emcl * sigm * (Math.pow(Tmrt + 273.15, 4) - Math.pow(Tcl + 273.15, 4)) / Adu;
|
|
601
|
+
const cbare = hc * (Ta - Tsk) * (1.0 - facl);
|
|
602
|
+
const cclo = hc * (Ta - Tcl) * Aclo / Adu;
|
|
603
|
+
|
|
604
|
+
const Kcs = (qmblood / 3600.0) * cb + 5.28;
|
|
605
|
+
|
|
606
|
+
return [
|
|
607
|
+
h + ere - Kcs * (Tcr - Tsk),
|
|
608
|
+
rbare + cbare + evap + Kcs * (Tcr - Tsk) - htcl * (Tsk - Tcl),
|
|
609
|
+
cclo + rclo + htcl * (Tsk - Tcl)
|
|
610
|
+
];
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// 3-variable Newton-Raphson system solver
|
|
614
|
+
const T = [37.0, 34.0, (Ta + Tmrt) / 2.0];
|
|
615
|
+
for (let it = 0; it < 40; it++) {
|
|
616
|
+
const f = syst3(T);
|
|
617
|
+
if (Math.max(Math.abs(f[0]), Math.abs(f[1]), Math.abs(f[2])) < 1e-4) break;
|
|
618
|
+
const J = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];
|
|
619
|
+
const eps = 1e-5;
|
|
620
|
+
for (let j = 0; j < 3; j++) {
|
|
621
|
+
const T_plus = [T[0], T[1], T[2]];
|
|
622
|
+
T_plus[j] += eps;
|
|
623
|
+
const f_plus = syst3(T_plus);
|
|
624
|
+
for (let i = 0; i < 3; i++) J[i][j] = (f_plus[i] - f[i]) / eps;
|
|
625
|
+
}
|
|
626
|
+
const det = (J[0][0] * (J[1][1] * J[2][2] - J[1][2] * J[2][1])
|
|
627
|
+
- J[0][1] * (J[1][0] * J[2][2] - J[1][2] * J[2][0])
|
|
628
|
+
+ J[0][2] * (J[1][0] * J[2][1] - J[1][1] * J[2][0]));
|
|
629
|
+
if (Math.abs(det) < 1e-12) break;
|
|
630
|
+
const d0 = (-f[0] * (J[1][1] * J[2][2] - J[1][2] * J[2][1]) + f[1] * (J[0][1] * J[2][2] - J[0][2] * J[2][1]) - f[2] * (J[0][1] * J[1][2] - J[0][2] * J[1][1])) / det;
|
|
631
|
+
const d1 = (f[0] * (J[1][0] * J[2][2] - J[1][2] * J[2][0]) - f[1] * (J[0][0] * J[2][2] - J[0][2] * J[2][0]) + f[2] * (J[0][0] * J[1][2] - J[0][2] * J[1][0])) / det;
|
|
632
|
+
const d2 = (-f[0] * (J[1][0] * J[2][1] - J[1][1] * J[2][0]) + f[1] * (J[0][0] * J[2][1] - J[0][1] * J[2][0]) - f[2] * (J[0][0] * J[1][1] - J[0][1] * J[1][0])) / det;
|
|
633
|
+
const damping = Math.min(1.0, 5.0 / (Math.abs(d0) + Math.abs(d1) + Math.abs(d2) + 1e-6));
|
|
634
|
+
T[0] += damping * d0;
|
|
635
|
+
T[1] += damping * d1;
|
|
636
|
+
T[2] += damping * d2;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// Indoor reference state: v = 0.1 m/s, rh = 50% (vpa = 12 hPa), clo = 0.9, met = 80 W
|
|
640
|
+
const Tcr = T[0], Tsk = T[1], Tcl = T[2];
|
|
641
|
+
const ref_icl = 0.9;
|
|
642
|
+
const ref_fcl = 1.0 + 0.31 * ref_icl;
|
|
643
|
+
const ref_facl = Math.max(0, Math.min(1, (173.51 * ref_icl - 2.36 - 100.76 * ref_icl * ref_icl + 19.28 * Math.pow(ref_icl, 3)) / 100));
|
|
644
|
+
const ref_Aclo = Adu * ref_facl + Adu * (ref_fcl - 1.0);
|
|
645
|
+
const ref_rcl = ref_icl / 6.45;
|
|
646
|
+
const ref_r2 = Adu * (ref_fcl - 1.0 + ref_facl) / (6.28 * ht * y);
|
|
647
|
+
const ref_r1 = ref_facl * Adu / (6.28 * ht * y);
|
|
648
|
+
const ref_htcl = (6.28 * ht * y * (ref_r2 - ref_r1)) / (ref_rcl * Math.log(ref_r2 / ref_r1) * ref_Aclo);
|
|
649
|
+
const ref_hc = 2.67 + 6.5 * Math.pow(0.1, 0.67);
|
|
650
|
+
const ref_he_diff = ref_hc * Lw;
|
|
651
|
+
const ref_fecl = 1.0 / (1.0 + 0.92 * ref_hc * ref_rcl);
|
|
652
|
+
const ref_R_ecl = (1.0 / (ref_fcl * ref_hc) + ref_rcl) / (Lw * 0.38);
|
|
653
|
+
const ref_vpa = 12.0;
|
|
654
|
+
|
|
655
|
+
const tbody = 0.1 * Tsk + 0.9 * Tcr;
|
|
656
|
+
const sig_body = Math.max(0, tbody - tbody_set);
|
|
657
|
+
const qmsw = Math.min(500.0, 304.94e-3 * sig_body * 1000.0);
|
|
658
|
+
const esw = (Lvap / 1000.0) * (qmsw / 3600.0);
|
|
659
|
+
const Pvsk = 6.105 * Math.exp((17.27 * (Tsk + 273.15) - 4717.03) / (237.7 + Tsk));
|
|
660
|
+
const emax = ref_he_diff * ref_fecl * (Pvsk - ref_vpa);
|
|
661
|
+
const w = emax > 0 ? Math.min(1.0, Math.max(0, esw / emax)) : 1.0;
|
|
662
|
+
const ediff = (1.0 - w) * (Pvsk - ref_vpa) / ref_R_ecl;
|
|
663
|
+
const evap = -(ediff + esw);
|
|
664
|
+
|
|
665
|
+
function evalRef(Tx) {
|
|
666
|
+
const texp_ref = 0.47 * Tx + 21.0;
|
|
667
|
+
const eres_ref = cair * (Tx - texp_ref) * dventpulm;
|
|
668
|
+
const vpexp_ref = 6.11 * Math.pow(10.0, 7.45 * texp_ref / (235.0 + texp_ref));
|
|
669
|
+
const erel_ref = 0.623 * (Lvap / p) * (ref_vpa - vpexp_ref) * dventpulm;
|
|
670
|
+
const ere_ref = eres_ref + erel_ref;
|
|
671
|
+
|
|
672
|
+
const rbare_ref = Aeffr * (1.0 - ref_facl) * emsk * sigm * (Math.pow(Tx + 273.15, 4) - Math.pow(Tsk + 273.15, 4)) / Adu;
|
|
673
|
+
const rclo_ref = feff * ref_Aclo * emcl * sigm * (Math.pow(Tx + 273.15, 4) - Math.pow(Tcl + 273.15, 4)) / Adu;
|
|
674
|
+
const cbare_ref = ref_hc * (Tx - Tsk) * (1.0 - ref_facl);
|
|
675
|
+
const cclo_ref = ref_hc * (Tx - Tcl) * ref_Aclo / Adu;
|
|
676
|
+
|
|
677
|
+
return h + ere_ref + rbare_ref + rclo_ref + cbare_ref + cclo_ref + evap;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
let lo = -50.0, hi = 70.0;
|
|
681
|
+
for (let it = 0; it < 40; it++) {
|
|
682
|
+
const mid = (lo + hi) / 2.0;
|
|
683
|
+
if (evalRef(mid) < 0) lo = mid; else hi = mid;
|
|
684
|
+
}
|
|
685
|
+
return (lo + hi) / 2.0;
|
|
686
|
+
}
|