1.6.0
Fix and enhance the concrete calculation Minify the about.css file
This commit is contained in:
+36
-16
@@ -12,7 +12,7 @@
|
||||
|
||||
import {
|
||||
vaporPressureHpa, solarElevationDeg, calcTmrt, utciApprox,
|
||||
calcConcreteTemp, calcVehicleInteriorTemp,
|
||||
calcConcreteTempPass, calcVehicleInteriorTemp,
|
||||
calcIndoorTempPass, calcManagedIndoorTempPass,
|
||||
} from './physics.js';
|
||||
import { windCompass8, uvSplit, cloudCategory, precipPenalty } from './utils.js';
|
||||
@@ -55,20 +55,23 @@ export function buildHourlyRows({ forecast, airQuality, location, vehicleType, v
|
||||
const soilT0 = h.soil_temperature_0cm ? h.soil_temperature_0cm[i] : null;
|
||||
const soilT6 = h.soil_temperature_6cm ? h.soil_temperature_6cm[i] : null;
|
||||
const soilM = h.soil_moisture_0_to_1cm ? h.soil_moisture_0_to_1cm[i] : null;
|
||||
// iso is a local wall-clock string e.g. "2026-05-13T14:00" (no Z).
|
||||
// For display we slice the string directly - no Date object needed.
|
||||
// For solarElevationDeg (which uses .getUTC* internally) we need the
|
||||
// true UTC instant: treat the local time as UTC then subtract the offset.
|
||||
// e.g. Brisbane UTC+10: local 14:00 - parse as UTC 14:00 - subtract 10h - UTC 04:00 -
|
||||
// iso is a local wall-clock string e.g. "2026-05-13T14:00" (no Z).
|
||||
// For solarElevationDeg (which uses .getUTC* internally) we need the
|
||||
// true UTC instant: treat the local time as UTC then subtract the offset.
|
||||
const dt = new Date(Date.parse(iso + 'Z') - utcOffsetMs);
|
||||
const elev = solarElevationDeg(location.lat, location.lon, dt);
|
||||
// Use direct_radiation (beam sunlight) + a fraction of diffuse for concrete.
|
||||
// direct_radiation is zero on fully overcast days - far more accurate than
|
||||
// shortwave_radiation which can be unreliably high even at 100% cloud cover.
|
||||
// Diffuse (scattered light through cloud) contributes ~20% as much heat to
|
||||
// a surface as direct beam, so we weight it accordingly.
|
||||
const effectiveRad = dir + dif * 0.2;
|
||||
const concreteT = calcConcreteTemp(Ta, effectiveRad, va);
|
||||
// iso is a local wall-clock string e.g. "2026-05-13T14:00" (no Z).
|
||||
// For display we slice the string directly - no Date object needed.
|
||||
// For solarElevationDeg (which uses .getUTC* internally) we need the
|
||||
// true UTC instant: treat the local time as UTC then subtract the offset.
|
||||
// e.g. Brisbane UTC+10: local 14:00 - parse as UTC 14:00 - subtract 10h - UTC 04:00 -
|
||||
const dt = new Date(Date.parse(iso + 'Z') - utcOffsetMs);
|
||||
const elev = solarElevationDeg(location.lat, location.lon, dt);
|
||||
// concreteT is now stamped in the two-pass section below (thermal lag).
|
||||
const vehicleT = calcVehicleInteriorTemp(Ta, glob, elev, vehicleType, vehicleVent);
|
||||
const eh = vaporPressureHpa(Ta, RH);
|
||||
const Tmrt = calcTmrt(Ta, dir, dif, glob, elev);
|
||||
@@ -132,20 +135,37 @@ export function buildHourlyRows({ forecast, airQuality, location, vehicleType, v
|
||||
cc, ccLow, ccMid, ccHigh, cloudCat,
|
||||
uv, uvA, uvB,
|
||||
precip, snow,
|
||||
soilT0, soilT6, soilM, concreteT, vehicleT,
|
||||
soilT0, soilT6, soilM, vehicleT,
|
||||
effectiveRad,
|
||||
elev, Tmrt, utci, utciAdj, eh, compass,
|
||||
visKm, aqi,
|
||||
grassPollen, birchPollen, alderPollen, mugwortPollen, olivePollen, ragweedPollen,
|
||||
};
|
||||
}) : [];
|
||||
|
||||
// Two-pass indoor temperature: needs the full hourly arrays so thermal
|
||||
// lag can look back at previous hours. Run after hourlyRows is built,
|
||||
// then stamp each row with its indoorT value.
|
||||
// Two-pass calculations: concrete thermal lag + indoor temperature.
|
||||
// Both need the full hourly arrays so they can look back at previous
|
||||
// hours. Run after hourlyRows is built, then stamp each row.
|
||||
if (hourlyRows.length > 0) {
|
||||
const TaArr = hourlyRows.map(r => r.Ta);
|
||||
const globArr = hourlyRows.map(r => r.glob);
|
||||
const elevArr = hourlyRows.map(r => r.elev);
|
||||
const TaArr = hourlyRows.map(r => r.Ta);
|
||||
const globArr = hourlyRows.map(r => r.glob);
|
||||
const elevArr = hourlyRows.map(r => r.elev);
|
||||
const radArr = hourlyRows.map(r => r.effectiveRad);
|
||||
const vaArr = hourlyRows.map(r => r.va);
|
||||
const uvArr = hourlyRows.map(r => r.uv);
|
||||
const cloudCatArr = hourlyRows.map(r => r.cloudCat);
|
||||
const soilMArr = hourlyRows.map(r => r.soilM);
|
||||
const precipArr = hourlyRows.map(r => r.precip);
|
||||
const snowArr = hourlyRows.map(r => r.snow);
|
||||
|
||||
// Concrete surface temperature with thermal lag (1.5 h time constant).
|
||||
// A slab baking in the sun retains heat when cloud rolls in, and takes
|
||||
// a couple of hours of sunshine to fully heat up from a cold start.
|
||||
const concreteTemps = calcConcreteTempPass(
|
||||
TaArr, radArr, vaArr, elevArr, uvArr, cloudCatArr, soilMArr, precipArr, snowArr
|
||||
);
|
||||
hourlyRows.forEach((r, i) => { r.concreteT = concreteTemps[i]; });
|
||||
|
||||
const indoorTemps = calcIndoorTempPass(TaArr, globArr, elevArr, buildingType);
|
||||
const managedTemps = calcManagedIndoorTempPass(TaArr, globArr, elevArr, buildingType);
|
||||
hourlyRows.forEach((r, i) => { r.indoorT = indoorTemps[i]; r.managedT = managedTemps[i]; });
|
||||
|
||||
Reference in New Issue
Block a user