import { useEffect, useMemo, useState } from "react"; import { FD_METHOD, buildPlanBundle, buildRunBundle, parseFdPlan, parsePlateResult, withEdits, } from "@plate-lab/core"; import { CflSlider, CodeView, FieldView, FramePlayer, LinePlot, RunStatus, useFramePlayer, useSolve } from "@plate-lab/components"; import { tutorialSpec } from "./tutorialSpec"; /** * Turn the time step past the stability limit and watch the scheme blow up. * The FD source is shown and editable; the run uses the edited text. */ export function CflExperiment() { const [cfl, setCfl] = useState(0.9); const [edits, setEdits] = useState>({}); const [showCode, setShowCode] = useState(false); const spec = useMemo(() => { const s = tutorialSpec(); s.fd.cfl = cfl; return s; }, [cfl]); const bundle = useMemo(() => withEdits(buildRunBundle(spec, FD_METHOD), edits), [spec, edits]); const solve = useSolve(parsePlateResult); const plan = useSolve(parseFdPlan); useEffect(() => { const pb = buildPlanBundle(spec, FD_METHOD); if (pb) void plan.run({ bundle: pb }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [spec.fd.cfl]); const result = solve.last; const nf = result?.frames.t.length ?? 0; const player = useFramePlayer(nf, 12, true); const absW = useMemo(() => (result ? Float64Array.from(result.probe.w, (v) => Math.abs(v)) : null), [result]); return (
Experiment: the time step against the stability limit
{plan.last && ( {plan.last.nx} × {plan.last.ny} grid, {plan.last.nsteps} steps )}
{showCode && ( )} {result && (
{result.info.stable ? "Stable: the amplitude stays bounded and decays through the damping terms." : "Unstable: the shortest wave the grid can hold is amplified by a fixed factor every step, so |w| grows exponentially until the run stops itself."}
)}
Run details
); }