mjbuehler's picture
Upload complete research archive under data/ (part 12)
ab4c7e1 verified
Raw History Blame Contribute Delete
2.69 kB
// worker_threads worker: generate + simulate one experiment, write per-run files, return a compact summary
const { parentPort, workerData } = require('worker_threads');
const fs = require('fs'), path = require('path'), os = require('os');
const { loadCore } = require('./load_core.js'); const HFL = loadCore();
function writeFrames(id, res, outDir) {
const fr = res.frames; if (!fr || !fr.length) return null; const N = fr[0].ux.length, E = fr[0].r.length;
const per = 2 * N + 2 * E; const buf = new Float32Array(per * fr.length); const index = [];
fr.forEach((f, k) => { buf.set(f.ux, k * per); buf.set(f.uy, k * per + N); buf.set(f.r, k * per + 2 * N); buf.set(f.Nax, k * per + 2 * N + E); index.push({ d: f.d, F: f.F, nEvents: f.nEvents }); });
fs.writeFileSync(path.join(outDir, id + '_frames.bin'), Buffer.from(buf.buffer));
fs.writeFileSync(path.join(outDir, id + '_frames.json'), JSON.stringify({ nFrames: fr.length, N, E, layout: 'per frame: ux[N], uy[N], r[E], Nax[E] float32 little-endian', frames: index }));
return id + '_frames.bin';
}
parentPort.on('message', (job) => {
const t0 = Date.now();
try {
const g = HFL.generate(job.params);
const res = HFL.simulate(g, { frames: job.saveFrames ? 'both' : 'none', maxFrames: job.maxFrames || 240 });
const b = HFL.exportBundle(res, g);
const rec = {
id: job.id, stage: job.stage, reason: job.reason, hypothesis: job.hypothesis, tags: job.tags || [], date: new Date().toISOString(), appVersion: HFL.VERSION,
params: res.params, seed: res.params.seed, branchingList: HFL.branchingList(res.params), structureStats: g.stats, W: g.W, H: g.H, t: g.t, N: res.N, E: res.E, status: res.status, mode: res.mode,
metrics: res.metrics, diagnostics: b.summary.diagnostics, curve: res.curve, events: res.events, grid: res.grid, finalActive: Array.from(res.finalActive), geometry: b.geometry,
runtimeMs: Date.now() - t0, host: os.hostname(), predictions: job.predictions || null,
};
if (job.saveFrames) rec.framesFile = writeFrames(job.id, res, job.outDir);
fs.writeFileSync(path.join(job.outDir, job.id + '.json'), JSON.stringify(rec));
const m = res.metrics;
parentPort.postMessage({ ok: true, id: job.id, summary: { id: job.id, stage: job.stage, status: res.status, converged: m.converged, N: res.N, E: res.E, events: m.nEvents, k0: m.k0, Fpeak: m.Fpeak, Wf: m.workToFailure, loc: m.localization, drop: m.maxLoadDropNorm, ppw: m.postPeakWorkFraction, mode: m.fractureMode, resid: res.diagnostics.maxResidual, ms: Date.now() - t0 } });
} catch (e) { parentPort.postMessage({ ok: false, id: job.id, error: String(e && e.stack || e), ms: Date.now() - t0 }); }
});