Environment 'Shade' temperatures.
Add shade to profiles
Add shade to table column
This commit is contained in:
fraxle
2026-06-27 15:15:59 +01:00
parent 05ab4cf76b
commit df3256462a
6 changed files with 146 additions and 83 deletions
+48
View File
@@ -12,6 +12,7 @@
// calcIndoorTempPass(TaArr, globArr, elevArr, buildingType) passive indoor temp
// calcManagedIndoorTempPass(TaArr, globArr, elevArr, buildingType) managed indoor temp
// calcVehicleInteriorTemp(Ta, globalRad, solElev, vehicleType, ventilated, speedMph)
// calcShadeAirTemp(Ta, effectiveRad, va, elev, shade) per-env shade air temp
// vaporPressureHpa(Ta, RH) Magnus formula - hPa
// solarElevationDeg(lat, lon, dateUTC) NOAA simplified solar position (-)
// calcTmrt(Ta, dirRad, diffRad, globalRad, solElev) Mean radiant temperature
@@ -469,6 +470,53 @@ export function calcVehicleInteriorTemp(Ta, globalRad, solElev, vehicleType = 'c
return Math.max(Ta, Math.min(Ti, 90));
}
// -------------------------------------------------------------------
// SHADE AIR TEMPERATURE (per-environment microclimate)
// -------------------------------------------------------------------
// Estimates the AIR temperature you'd actually experience sitting in
// the typical shade of the selected Solar Model - NOT the felt temp.
//
// The official Air column is the standardised open-ground, 2 m,
// shaded-screen value for a ~2 km model grid cell. A real sitting
// spot is a sheltered sun-trap: surrounding surfaces (walls, sand,
// rock) re-radiate heat into the still air pocket, while wind mixing
// pulls the pocket back toward the official reading. The kind of
// shelter and the heat of the surroundings differ by environment,
// which is what the per-env `shade` block captures.
//
// IMPORTANT: this is an air-temperature nudge, deliberately gentle.
// The radiant load of direct sun is already handled by Tmrt/SunSoak,
// so we do NOT re-add it here - that would double-count the sun.
//
// shade.offset - base air-temp delta for this environment's shade (-C).
// Warmer for urban/desert (heat island, baking ground),
// cooler for river/forest (evaporative, canopy shade).
// shade.shelter - 0-1 wind shelter. High = enclosed (canyon, canopy),
// so wind mixing has little effect. Low = breezy
// (open water, single beach umbrella).
// shade.sun - 0-~1.2 surface solar gain. How sun-baked the
// surroundings are: hot concrete/sand high, shaded
// forest floor / cool water low. Drives how much the
// still air warms on a sunny hour.
//
// Behaviour: a calm sunny hour in a sheltered, sun-baked environment
// reads a degree or two above official Air; a windy or overcast hour
// collapses back toward it.
// -------------------------------------------------------------------
export const SHADE_K_SUN = 1.5; // surface-warming strength (per full-sun, fully sun-baked)
export const SHADE_K_WIND = 0.15; // wind-mixing strength (per m/s, fully exposed)
export function calcShadeAirTemp(Ta, effectiveRad, va, elev, shade) {
if (Ta == null || !shade) return Ta ?? null;
const rad = Math.max(0, Math.min(1, (effectiveRad || 0) / 800)); // 0-1, saturates ~800 W/m-
const daytime = (elev != null && elev > 0) ? 1 : 0;
const sunTerm = SHADE_K_SUN * (shade.sun ?? 0) * rad * daytime;
const windTerm = SHADE_K_WIND * (1 - (shade.shelter ?? 0)) * Math.max(0, va || 0);
const adj = (shade.offset ?? 0) + sunTerm - windTerm;
// Keep the nudge sane - this is air temp, not a felt-temp delta.
return Ta + Math.max(-5, Math.min(6, adj));
}
// -- FUTURE FEATURE v2: Pets Profile - Fur Temperature & Heat Stress ----------
// Dogs and cats experience heat very differently from humans:
//