Skip to content

Commit 09dbb5b

Browse files
authored
Merge pull request #163 from classmodel/fireplume-update
Fireplume update - also see #161
2 parents c58a419 + beb96a1 commit 09dbb5b

File tree

7 files changed

+140
-126
lines changed

7 files changed

+140
-126
lines changed

apps/class-solid/src/components/Analysis.tsx

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Config } from "@classmodel/class/config";
2-
import { type Parcel, calculatePlume } from "@classmodel/class/fire";
2+
import { calculatePlume, transposePlumeData } from "@classmodel/class/fire";
33
import {
44
type ClassOutput,
55
type OutputVariableKey,
@@ -45,7 +45,7 @@ import { MdiCamera, MdiDelete, MdiImageFilterCenterFocus } from "./icons";
4545
import { AxisBottom, AxisLeft, getNiceAxisLimits } from "./plots/Axes";
4646
import { Chart, ChartContainer, type ChartData } from "./plots/ChartContainer";
4747
import { Legend } from "./plots/Legend";
48-
import { Line, Plume, type Point } from "./plots/Line";
48+
import { Line, type Point } from "./plots/Line";
4949
import { SkewTPlot, type SoundingRecord } from "./plots/skewTlogP";
5050
import { Button } from "./ui/button";
5151
import { Card, CardContent, CardHeader, CardTitle } from "./ui/card";
@@ -239,16 +239,25 @@ export function VerticalProfilePlot({
239239
"Specific humidity [kg/kg]": "qt",
240240
"u-wind component [m/s]": "u",
241241
"v-wind component [m/s]": "v",
242+
"vertical velocity [m/s]": "w",
242243
"Pressure [Pa]": "p",
243244
"Exner function [-]": "exner",
244245
"Temperature [K]": "T",
245246
"Dew point temperature [K]": "Td",
246247
"Density [kg/m³]": "rho",
248+
"Relative humidity [%]": "rh",
247249
} as const satisfies Record<string, keyof ClassProfile>;
248250

249251
const classVariable = () =>
250252
variableOptions[analysis.variable as keyof typeof variableOptions];
251253

254+
type PlumeVariable = "theta" | "qt" | "thetav" | "T" | "Td" | "rh" | "w";
255+
function isPlumeVariable(v: string): v is PlumeVariable {
256+
return ["theta", "qt", "thetav", "T", "Td", "rh", "w"].includes(v);
257+
}
258+
259+
const showPlume = createMemo(() => isPlumeVariable(classVariable()));
260+
252261
const observations = () =>
253262
flatObservations().map((o) => observationsForProfile(o, classVariable()));
254263

@@ -266,10 +275,17 @@ export function VerticalProfilePlot({
266275
const firePlumes = () =>
267276
flatExperiments().map((e, i) => {
268277
const { config, output, ...formatting } = e;
269-
if (config.sw_fire) {
278+
if (config.sw_fire && isPlumeVariable(classVariable())) {
279+
const plume = transposePlumeData(
280+
calculatePlume(config, profileData()[i].data),
281+
);
270282
return {
271283
...formatting,
272-
data: calculatePlume(config, profileData()[i].data),
284+
linestyle: "4",
285+
data: plume.z.map((z, i) => ({
286+
x: plume[classVariable() as PlumeVariable][i],
287+
y: z,
288+
})),
273289
};
274290
}
275291
return { ...formatting, data: [] };
@@ -288,10 +304,12 @@ export function VerticalProfilePlot({
288304
})) as ChartData<Point>[];
289305

290306
const allX = () => [
307+
...firePlumes().flatMap((p) => p.data.map((d) => d.x)),
291308
...profileDataForPlot().flatMap((p) => p.data.map((d) => d.x)),
292309
...observations().flatMap((obs) => obs.data.map((d) => d.x)),
293310
];
294311
const allY = () => [
312+
...firePlumes().flatMap((p) => p.data.map((d) => d.y)),
295313
...profileDataForPlot().flatMap((p) => p.data.map((d) => d.y)),
296314
...observations().flatMap((obs) => obs.data.map((d) => d.y)),
297315
];
@@ -322,10 +340,6 @@ export function VerticalProfilePlot({
322340
setResetPlot(analysis.id);
323341
}
324342

325-
const showPlume = createMemo(() => {
326-
return ["theta", "qt", "thetav", "T", "Td"].includes(classVariable());
327-
});
328-
329343
return (
330344
<>
331345
<div class="flex flex-col gap-2">
@@ -356,10 +370,7 @@ export function VerticalProfilePlot({
356370
{(d) => (
357371
<Show when={toggles[d.label]}>
358372
<Show when={showPlume()}>
359-
<Plume
360-
d={d}
361-
variable={classVariable as () => keyof Parcel}
362-
/>
373+
<Line {...d} />
363374
</Show>
364375
</Show>
365376
)}
Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { Parcel } from "@classmodel/class/fire";
21
import * as d3 from "d3";
32
import { createSignal } from "solid-js";
43
import type { ChartData } from "./ChartContainer";
@@ -36,34 +35,3 @@ export function Line(d: ChartData<Point>) {
3635
</path>
3736
);
3837
}
39-
40-
export function Plume({
41-
d,
42-
variable,
43-
}: { d: ChartData<Parcel>; variable: () => keyof Parcel }) {
44-
const [chart, _updateChart] = useChartContext();
45-
const [hovered, setHovered] = createSignal(false);
46-
47-
const l = d3.line<Parcel>(
48-
(d) => chart.scaleX(d[variable()]),
49-
(d) => chart.scaleY(d.z),
50-
);
51-
52-
const stroke = () => (hovered() ? highlight("#ff0000") : "#ff0000");
53-
54-
return (
55-
<path
56-
clip-path="url(#clipper)"
57-
onMouseEnter={() => setHovered(true)}
58-
onMouseLeave={() => setHovered(false)}
59-
fill="none"
60-
stroke={stroke()}
61-
stroke-dasharray={"4"}
62-
stroke-width="2"
63-
d={l(d.data) || ""}
64-
class="cursor-pointer"
65-
>
66-
<title>{`Fire plume for ${d.label}`}</title>
67-
</path>
68-
);
69-
}

packages/class/src/config.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,15 +408,15 @@ const untypedSchema = {
408408
symbol: "L<sub>fire</sub>",
409409
type: "number",
410410
unit: "m",
411-
default: 10000,
411+
default: 1000,
412412
title: "Length of the fire",
413413
"ui:group": "Fire",
414414
},
415415
d: {
416416
symbol: "d<sub>fire</sub>",
417417
type: "number",
418418
unit: "m",
419-
default: 300,
419+
default: 10,
420420
title: "Depth of the fire",
421421
"ui:group": "Fire",
422422
},
@@ -432,16 +432,24 @@ const untypedSchema = {
432432
symbol: "C<sub>fire</sub>",
433433
type: "number",
434434
unit: "J kg⁻¹",
435-
default: 17.781e6,
435+
default: 18.6208e6,
436436
title: "Heat stored in fuel",
437437
"ui:group": "Fire",
438438
},
439+
Cq: {
440+
symbol: "C<sub>q,fire</sub>",
441+
type: "number",
442+
unit: "kg kg⁻¹",
443+
default: 0,
444+
title: "Moisture per kg fuel released into plume",
445+
"ui:group": "Fire",
446+
},
439447
omega: {
440448
symbol: "ω<sub>fire</sub>",
441449
type: "number",
442450
unit: "kg m⁻²",
443-
default: 7.6,
444-
title: "Fuel mass per area",
451+
default: 0.1,
452+
title: "Consumed fuel mass per area",
445453
"ui:group": "Fire",
446454
},
447455
spread: {
@@ -458,7 +466,7 @@ const untypedSchema = {
458466
unit: "-",
459467
default: 0.7,
460468
title:
461-
"Fraction of F converted into radiative heating, and not into diffused into the atmosphere",
469+
"Fraction of F converted into radiative heating, and not diffused into the atmosphere",
462470
"ui:group": "Fire",
463471
},
464472
},
@@ -522,6 +530,7 @@ export type FireConfig = {
522530
d: number;
523531
h0: number;
524532
C: number;
533+
Cq: number;
525534
omega: number;
526535
spread: number;
527536
radiativeLoss: number;

0 commit comments

Comments
 (0)