Trim About, result files only from the CLI, copyable per-instance run command
3 changed files+62−85
src/app/pages/AboutPage.tsxmodified+20−26View file
@@ -11,18 +11,16 @@ export function AboutPage() {
1111 </p>
1212 <h1>About</h1>
1313 <p>
14- A limitation of most solver comparisons is that they fix a
15- discretization, which quietly decides much of the outcome. Here each{" "}
16- <strong>problem</strong> is posed in the continuum, with an exact or
17- highly accurate reference solution; a solver chooses its own
18- discretization and is scored at problem-specified evaluation points.
19- Each problem defines its own interface and a short list of official{" "}
20- <strong>instances</strong> (parameter combinations) in a written
21- specification, so every solver is compared on identical inputs.
22- Solvers are MATLAB function files run by{" "}
23- <a href="https://numbl.org">numbl</a> (MATLAB syntax in the browser
24- and in node), so everything on this site runs client side, and the
25- identical harness runs from the command line.
14+ fastandaccurate benchmarks PDE solvers on speed and accuracy
15+ together. Each <strong>problem</strong> is posed in the continuum,
16+ with an exact or highly accurate reference solution; a solver chooses
17+ its own discretization and is scored at problem-specified evaluation
18+ points. A problem defines its own solver interface and a short list
19+ of official <strong>instances</strong> (parameter combinations) in a
20+ written specification, so every solver is compared on identical
21+ inputs. The solvers on this site are MATLAB function files run by{" "}
22+ <a href="https://numbl.org">numbl</a>, client side; the identical
23+ harness runs from the command line.
2624 </p>
2725
2826 <h2>Measurement</h2>
@@ -33,26 +31,22 @@ export function AboutPage() {
3331 points defined per instance, relative to the reference solution.
3432 Timing is one untimed warmup run (which absorbs JIT compilation),
3533 then the median of repeated timed runs; a run includes the solver's
36- own discretization, assembly, solve, and evaluation. There is
37- deliberately no single ranking: which curve is best can differ by
38- accuracy regime, instance, and machine, and the site presents the
39- curves rather than a verdict. Times from different machines are not
40- comparable; every result records its environment, and the charts
41- label curves by machine.
34+ own discretization, assembly, solve, and evaluation.
4235 </p>
4336
4437 <h2>Results and provenance</h2>
4538 <p>
4639 Results are JSON files in{" "}
4740 <a href={RESULTS_REPO_URL}>fastandaccurate-results</a>, added by pull
48- request; the site reads that repository statically, so there is no
49- database and no server. Every result carries its provenance: the
50- instance spec and its hash, solver id and version, timing protocol,
51- runtime, numbl version, and machine. Results produced by in-browser
52- solvers can be rerun by any visitor on their own machine, directly on
53- the problem page. Results from solvers outside the repository (and,
54- in the future, from other languages and hardware) enter the same way
55- and are marked as not reproducible in the browser.
41+ request; the site reads that repository statically. Every result
42+ carries its provenance: the instance spec and its hash, solver id and
43+ version, timing protocol, runtime, numbl version, and machine.
44+ Result files are produced by the command line; solvers included on
45+ the site can also be rerun in the browser, directly on the problem
46+ page, to compare against the committed curves. Results from solvers
47+ outside the repository (and, in the future, from other languages and
48+ hardware) enter the same way and are marked as not reproducible in
49+ the browser.
5650 </p>
5751
5852 <h2>Running outside the browser</h2>
src/app/pages/HomePage.tsxmodified+3−3View file
@@ -9,9 +9,9 @@ export function HomePage() {
99 Each problem is posed in the continuum with an exact or highly
1010 accurate reference solution; a solver chooses its own discretization
1111 and is compared by <em>work-precision curves</em>, error against
12- compute time. Results can be reproduced in the browser and submitted
13- by pull request. See <a href="#/about">About</a> for how measurement
14- and submission work.
12+ compute time. Results are submitted by pull request, and solvers
13+ included on the site can be rerun in the browser for comparison. See{" "}
14+ <a href="#/about">About</a> for how measurement and submission work.
1515 </p>
1616
1717 <h2>Problems</h2>
src/app/pages/ProblemPage.tsxmodified+39−56View file
@@ -4,12 +4,8 @@ import {
44 getInstance,
55 PROBLEM_ID,
66 } from "../../problems/laplace2d/spec";
7-import { SOLVERS, getSolver } from "../../solvers";
8-import {
9- buildResultFile,
10- type ResultFile,
11- type ResultPoint,
12-} from "../../harness/resultSchema";
7+import { SOLVERS } from "../../solvers";
8+import type { ResultFile, ResultPoint } from "../../harness/resultSchema";
139 import {
1410 environmentLabel,
1511 fetchCommittedResults,
@@ -48,9 +44,15 @@ export function ProblemPage({ problemId }: { problemId: string }) {
4844 const [running, setRunning] = useState<string | null>(null);
4945 const [runStatus, setRunStatus] = useState<string | null>(null);
5046 const [repeats, setRepeats] = useState(3);
51- const [machineLabel, setMachineLabel] = useState("");
47+ const [copied, setCopied] = useState(false);
5248
5349 const inst = getInstance(instanceId);
50+ const visibleSolverList = SOLVERS.filter((s) => !hidden.has(s.id));
51+ const cliCommand =
52+ `npx https://concept-collection.github.io/fastandaccurate/cli.tgz?v=${__BUILD_ID__} ` +
53+ `run --instance ${instanceId}` +
54+ (visibleSolverList.length === 1 ? ` --solver ${visibleSolverList[0].id}` : "") +
55+ ` --label "my machine"`;
5456
5557 useEffect(() => {
5658 fetchCommittedResults()
@@ -147,36 +149,6 @@ export function ProblemPage({ problemId }: { problemId: string }) {
147149 }
148150 }
149151
150- async function downloadRun(run: LocalRun) {
151- const manifest = getSolver(run.solverId);
152- const result = await buildResultFile({
153- instance: getInstance(run.instanceId),
154- solver: {
155- id: manifest.id,
156- version: manifest.version,
157- backend: manifest.backend,
158- source: "builtin",
159- },
160- environment: {
161- kind: "browser",
162- runtime: navigator.userAgent,
163- numblVersion: __NUMBL_VERSION__,
164- machineLabel: machineLabel || undefined,
165- browserReproducible: true,
166- },
167- repeats: run.repeats,
168- points: run.points,
169- });
170- const blob = new Blob([JSON.stringify(result, null, 2) + "\n"], {
171- type: "application/json",
172- });
173- const a = document.createElement("a");
174- a.href = URL.createObjectURL(blob);
175- a.download = `${PROBLEM_ID}.${run.instanceId}.${run.solverId}.browser.json`;
176- a.click();
177- URL.revokeObjectURL(a.href);
178- }
179-
180152 function loadFiles(files: FileList | null) {
181153 if (!files) return;
182154 for (const file of Array.from(files)) {
@@ -325,23 +297,34 @@ export function ProblemPage({ problemId }: { problemId: string }) {
325297 </label>
326298 </div>
327299 {runStatus && <p className="small muted">{runStatus}</p>}
300+ <h3>Run this on your machine</h3>
301+ <p className="small muted" style={{ maxWidth: 640 }}>
302+ Browser runs are for comparison only; result files are produced
303+ outside the browser. This command runs the{" "}
304+ {visibleSolverList.length === 1
305+ ? `${visibleSolverList[0].id} sweep`
306+ : "same sweeps"}{" "}
307+ on the <code>{instanceId}</code> instance (node 20 or newer) and
308+ writes result JSON files, which can be loaded below to see them on
309+ this chart, and submitted by pull request (see{" "}
310+ <a href="#/about">About</a>).
311+ </p>
312+ <div className="row" style={{ alignItems: "flex-start", gap: 10 }}>
313+ <pre style={{ margin: 0, flex: "1 1 420px", overflowX: "auto" }}>
314+ {cliCommand}
315+ </pre>
316+ <button
317+ onClick={() => {
318+ navigator.clipboard.writeText(cliCommand).then(() => {
319+ setCopied(true);
320+ setTimeout(() => setCopied(false), 1500);
321+ });
322+ }}
323+ >
324+ {copied ? "copied" : "Copy"}
325+ </button>
326+ </div>
328327 <div className="row" style={{ marginTop: 10, alignItems: "center" }}>
329- <label className="small">
330- machine label{" "}
331- <input
332- type="text"
333- placeholder="e.g. office workstation"
334- value={machineLabel}
335- onChange={(e) => setMachineLabel(e.target.value)}
336- />
337- </label>
338- {localRuns
339- .filter((r) => r.done && r.instanceId === instanceId)
340- .map((r) => (
341- <button key={r.key} onClick={() => downloadRun(r)}>
342- Download {r.solverId} result JSON
343- </button>
344- ))}
345328 <label className="small">
346329 load result file{" "}
347330 <input
@@ -363,9 +346,9 @@ export function ProblemPage({ problemId }: { problemId: string }) {
363346 <SolutionSection inst={inst} />
364347
365348 <p className="small muted" style={{ marginTop: "2.2rem" }}>
366- The same sweeps run outside the browser with the command line, and
367- both browser and command-line results are submitted by pull request
368- to the <a href={RESULTS_REPO_URL}>results repository</a>; see{" "}
349+ Result files are produced with the command line (above) and
350+ submitted by pull request to the{" "}
351+ <a href={RESULTS_REPO_URL}>results repository</a>; see{" "}
369352 <a href="#/about">About</a>.
370353 </p>
371354 </>