1.44 - New Filters, profiles & Mobile fixes

This commit is contained in:
fraxle
2026-05-17 16:01:34 +01:00
parent bc4fd3e6f1
commit 1cd2cd0ab4
11 changed files with 640 additions and 298 deletions
+40 -31
View File
@@ -1,18 +1,19 @@
// ════════════════════════════════════════════════════════════════════════
// physics.js — Physical constants and meteorological calculations.
//
// Exports:
// SIGMA, EPSILON_P, A_K, ALBEDO_GRASS (radiation constants)
// vaporPressureHpa(Ta, RH) Magnus formula → hPa
// solarElevationDeg(lat, lon, dateUTC) NOAA simplified solar position
// calcTmrt(Ta, dirRad, diffRad, globalRad, solElev) Mean radiant temp
// utciApprox(Ta, Tmrt, va10, ehPa) Bröde et al. 2012 polynomial
// calcVehicleInteriorTemp(Ta, globalRad, solElev, vehicleType, ventilated)
// calcIndoorTempPass(TaArr, globArr, elevArr, buildingType)
// calcManagedIndoorTempPass(TaArr, globArr, elevArr, buildingType)
// All numbers are peer-reviewed constants or coefficients. Nothing in
// here should need editing unless the underlying science changes.
//
// Nothing in here should need editing unless the underlying science
// changes. All numbers are peer-reviewed constants or coefficients.
// Exports (in order of appearance):
// SIGMA, EPSILON_P, A_K, ALBEDO_GRASS, ALBEDO_CONCRETE (radiation constants)
// calcConcreteTemp(Ta, globalRad, windSpeed) urban surface temp
// calcIndoorTempPass(TaArr, globArr, elevArr, buildingType) passive indoor temp
// calcManagedIndoorTempPass(TaArr, globArr, elevArr, buildingType) managed indoor temp
// calcVehicleInteriorTemp(Ta, globalRad, solElev, vehicleType, ventilated)
// vaporPressureHpa(Ta, RH) Magnus formula → hPa
// solarElevationDeg(lat, lon, dateUTC) NOAA simplified solar position (°)
// calcTmrt(Ta, dirRad, diffRad, globalRad, solElev) Mean radiant temperature
// utciApprox(Ta, Tmrt, va10, ehPa) Bröde et al. 2012 UTCI polynomial
// ════════════════════════════════════════════════════════════════════════
import { VEHICLE_TYPES, BUILDING_TYPES } from './utils.js';
@@ -104,23 +105,6 @@ export function calcConcreteTemp(Ta, globalRad, windSpeed) {
// > 32 °C — hot; risk for elderly and vulnerable occupants
// ═══════════════════════════════════════════════════════════════════
// Single-hour instantaneous heat load (W/m² effective, indoor side).
// Used internally by calcIndoorTempPass — not exported.
function _houseHeatLoad(Ta, globalRad, solElev) {
// Wall + roof conduction: U-value ~0.35 W/m²K × effective envelope area ratio
// We express as a gain-per-degree-delta — applied against Ti later in the pass.
// (See calcIndoorTempPass for how this feeds the lag model.)
// Window solar gain: glazing ratio 0.16, g-value 0.63 (standard double glazing),
// averaged across orientations (0.5 factor — not all windows face the sun).
const glazingRatio = 0.16;
const gValue = 0.63;
const orientFactor = 0.50;
const solarGain = globalRad * glazingRatio * gValue * orientFactor;
return { conductionDelta: Ta, solarGain };
}
// Two-pass function: call with the full arrays of hourly Ta and globalRad.
// Returns an array of indoor temperatures, one per hour.
// buildingType must be a key of BUILDING_TYPES; defaults to 'brick'.
@@ -332,13 +316,24 @@ export function calcVehicleInteriorTemp(Ta, globalRad, solElev, vehicleType = 'c
// for road-trip planning, dog-in-car safety at a rest stop vs. motorway, etc.
// ─────────────────────────────────────────────────────────────────────────────
// Vapour pressure (Magnus → hPa)
// ═══════════════════════════════════════════════════════════════════
// VAPOUR PRESSURE — Magnus formula.
// ───────────────────────────────────────────────────────────────────
// Converts air temperature (°C) and relative humidity (%) to vapour
// pressure in hPa. Used as the humidity input to utciApprox().
// ═══════════════════════════════════════════════════════════════════
export function vaporPressureHpa(Ta, RH) {
const es = 6.105 * Math.exp((17.27 * Ta) / (237.7 + Ta));
return es * (RH / 100);
}
// Solar elevation (NOAA simplified, degrees)
// ═══════════════════════════════════════════════════════════════════
// SOLAR ELEVATION — NOAA simplified algorithm (degrees above horizon).
// ───────────────────────────────────────────────────────────────────
// Accurate to within ~0.01° for most practical purposes. Returns a
// negative value when the sun is below the horizon (civil twilight
// starts at 6°, nautical at 12°, astronomical at 18°).
// ═══════════════════════════════════════════════════════════════════
export function solarElevationDeg(lat, lon, dateUTC) {
const start = Date.UTC(dateUTC.getUTCFullYear(), 0, 0);
const diff = dateUTC - start;
@@ -374,7 +369,21 @@ export function solarElevationDeg(lat, lon, dateUTC) {
return (Math.PI / 2 - zenith) * (180 / Math.PI);
}
// Mean radiant temperature
// ═══════════════════════════════════════════════════════════════════
// MEAN RADIANT TEMPERATURE (Tmrt)
// ───────────────────────────────────────────────────────────────────
// Tmrt is the uniform temperature of an imaginary enclosure that would
// cause the same net radiation exchange as the actual environment.
// It accounts for:
// • Direct solar beam (DNI), scaled by the projected-area factor fp
// • Diffuse sky radiation (scattered and cloud-reflected)
// • Ground-reflected shortwave (albedo × global radiation)
// • Longwave thermal emission from surrounding surfaces (≈ blackbody at Ta)
//
// The fabric index 0.308 (fp formula from ISO 7933) projects the sun
// onto a standing person's silhouette as a function of solar elevation.
// Output feeds directly into utciApprox() as the Tmrt argument.
// ═══════════════════════════════════════════════════════════════════
export function calcTmrt(Ta, dirRad, diffRad, globalRad, solElev) {
const TaK = Ta + 273.15;
let fp = 0;