From 069a607b78313735696cad87d4d3da01cf60ac78 Mon Sep 17 00:00:00 2001 From: Peter Kalverla Date: Mon, 26 May 2025 08:40:06 +0200 Subject: [PATCH 01/12] Refactoring python fireplume code --- plume.ipynb | 677 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 677 insertions(+) create mode 100644 plume.ipynb diff --git a/plume.ipynb b/plume.ipynb new file mode 100644 index 0000000..9d3b889 --- /dev/null +++ b/plume.ipynb @@ -0,0 +1,677 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "ecaf870d", + "metadata": {}, + "outputs": [], + "source": [ + "# ============================================================================\n", + "# thermodynamics.py\n", + "# ============================================================================\n", + "\n", + "import numpy as np\n", + "from typing import Tuple\n", + "\n", + "# Physical constants\n", + "CP = 1005.0 # Specific heat at constant pressure [J/kg/K]\n", + "LV = 2.5e6 # Latent heat of vaporization [J/kg]\n", + "RV = 461.5 # Gas constant for water vapor [J/kg/K]\n", + "RD = 287.04 # Gas constant for dry air [J/kg/K]\n", + "G = 9.81 # Gravitational acceleration [m/s²]\n", + "EP = 0.622 # Ratio of molecular weights (dry air / water vapor)\n", + "\n", + "\n", + "def virtual_temperature(\n", + " theta: np.ndarray, qt: np.ndarray, ql: np.ndarray\n", + ") -> np.ndarray:\n", + " \"\"\"\n", + " Calculate virtual potential temperature\n", + "\n", + " Args:\n", + " theta: Potential temperature [K]\n", + " qt: Total specific humidity [kg/kg]\n", + " ql: Liquid water mixing ratio [kg/kg]\n", + "\n", + " Returns:\n", + " Virtual potential temperature [K]\n", + " \"\"\"\n", + " return theta * (1.0 - (1.0 - RV / RD) * qt - RV / RD * ql)\n", + "\n", + "\n", + "def esat_liq(t: np.ndarray) -> np.ndarray:\n", + " \"\"\"Calculate saturation vapor pressure over liquid water [Pa]\"\"\"\n", + " Tc = t - 273.15\n", + " Tc = np.minimum(Tc, 50) # Avoid excess values\n", + " return 611.21 * np.exp(17.502 * Tc / (240.97 + Tc))\n", + "\n", + "\n", + "def qsat_liq(p: np.ndarray, t: np.ndarray) -> np.ndarray:\n", + " \"\"\"Calculate saturation specific humidity over liquid water [kg/kg]\"\"\"\n", + " return EP * esat_liq(t) / (p - (1.0 - EP) * esat_liq(t))\n", + "\n", + "\n", + "def dqsatdT_liq(p: np.ndarray, t: np.ndarray) -> np.ndarray:\n", + " \"\"\"Calculate derivative of saturation specific humidity with respect to temperature\"\"\"\n", + " den = p - esat_liq(t) * (1.0 - EP)\n", + " return (\n", + " (EP / den + (1.0 - EP) * EP * esat_liq(t) / den**2)\n", + " * LV\n", + " * esat_liq(t)\n", + " / (RV * t**2)\n", + " )\n", + "\n", + "\n", + "def calc_thetav(thl: float, qt: float, p: float, exner: float) -> Tuple[float, float]:\n", + " \"\"\"\n", + " Calculate virtual potential temperature with saturation adjustment\n", + "\n", + " Args:\n", + " thl: Liquid water potential temperature [K]\n", + " qt: Total specific humidity [kg/kg]\n", + " p: Pressure [Pa]\n", + " exner: Exner function [-]\n", + "\n", + " Returns:\n", + " (virtual potential temperature [K], saturation specific humidity [kg/kg])\n", + " \"\"\"\n", + " tl = exner * thl\n", + " qsat = qsat_liq(p, tl)\n", + "\n", + " if qt - qsat <= 0.0:\n", + " return virtual_temperature(thl, qt, 0.0), qsat\n", + "\n", + " # Newton-Raphson iteration for saturation adjustment\n", + " niter = 0\n", + " nitermax = 100\n", + " tnr = tl\n", + " tnr_old = 1e9\n", + "\n", + " while (np.abs(tnr - tnr_old) / tnr_old > 1e-5) and (niter < nitermax):\n", + " niter += 1\n", + " tnr_old = tnr\n", + " qsat = qsat_liq(p, tnr)\n", + " f = tnr - tl - LV / CP * (qt - qsat)\n", + " f_prime = 1 + LV / CP * dqsatdT_liq(p, tnr)\n", + " tnr -= f / f_prime\n", + "\n", + " ql = qt - qsat\n", + " return virtual_temperature(tnr / exner, qt, ql), qsat" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "68c97875", + "metadata": {}, + "outputs": [], + "source": [ + "# ============================================================================\n", + "# profiles.py\n", + "# ============================================================================\n", + "\n", + "from dataclasses import dataclass\n", + "from typing import List\n", + "import numpy as np\n", + "# from thermodynamics import virtual_temperature, RD, CP, G\n", + "\n", + "\n", + "@dataclass\n", + "class ClassOutput:\n", + " \"\"\"Relevant variables from Class output.\"\"\"\n", + "\n", + " h: float # Boundary layer height [m]\n", + " theta: float # Potential temperature in boundary layer [K]\n", + " dtheta: float # Jump at top of boundary layer [K]\n", + " dqt: float # Jump at top of boundary layer [kg/kg]\n", + " qt: float # Total specific humidity in boundary layer [kg/kg]\n", + " du: float # Jump at top of boundary layer [m/s]\n", + " u: float # U-component in boundary layer [m/s]\n", + " dv: float # Jump at top of boundary layer [m/s]\n", + " v: float # V-component in boundary layer [m/s]\n", + "\n", + "\n", + "\n", + "@dataclass\n", + "class ClassInput:\n", + " \"\"\"Input parameters from CLASS config\"\"\"\n", + " # TODO: add p0 to class config\n", + " p0: float # Surface pressure [Pa]\n", + "\n", + " # Piecewise potential temperature profile\n", + " z_theta: List[float] # Heights of segment boundaries [m]\n", + " gamma_theta: List[float] # Temperature lapse rates in each segment [K/m]\n", + "\n", + " # Piecewise specific humidity profile\n", + " z_qt: List[float] # Heights of segment boundaries [m]\n", + " gamma_qt: List[float] # Humidity lapse rates in each segment [1/m]\n", + "\n", + " # Piecewise wind profiles\n", + " z_u: List[float] # Heights of segment boundaries [m]\n", + " gamma_u: List[float] # U-wind lapse rates in each segment [1/s]\n", + "\n", + " z_v: List[float] # Heights of segment boundaries [m]\n", + " gamma_v: List[float] # V-wind lapse rates in each segment [1/s]\n", + "\n", + "\n", + "@dataclass\n", + "class AtmosphericProfile:\n", + " \"\"\"Atmospheric vertical profiles\"\"\"\n", + "\n", + " z: np.ndarray # Height levels (cell centers) [m]\n", + " theta: np.ndarray # Potential temperature [K]\n", + " qt: np.ndarray # Total specific humidity [kg/kg]\n", + " u: np.ndarray # U-component of wind [m/s]\n", + " v: np.ndarray # V-component of wind [m/s]\n", + " thetav: np.ndarray # Virtual potential temperature [K]\n", + " p: np.ndarray # Pressure [Pa]\n", + " exner: np.ndarray # Exner function [-]\n", + " T: np.ndarray # Temperature [K]\n", + " rho: np.ndarray # Density [kg/m³]\n", + "\n", + "\n", + "def _piecewise_profile(\n", + " z: np.ndarray,\n", + " h: float,\n", + " ml_value: float,\n", + " jump: float,\n", + " z_segments: List[float],\n", + " gamma_segments: List[float],\n", + ") -> np.ndarray:\n", + " \"\"\"\n", + " Create CLASS-style piecewise profile: mixed layer + inversion + free troposphere\n", + "\n", + " Args:\n", + " z: Height array [m]\n", + " h: Mixed-layer height [m]\n", + " ml_value: Value in mixed layer (mixed layer)\n", + " jump: Jump at mixed layer top (inversion)\n", + " z_segments: Heights defining free troposphere segments [m]\n", + " gamma_segments: Lapse rates in free troposphere segments [unit/m]\n", + "\n", + " Returns:\n", + " Profile values at height levels z\n", + " \"\"\"\n", + " profile = np.zeros_like(z)\n", + "\n", + " for i, _z in enumerate(z):\n", + " if _z <= h:\n", + " # Mixed layer: constant value\n", + " profile[i] = ml_value\n", + " else:\n", + " # Above boundary layer: start with jump, then apply lapse rates\n", + " current_value = ml_value + jump\n", + " anchor_point = h\n", + "\n", + " # Find which segment this height falls into\n", + " for seg_idx, z_top in enumerate(z_segments):\n", + " if z_top < h:\n", + " # Mixed layer has grown beyond this segment; irrelevant\n", + " continue\n", + " if _z >= z_top:\n", + " # We've passed this segment; add its contribution and update anchor\n", + " dz = z_top - anchor_point\n", + " current_value += gamma_segments[seg_idx] * dz\n", + " anchor_point = z_top\n", + " else:\n", + " # Height falls within this segment\n", + " dz = _z - anchor_point\n", + " current_value += gamma_segments[seg_idx] * dz\n", + " break\n", + " else:\n", + " # Extend profile with last value of lapse rate\n", + " # Shouldn't be needed, but can't enforce equal heights of segments in form\n", + " dz = _z - z_top\n", + " current_value += gamma_segments[seg_idx] * dz\n", + "\n", + " profile[i] = current_value\n", + "\n", + " return profile\n", + "\n", + "\n", + "def generate_profiles(\n", + " config: ClassInput, output: ClassOutput, dz=1\n", + ") -> AtmosphericProfile:\n", + " \"\"\"\n", + " Generate vertical atmospheric profiles from CLASS output\n", + "\n", + " Args:\n", + " class_config: CLASS model configuration (subset)\n", + " class_output: CLASS model output (subset)\n", + " dz: grid spacing\n", + "\n", + " Returns:\n", + " AtmosphericProfile with all computed variables\n", + " \"\"\"\n", + " # z_top should be the same for all variables, but this is not guaranteed!\n", + " z_top = config.z_theta[-1]\n", + "\n", + " # Generate height arrays (cell centers only)\n", + " z = np.arange(0 + dz / 2, z_top, dz)\n", + "\n", + " # Generate half-levels for pressure calculation\n", + " zh = np.arange(0, z_top + dz / 2, dz)\n", + "\n", + " # Calculate piecewise profiles\n", + " theta = _piecewise_profile(\n", + " z, output.h, output.theta, output.dtheta, config.z_theta, config.gamma_theta\n", + " )\n", + "\n", + " qt = _piecewise_profile(\n", + " z, output.h, output.qt, output.dqt, config.z_qt, config.gamma_qt\n", + " )\n", + "\n", + " u = _piecewise_profile(z, output.h, output.u, output.du, config.z_u, config.gamma_u)\n", + "\n", + " v = _piecewise_profile(z, output.h, output.v, output.dv, config.z_v, config.gamma_v)\n", + "\n", + " # Calculate virtual potential temperature (assuming dry base state)\n", + " thetav = virtual_temperature(theta, qt, np.zeros_like(qt))\n", + "\n", + " # For pressure calculation, we need profiles on half-levels\n", + " thetah = _piecewise_profile(\n", + " zh, output.h, output.theta, output.dtheta, config.z_theta, config.gamma_theta\n", + " )\n", + " qth = _piecewise_profile(\n", + " zh, output.h, output.qt, output.dqt, config.z_qt, config.gamma_qt\n", + " )\n", + " thetavh = virtual_temperature(thetah, qth, np.zeros_like(qth))\n", + "\n", + " # Compute pressure profile using hydrostatic balance\n", + " ph_Rdcp = np.zeros_like(zh)\n", + " ph_Rdcp[0] = config.p0 ** (RD / CP)\n", + " for i in range(1, len(ph_Rdcp)):\n", + " ph_Rdcp[i] = (\n", + " ph_Rdcp[i - 1] - G / CP * config.p0 ** (RD / CP) / thetavh[i - 1] * dz\n", + " )\n", + "\n", + " ph = ph_Rdcp ** (CP / RD)\n", + " p = np.exp(0.5 * (np.log(ph[:-1]) + np.log(ph[1:])))\n", + "\n", + " # Calculate Exner function, temperature, and density\n", + " exner = (p / config.p0) ** (RD / CP)\n", + " T = exner * theta\n", + " rho = p / (RD * exner * thetav)\n", + "\n", + " return AtmosphericProfile(\n", + " z=z, theta=theta, qt=qt, u=u, v=v, thetav=thetav, p=p, exner=exner, T=T, rho=rho\n", + " )\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a94e80d1", + "metadata": {}, + "outputs": [], + "source": [ + "# ============================================================================\n", + "# fireplume.py\n", + "# ============================================================================\n", + "\n", + "from dataclasses import dataclass, fields\n", + "from typing import List\n", + "import numpy as np\n", + "# from thermodynamics import calc_thetav, G, CP, LV\n", + "\n", + "\n", + "@dataclass\n", + "class FireParameters:\n", + " \"\"\"Fire characteristics and parameters\"\"\"\n", + "\n", + " L: float # Length of the fire [m]\n", + " d: float # Depth of the fire [m]\n", + " h0: float # Height where fire starts [m]\n", + " C: float # Heat stored in fuel [J/kg]\n", + " omega: float # Fuel mass per area [kg/m²]\n", + " v: float # Rate of spread of the fire [m/s]\n", + " radiative_loss: float # Fraction of F converted to radiative heating\n", + "\n", + "\n", + "@dataclass\n", + "class PlumeConfig:\n", + " \"\"\"Configuration parameters for plume model\"\"\"\n", + "\n", + " z_sl: float = 100.0 # Surface layer height [m]\n", + " lambda_mix: float = 30.0 # Mixing length in surface layer [m]\n", + " beta: float = 1.0 # Fractional detrainment above surface layer\n", + "\n", + "\n", + "@dataclass\n", + "class Parcel:\n", + " z: float # Height levels [m]\n", + " w: float # Vertical velocity [m/s]\n", + " theta: float # Potential temperature [K]\n", + " qt: float # Total specific humidity [kg/kg]\n", + " thetav: float # Virtual potential temperature [K]\n", + " qsat: float # Saturation specific humidity [kg/kg]\n", + " b: float # Buoyancy [m/s²]\n", + " m: float # Mass flux [kg/m²/s]\n", + " area: float # Cross-sectional area [m²]\n", + " e: float # Entrainment rate [kg/m²/s]\n", + " d: float # Detrainment rate [kg/m²/s]\n", + "\n", + "\n", + "def initialize_fire_parcel(background: AtmosphericProfile, fire: FireParameters):\n", + " # Start with parcel props from ambient air\n", + " z = background.z[0]\n", + " theta = background.theta[0]\n", + " thetav_ambient = background.thetav[0]\n", + " qt = background.qt[0]\n", + " rho = background.rho[0]\n", + " p = background.p[0]\n", + " exner = background.exner[0]\n", + "\n", + " # Calculate fire properties\n", + " area = fire.L * fire.d\n", + " F_fire = fire.omega * fire.C * fire.v / fire.d * (1 - fire.radiative_loss)\n", + " F_q_fire = 0.0 * F_fire # Dry plume for now\n", + " w = (3 * G * F_fire * fire.h0 / (2 * rho * CP * thetav_ambient)) ** (1.0 / 3)\n", + "\n", + " # Add excess temperature/humidity and update thetav/qsat accordingly\n", + " dtheta = F_fire / (rho * CP * w)\n", + " dqv = F_q_fire / (rho * LV * w)\n", + " theta += dtheta\n", + " qt += dqv\n", + " thetav, qsat = calc_thetav(theta, qt, p, exner) # Note: thetav != thetav_ambient\n", + "\n", + " # Calculate parcel buoyancy\n", + " b = G / background.thetav[0] * (thetav - thetav_ambient)\n", + "\n", + " # Store parcel props\n", + " return Parcel(\n", + " z=z,\n", + " w=w,\n", + " theta=theta,\n", + " qt=qt,\n", + " thetav=thetav,\n", + " qsat=qsat,\n", + " b=b,\n", + " area=fire.L * fire.d,\n", + " m=rho * area * w,\n", + " e=rho * area / (2 * w) * b,\n", + " d=0,\n", + " )\n", + "\n", + "\n", + "def calculate_plume(\n", + " fire: FireParameters,\n", + " background: AtmosphericProfile,\n", + " plume_config: PlumeConfig,\n", + " dz: float,\n", + ") -> list[Parcel]:\n", + " plume: list[Parcel] = []\n", + " crossed_sl = False\n", + " for i, z in enumerate(background.z):\n", + " if i == 0:\n", + " parcel = initialize_fire_parcel(background, fire)\n", + " detrainment_rate = plume_config.lambda_mix**0.5 / parcel.area**0.5\n", + " else:\n", + " # Update parcel\n", + " # Mass flux through plume\n", + " m = parcel.m + (parcel.e - parcel.d) * dz\n", + "\n", + " # Apply mass flux to conserved variables\n", + " theta = (\n", + " parcel.theta\n", + " - parcel.e * (parcel.theta - background.theta[i - 1]) / parcel.m * dz\n", + " )\n", + " qt = (\n", + " parcel.qt\n", + " - parcel.e * (parcel.qt - background.qt[i - 1]) / parcel.m * dz\n", + " )\n", + "\n", + " # Calculate virtual potential temperature and buoyancy\n", + " thetav, qsat = calc_thetav(theta, qt, background.p[i], background.exner[i])\n", + " b = G / background.thetav[i] * (thetav - background.thetav[i])\n", + "\n", + " # Solve vertical velocity equation\n", + " a_w = 1\n", + " b_w = 0\n", + " w = (\n", + " parcel.w\n", + " + (\n", + " -b_w * parcel.e * parcel.w\n", + " + a_w * parcel.area * background.rho[i - 1] * parcel.b\n", + " )\n", + " / parcel.m\n", + " * dz\n", + " )\n", + "\n", + " # Calculate entrainment and detrainment\n", + " if z < plume_config.z_sl:\n", + " # Surface layer formulation\n", + " e = parcel.area * background.rho[i - 1] / (2 * parcel.w) * parcel.b\n", + " d = (\n", + " parcel.area\n", + " * background.rho[i - 1]\n", + " * detrainment_rate\n", + " * (z**0.5 * (w - parcel.w) / dz + parcel.w / (2 * z**0.5))\n", + " )\n", + " else:\n", + " # Above surface layer\n", + " if not crossed_sl:\n", + " epsi = parcel.e / parcel.m\n", + " delt = epsi / plume_config.beta\n", + " crossed_sl = True\n", + "\n", + " e = epsi * m\n", + " d = delt * m\n", + "\n", + " area = m / (background.rho[i] * w)\n", + "\n", + " # Update parcel\n", + " parcel = Parcel(\n", + " z=z,\n", + " w=w,\n", + " theta=theta,\n", + " qt=qt,\n", + " thetav=thetav,\n", + " qsat=qsat,\n", + " b=b,\n", + " area=area,\n", + " m=m,\n", + " e=e,\n", + " d=d,\n", + " )\n", + "\n", + " if w < 0 or area <= 0:\n", + " break\n", + "\n", + " plume.append(parcel)\n", + "\n", + " return plume\n", + "\n", + "\n", + "def transpose_plume_data(plume: list[Parcel]) -> dict[str, np.ndarray]:\n", + " \"\"\"Convert array of objects into object of arrays.\"\"\"\n", + " if not plume:\n", + " return {}\n", + "\n", + " # Get field names from the dataclass\n", + " field_names = [field.name for field in fields(plume[0])]\n", + "\n", + " # Extract arrays for each field\n", + " transposed = {}\n", + " for field_name in field_names:\n", + " transposed[field_name] = np.array(\n", + " [getattr(parcel, field_name) for parcel in plume]\n", + " )\n", + "\n", + " return transposed\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "ebb0c7e7", + "metadata": {}, + "outputs": [], + "source": [ + "# Define CLASS input parameters with piecewise profiles\n", + "config = ClassInput(\n", + " p0 = 101300,\n", + " z_theta=[10000],\n", + " gamma_theta=[0.006],\n", + " z_qt=[10000],\n", + " gamma_qt=[-0.0001e-3],\n", + " z_u=[10000],\n", + " gamma_u=[0.001],\n", + " z_v=[10000],\n", + " gamma_v=[0.0005],\n", + ")\n", + "output = ClassOutput(\n", + " h=1000,\n", + " theta=300,\n", + " dtheta=2,\n", + " qt=0.0085,\n", + " dqt=-0.001,\n", + " u=5.0,\n", + " du=0,\n", + " v=2.0,\n", + " dv=0,\n", + ")\n", + "\n", + "background = generate_profiles(config, output)\n", + "\n", + "\n", + "plume_config = PlumeConfig()\n", + "fire = FireParameters(\n", + " L=10000, d=300, h0=20, C=17.781e6, omega=7.6, v=1.5, radiative_loss=0.7\n", + ")\n", + "plume = calculate_plume(fire, background, plume_config, dz=1)\n", + "plume_t = transpose_plume_data(plume)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "65fb84c5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 0, 'T')" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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p9qhJJVZH7eemOU5Msvj1AL+rGeHPzdt0vPzoufYaebM9nyb7fHGE392iZXon6+pB+ARERERERER6RFX5omIiIiIiIh0hsU8ERERERERkc6wmCciIiIiIiLSGRbzRERERERERDrDYn4ann32WUiSNOmP2+2O/b0QAs8++yyKi4uRmpqKO+64AydOnJj0Nfx+P5566ink5+cjPT0dDz/8MDo6Oibd4/F4sG3bNrhcLrhcLmzbtg1er3fSPW1tbfjgBz+I9PR05Ofn4zOf+QwCgUBcHuc777yDD37wgyguLoYkSfjVr3416e+19jgbGxuxZcsWpKamoqSkBF/96lfBeY439p3vfAdVVVVISUnB2rVr8e67717z3rfffvuq3JckCadPn05ixDN3o1yeyp49e7B27VqkpKSguroaL7zwQuID1anvfve7WLlyJbKyspCVlYVNmzbht7/9bezv4/VaYTQ3+rn9yZ/8yVX/X9u4ceOkr2HGn1s8zeT1D5je68JLL72EZcuWwel0YtmyZXjllVcm/X1lZeWUr6Of/vSnNR97KBTC3/3d36Gqqgqpqamorq7GV7/6VUQikRnFTokx05x48cUXsWrVKqSlpaGoqAh/+qd/ioGBgSRFOzf8vT59O3bswPr165GZmYmCggJ86EMfwpkzZybdw983c6Op90GCbuiZZ54Ry5cvF93d3bE/vb29sb9/7rnnRGZmpnjppZdEY2OjeOSRR0RRUZEYGhqK3fPEE0+IkpISsXv3bnH48GFx5513ilWrVolQKBS754EHHhA1NTWirq5O1NXViZqaGrF169bY34dCIVFTUyPuvPNOcfjwYbF7925RXFwsnnzyybg8ztdee018+ctfFi+99JIAIF555ZVJf6+lx+nz+URhYaF49NFHRWNjo3jppZdEZmam+MY3vhGXn4VR7dy5U9jtdvH9739fnDx5Unz2s58V6enporW1dcr733rrLQFAnDlzZlL+X/58atGNcvlKTU1NIi0tTXz2s58VJ0+eFN///veF3W4Xv/zlL5MTsM68+uqr4je/+Y04c+aMOHPmjPjbv/1bYbfbxfHjx4UQ8XutMJob/dw+8YlPiAceeGDS/9cGBgYmfQ0z/tziZaavf9N5XairqxNWq1V87WtfE6dOnRJf+9rXhM1mE3v37o3d09vbO+k53b17twAg3nrrLc3H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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "plt.figure(figsize=(10, 4.5), constrained_layout=True)\n", + "plt.subplot(161)\n", + "plt.plot(background.p, background.z)\n", + "plt.xlabel(\"p\")\n", + "plt.subplot(162)\n", + "plt.plot(background.rho, background.z)\n", + "plt.xlabel(\"rho\")\n", + "plt.subplot(163)\n", + "plt.plot(background.theta, background.z)\n", + "plt.plot(background.thetav, background.z)\n", + "plt.xlabel(\"theta\")\n", + "plt.subplot(164)\n", + "plt.plot(background.qt, background.z)\n", + "plt.xlabel(\"qt\")\n", + "plt.subplot(165)\n", + "plt.plot(background.exner, background.z)\n", + "plt.xlabel(\"exner\")\n", + "plt.subplot(166)\n", + "plt.plot(background.T, background.z)\n", + "plt.xlabel(\"T\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f7d30d35", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 0, 'buoyancy')" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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O7tJ+lhb/wCIZcuW6dqYQj/NUUPkb0NrqHwj6ZnjNk9DutP/Z13JhLhxlx4iIiIiIiIiMgpmec08ERERERERkTFjMU9ERERERERkZFjMExERERERERkZFvNERERERERERobFPBEREREREZGRYTFPREREREREZGRYzBMREREREREZGRbzREREREREREaGxbwBio6OhkwmQ05OjtShEBFRPbVo0QKLFi2SOgwyAT/++CMcHR11r99991106tRJsniIiG4lMjIS06ZNkzoMs8Fi3gA0VtLLZDL89ttvDT5dorpgIUOmJjIyEosXL5Y6DCLMnDkTf/31l9RhEBGRxFjMExER3cH169exb98+DB48WOpQyIiVlZU1yHTs7Ozg4uLSINMiIiLjxWJeYuPHj8fu3bvx+eefQyaTQSaT4cKFCwCAmJgYdO3aFTY2NujZsycSExP13rtx40aEhobCysoKAQEBeO+991BRUQGg8qgoADzyyCOQyWS61+fPn8fQoUPh7u4OOzs7dOvWDTt27Giq7pIJKSwsxNixY2FnZwdPT08sWLBAd5ZJZGQkLl68iOnTp+vymsgQCCEwf/58BAQEwNraGiEhIfj111/v+L7NmzcjJCQEzZs3r3V8RkYGBg8eDGtra/j7+2PlypUNHToZocjISEyZMgUzZsyAq6sr+vXrh88++wzBwcGwtbWFj48Pnn/+eRQUFOi978cff4Svry9sbGzwyCOPICsrS2/8zafZ13aG37BhwzB+/Hjd62+++QatW7eGlZUV3N3d8dhjjzV0d8mMbNy4EY6OjtBqtQCAuLg4yGQyzJo1S9dm0qRJGDVqlFQhkoQqKiowZcoUODo6wsXFBW+99RaEEABqP3PY0dERP/74o+71iRMn0LdvX1hbW8PFxQUTJ07UrSf37NkDpVKJtLQ0vWm8/PLL6N27NwAgKysLo0aNgre3N2xsbBAcHIxVq1bptY+MjMSLL76IV155Bc7OzvDw8MC7776r1yYnJwcTJ06Eu7s7rKysEBQUhE2bNqGwsBAODg41th82btwIW1tb5Ofn13fR3TUW8xL7/PPPER4ejmeffRapqalITU2Fj48PAODNN9/EggULcOTIEVhYWGDChAm6923duhVPPvkkXnzxRcTHx2PJkiX48ccf8eGHHwIADh8+DABYtmwZUlNTda8LCgrw0EMPYceOHYiNjUVUVBQGDx6MlJSUJu45GbtZs2Zh165dWL9+PbZt24bo6GjExMQAANatWwdvb2/MmTNHl9dEhuCtt97CsmXL8O233+LUqVOYPn06nnzySezevfu279uwYQOGDh16y/Hjx4/HhQsXsHPnTvz666/45ptvkJGR0dDhkxH66aefYGFhgX/++QdLliyBXC7HF198gZMnT+Knn37Czp078corr+jaHzx4EBMmTMDzzz+PuLg49OnTBx988ME9xXDkyBG8+OKLmDNnDhITE7FlyxbdRi9RffTu3Rv5+fmIjY0FAOzevRuurq5669Lo6GhERERIFSJJqGq9d/DgQXzxxRdYuHAhvv/++zq9t6ioCAMGDICTkxMOHz6MNWvWYMeOHZgyZQqAytwLCAjAihUrdO+pqKjAzz//jKeeegoAUFJSgtDQUGzatAknT57ExIkTMWbMGBw8eLBGnLa2tjh48CDmz5+POXPmYPv27QAArVaLgQMHYt++ffj5558RHx+PefPmQaFQwNbWFo8//jiWLVumN71ly5bhscceg729fb2X3V0TJLmIiAjx0ksv6V7v2rVLABA7duzQDdu8ebMAIIqLi4UQQtx///3io48+0pvOihUrhKenp+41ALF+/fo7zj8wMFB8+eWX99YJMiv5+flCpVKJ1atX64ZlZWUJa2trXS77+fmJhQsXShMgUS0KCgqElZWV2Ldvn97wp59+WowaNeqW7yspKRH29vbi+PHjtY5PTEwUAMSBAwd0wxISEgQA/g+YuYiICNGpU6fbtvm///s/4eLions9atQoMWDAAL02I0eOFGq1Wvd69uzZIiQkRG8+1bcjhBBi6NChYty4cUIIIdauXSscHBxEXl5evfpBVJsuXbqITz/9VAghxLBhw8SHH34oVCqVyMvLE6mpqQKASEhIkDhKamoRERGiffv2QqvV6oa9+uqron379kKI2usTtVotli1bJoQQ4rvvvhNOTk6ioKBAN37z5s1CLpeLtLQ0IYQQH3/8sW56Qgjx22+/CTs7O7333Oyhhx4SL7/8sl6cvXr10mvTrVs38eqrrwohhNi6dauQy+UiMTGx1ukdPHhQKBQKceXKFSGEENeuXRNKpVJER0ffMobGwCPzBqxjx466vz09PQFAd6QnJiYGc+bMgZ2dne6n6uh+UVHRLadZWFiIV155BYGBgXB0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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(10, 4.5), constrained_layout=True)\n", + "plt.subplot(161)\n", + "plt.plot(plume_t[\"theta\"], plume_t[\"z\"])\n", + "plt.plot(background.theta, background.z, \"k:\")\n", + "plt.xlabel(\"theta\")\n", + "plt.subplot(162)\n", + "plt.plot(plume_t[\"qt\"], plume_t[\"z\"])\n", + "plt.plot(plume_t[\"qsat\"], plume_t[\"z\"])\n", + "plt.plot(background.qt, background.z, \"k:\")\n", + "plt.xlabel(\"qt\")\n", + "plt.xlim(0, 0.01)\n", + "plt.subplot(163)\n", + "plt.plot(plume_t[\"e\"] / plume_t[\"m\"], plume_t[\"z\"])\n", + "plt.plot(plume_t[\"d\"] / plume_t[\"m\"], plume_t[\"z\"])\n", + "plt.xlabel(\"e / d\")\n", + "plt.subplot(164)\n", + "plt.plot((plume_t[\"area\"] / np.pi) ** 0.5, plume_t[\"z\"])\n", + "plt.xlabel(\"radius\")\n", + "plt.subplot(165)\n", + "plt.plot(plume_t[\"w\"], plume_t[\"z\"])\n", + "plt.xlabel(\"w\")\n", + "plt.subplot(166)\n", + "# plt.plot(plume_t[\"m\"], plume_t[\"z\"])\n", + "# plt.xlabel('mass flux')\n", + "plt.plot(plume_t[\"b\"], plume_t[\"z\"])\n", + "plt.xlabel(\"buoyancy\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "effortsharing_env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 852b75b526cd94293bfbba4a2dc6e285ba06ebec Mon Sep 17 00:00:00 2001 From: Peter Kalverla Date: Wed, 28 May 2025 10:14:51 +0200 Subject: [PATCH 02/12] Rename some variables; add fire settings to config; add output as single time --- .../src/lib/presets/death-valley.json | 7 +- .../class-solid/src/lib/presets/varnavas.json | 10 +- apps/class-solid/src/lib/profiles.ts | 28 ++-- apps/class-solid/tests/big-app-state.json | 4 +- packages/class/src/class.ts | 18 +-- packages/class/src/config.ts | 131 ++++++++++++++++-- packages/class/src/config_utils.test.ts | 12 +- packages/class/src/output.ts | 4 + packages/class/src/validate.test.ts | 6 +- 9 files changed, 169 insertions(+), 51 deletions(-) diff --git a/apps/class-solid/src/lib/presets/death-valley.json b/apps/class-solid/src/lib/presets/death-valley.json index 440c683..fa17789 100644 --- a/apps/class-solid/src/lib/presets/death-valley.json +++ b/apps/class-solid/src/lib/presets/death-valley.json @@ -10,10 +10,11 @@ "runtime": 43200, "wtheta": [0.1], "advtheta": 0, - "gammatheta": [0.006], + "gamma_theta": [0.006], "wq": [0.0001], "advq": 0, - "gammaq": [0], + "gamma_qt": [0], "divU": 0, - "beta": 0.2 + "beta": 0.2, + "p0": 101300 } diff --git a/apps/class-solid/src/lib/presets/varnavas.json b/apps/class-solid/src/lib/presets/varnavas.json index 1fecfad..9b0da11 100644 --- a/apps/class-solid/src/lib/presets/varnavas.json +++ b/apps/class-solid/src/lib/presets/varnavas.json @@ -4,12 +4,12 @@ "h": 665.4086303710938, "theta": 301.971435546875, "dtheta": 0.889312744140625, - "gammatheta": [0.0015336532378569245, 0.006792282219976187], + "gamma_theta": [0.0015336532378569245, 0.006792282219976187], "z_theta": [1667.025390625, 3720], "q": 0.010794480331242085, "dq": -0.001073240302503109, - "gammaq": [-2.382889988439274e-6, -2.5458646177867195e-6], - "z_q": [1360.52392578125, 3720], + "gamma_qt": [-2.382889988439274e-6, -2.5458646177867195e-6], + "z_qt": [1360.52392578125, 3720], "divU": 1.0981982995872386e-5, "u": -1.6769592761993408, "du": -1.1726601123809814, @@ -38,5 +38,7 @@ "beta": 0.2, "ustar": 0.3, "dt": 60, - "runtime": 43200 + "runtime": 43200, + "p0": 101300 + } diff --git a/apps/class-solid/src/lib/profiles.ts b/apps/class-solid/src/lib/profiles.ts index 62f4170..2cc9f4e 100644 --- a/apps/class-solid/src/lib/profiles.ts +++ b/apps/class-solid/src/lib/profiles.ts @@ -20,7 +20,7 @@ export function getVerticalProfiles( let z = output.h.slice(t)[0]; let theta = output.theta.slice(t)[0]; const dtheta = output.dtheta.slice(t)[0]; - const gammatheta = config.gammatheta; + const gamma_theta = config.gamma_theta; const z_theta = config.z_theta; const maxHeight = z_theta.slice(-1)[0]; @@ -37,7 +37,7 @@ export function getVerticalProfiles( // Free troposphere while (z < maxHeight) { const idx = findInsertIndex(z_theta, z); - const lapse_rate = gammatheta[idx] ?? 0; + const lapse_rate = gamma_theta[idx] ?? 0; const dz = z_theta[idx] - z; z += dz; theta += lapse_rate * dz; @@ -50,9 +50,9 @@ export function getVerticalProfiles( let z = output.h.slice(t)[0]; let q = output.q.slice(t)[0]; const dq = output.dq.slice(t)[0]; - const gammaq = config.gammaq; - const z_q = config.z_q; - const maxHeight = z_q.slice(-1)[0]; + const gamma_qt = config.gamma_qt; + const z_qt = config.z_qt; + const maxHeight = z_qt.slice(-1)[0]; // Mixed layer const profile = [ @@ -66,9 +66,9 @@ export function getVerticalProfiles( // Free troposphere while (z < maxHeight) { - const idx = findInsertIndex(z_q, z); - const lapse_rate = gammaq[idx] ?? 0; - const dz = z_q[idx] - z; + const idx = findInsertIndex(z_qt, z); + const lapse_rate = gamma_qt[idx] ?? 0; + const dz = z_qt[idx] - z; z += dz; q += lapse_rate * dz; profile.push({ x: q, y: z }); @@ -236,10 +236,10 @@ export function getThermodynamicProfiles( const dtheta = output.dtheta.slice(t)[0]; const dq = output.dq.slice(t)[0]; const h = output.h.slice(t)[0]; - const gammaTheta = config.gammatheta; - const gammaq = config.gammaq; + const gamma_theta = config.gamma_theta; + const gamma_qt = config.gamma_qt; const z_theta = config.z_theta; - const z_q = config.z_q; + const z_qt = config.z_qt; const nz = 25; let dz = h / nz; @@ -272,9 +272,9 @@ export function getThermodynamicProfiles( while (p > 100) { // Note: idx can exceed length of anchor points, then lapse becomes undefined and profile stops const idx_th = findInsertIndex(z_theta, z); - const lapse_theta = gammaTheta[idx_th]; - const idx_q = findInsertIndex(z_q, z); - const lapse_q = gammaq[idx_q]; + const lapse_theta = gamma_theta[idx_th]; + const idx_q = findInsertIndex(z_qt, z); + const lapse_q = gamma_qt[idx_q]; theta += dz * lapse_theta; q += dz * lapse_q; p += pressureDiff(T, q, p, dz); diff --git a/apps/class-solid/tests/big-app-state.json b/apps/class-solid/tests/big-app-state.json index a61213e..8017995 100644 --- a/apps/class-solid/tests/big-app-state.json +++ b/apps/class-solid/tests/big-app-state.json @@ -16,10 +16,10 @@ "mixedLayer": { "wtheta": 0.1, "advtheta": 0, - "gammatheta": [0.006], + "gamma_theta": [0.006], "wq": [0.0001], "advq": 0, - "gammaq": [0], + "gamma_qt": [0], "divU": 0, "beta": 0.2 } diff --git a/packages/class/src/class.ts b/packages/class/src/class.ts index c3f4a25..d71a00a 100644 --- a/packages/class/src/class.ts +++ b/packages/class/src/class.ts @@ -131,7 +131,7 @@ export class CLASS { get dthetatend(): number { this.assertMixedLayer(); const w_th_ft = 0.0; // TODO: add free troposphere switch - return this.gammatheta * this.we - this.thetatend + w_th_ft; + return this.gamma_theta * this.we - this.thetatend + w_th_ft; } /** Tendency of mixed-layer specific humidity [kg kg-1 s-1] */ @@ -144,7 +144,7 @@ export class CLASS { get dqtend(): number { this.assertMixedLayer(); const w_q_ft = 0; // TODO: add free troposphere switch - return this.gammaq * this.we - this.qtend + w_q_ft; + return this.gamma_qt * this.we - this.qtend + w_q_ft; } /** Entrainment velocity [m s-1]. */ @@ -212,19 +212,19 @@ export class CLASS { // Lapse rates /** Free atmosphere potential temperature lapse rate */ - get gammatheta(): number { + get gamma_theta(): number { this.assertMixedLayer(); - const { z_theta, gammatheta } = this._cfg; + const { z_theta, gamma_theta } = this._cfg; const i = findInsertIndex(z_theta, this.ml.h); - return gammatheta[i] ?? 0; + return gamma_theta[i] ?? 0; } /** Free atmosphere specific humidity lapse rate */ - get gammaq(): number { + get gamma_qt(): number { this.assertMixedLayer(); - const { z_q, gammaq } = this._cfg; - const i = findInsertIndex(z_q, this.ml.h); - return gammaq[i] ?? 0; + const { z_qt, gamma_qt } = this._cfg; + const i = findInsertIndex(z_qt, this.ml.h); + return gamma_qt[i] ?? 0; } /** Free atmosphere u-wind lapse rate */ diff --git a/packages/class/src/config.ts b/packages/class/src/config.ts index 480735d..aceb716 100644 --- a/packages/class/src/config.ts +++ b/packages/class/src/config.ts @@ -56,6 +56,12 @@ const untypedSchema = { title: "Wind switch", default: false, }, + sw_fire: { + type: "boolean", + "ui:group": "Fire", + title: "Fire switch", + default: false, + }, }, required: ["name", "dt", "runtime"], allOf: [ @@ -134,7 +140,7 @@ const untypedSchema = { default: 0, title: "Advection of heat", }, - gammatheta: { + gamma_theta: { symbol: "γθ", type: "array", items: { @@ -166,7 +172,7 @@ const untypedSchema = { default: 0, title: "Advection of moisture", }, - gammaq: { + gamma_qt: { symbol: "γq", type: "array", items: { @@ -193,6 +199,14 @@ const untypedSchema = { default: 0.2, title: "Entrainment ratio for virtual heat", }, + p0: { + symbol: "p0", + type: "number", + default: 101300, + unit: "Pa", + "ui:group": "Mixed layer", + title: "Surface pressure", + }, z_theta: { symbol: "zθ", type: "array", @@ -207,7 +221,7 @@ const untypedSchema = { description: "Each value specifies the end of the corresponding segment in γ_θ", }, - z_q: { + z_qt: { symbol: "zq", type: "array", items: { @@ -230,14 +244,15 @@ const untypedSchema = { "dq", "wtheta", "advtheta", - "gammatheta", + "gamma_theta", "wq", + "p0", "advq", - "gammaq", + "gamma_qt", "divU", "beta", "z_theta", - "z_q", + "z_qt", ], }, }, @@ -378,6 +393,86 @@ const untypedSchema = { ], }, }, + { + if: { + properties: { + sw_fire: { + const: true, + }, + }, + }, + // biome-ignore lint/suspicious/noThenProperty: part of JSON Schema + then: { + properties: { + L_fire: { + symbol: "Lfire", + type: "number", + unit: "m", + default: 10000, + title: "Length of the fire", + "ui:group": "Fire", + }, + d_fire: { + symbol: "dfire", + type: "number", + unit: "m", + default: 300, + title: "Depth of the fire", + "ui:group": "Fire", + }, + h0_fire: { + symbol: "h0, fire", + type: "number", + unit: "m", + default: 20, + title: "Height to start", + "ui:group": "Fire", + }, + C_fire: { + symbol: "Cfire", + type: "number", + unit: "J kg⁻¹", + default: 17.781e6, + title: "Heat stored in fuel", + "ui:group": "Fire", + }, + omega_fire: { + symbol: "ωfire", + type: "number", + unit: "kg m⁻²", + default: 7.6, + title: "Fuel mass per area", + "ui:group": "Fire", + }, + v_fire: { + symbol: "vfire", + type: "number", + unit: "m s⁻¹", + default: 1.5, + title: "Rate of spread of the fire", + "ui:group": "Fire", + }, + radiative_loss_fire: { + symbol: "rlfire", + type: "number", + unit: "-", + default: 0.7, + title: + "Fraction of F converted into radiative heating, and not into diffused into the atmosphere", + "ui:group": "Fire", + }, + }, + required: [ + "L_fire", + "d_fire", + "h0_fire", + "C_fire", + "omega_fire", + "v_fire", + "radiative_loss_fire", + ], + }, + }, ], }; @@ -415,23 +510,39 @@ export type MixedLayerConfig = { dq: number; wtheta: number[]; advtheta: number; - gammatheta: number[]; + gamma_theta: number[]; wq: number[]; advq: number; - gammaq: number[]; + gamma_qt: number[]; divU: number; beta: number; + p0: number; z_theta: number[]; - z_q: number[]; + z_qt: number[]; }; type NoMixedLayerConfig = { sw_ml?: false; }; +export type FireConfig = { + sw_fire: true; + L: number; + d: number; + h0: number; + C: number; + omega: number; + v: number; + radiative_loss: number; +}; +type NoFireConfig = { + sw_fire?: false; +}; + // TODO: Don't allow WindConfig with NoMixedLayerConfig export type Config = GeneralConfig & (MixedLayerConfig | NoMixedLayerConfig) & - (WindConfig | NoWindConfig); + (WindConfig | NoWindConfig) & + (FireConfig | NoFireConfig); export type JsonSchemaOfConfig = JSONSchemaType; export const jsonSchemaOfConfig = diff --git a/packages/class/src/config_utils.test.ts b/packages/class/src/config_utils.test.ts index 9eb85fd..d820e09 100644 --- a/packages/class/src/config_utils.test.ts +++ b/packages/class/src/config_utils.test.ts @@ -16,10 +16,10 @@ describe("pruneConfig()", () => { runtime: 4320, wtheta: 0.1, advtheta: 0, - gammatheta: 0.006, + gamma_theta: 0.006, wq: 0.0001, advq: 0, - gammaq: 0, + gamma_qt: 0, divU: 0, beta: 0.2, }; @@ -35,10 +35,10 @@ describe("pruneConfig()", () => { runtime: 4320, wtheta: 0.1, advtheta: 0, - gammatheta: 0.006, + gamma_theta: 0.006, wq: 0.0001, advq: 0, - gammaq: 0, + gamma_qt: 0, divU: 0, beta: 0.2, }; @@ -54,10 +54,10 @@ describe("pruneConfig()", () => { runtime: 4320, wtheta: 0.1, advtheta: 0, - gammatheta: 0.006, + gamma_theta: 0.006, wq: 0.0001, advq: 0, - gammaq: 0, + gamma_qt: 0, divU: 0, beta: 0.212, }; diff --git a/packages/class/src/output.ts b/packages/class/src/output.ts index 1fc455f..8c101bc 100644 --- a/packages/class/src/output.ts +++ b/packages/class/src/output.ts @@ -113,3 +113,7 @@ export const outputVariables: OutputVariable[] = [ export type ClassOutput = { [K in (typeof outputVariables)[number]["key"]]: number[]; }; + +export type ClassOutputAtSingleTime = { + [K in (typeof outputVariables)[number]["key"]]: number; +}; \ No newline at end of file diff --git a/packages/class/src/validate.test.ts b/packages/class/src/validate.test.ts index e125466..a9bd19f 100644 --- a/packages/class/src/validate.test.ts +++ b/packages/class/src/validate.test.ts @@ -57,14 +57,14 @@ describe("parse", () => { dq: -0.001, wtheta: [0.1], advtheta: 0, - gammatheta: [0.006], + gamma_theta: [0.006], wq: [0.0001], advq: 0, - gammaq: [0], + gamma_qt: [0], divU: 0, beta: 0.2, z_theta: [5000], - z_q: [5000], + z_qt: [5000], u: 6, du: 4, advu: 0, From d71f374ed0b6c5fcd72fc72659c2217111e8c284 Mon Sep 17 00:00:00 2001 From: Peter Kalverla Date: Wed, 28 May 2025 19:17:03 +0200 Subject: [PATCH 03/12] use gridded profiles from class package in app. TODO: fix piecewise lapse rate, it shouldn't vary in time --- apps/class-solid/src/components/Analysis.tsx | 103 ++++++--- .../class-solid/src/components/plots/Axes.tsx | 9 +- .../src/components/plots/Legend.tsx | 4 +- .../src/components/plots/skewTlogP.tsx | 2 +- apps/class-solid/src/lib/profiles.ts | 212 ++---------------- packages/class/package.json | 7 + packages/class/src/class.ts | 24 +- packages/class/src/config.ts | 16 +- packages/class/src/output.ts | 75 +++---- packages/class/src/profiles.ts | 207 +++++++++++++++++ packages/class/src/runner.ts | 18 +- packages/class/src/thermodynamics.ts | 80 +++++++ 12 files changed, 452 insertions(+), 305 deletions(-) create mode 100644 packages/class/src/profiles.ts create mode 100644 packages/class/src/thermodynamics.ts diff --git a/apps/class-solid/src/components/Analysis.tsx b/apps/class-solid/src/components/Analysis.tsx index 589120d..38aff4a 100644 --- a/apps/class-solid/src/components/Analysis.tsx +++ b/apps/class-solid/src/components/Analysis.tsx @@ -1,5 +1,10 @@ import type { Config } from "@classmodel/class/config"; -import { type ClassOutput, outputVariables } from "@classmodel/class/output"; +import { + type ClassOutput, + OutputVariableKey, + outputVariables, +} from "@classmodel/class/output"; +import { type ClassProfile, NoProfile } from "@classmodel/class/profiles"; import * as d3 from "d3"; import { saveAs } from "file-saver"; import { toBlob } from "html-to-image"; @@ -34,10 +39,10 @@ import { } from "~/lib/store"; import { MdiCamera, MdiDelete, MdiImageFilterCenterFocus } from "./icons"; import { AxisBottom, AxisLeft, getNiceAxisLimits } from "./plots/Axes"; -import { Chart, ChartContainer } from "./plots/ChartContainer"; +import { Chart, ChartContainer, type ChartData } from "./plots/ChartContainer"; import { Legend } from "./plots/Legend"; -import { Line } from "./plots/Line"; -import { SkewTPlot } from "./plots/skewTlogP"; +import { Line, type Point } from "./plots/Line"; +import { SkewTPlot, type SoundingRecord } from "./plots/skewTlogP"; import { Button } from "./ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "./ui/card"; import { @@ -115,23 +120,20 @@ const uniqueTimes = () => [...new Set(_allTimes())].sort((a, b) => a - b); // TODO: could memoize all reactive elements here, would it make a difference? export function TimeSeriesPlot({ analysis }: { analysis: TimeseriesAnalysis }) { - const symbols = Object.fromEntries( - outputVariables.map((v) => [v.key, v.symbol]), - ); - const getKey = Object.fromEntries( - outputVariables.map((v) => [v.symbol, v.key]), - ); + const vars = Object.entries(outputVariables); + const symbols = Object.fromEntries(vars.map(([k, v]) => [k, v.symbol])); + const getKey = Object.fromEntries(vars.map(([k, v]) => [v.symbol, k])); const labels = Object.fromEntries( - outputVariables.map((v) => [v.key, `${v.symbol} [${v.unit}]`]), + vars.map(([k, v]) => [k, `${v.symbol} [${v.unit}]`]), ); const allX = () => flatExperiments().flatMap((e) => - e.output ? e.output[analysis.xVariable] : [], + e.output ? e.output[analysis.xVariable as OutputVariableKey] : [], ); const allY = () => flatExperiments().flatMap((e) => - e.output ? e.output[analysis.yVariable] : [], + e.output ? e.output[analysis.yVariable as OutputVariableKey] : [], ); const granularity = () => (analysis.xVariable === "t" ? 600 : undefined); @@ -146,8 +148,12 @@ export function TimeSeriesPlot({ analysis }: { analysis: TimeseriesAnalysis }) { data: // Zip x[] and y[] into [x, y][] output?.t.map((_, t) => ({ - x: output ? output[analysis.xVariable][t] : Number.NaN, - y: output ? output[analysis.yVariable][t] : Number.NaN, + x: output + ? output[analysis.xVariable as OutputVariableKey][t] + : Number.NaN, + y: output + ? output[analysis.yVariable as OutputVariableKey][t] + : Number.NaN, })) || [], }; }); @@ -225,10 +231,16 @@ export function VerticalProfilePlot({ }: { analysis: ProfilesAnalysis }) { const variableOptions = { "Potential temperature [K]": "theta", - "Specific humidity [kg/kg]": "q", + "Virtual potential temperature [K]": "thetav", + "Specific humidity [kg/kg]": "qt", "u-wind component [m/s]": "u", "v-wind component [m/s]": "v", - }; + "Pressure [Pa]": "p", + "Exner function [-]": "exner", + "Temperature [K]": "T", + "Dew point temperature [K]": "Td", + "Density [kg/m³]": "rho", + } as const satisfies Record; const classVariable = () => variableOptions[analysis.variable as keyof typeof variableOptions]; @@ -243,23 +255,33 @@ export function VerticalProfilePlot({ return { ...formatting, data: - t !== -1 // -1 now means "not found in array" rather than last index - ? getVerticalProfiles( - e.output, - e.config, - classVariable(), - analysis.time, - ) - : [], + t !== -1 && // -1 means time not found in array + output && // Output must be defined + config.sw_ml // config must include mixed layer + ? // TODO: can't we use t here? + getVerticalProfiles(e.output, e.config, analysis.time) + : NoProfile, }; }); + // TODO: There should be a way that this isn't needed. + const profileDataForPlot = () => + profileData().map(({ data, label, color, linestyle }) => ({ + label, + color, + linestyle, + data: data.z.map((z, i) => ({ + x: data[classVariable()][i], + y: z, + })), + })) as ChartData[] + const allX = () => [ - ...profileData().flatMap((p) => p.data.map((d) => d.x)), + ...profileDataForPlot().flatMap((p) => p.data.map((d) => d.x)), ...observations().flatMap((obs) => obs.data.map((d) => d.x)), ]; const allY = () => [ - ...profileData().flatMap((p) => p.data.map((d) => d.y)), + ...profileDataForPlot().flatMap((p) => p.data.map((d) => d.y)), ...observations().flatMap((obs) => obs.data.map((d) => d.y)), ]; @@ -301,7 +323,7 @@ export function VerticalProfilePlot({ - + {(d) => ( @@ -412,20 +434,37 @@ export function ThermodynamicPlot({ analysis }: { analysis: SkewTAnalysis }) { return { ...formatting, data: - t !== -1 // -1 now means "not found in array" rather than last index - ? getThermodynamicProfiles(e.output, e.config, t) - : [], + // TODO reuse get profiles now here + t !== -1 && // -1 means time not found in array + output && // Output must be defined + config.sw_ml // config must include mixed layer + ? getVerticalProfiles(e.output, e.config, t) + : NoProfile, }; }); const observations = () => flatObservations().map((o) => observationsForSounding(o)); + // TODO: There should be a way that this isn't needed. + const profileDataForPlot = () => + skewTData().map(({ data, label, color, linestyle }) => ({ + label, + color, + linestyle, + data: data.p.map((p, i) => ({ + p: p / 100, + T: data.T[i], + Td: data.Td[i], + })), + })) as ChartData[]; + + console.log(profileDataForPlot()); return ( <> [...skewTData(), ...observations()]} + data={() => [...profileDataForPlot(), ...observations()]} /> {TimeSlider( () => analysis.time, diff --git a/apps/class-solid/src/components/plots/Axes.tsx b/apps/class-solid/src/components/plots/Axes.tsx index 76a3a25..353680c 100644 --- a/apps/class-solid/src/components/plots/Axes.tsx +++ b/apps/class-solid/src/components/plots/Axes.tsx @@ -81,12 +81,13 @@ export function getNiceAxisLimits( extraMargin = 0, roundTo?: number, // Optional rounding step, e.g. 600 for 10 minutes ): [number, number] { - const max = Math.max(...data); - const min = Math.min(...data); + const max = Math.max(...data.filter(Number.isFinite)); + const min = Math.min(...data.filter(Number.isFinite)); const range = max - min; - // Avoid NaNs on axis for constant values - if (range === 0) return [min - 1, max + 1]; + if (range === 0) + // Avoid NaNs on axis for constant values + return [min - 1, max + 1]; const step = roundTo ?? 10 ** Math.floor(Math.log10(range)); diff --git a/apps/class-solid/src/components/plots/Legend.tsx b/apps/class-solid/src/components/plots/Legend.tsx index db78173..04f14e2 100644 --- a/apps/class-solid/src/components/plots/Legend.tsx +++ b/apps/class-solid/src/components/plots/Legend.tsx @@ -3,8 +3,10 @@ import { createUniqueId } from "solid-js"; import type { ChartData } from "./ChartContainer"; import { useChartContext } from "./ChartContainer"; +type LegendData = Omit, "data">; + export interface LegendProps { - entries: () => ChartData[]; + entries: () => LegendData[]; toggles: Record; onChange: (key: string, value: boolean) => void; } diff --git a/apps/class-solid/src/components/plots/skewTlogP.tsx b/apps/class-solid/src/components/plots/skewTlogP.tsx index 684fd82..d46f240 100644 --- a/apps/class-solid/src/components/plots/skewTlogP.tsx +++ b/apps/class-solid/src/components/plots/skewTlogP.tsx @@ -11,7 +11,7 @@ import { useChartContext, } from "./ChartContainer"; import { Legend } from "./Legend"; -interface SoundingRecord { +export interface SoundingRecord { p: number; T: number; Td: number; diff --git a/apps/class-solid/src/lib/profiles.ts b/apps/class-solid/src/lib/profiles.ts index 2cc9f4e..0b43655 100644 --- a/apps/class-solid/src/lib/profiles.ts +++ b/apps/class-solid/src/lib/profiles.ts @@ -1,5 +1,6 @@ import type { Config } from "@classmodel/class/config"; -import type { ClassOutput } from "@classmodel/class/output"; +import { type ClassOutput, getOutputAtTime } from "@classmodel/class/output"; +import { NoProfile, generateProfiles } from "@classmodel/class/profiles"; import { findInsertIndex } from "@classmodel/class/utils"; import type { Point } from "~/components/plots/Line"; import type { Observation } from "./experiment_config"; @@ -8,139 +9,20 @@ import type { Observation } from "./experiment_config"; export function getVerticalProfiles( output: ClassOutput | undefined, config: Config, - variable = "theta", - t = -1, -): Point[] { + t = 0, +) { // Guard against undefined output if (output === undefined || !config.sw_ml) { - return []; - } - - if (variable === "theta") { - let z = output.h.slice(t)[0]; - let theta = output.theta.slice(t)[0]; - const dtheta = output.dtheta.slice(t)[0]; - const gamma_theta = config.gamma_theta; - const z_theta = config.z_theta; - const maxHeight = z_theta.slice(-1)[0]; - - // Mixed layer - const profile = [ - { x: theta, y: 0 }, - { x: theta, y: z }, - ]; - - // Inversion - theta += dtheta; - profile.push({ x: theta, y: z }); - - // Free troposphere - while (z < maxHeight) { - const idx = findInsertIndex(z_theta, z); - const lapse_rate = gamma_theta[idx] ?? 0; - const dz = z_theta[idx] - z; - z += dz; - theta += lapse_rate * dz; - profile.push({ x: theta, y: z }); - } - return profile; - } - - if (variable === "q") { - let z = output.h.slice(t)[0]; - let q = output.q.slice(t)[0]; - const dq = output.dq.slice(t)[0]; - const gamma_qt = config.gamma_qt; - const z_qt = config.z_qt; - const maxHeight = z_qt.slice(-1)[0]; - - // Mixed layer - const profile = [ - { x: q, y: 0 }, - { x: q, y: z }, - ]; - - // Inversion - q += dq; - profile.push({ x: q, y: z }); - - // Free troposphere - while (z < maxHeight) { - const idx = findInsertIndex(z_qt, z); - const lapse_rate = gamma_qt[idx] ?? 0; - const dz = z_qt[idx] - z; - z += dz; - q += lapse_rate * dz; - profile.push({ x: q, y: z }); - } - return profile; - } - - if (config.sw_wind && variable === "u") { - let z = output.h.slice(t)[0]; - let u = output.u.slice(t)[0]; - const du = output.du.slice(t)[0]; - const gammau = config.gamma_u; - const z_u = config.z_u; - const maxHeight = z_u.slice(-1)[0]; - - // Mixed layer - const profile = [ - { x: u, y: 0 }, - { x: u, y: z }, - ]; - - // Inversion - u += du; - profile.push({ x: u, y: z }); - - // Free troposphere - while (z < maxHeight) { - const idx = findInsertIndex(z_u, z); - const lapse_rate = gammau[idx] ?? 0; - const dz = z_u[idx] - z; - z += dz; - u += lapse_rate * dz; - profile.push({ x: u, y: z }); - } - return profile; - } - - if (config.sw_wind && variable === "v") { - let z = output.h.slice(t)[0]; - let v = output.v.slice(t)[0]; - const dv = output.dv.slice(t)[0]; - const gammav = config.gamma_v; - const z_v = config.z_v; - const maxHeight = z_v.slice(-1)[0]; - - // Mixed layer - const profile = [ - { x: v, y: 0 }, - { x: v, y: z }, - ]; - - // Inversion - v += dv; - profile.push({ x: v, y: z }); - - // Free troposphere - while (z < maxHeight) { - const idx = findInsertIndex(z_v, z); - const lapse_rate = gammav[idx] ?? 0; - const dz = z_v[idx] - z; - z += dz; - v += lapse_rate * dz; - profile.push({ x: v, y: z }); - } - return profile; + return NoProfile; } - return []; + const outputAtTime = getOutputAtTime(output, t); + return generateProfiles(config, outputAtTime); } /** * https://en.wikipedia.org/wiki/Dew_point#Calculating_the_dew_point + * p should be in hPa */ const dewpoint = (q: number, p: number) => { // Empirical fit parameters (Sonntag1990, see wikipedia entry for more options) @@ -221,73 +103,6 @@ function calculateSpecificHumidity(T: number, p: number, rh: number) { return w / (1 + w); } -export function getThermodynamicProfiles( - output: ClassOutput | undefined, - config: Config, - t = -1, -) { - // Guard against undefined output - if (output === undefined || !config.sw_ml) { - return []; - } - - let theta = output.theta.slice(t)[0]; - let q = output.q.slice(t)[0]; - const dtheta = output.dtheta.slice(t)[0]; - const dq = output.dq.slice(t)[0]; - const h = output.h.slice(t)[0]; - const gamma_theta = config.gamma_theta; - const gamma_qt = config.gamma_qt; - const z_theta = config.z_theta; - const z_qt = config.z_qt; - - const nz = 25; - let dz = h / nz; - const zArrayMixedLayer = [...Array(nz).keys()].map((i) => i * dz); - - let p = 1000; // hPa?? - let T = theta; - let Td = dewpoint(q, p); - const soundingData: { p: number; T: number; Td: number }[] = [{ p, T, Td }]; - - // Mixed layer - for (const z of zArrayMixedLayer) { - p += pressureDiff(T, q, p, dz); - T = thetaToT(theta, p); - Td = dewpoint(q, p); - - soundingData.push({ p, T, Td }); - } - - // Inversion - theta += dtheta; - q += dq; - T = thetaToT(theta, p); - Td = dewpoint(q, p); - soundingData.push({ p, T, Td }); - - // Free troposphere - let z = zArrayMixedLayer.slice(-1)[0]; - dz = 200; - while (p > 100) { - // Note: idx can exceed length of anchor points, then lapse becomes undefined and profile stops - const idx_th = findInsertIndex(z_theta, z); - const lapse_theta = gamma_theta[idx_th]; - const idx_q = findInsertIndex(z_qt, z); - const lapse_q = gamma_qt[idx_q]; - theta += dz * lapse_theta; - q += dz * lapse_q; - p += pressureDiff(T, q, p, dz); - z += dz; - T = thetaToT(theta, p); - Td = dewpoint(q, p); - - soundingData.push({ p, T, Td }); - } - - return soundingData; -} - export function observationsForProfile(obs: Observation, variable = "theta") { return { label: obs.name, @@ -298,7 +113,7 @@ export function observationsForProfile(obs: Observation, variable = "theta") { const rh = obs.relativeHumidity[i]; const p = obs.pressure[i]; const theta = tToTheta(T, p); - const q = calculateSpecificHumidity(T, p, rh); + const qt = calculateSpecificHumidity(T, p, rh); const { u, v } = windSpeedDirectionToUV( obs.windSpeed[i], obs.windDirection[i], @@ -307,14 +122,17 @@ export function observationsForProfile(obs: Observation, variable = "theta") { switch (variable) { case "theta": return { y: h, x: theta }; - case "q": - return { y: h, x: q }; + case "qt": + return { y: h, x: qt }; case "u": return { y: h, x: u }; case "v": return { y: h, x: v }; default: - throw new Error(`Unknown variable '${variable}'`); + console.warn( + "Unknown variable '${variable}' for observation profile.", + ); + return { y: Number.NaN, x: Number.NaN }; } }), }; diff --git a/packages/class/package.json b/packages/class/package.json index 9d0f756..27e18dc 100644 --- a/packages/class/package.json +++ b/packages/class/package.json @@ -41,6 +41,13 @@ "types": "./dist/output.d.ts" } }, + "./profiles": { + "import": { + "default": "./dist/profiles.js", + "types": "./dist/profiles.d.ts" + + } + }, "./utils": { "import": { "default": "./dist/utils.js", diff --git a/packages/class/src/class.ts b/packages/class/src/class.ts index d71a00a..886f728 100644 --- a/packages/class/src/class.ts +++ b/packages/class/src/class.ts @@ -22,8 +22,8 @@ type MixedLayer = { h: number; theta: number; dtheta: number; - q: number; - dq: number; + qt: number; + dqt: number; }; export class CLASS { @@ -40,8 +40,8 @@ export class CLASS { this._cfg = config; // Initialize state variables from config if (config.sw_ml) { - const { h, theta, dtheta, q, dq } = config; - this.ml = { h, theta, dtheta, q, dq }; + const { h, theta, dtheta, qt, dqt } = config; + this.ml = { h, theta, dtheta, qt, dqt }; if (config.sw_wind) { const { u, v, du, dv } = config; @@ -59,8 +59,8 @@ export class CLASS { this.ml.h += dt * this.htend; this.ml.theta += dt * this.thetatend; this.ml.dtheta += dt * this.dthetatend; - this.ml.q += dt * this.qtend; - this.ml.dq += dt * this.dqtend; + this.ml.qt += dt * this.qtend; + this.ml.dqt += dt * this.dqttend; if (this.wind) { this.wind.u += dt * this.utend; this.wind.v += dt * this.vtend; @@ -141,7 +141,7 @@ export class CLASS { } /** Tendency of specific humidity jump at h[kg kg-1 s-1] */ - get dqtend(): number { + get dqttend(): number { this.assertMixedLayer(); const w_q_ft = 0; // TODO: add free troposphere switch return this.gamma_qt * this.we - this.qtend + w_q_ft; @@ -174,7 +174,7 @@ export class CLASS { /** Entrainment moisture flux [kg kg-1 m s-1]. */ get wqe(): number { this.assertMixedLayer(); - return -this.we * this.ml.dq; + return -this.we * this.ml.dqt; } /** Entrainment kinematic virtual heat flux [K m s-1]. */ @@ -188,8 +188,8 @@ export class CLASS { this.assertMixedLayer(); return ( (this.ml.theta + this.ml.dtheta) * - (1.0 + 0.61 * (this.ml.q + this.ml.dq)) - - this.ml.theta * (1.0 + 0.61 * this.ml.q) + (1.0 + 0.61 * (this.ml.qt + this.ml.dqt)) - + this.ml.theta * (1.0 + 0.61 * this.ml.qt) ); } @@ -266,8 +266,8 @@ export class CLASS { } } - get q() { - return this.ml?.q || 999; + get qt() { + return this.ml?.qt || 999; } /** diff --git a/packages/class/src/config.ts b/packages/class/src/config.ts index aceb716..022cb28 100644 --- a/packages/class/src/config.ts +++ b/packages/class/src/config.ts @@ -104,16 +104,16 @@ const untypedSchema = { default: 1, unit: "K", }, - q: { - symbol: "q", + qt: { + symbol: "qt", type: "number", "ui:group": "Mixed layer", unit: "kg kg⁻¹", default: 0.008, title: "Mixed-layer specific humidity", }, - dq: { - symbol: "Δq", + dqt: { + symbol: "Δqt", type: "number", description: "Specific humidity jump at h", unit: "kg kg⁻¹", @@ -240,8 +240,8 @@ const untypedSchema = { "h", "theta", "dtheta", - "q", - "dq", + "qt", + "dqt", "wtheta", "advtheta", "gamma_theta", @@ -506,8 +506,8 @@ export type MixedLayerConfig = { h: number; theta: number; dtheta: number; - q: number; - dq: number; + qt: number; + dqt: number; wtheta: number[]; advtheta: number; gamma_theta: number[]; diff --git a/packages/class/src/output.ts b/packages/class/src/output.ts index 8c101bc..aa18c89 100644 --- a/packages/class/src/output.ts +++ b/packages/class/src/output.ts @@ -1,119 +1,106 @@ -export interface OutputVariable { - key: string; +export interface VariableInfo { title: string; unit: string; symbol: string; } -export const outputVariables: OutputVariable[] = [ - { - key: "t", +export const outputVariables = { + t: { title: "Time", unit: "s", symbol: "t", }, - { - key: "h", + h: { title: "ABL height", unit: "m", symbol: "h", }, - { - key: "theta", + theta: { title: "Potential temperature", unit: "K", symbol: "θ", }, - { - key: "dtheta", + dtheta: { title: "Potential temperature jump", unit: "K", symbol: "Δθ", }, - { - key: "q", + qt: { title: "Specific humidity", unit: "kg kg⁻¹", symbol: "q", }, - { - key: "dq", + dqt: { title: "Specific humidity jump", unit: "kg kg⁻¹", symbol: "Δq", }, - { - key: "dthetav", + dthetav: { title: "Virtual temperature jump at h", unit: "K", symbol: "Δθᵥ", }, - { - key: "we", + we: { title: "Entrainment velocity", unit: "m s⁻¹", symbol: "wₑ", }, - { - key: "ws", + ws: { title: "Large-scale vertical velocity", unit: "m s⁻¹", symbol: "wₛ", }, - { - key: "wthetave", + wthetave: { title: "Entrainment virtual heat flux", unit: "K m s⁻¹", symbol: "(w'θ')ᵥₑ", }, - { - key: "wthetav", + wthetav: { title: "Surface virtual heat flux", unit: "K m s⁻¹", symbol: "(w'θ')ᵥ", }, - { - key: "wtheta", + wtheta: { title: "Surface kinematic heat flux", unit: "K m s⁻¹", symbol: "(w'θ')ₛ", }, - { - key: "wq", + wq: { title: "Surface kinematic heat flux", unit: "kg kg⁻¹ m s⁻¹", symbol: "(w'q')ₛ", }, - { - key: "u", + u: { title: "Mixed-layer u-wind component", unit: "m s⁻¹", symbol: "u", }, - { - key: "v", + v: { title: "Mixed-layer v-wind component", unit: "m s⁻¹", symbol: "v", }, - { - key: "du", + du: { title: "U-wind jump at h", unit: "m s⁻¹", symbol: "Δu", }, - { - key: "dv", + dv: { title: "V-wind jump at h", unit: "m s⁻¹", symbol: "Δv", }, -]; +} as const satisfies Record; -export type ClassOutput = { - [K in (typeof outputVariables)[number]["key"]]: number[]; -}; +export type OutputVariableKey = keyof typeof outputVariables; +export type ClassOutput = Record; +export type ClassOutputAtSingleTime = Record; -export type ClassOutputAtSingleTime = { - [K in (typeof outputVariables)[number]["key"]]: number; -}; \ No newline at end of file +export function getOutputAtTime( + output: ClassOutput, + timeIndex: number, +): ClassOutputAtSingleTime { + return Object.fromEntries( + Object.entries(output).map(([key, values]) => [key, values[timeIndex]]), + ) as ClassOutputAtSingleTime; +} \ No newline at end of file diff --git a/packages/class/src/profiles.ts b/packages/class/src/profiles.ts new file mode 100644 index 0000000..8b00672 --- /dev/null +++ b/packages/class/src/profiles.ts @@ -0,0 +1,207 @@ +// profiles.ts + +import type { Config as ClassConfig, MixedLayerConfig } from "./config.js"; +import type { ClassOutputAtSingleTime } from "./output.js"; +import { dewpoint, virtualTemperature } from "./thermodynamics.js"; + +const CONSTANTS = { + g: 9.81, // Gravity [m/s²] + cp: 1004, // Specific heat of dry air at constant pressure [J/(kg·K)] + Rd: 287, // Specific gas constant for dry air [J/(kg·K)] +}; + +/** + * Atmospheric vertical profiles + */ +export type ClassProfile { + z: number[]; // Height levels (cell centers) [m] + theta: number[]; // Potential temperature [K] + thetav: number[]; // Virtual potential temperature [K] + qt: number[]; // Total specific humidity [kg/kg] + u: number[]; // U-component of wind [m/s] + v: number[]; // V-component of wind [m/s] + p: number[]; // Pressure [Pa] + exner: number[]; // Exner function [-] + T: number[]; // Temperature [K] + Td: number[]; // Dew point temperature [K] + rho: number[]; // Density [kg/m³] +} + +export const NoProfile = { + z: [], + theta: [], + thetav: [], + qt: [], + u: [], + v: [], + p: [], + exner: [], + T: [], + Td: [], + rho: [], +}; + +/** + * Generate vertical atmospheric profiles based on CLASS config + output + */ +export function generateProfiles( + config: ClassConfig & MixedLayerConfig, + output: ClassOutputAtSingleTime, + dz = 1, +): ClassProfile { + const { Rd, cp, g } = CONSTANTS; + const { h, theta, qt, u, v, dtheta, dqt, du, dv } = output; + const { z_theta, z_qt, gamma_theta, gamma_qt } = config; + const { p0 } = config; + + // Determine top of profile based on the lowest z value across all variables + const getLastValue = (arr: number[]) => arr[arr.length - 1]; + const zTop = Math.min(...[z_theta, z_qt].map(getLastValue)); + + // Calculate piecewise profiles for potential temperature and specific humidity + const z = arange(0 + dz / 2, zTop, dz); + const thetaProf = piecewiseProfile(z, h, theta, dtheta, z_theta, gamma_theta); + const qtProfile = piecewiseProfile(z, h, qt, dqt, z_qt, gamma_qt); + + // For pressure calculation, we need profiles on half-levels + const zh = arange(0, zTop + dz / 2, dz); + const thetah = piecewiseProfile(zh, h, theta, dtheta, z_theta, gamma_theta); + const qth = piecewiseProfile(zh, h, qt, dqt, z_qt, gamma_qt); + + // Calculate virtual temperature, asssume base state is dry, so no saturation adjustment + const thetav = thetaProf.map((t, i) => + virtualTemperature(t, qtProfile[i], 0), + ); + const thetavh = thetah.map((t, i) => virtualTemperature(t, qth[i], 0)); + + // Pressure and other thermodynamic variables + const p = calculatePressureProfile(zh, p0, Rd, cp, g, thetavh, dz); + const exner = p.map((pressure) => (pressure / p0) ** (Rd / cp)); + const T = exner.map((ex, i) => ex * thetaProf[i]); + const Td = p.map((p, i) => dewpoint(qtProfile[i], p/100)); + const rho = p.map((pressure, i) => pressure / (Rd * exner[i] * thetav[i])); + + // Include wind + let uProfile: number[]; + let vProfile: number[]; + if (config.sw_wind) { + const { z_u, z_v, gamma_u, gamma_v } = config; + uProfile = piecewiseProfile(z, h, u, du, z_u, gamma_u); + vProfile = piecewiseProfile(z, h, v, dv, z_v, gamma_v); + } else { + uProfile = new Array(z.length).fill(999); + vProfile = new Array(z.length).fill(999); + } + + return { + z, + theta: thetaProf, + qt: qtProfile, + u: uProfile, + v: vProfile, + thetav, + p, + exner, + T, + Td, + rho, + }; +} + +/** + * Compute pressure profile using hydrostatic balance + */ +function calculatePressureProfile( + zh: number[], + p0: number, + Rd: number, + cp: number, + g: number, + thetavh: number[], + dz: number, +) { + const phRdcp = new Array(zh.length).fill(0); + phRdcp[0] = p0 ** (Rd / cp); + + for (let i = 1; i < phRdcp.length; i++) { + phRdcp[i] = + phRdcp[i - 1] - (((g / cp) * p0 ** (Rd / cp)) / thetavh[i - 1]) * dz; + } + + const ph = phRdcp.map((x) => x ** (cp / Rd)); + const p = ph + .slice(0, -1) + .map((val, i) => Math.exp(0.5 * (Math.log(val) + Math.log(ph[i + 1])))); + return p; +} + +/** + * Generate array with specified range and step + */ +function arange(start: number, stop: number, step: number): number[] { + const result: number[] = []; + for (let i = start; i < stop; i += step) { + result.push(i); + } + return result; +} + +/** + * Create CLASS-style piecewise profile: mixed layer + inversion + free troposphere segments + */ +function piecewiseProfile( + z: number[], + h: number, + mlValue: number, + jump: number, + zSegments: number[], + gammaSegments: number[], +): number[] { + const profile = new Array(z.length).fill(0); + + for (let i = 0; i < z.length; i++) { + const _z = z[i]; + + if (_z <= h) { + // Mixed layer: constant value + profile[i] = mlValue; + } else { + // Above mixed layer: start with jump, then apply lapse rates + let currentValue = mlValue + jump; + let anchorPoint = h; + + // Find which segment this height falls into + let segIdx = 0; + for (segIdx = 0; segIdx < zSegments.length; segIdx++) { + const zTop = zSegments[segIdx]; + + if (zTop < h) { + // Mixed layer has grown beyond this segment; irrelevant + continue; + } + + if (_z >= zTop) { + // We've passed this segment; add its contribution and update anchor + const dz = zTop - anchorPoint; + currentValue += gammaSegments[segIdx] * dz; + anchorPoint = zTop; + } else { + // Height falls within this segment + const dz = _z - anchorPoint; + currentValue += gammaSegments[segIdx] * dz; + break; + } + } + + // Handle case where we've gone beyond all segments + if (segIdx === zSegments.length && _z > zSegments[zSegments.length - 1]) { + const dz = _z - zSegments[zSegments.length - 1]; + currentValue += gammaSegments[gammaSegments.length - 1] * dz; + } + + profile[i] = currentValue; + } + } + + return profile; +} diff --git a/packages/class/src/runner.ts b/packages/class/src/runner.ts index 644bc41..480874a 100644 --- a/packages/class/src/runner.ts +++ b/packages/class/src/runner.ts @@ -5,7 +5,11 @@ */ import { CLASS } from "./class.js"; import type { Config } from "./config.js"; -import { type ClassOutput, outputVariables } from "./output.js"; +import { + type ClassOutput, + type OutputVariableKey, + outputVariables, +} from "./output.js"; import { parse } from "./validate.js"; /** @@ -19,18 +23,20 @@ export function runClass(config: Config, freq = 600): ClassOutput { const validatedConfig = parse(config); const model = new CLASS(validatedConfig); + const output_keys = Object.keys(outputVariables) as OutputVariableKey[]; + const writeOutput = () => { - for (const v of outputVariables) { - const value = model.getValue(v.key); + for (const key of output_keys) { + const value = model.getValue(key); if (value !== undefined) { - (output[v.key] as number[]).push(value as number); + (output[key] as number[]).push(value as number); } } }; const output = Object.fromEntries( - outputVariables.map((v) => [v.key, []]), - ) as ClassOutput; + output_keys.map((key) => [key, []]), + ) as unknown as ClassOutput; // Initial time writeOutput(); diff --git a/packages/class/src/thermodynamics.ts b/packages/class/src/thermodynamics.ts new file mode 100644 index 0000000..9d79659 --- /dev/null +++ b/packages/class/src/thermodynamics.ts @@ -0,0 +1,80 @@ +// thermodynamics.ts + +// Constants +const Rd = 287; // Gas constant for dry air [J/kg/K] +const Rv = 461; // Gas constant for water vapor [J/kg/K] +const cp = 1004; // Specific heat of dry air at constant pressure [J/kg/K] +const Lv = 2.5e6; // Latent heat of vaporization [J/kg] +const ep = Rd / Rv; + +export function virtualTemperature(t: number, qt: number, ql: number): number { + return t * (1.0 - (1.0 - Rv / Rd) * qt - (Rv / Rd) * ql); +} + +export function esatLiq(t: number): number { + const Tc = Math.min(t - 273.15, 50); // limit to avoid excessive values + return 611.21 * Math.exp((17.502 * Tc) / (240.97 + Tc)); +} + +export function qsatLiq(p: number, t: number): number { + const e = esatLiq(t); + return (ep * e) / (p - (1.0 - ep) * e); +} + +export function dqsatdTLiq(p: number, t: number): number { + const e = esatLiq(t); + const den = p - e * (1.0 - ep); + return ( + ((ep / den + ((1.0 - ep) * ep * e) / (den * den)) * Lv * e) / (Rv * t * t) + ); +} + +export function calcThetav( + thl: number, + qt: number, + p: number, + exner: number, +): [number, number] { + const tl = exner * thl; + let qsat = qsatLiq(p, tl); + let ql = 0.0; + + if (qt <= qsat) { + return [virtualTemperature(thl, qt, 0.0), qsat]; + } + + // Newton-Raphson iteration + let tnr = tl; + let tnr_old = 1e9; + let iter = 0; + const maxIter = 100; + + while (Math.abs(tnr - tnr_old) / tnr_old > 1e-5 && iter < maxIter) { + tnr_old = tnr; + qsat = qsatLiq(p, tnr); + const f = tnr - tl - (Lv / cp) * (qt - qsat); + const f_prime = 1 + (Lv / cp) * dqsatdTLiq(p, tnr); + tnr -= f / f_prime; + iter++; + } + + ql = qt - qsat; + return [virtualTemperature(tnr / exner, qt, ql), qsat]; +} + +/** + * https://en.wikipedia.org/wiki/Dew_point#Calculating_the_dew_point + */ +export function dewpoint(q: number, p: number) { + // Empirical fit parameters (Sonntag1990, see wikipedia entry for more options) + const A = 6.112; + const B = 17.62; + const C = 243.12; + + const w = q / (1 - q); // mixing ratio + const e = (w * p) / (w + 0.622); // Actual vapour pressure; Wallace and Hobbs 3.59 + + const Td = (C * Math.log(e / A)) / (B - Math.log(e / A)); + + return Td + 273.15; +} From 92b6cca8a7d3fc9025af0e03d0a081c21f4f59d9 Mon Sep 17 00:00:00 2001 From: Peter Kalverla Date: Wed, 28 May 2025 19:59:32 +0200 Subject: [PATCH 04/12] Refactor piecewise lapse rate in gridded version; behaviour seems consistent now, but still observe strange behaviour around the time that the ML starts to shrink in the varnavas case, where the ML is pushing the free troposphere profile away --- packages/class/src/profiles.ts | 72 +++++++++++++++++----------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/packages/class/src/profiles.ts b/packages/class/src/profiles.ts index 8b00672..eabfaa9 100644 --- a/packages/class/src/profiles.ts +++ b/packages/class/src/profiles.ts @@ -13,7 +13,7 @@ const CONSTANTS = { /** * Atmospheric vertical profiles */ -export type ClassProfile { +export interface ClassProfile { z: number[]; // Height levels (cell centers) [m] theta: number[]; // Potential temperature [K] thetav: number[]; // Virtual potential temperature [K] @@ -78,7 +78,7 @@ export function generateProfiles( const p = calculatePressureProfile(zh, p0, Rd, cp, g, thetavh, dz); const exner = p.map((pressure) => (pressure / p0) ** (Rd / cp)); const T = exner.map((ex, i) => ex * thetaProf[i]); - const Td = p.map((p, i) => dewpoint(qtProfile[i], p/100)); + const Td = p.map((p, i) => dewpoint(qtProfile[i], p / 100)); const rho = p.map((pressure, i) => pressure / (Rd * exner[i] * thetav[i])); // Include wind @@ -157,51 +157,51 @@ function piecewiseProfile( zSegments: number[], gammaSegments: number[], ): number[] { - const profile = new Array(z.length).fill(0); + const profile = new Array(z.length); for (let i = 0; i < z.length; i++) { const _z = z[i]; + // Case 1: Mixed layer — constant value if (_z <= h) { - // Mixed layer: constant value profile[i] = mlValue; - } else { - // Above mixed layer: start with jump, then apply lapse rates - let currentValue = mlValue + jump; - let anchorPoint = h; - - // Find which segment this height falls into - let segIdx = 0; - for (segIdx = 0; segIdx < zSegments.length; segIdx++) { - const zTop = zSegments[segIdx]; - - if (zTop < h) { - // Mixed layer has grown beyond this segment; irrelevant - continue; - } - - if (_z >= zTop) { - // We've passed this segment; add its contribution and update anchor - const dz = zTop - anchorPoint; - currentValue += gammaSegments[segIdx] * dz; - anchorPoint = zTop; - } else { - // Height falls within this segment - const dz = _z - anchorPoint; - currentValue += gammaSegments[segIdx] * dz; - break; - } + continue; + } + + // Case 2: Above mixed layer + let value = mlValue + jump; + let lowerBound = h; + + // Traverse lapse rate segments + for (let j = 0; j < zSegments.length; j++) { + const upperBound = zSegments[j]; + const lapse = gammaSegments[j]; + + if (upperBound < h) { + // Mixed layer has fully consumed segment, skip it + continue; } - // Handle case where we've gone beyond all segments - if (segIdx === zSegments.length && _z > zSegments[zSegments.length - 1]) { - const dz = _z - zSegments[zSegments.length - 1]; - currentValue += gammaSegments[gammaSegments.length - 1] * dz; + if (_z > upperBound) { + // Entire segment is below current height + value += lapse * (upperBound - lowerBound); + lowerBound = upperBound; + } else { + // Partial segment contribution + value += lapse * (_z - lowerBound); + lowerBound = _z; + break; // done accumulating } + } - profile[i] = currentValue; + // Case 3: Height is above all defined segments + if (_z > lowerBound) { + const lapse = gammaSegments[gammaSegments.length - 1]; + value += lapse * (_z - lowerBound); } + + profile[i] = value; } return profile; -} +} \ No newline at end of file From 44cc911acf59a59120eb7b4264b2ed52396cc7ad Mon Sep 17 00:00:00 2001 From: Peter Kalverla Date: Fri, 6 Jun 2025 12:13:55 +0200 Subject: [PATCH 05/12] Access fire plume model in web app; can now see the data in console, but still need to include it in plot --- apps/class-solid/src/components/Analysis.tsx | 65 +++--- apps/class-solid/src/lib/profiles.ts | 15 -- apps/class-solid/tests/fire.json | 22 ++ packages/class/package.json | 7 + packages/class/src/cli.ts | 4 +- packages/class/src/config.ts | 32 ++- packages/class/src/fire.ts | 216 +++++++++++++++++++ packages/class/src/profiles.ts | 6 +- 8 files changed, 298 insertions(+), 69 deletions(-) create mode 100644 apps/class-solid/tests/fire.json create mode 100644 packages/class/src/fire.ts diff --git a/apps/class-solid/src/components/Analysis.tsx b/apps/class-solid/src/components/Analysis.tsx index 38aff4a..de89f3a 100644 --- a/apps/class-solid/src/components/Analysis.tsx +++ b/apps/class-solid/src/components/Analysis.tsx @@ -1,10 +1,16 @@ -import type { Config } from "@classmodel/class/config"; +import type { Config, MixedLayerConfig } from "@classmodel/class/config"; +import { calculatePlume } from "@classmodel/class/fire"; import { type ClassOutput, - OutputVariableKey, + type OutputVariableKey, + getOutputAtTime, outputVariables, } from "@classmodel/class/output"; -import { type ClassProfile, NoProfile } from "@classmodel/class/profiles"; +import { + type ClassProfile, + NoProfile, + generateProfiles, +} from "@classmodel/class/profiles"; import * as d3 from "d3"; import { saveAs } from "file-saver"; import { toBlob } from "html-to-image"; @@ -23,8 +29,6 @@ import { import { createStore } from "solid-js/store"; import type { Observation } from "~/lib/experiment_config"; import { - getThermodynamicProfiles, - getVerticalProfiles, observationsForProfile, observationsForSounding, } from "~/lib/profiles"; @@ -252,18 +256,27 @@ export function VerticalProfilePlot({ flatExperiments().map((e) => { const { config, output, ...formatting } = e; const t = output?.t.indexOf(uniqueTimes()[analysis.time]); - return { - ...formatting, - data: - t !== -1 && // -1 means time not found in array - output && // Output must be defined - config.sw_ml // config must include mixed layer - ? // TODO: can't we use t here? - getVerticalProfiles(e.output, e.config, analysis.time) - : NoProfile, - }; + if (config.sw_ml && output && t !== undefined && t !== -1) { + const outputAtTime = getOutputAtTime(output, t); + return { ...formatting, data: generateProfiles(config, outputAtTime) }; + } + return { ...formatting, data: NoProfile }; }); + const firePlumes = () => + flatExperiments().map((e, i) => { + const { config, output, ...formatting } = e; + if (config.sw_fire) { + return { + ...formatting, + data: calculatePlume(config, profileData()[i].data), + }; + } + return { ...formatting, data: [] }; + }); + + console.log(firePlumes()); + // TODO: There should be a way that this isn't needed. const profileDataForPlot = () => profileData().map(({ data, label, color, linestyle }) => ({ @@ -274,7 +287,7 @@ export function VerticalProfilePlot({ x: data[classVariable()][i], y: z, })), - })) as ChartData[] + })) as ChartData[]; const allX = () => [ ...profileDataForPlot().flatMap((p) => p.data.map((d) => d.x)), @@ -427,20 +440,15 @@ function Picker(props: PickerProps) { } export function ThermodynamicPlot({ analysis }: { analysis: SkewTAnalysis }) { - const skewTData = () => + const profileData = () => flatExperiments().map((e) => { const { config, output, ...formatting } = e; const t = output?.t.indexOf(uniqueTimes()[analysis.time]); - return { - ...formatting, - data: - // TODO reuse get profiles now here - t !== -1 && // -1 means time not found in array - output && // Output must be defined - config.sw_ml // config must include mixed layer - ? getVerticalProfiles(e.output, e.config, t) - : NoProfile, - }; + if (config.sw_ml && output && t !== undefined && t !== -1) { + const outputAtTime = getOutputAtTime(output, t); + return { ...formatting, data: generateProfiles(config, outputAtTime) }; + } + return { ...formatting, data: NoProfile }; }); const observations = () => @@ -448,7 +456,7 @@ export function ThermodynamicPlot({ analysis }: { analysis: SkewTAnalysis }) { // TODO: There should be a way that this isn't needed. const profileDataForPlot = () => - skewTData().map(({ data, label, color, linestyle }) => ({ + profileData().map(({ data, label, color, linestyle }) => ({ label, color, linestyle, @@ -459,7 +467,6 @@ export function ThermodynamicPlot({ analysis }: { analysis: SkewTAnalysis }) { })), })) as ChartData[]; - console.log(profileDataForPlot()); return ( <> { * Create a DSV (delimiter-separated values) string from an object of arrays. */ function dsv(output: ClassOutput, delimiter: string): string { - const keys = Object.keys(output); + const keys = Object.keys(output) as OutputVariableKey[]; // order of headers is now in which they were added to the object // TODO make configurable: which columns and in which order const headers = keys.join(delimiter); diff --git a/packages/class/src/config.ts b/packages/class/src/config.ts index 022cb28..5f18b1a 100644 --- a/packages/class/src/config.ts +++ b/packages/class/src/config.ts @@ -404,7 +404,7 @@ const untypedSchema = { // biome-ignore lint/suspicious/noThenProperty: part of JSON Schema then: { properties: { - L_fire: { + L: { symbol: "Lfire", type: "number", unit: "m", @@ -412,7 +412,7 @@ const untypedSchema = { title: "Length of the fire", "ui:group": "Fire", }, - d_fire: { + d: { symbol: "dfire", type: "number", unit: "m", @@ -420,7 +420,7 @@ const untypedSchema = { title: "Depth of the fire", "ui:group": "Fire", }, - h0_fire: { + h0: { symbol: "h0, fire", type: "number", unit: "m", @@ -428,7 +428,7 @@ const untypedSchema = { title: "Height to start", "ui:group": "Fire", }, - C_fire: { + C: { symbol: "Cfire", type: "number", unit: "J kg⁻¹", @@ -436,7 +436,7 @@ const untypedSchema = { title: "Heat stored in fuel", "ui:group": "Fire", }, - omega_fire: { + omega: { symbol: "ωfire", type: "number", unit: "kg m⁻²", @@ -444,7 +444,7 @@ const untypedSchema = { title: "Fuel mass per area", "ui:group": "Fire", }, - v_fire: { + spread: { symbol: "vfire", type: "number", unit: "m s⁻¹", @@ -452,7 +452,7 @@ const untypedSchema = { title: "Rate of spread of the fire", "ui:group": "Fire", }, - radiative_loss_fire: { + radiativeLoss: { symbol: "rlfire", type: "number", unit: "-", @@ -462,15 +462,7 @@ const untypedSchema = { "ui:group": "Fire", }, }, - required: [ - "L_fire", - "d_fire", - "h0_fire", - "C_fire", - "omega_fire", - "v_fire", - "radiative_loss_fire", - ], + required: ["L", "d", "h0", "C", "omega", "spread", "radiativeLoss"], }, }, ], @@ -497,7 +489,7 @@ export type WindConfig = { z_v: number[]; ustar: number; }; -type NoWindConfig = { +export type NoWindConfig = { sw_wind?: false; }; @@ -531,10 +523,10 @@ export type FireConfig = { h0: number; C: number; omega: number; - v: number; - radiative_loss: number; + spread: number; + radiativeLoss: number; }; -type NoFireConfig = { +export type NoFireConfig = { sw_fire?: false; }; diff --git a/packages/class/src/fire.ts b/packages/class/src/fire.ts new file mode 100644 index 0000000..072a68f --- /dev/null +++ b/packages/class/src/fire.ts @@ -0,0 +1,216 @@ +// ============================================================================ +// fireplume.ts +// ============================================================================ + +import type { FireConfig } from "./config.js"; +import type { ClassProfile } from "./profiles.js"; +import { calcThetav } from "./thermodynamics.js"; + +// Constants +const g = 9.81; // Gravitational acceleration [m/s²] +const cp = 1004; // Specific heat at constant pressure [J/kg/K] +const Lv = 2.5e6; // Latent heat of vaporization [J/kg] + +/** + * Configuration parameters for plume model + */ +interface PlumeConfig { + zSl: number; // Surface layer height [m] + lambdaMix: number; // Mixing length in surface layer [m] + beta: number; // Fractional detrainment above surface layer + dz: number; // Grid spacing [m] +} + +/** + * Default plume configuration + */ +const defaultPlumeConfig: PlumeConfig = { + zSl: 100.0, + lambdaMix: 30.0, + beta: 1.0, + dz: 1.0, +}; + +/** + * Parcel properties at a given height + */ +interface Parcel { + z: number; // Height levels [m] + w: number; // Vertical velocity [m/s] + theta: number; // Potential temperature [K] + qt: number; // Total specific humidity [kg/kg] + thetav: number; // Virtual potential temperature [K] + qsat: number; // Saturation specific humidity [kg/kg] + b: number; // Buoyancy [m/s²] + m: number; // Mass flux [kg/m²/s] + area: number; // Cross-sectional area [m²] + e: number; // Entrainment rate [kg/m²/s] + d: number; // Detrainment rate [kg/m²/s] +} + +/** + * Initialize fire parcel with ambient conditions and fire properties + */ +function initializeFireParcel( + background: ClassProfile, + fire: FireConfig, +): Parcel { + // Start with parcel props from ambient air + const z = background.z[0]; + let theta = background.theta[0]; + const thetavAmbient = background.thetav[0]; + let qt = background.qt[0]; + const rho = background.rho[0]; + const p = background.p[0]; + const exner = background.exner[0]; + + // Calculate fire properties + const area = fire.L * fire.d; + const FFire = + ((fire.omega * fire.C * fire.spread) / fire.d) * (1 - fire.radiativeLoss); + const FqFire = 0.0 * FFire; // Dry plume for now + + // Use cube root as the root may be negative and js will yield NaN for a complex number result + const w = Math.cbrt( + (3 * g * FFire * fire.h0) / (2 * rho * cp * thetavAmbient), + ); + + // Add excess temperature/humidity and update thetav/qsat accordingly + const dtheta = FFire / (rho * cp * w); + const dqv = FqFire / (rho * Lv * w); + theta += dtheta; + qt += dqv; + + const [thetav, qsat] = calcThetav(theta, qt, p, exner); + + // Calculate parcel buoyancy + const b = (g / background.thetav[0]) * (thetav - thetavAmbient); + + // Store parcel props + return { + z, + w, + theta, + qt, + thetav, + qsat, + b, + area: fire.L * fire.d, + m: rho * area * w, + e: ((rho * area) / (2 * w)) * b, + d: 0, + }; +} + +/** + * Calculate plume evolution through the atmosphere + */ +export function calculatePlume( + fire: FireConfig, + bg: ClassProfile, + plumeConfig: PlumeConfig = defaultPlumeConfig, +): Parcel[] { + const { dz } = plumeConfig; + let parcel = initializeFireParcel(bg, fire); + const plume: Parcel[] = [parcel]; + + const detrainmentRate0 = plumeConfig.lambdaMix ** 0.5 / parcel.area ** 0.5; + let crossedSl = false; + let epsi = 0; + let delt = 0; + + for (let i = 1; i < bg.z.length; i++) { + const z = bg.z[i]; + + // Mass flux through plume + const m = parcel.m + (parcel.e - parcel.d) * dz; + const emz = (parcel.e / parcel.m) * dz; + const theta = parcel.theta - emz * (parcel.theta - bg.theta[i - 1]); + const qt = parcel.qt - emz * (parcel.qt - bg.qt[i - 1]); + + // Calculate virtual potential temperature and buoyancy + const [thetav, qsat] = calcThetav(theta, qt, bg.p[i], bg.exner[i]); + const b = (g / bg.thetav[i]) * (thetav - bg.thetav[i]); + + // Solve vertical velocity equation + const aW = 1; + const bW = 0; + const w = + parcel.w + + ((-bW * parcel.e * parcel.w + + aW * parcel.area * bg.rho[i - 1] * parcel.b) / + parcel.m) * + dz; + + // Calculate entrainment and detrainment + let e: number; + let d: number; + + if (z < plumeConfig.zSl) { + // Surface layer formulation + e = ((parcel.area * bg.rho[i - 1]) / (2 * parcel.w)) * parcel.b; + d = + parcel.area * + bg.rho[i - 1] * + detrainmentRate0 * + ((z ** 0.5 * (w - parcel.w)) / dz + parcel.w / (2 * z ** 0.5)); + } else { + // Above surface layer + if (!crossedSl) { + epsi = parcel.e / parcel.m; + delt = epsi / plumeConfig.beta; + crossedSl = true; + } + + e = epsi * m; + d = delt * m; + } + + const area = m / (bg.rho[i] * w); + + // Update parcel + parcel = { + z, + w, + theta, + qt, + thetav, + qsat, + b, + area, + m, + e, + d, + }; + + if (w < 0 || area <= 0) { + break; + } + + plume.push(parcel); + } + return plume; +} + +/** + * Convert array of objects into object of arrays + */ +export function transposePlumeData( + plume: Parcel[], +): Record { + if (plume.length === 0) { + return {} as Record; + } + + // Get field names from the first parcel object + const fieldNames = Object.keys(plume[0]) as (keyof Parcel)[]; + + // Extract arrays for each field + const transposed = {} as Record; + + for (const fieldName of fieldNames) { + transposed[fieldName] = plume.map((parcel) => parcel[fieldName]); + } + + return transposed; +} diff --git a/packages/class/src/profiles.ts b/packages/class/src/profiles.ts index eabfaa9..531500b 100644 --- a/packages/class/src/profiles.ts +++ b/packages/class/src/profiles.ts @@ -1,6 +1,6 @@ // profiles.ts -import type { Config as ClassConfig, MixedLayerConfig } from "./config.js"; +import type { MixedLayerConfig, NoWindConfig, WindConfig } from "./config.js"; import type { ClassOutputAtSingleTime } from "./output.js"; import { dewpoint, virtualTemperature } from "./thermodynamics.js"; @@ -27,7 +27,7 @@ export interface ClassProfile { rho: number[]; // Density [kg/m³] } -export const NoProfile = { +export const NoProfile: ClassProfile = { z: [], theta: [], thetav: [], @@ -45,7 +45,7 @@ export const NoProfile = { * Generate vertical atmospheric profiles based on CLASS config + output */ export function generateProfiles( - config: ClassConfig & MixedLayerConfig, + config: MixedLayerConfig & (WindConfig | NoWindConfig), output: ClassOutputAtSingleTime, dz = 1, ): ClassProfile { From 0f94cbf7cb044a9ca460b811f42646f68dad8fcf Mon Sep 17 00:00:00 2001 From: Peter Kalverla Date: Fri, 6 Jun 2025 12:40:57 +0200 Subject: [PATCH 06/12] Use last index if height or time exceed specified lapse rate segments or hourly flux values, resp --- packages/class/src/class.ts | 8 ++++---- packages/class/src/utils.ts | 11 ++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/class/src/class.ts b/packages/class/src/class.ts index 886f728..9fd6142 100644 --- a/packages/class/src/class.ts +++ b/packages/class/src/class.ts @@ -216,7 +216,7 @@ export class CLASS { this.assertMixedLayer(); const { z_theta, gamma_theta } = this._cfg; const i = findInsertIndex(z_theta, this.ml.h); - return gamma_theta[i] ?? 0; + return gamma_theta.slice(i)[0]; } /** Free atmosphere specific humidity lapse rate */ @@ -224,7 +224,7 @@ export class CLASS { this.assertMixedLayer(); const { z_qt, gamma_qt } = this._cfg; const i = findInsertIndex(z_qt, this.ml.h); - return gamma_qt[i] ?? 0; + return gamma_qt.slice(i)[0]; } /** Free atmosphere u-wind lapse rate */ @@ -232,7 +232,7 @@ export class CLASS { this.assertWind(); const { z_u, gamma_u } = this._cfg; const i = findInsertIndex(z_u, this.ml.h); - return gamma_u[i] ?? 0; + return gamma_u.slice(i)[0]; } /** Free atmosphere v-wind lapse rate */ @@ -240,7 +240,7 @@ export class CLASS { this.assertWind(); const { z_v, gamma_v } = this._cfg; const i = findInsertIndex(z_v, this.ml.h); - return gamma_v[i] ?? 0; + return gamma_v.slice(i)[0]; } // Type guards diff --git a/packages/class/src/utils.ts b/packages/class/src/utils.ts index 894948d..923d3ba 100644 --- a/packages/class/src/utils.ts +++ b/packages/class/src/utils.ts @@ -4,16 +4,17 @@ * * @param arr array with hourly reference values for variable * @param t time in seconds - * @param pad fill value if t/3600 exceeds array length * @returns interpolated value */ -export function interpolateHourly(arr: number[], t: number, pad = 0) { +export function interpolateHourly(arr: number[], t: number) { const maxIndex = arr.length - 1; const i = Math.floor(t / 3600); - const p = (t % 3600) / 3600; - const left = i <= maxIndex ? arr[i] : pad; - const right = i + 1 <= maxIndex ? arr[i + 1] : pad; + if (i >= maxIndex) return arr[maxIndex]; + + const p = (t % 3600) / 3600; + const left = arr[i]; + const right = arr[i + 1]; return left + p * (right - left); } From 830578a6a57fd683116b465224d76eefed0f6c7b Mon Sep 17 00:00:00 2001 From: Peter Kalverla Date: Fri, 6 Jun 2025 12:41:40 +0200 Subject: [PATCH 07/12] Include fire profiles in plot; hardcoded for now, but it seems to work well --- apps/class-solid/src/components/Analysis.tsx | 10 +++++- .../class-solid/src/components/plots/Line.tsx | 32 +++++++++++++++++++ apps/class-solid/src/lib/profiles.ts | 5 --- packages/class/src/fire.ts | 2 +- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/apps/class-solid/src/components/Analysis.tsx b/apps/class-solid/src/components/Analysis.tsx index de89f3a..837f8ff 100644 --- a/apps/class-solid/src/components/Analysis.tsx +++ b/apps/class-solid/src/components/Analysis.tsx @@ -45,7 +45,7 @@ import { MdiCamera, MdiDelete, MdiImageFilterCenterFocus } from "./icons"; import { AxisBottom, AxisLeft, getNiceAxisLimits } from "./plots/Axes"; import { Chart, ChartContainer, type ChartData } from "./plots/ChartContainer"; import { Legend } from "./plots/Legend"; -import { Line, type Point } from "./plots/Line"; +import { Line, Plume, type Point } from "./plots/Line"; import { SkewTPlot, type SoundingRecord } from "./plots/skewTlogP"; import { Button } from "./ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "./ui/card"; @@ -350,6 +350,14 @@ export function VerticalProfilePlot({ )} + + {(d) => ( + + + + + )} + ) { ); } + +export function Plume({ + d, + variable, +}: { d: ChartData; variable: keyof Parcel }) { + const [chart, _updateChart] = useChartContext(); + const [hovered, setHovered] = createSignal(false); + + const l = d3.line( + (d) => chart.scaleX(d[variable]), + (d) => chart.scaleY(d.z), + ); + + const stroke = () => (hovered() ? highlight(d.color) : d.color); + + return ( + setHovered(true)} + onMouseLeave={() => setHovered(false)} + fill="none" + stroke={stroke()} + stroke-dasharray={d.linestyle} + stroke-width="2" + d={l(d.data) || ""} + class="cursor-pointer" + > + {d.label} + + ); +} diff --git a/apps/class-solid/src/lib/profiles.ts b/apps/class-solid/src/lib/profiles.ts index 005a900..a0c9d17 100644 --- a/apps/class-solid/src/lib/profiles.ts +++ b/apps/class-solid/src/lib/profiles.ts @@ -1,8 +1,3 @@ -import type { Config } from "@classmodel/class/config"; -import { type ClassOutput, getOutputAtTime } from "@classmodel/class/output"; -import { NoProfile, generateProfiles } from "@classmodel/class/profiles"; -import { findInsertIndex } from "@classmodel/class/utils"; -import type { Point } from "~/components/plots/Line"; import type { Observation } from "./experiment_config"; /** diff --git a/packages/class/src/fire.ts b/packages/class/src/fire.ts index 072a68f..d86684f 100644 --- a/packages/class/src/fire.ts +++ b/packages/class/src/fire.ts @@ -34,7 +34,7 @@ const defaultPlumeConfig: PlumeConfig = { /** * Parcel properties at a given height */ -interface Parcel { +export interface Parcel { z: number; // Height levels [m] w: number; // Vertical velocity [m/s] theta: number; // Potential temperature [K] From 89942ab32572a0c8e51d41b3025b38cdb24be2a9 Mon Sep 17 00:00:00 2001 From: Peter Kalverla Date: Fri, 6 Jun 2025 14:39:07 +0200 Subject: [PATCH 08/12] Plume variables now respond to variable picker --- apps/class-solid/src/components/Analysis.tsx | 16 +++++++++++----- apps/class-solid/src/components/plots/Line.tsx | 10 +++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/apps/class-solid/src/components/Analysis.tsx b/apps/class-solid/src/components/Analysis.tsx index 837f8ff..c74bf16 100644 --- a/apps/class-solid/src/components/Analysis.tsx +++ b/apps/class-solid/src/components/Analysis.tsx @@ -1,5 +1,5 @@ import type { Config, MixedLayerConfig } from "@classmodel/class/config"; -import { calculatePlume } from "@classmodel/class/fire"; +import { Parcel, calculatePlume } from "@classmodel/class/fire"; import { type ClassOutput, type OutputVariableKey, @@ -275,8 +275,6 @@ export function VerticalProfilePlot({ return { ...formatting, data: [] }; }); - console.log(firePlumes()); - // TODO: There should be a way that this isn't needed. const profileDataForPlot = () => profileData().map(({ data, label, color, linestyle }) => ({ @@ -324,6 +322,10 @@ export function VerticalProfilePlot({ setResetPlot(analysis.id); } +const showPlume = createMemo(() => { + return ["theta", "qt", "thetav"].includes(classVariable()); +}); + return ( <>
@@ -353,8 +355,12 @@ export function VerticalProfilePlot({ {(d) => ( - - + + keyof Parcel} + /> + )} diff --git a/apps/class-solid/src/components/plots/Line.tsx b/apps/class-solid/src/components/plots/Line.tsx index 45a3c15..aa5aa53 100644 --- a/apps/class-solid/src/components/plots/Line.tsx +++ b/apps/class-solid/src/components/plots/Line.tsx @@ -40,16 +40,16 @@ export function Line(d: ChartData) { export function Plume({ d, variable, -}: { d: ChartData; variable: keyof Parcel }) { +}: { d: ChartData; variable: () => keyof Parcel }) { const [chart, _updateChart] = useChartContext(); const [hovered, setHovered] = createSignal(false); const l = d3.line( - (d) => chart.scaleX(d[variable]), + (d) => chart.scaleX(d[variable()]), (d) => chart.scaleY(d.z), ); - const stroke = () => (hovered() ? highlight(d.color) : d.color); + const stroke = () => (hovered() ? highlight("#ff0000") : "#ff0000"); return ( setHovered(false)} fill="none" stroke={stroke()} - stroke-dasharray={d.linestyle} + stroke-dasharray={"4"} stroke-width="2" d={l(d.data) || ""} class="cursor-pointer" > - {d.label} + {`Fire plume for ${d.label}`} ); } From c29cf09cc731b62e5b45fca0f764b0b8f9cd684c Mon Sep 17 00:00:00 2001 From: Peter Kalverla Date: Fri, 6 Jun 2025 15:07:50 +0200 Subject: [PATCH 09/12] Also include fire plume in thermodynamic plot --- apps/class-solid/src/components/Analysis.tsx | 22 +++++++++++++++++-- .../src/components/plots/skewTlogP.tsx | 9 +++++--- packages/class/src/fire.ts | 16 +++++++++++++- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/apps/class-solid/src/components/Analysis.tsx b/apps/class-solid/src/components/Analysis.tsx index c74bf16..1813a83 100644 --- a/apps/class-solid/src/components/Analysis.tsx +++ b/apps/class-solid/src/components/Analysis.tsx @@ -323,7 +323,7 @@ export function VerticalProfilePlot({ } const showPlume = createMemo(() => { - return ["theta", "qt", "thetav"].includes(classVariable()); + return ["theta", "qt", "thetav", "T", "Td"].includes(classVariable()); }); return ( @@ -465,6 +465,20 @@ export function ThermodynamicPlot({ analysis }: { analysis: SkewTAnalysis }) { return { ...formatting, data: NoProfile }; }); + const firePlumes = () => + flatExperiments().map((e, i) => { + const { config, output, ...formatting } = e; + if (config.sw_fire) { + return { + ...formatting, + color: "#ff0000", + label: `${formatting.label} - fire plume`, + data: calculatePlume(config, profileData()[i].data), + }; + } + return { ...formatting, data: [] }; + }) as ChartData[]; + const observations = () => flatObservations().map((o) => observationsForSounding(o)); @@ -485,7 +499,11 @@ export function ThermodynamicPlot({ analysis }: { analysis: SkewTAnalysis }) { <> [...profileDataForPlot(), ...observations()]} + data={() => [ + ...profileDataForPlot(), + ...observations(), + ...firePlumes(), + ]} /> {TimeSlider( () => analysis.time, diff --git a/apps/class-solid/src/components/plots/skewTlogP.tsx b/apps/class-solid/src/components/plots/skewTlogP.tsx index d46f240..9bc813c 100644 --- a/apps/class-solid/src/components/plots/skewTlogP.tsx +++ b/apps/class-solid/src/components/plots/skewTlogP.tsx @@ -167,9 +167,12 @@ export function SkewTPlot(props: { const [toggles, setToggles] = createStore>({}); + const dataForLegend = () => + props.data().filter((d) => !d.label.includes("- fire plume")); + // Initialize all lines as visible createEffect(() => { - for (const d of props.data()) { + for (const d of dataForLegend()) { setToggles(d.label, true); } }); @@ -183,12 +186,12 @@ export function SkewTPlot(props: { if (!toggles || !cd) { return true; } - return toggles[cd.label]; + return toggles[cd.label.replace(" - fire plume", "")]; } return ( - + Date: Fri, 6 Jun 2025 15:08:41 +0200 Subject: [PATCH 10/12] formatting --- apps/class-solid/src/components/Analysis.tsx | 10 +++++----- apps/class-solid/src/lib/presets/varnavas.json | 1 - apps/class-solid/tests/fire.json | 14 ++++---------- packages/class/package.json | 2 -- packages/class/src/output.ts | 2 +- packages/class/src/profiles.ts | 2 +- 6 files changed, 11 insertions(+), 20 deletions(-) diff --git a/apps/class-solid/src/components/Analysis.tsx b/apps/class-solid/src/components/Analysis.tsx index 1813a83..9235c05 100644 --- a/apps/class-solid/src/components/Analysis.tsx +++ b/apps/class-solid/src/components/Analysis.tsx @@ -1,5 +1,5 @@ -import type { Config, MixedLayerConfig } from "@classmodel/class/config"; -import { Parcel, calculatePlume } from "@classmodel/class/fire"; +import type { Config } from "@classmodel/class/config"; +import { type Parcel, calculatePlume } from "@classmodel/class/fire"; import { type ClassOutput, type OutputVariableKey, @@ -322,9 +322,9 @@ export function VerticalProfilePlot({ setResetPlot(analysis.id); } -const showPlume = createMemo(() => { - return ["theta", "qt", "thetav", "T", "Td"].includes(classVariable()); -}); + const showPlume = createMemo(() => { + return ["theta", "qt", "thetav", "T", "Td"].includes(classVariable()); + }); return ( <> diff --git a/apps/class-solid/src/lib/presets/varnavas.json b/apps/class-solid/src/lib/presets/varnavas.json index 9b0da11..2020544 100644 --- a/apps/class-solid/src/lib/presets/varnavas.json +++ b/apps/class-solid/src/lib/presets/varnavas.json @@ -40,5 +40,4 @@ "dt": 60, "runtime": 43200, "p0": 101300 - } diff --git a/apps/class-solid/tests/fire.json b/apps/class-solid/tests/fire.json index d84a8f8..679882f 100644 --- a/apps/class-solid/tests/fire.json +++ b/apps/class-solid/tests/fire.json @@ -6,17 +6,11 @@ "theta": 300, "dtheta": 2, "qt": 0.0085, - "gamma_qt": [ - -1e-7 - ], - "z_theta": [ - 10000 - ], - "z_qt": [ - 10000 - ], + "gamma_qt": [-1e-7], + "z_theta": [10000], + "z_qt": [10000], "sw_fire": true }, "preset": "Default", "permutations": [] -} \ No newline at end of file +} diff --git a/packages/class/package.json b/packages/class/package.json index 8a0a62d..1da4221 100644 --- a/packages/class/package.json +++ b/packages/class/package.json @@ -45,14 +45,12 @@ "import": { "default": "./dist/profiles.js", "types": "./dist/profiles.d.ts" - } }, "./fire": { "import": { "default": "./dist/fire.js", "types": "./dist/fire.d.ts" - } }, "./utils": { diff --git a/packages/class/src/output.ts b/packages/class/src/output.ts index aa18c89..7fa5e58 100644 --- a/packages/class/src/output.ts +++ b/packages/class/src/output.ts @@ -103,4 +103,4 @@ export function getOutputAtTime( return Object.fromEntries( Object.entries(output).map(([key, values]) => [key, values[timeIndex]]), ) as ClassOutputAtSingleTime; -} \ No newline at end of file +} diff --git a/packages/class/src/profiles.ts b/packages/class/src/profiles.ts index 531500b..63410b0 100644 --- a/packages/class/src/profiles.ts +++ b/packages/class/src/profiles.ts @@ -204,4 +204,4 @@ function piecewiseProfile( } return profile; -} \ No newline at end of file +} From 9fbe43e07bc0045192a5440a819dce8906706a09 Mon Sep 17 00:00:00 2001 From: Peter Kalverla Date: Fri, 6 Jun 2025 15:09:57 +0200 Subject: [PATCH 11/12] type fix --- apps/class-solid/src/lib/download.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/class-solid/src/lib/download.ts b/apps/class-solid/src/lib/download.ts index f512e7e..d965a65 100644 --- a/apps/class-solid/src/lib/download.ts +++ b/apps/class-solid/src/lib/download.ts @@ -1,4 +1,4 @@ -import type { ClassOutput } from "@classmodel/class/output"; +import type { ClassOutput, OutputVariableKey } from "@classmodel/class/output"; import { BlobReader, BlobWriter, ZipWriter } from "@zip.js/zip.js"; import { toPartial } from "./encode"; import type { ExperimentConfig } from "./experiment_config"; @@ -12,7 +12,7 @@ export function toConfigBlob(experiment: ExperimentConfig) { } function outputToCsv(output: ClassOutput) { - const headers = Object.keys(output); + const headers = Object.keys(output) as OutputVariableKey[]; const lines = [headers.join(",")]; for (let i = 0; i < output[headers[0]].length; i++) { lines.push(headers.map((h) => output[h][i]).join(",")); From dbd8c4f5b0224913a5779450d4a9b1bc480ed7ec Mon Sep 17 00:00:00 2001 From: Peter Kalverla Date: Fri, 6 Jun 2025 15:18:50 +0200 Subject: [PATCH 12/12] Update reference data for tests --- packages/class/src/validate.test.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/class/src/validate.test.ts b/packages/class/src/validate.test.ts index a9bd19f..98348eb 100644 --- a/packages/class/src/validate.test.ts +++ b/packages/class/src/validate.test.ts @@ -53,8 +53,8 @@ describe("parse", () => { h: 200, theta: 288, dtheta: 1, - q: 0.008, - dq: -0.001, + qt: 0.008, + dqt: -0.001, wtheta: [0.1], advtheta: 0, gamma_theta: [0.006], @@ -63,6 +63,7 @@ describe("parse", () => { gamma_qt: [0], divU: 0, beta: 0.2, + p0: 101300, z_theta: [5000], z_qt: [5000], u: 6, @@ -76,12 +77,20 @@ describe("parse", () => { gamma_v: [0], z_v: [5000], ustar: 0.3, + L: 10000, + d: 300, + h0: 20, + C: 17781000, + omega: 7.6, + spread: 1.5, + radiativeLoss: 0.7, name: "", description: "", dt: 60, runtime: 43200, sw_ml: true, sw_wind: false, + sw_fire: false, }; assert.deepEqual(output, expected); });