fix(reactor): X_A_init default 0.001 → 200; add timeStep-unit regression test

Two fixes for the reactor unit-confusion drift surfaced in the 2026-05-19
wiki uplift:

1. X_A_init default in reactor.html was 0.001 g COD/m³, which is
   effectively zero nitrifying biomass — the reactor cannot nitrify
   ammonia under that initial condition (per the project memory note,
   ~50 mg/L is the minimum). Aligned to the schema default of 200 in
   generalFunctions/src/configs/reactor.json. Same change in
   test/helpers/factories.js so the test factory mirrors the operational
   default; tests that need low-biomass scenarios already override.

2. New test/basic/timestep-units.basic.test.js locks in the
   `config.timeStep is interpreted as seconds` contract — verifies the
   engine's days-stored / seconds-input invariant and asserts the
   schema declares `unit: "s"`, `default: 1`. Companion to the schema
   fix in the generalFunctions submodule.

Full test suite: 49/49 pass (was 46/46 + 3 new).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
znetsixe
2026-05-19 13:01:10 +02:00
parent 6b8ae5cfc3
commit 346a3ce2ab
3 changed files with 46 additions and 2 deletions

View File

@@ -0,0 +1,44 @@
'use strict';
// Locks in the contract that `config.timeStep` is interpreted as SECONDS by
// the reactor kinetics engine. Before 2026-05-19 the schema labelled the field
// `unit: "h"` while reactor.html labelled it `[s]` and baseEngine divided by
// 86400 (seconds-per-day) to convert to internal days. A 0.001 schema default
// — read as hours — would have produced a 3.6 s step; read as seconds it is a
// 1 ms step. The fix aligned the schema to seconds. This test prevents the
// drift from reappearing.
const test = require('node:test');
const assert = require('node:assert/strict');
const { Reactor_CSTR } = require('../../src/specificClass');
const { makeReactorConfig } = require('../helpers/factories');
const SECONDS_PER_DAY = 24 * 60 * 60;
function makeEngine(timeStepSeconds) {
return new Reactor_CSTR(makeReactorConfig({ reactor_type: 'CSTR', n_inlets: 1, timeStep: timeStepSeconds }));
}
test('engine stores timeStep in days, treating input as seconds', () => {
const eng = makeEngine(1);
assert.ok(Math.abs(eng.timeStep - 1 / SECONDS_PER_DAY) < 1e-15,
`engine.timeStep should be 1/86400 days for a 1-second config; got ${eng.timeStep}`);
});
test('engine timeStep scales linearly with config.timeStep (seconds in)', () => {
const a = makeEngine(1);
const b = makeEngine(10);
assert.ok(Math.abs(b.timeStep - 10 * a.timeStep) < 1e-15,
'engine.timeStep must scale linearly with config.timeStep; broke the seconds→days conversion');
});
test('schema default for timeStep matches the seconds convention', () => {
const path = require('node:path');
const gfRoot = path.dirname(require.resolve('generalFunctions'));
const schema = require(path.join(gfRoot, 'src/configs/reactor.json'));
assert.equal(schema.reactor.timeStep.rules.unit, 's',
'schema timeStep.unit must be "s" — engine treats input as seconds');
assert.equal(schema.reactor.timeStep.default, 1,
'schema timeStep.default must be 1 (1 second), matching reactor.html');
});

View File

@@ -21,7 +21,7 @@ function makeUiConfig(overrides = {}) {
X_S_init: 75,
X_H_init: 30,
X_STO_init: 0,
X_A_init: 0.001,
X_A_init: 200,
X_TS_init: 125,
timeStep: 1,
enableLog: false,