From 3a820df7f2ef37499347fdca842acec40c5ec765 Mon Sep 17 00:00:00 2001
From: HorriblePerson555 <47578455+HorriblePerson555@users.noreply.github.com>
Date: Mon, 20 Oct 2025 16:45:53 +0200
Subject: [PATCH 1/8] Non-functioning prototype with partial rotating machine
integration
---
src/specificClass.js | 34 +++++++++++++++++++++++++++-------
1 file changed, 27 insertions(+), 7 deletions(-)
diff --git a/src/specificClass.js b/src/specificClass.js
index bd5af1b..ebd08bf 100644
--- a/src/specificClass.js
+++ b/src/specificClass.js
@@ -32,6 +32,7 @@ class Reactor {
this.upstreamReactor = null;
this.downstreamReactor = null;
+ this.returnPump = null;
this.asm = new ASM3();
@@ -72,10 +73,14 @@ class Reactor {
* @returns {object} Effluent data object (msg), defaults to inlet 0.
*/
get getEffluent() { // getter for Effluent, defaults to inlet 0
- if (isArray(this.state.at(-1))) {
- return { topic: "Fluent", payload: { inlet: 0, F: math.sum(this.Fs), C: this.state.at(-1) }, timestamp: this.currentTime };
+ const Cs = isArray(this.state.at(-1)) ? this.state.at(-1) : this.state;
+ const effluent = [{ topic: "Fluent", payload: { inlet: 0, F: math.sum(this.Fs), C: Cs }, timestamp: this.currentTime }];
+ if (this.returnPump) {
+ const recirculationFlow = this.returnPump.measurements.type("flow").variant("measured").position("atEquipement").getValue();
+ effluent[0].F -= recirculationFlow;
+ effluent.push({ topic: "Fluent", payload: { inlet: 1, F: recirculationFlow, C: Cs }, timestamp: this.currentTime });
}
- return { topic: "Fluent", payload: { inlet: 0, F: math.sum(this.Fs), C: this.state }, timestamp: this.currentTime };
+ return effluent;
}
/**
@@ -105,13 +110,17 @@ class Reactor {
registerChild(child, softwareType) {
switch (softwareType) {
case "measurement":
- this.logger.debug(`Registering measurement child.`);
+ this.logger.debug(`Registering measurement child...`);
this._connectMeasurement(child);
break;
case "reactor":
- this.logger.debug(`Registering reactor child.`);
+ this.logger.debug(`Registering reactor child...`);
this._connectReactor(child);
break;
+ case "machine":
+ this.logger.debug(`Registering rotating machine child...`);
+ this._connectRotatingMachine(child);
+ break;
default:
this.logger.error(`Unrecognized softwareType: ${softwareType}`);
@@ -150,7 +159,7 @@ class Reactor {
return;
}
- if (reactorChild.functionality.positionVsParent != "upstream") {
+ if (reactorChild.config.functionality.positionVsParent != "upstream") {
this.logger.warn("Reactor children of reactors should always be upstream.");
}
@@ -158,6 +167,7 @@ class Reactor {
this.logger.warn("Significant grid sizing discrepancies between adjacent reactors! Change resolutions to match reactors grid step, or implement boundary value interpolation.");
}
+ // set upstream and downstream reactor variable in current and child nodes respectively for easy access
this.upstreamReactor = reactorChild;
reactorChild.downstreamReactor = this;
@@ -167,6 +177,16 @@ class Reactor {
});
}
+ _connectRotatingMachine(rotatingMachineChild) {
+ if (!rotatingMachineChild) {
+ this.logger.warn("Invalid rotating machine provided.");
+ return;
+ }
+
+ if (rotatingMachineChild.config.functionality.positionVsParent == "downstream") {
+ this.returnPump = rotatingMachineChild;
+ }
+ }
_updateMeasurement(measurementType, value, position, context) {
this.logger.debug(`---------------------- updating ${measurementType} ------------------ `);
@@ -190,7 +210,7 @@ class Reactor {
const day2ms = 1000 * 60 * 60 * 24;
if (this.upstreamReactor) {
- this.setInfluent = this.upstreamReactor.getEffluent;
+ this.setInfluent = this.upstreamReactor.getEffluent[0]; // grab main effluent upstream reactor
}
let n_iter = Math.floor(this.speedUpFactor * (newTime-this.currentTime) / (this.timeStep*day2ms));
--
2.49.1
From 018215934eee871f64a765da311812f6cdd8f21c Mon Sep 17 00:00:00 2001
From: HorriblePerson555 <47578455+HorriblePerson555@users.noreply.github.com>
Date: Mon, 20 Oct 2025 17:37:29 +0200
Subject: [PATCH 2/8] Fix recirculation flow measurement to use getCurrentValue
and handle undefined values
---
src/specificClass.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/specificClass.js b/src/specificClass.js
index ebd08bf..44f41af 100644
--- a/src/specificClass.js
+++ b/src/specificClass.js
@@ -76,8 +76,8 @@ class Reactor {
const Cs = isArray(this.state.at(-1)) ? this.state.at(-1) : this.state;
const effluent = [{ topic: "Fluent", payload: { inlet: 0, F: math.sum(this.Fs), C: Cs }, timestamp: this.currentTime }];
if (this.returnPump) {
- const recirculationFlow = this.returnPump.measurements.type("flow").variant("measured").position("atEquipement").getValue();
- effluent[0].F -= recirculationFlow;
+ const recirculationFlow = this.returnPump.measurements.type("flow").variant("measured").position("atEquipement").getCurrentValue();
+ effluent[0].F -= recirculationFlow || 0;
effluent.push({ topic: "Fluent", payload: { inlet: 1, F: recirculationFlow, C: Cs }, timestamp: this.currentTime });
}
return effluent;
--
2.49.1
From 7b38c2f51a0e1eb2fb00e6657129357292776a31 Mon Sep 17 00:00:00 2001
From: HorriblePerson555 <47578455+HorriblePerson555@users.noreply.github.com>
Date: Tue, 21 Oct 2025 12:32:21 +0200
Subject: [PATCH 3/8] Refactor recirculation flow calculation to ensure
non-negative flow rates and correct measurement position
---
src/specificClass.js | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/specificClass.js b/src/specificClass.js
index 44f41af..3f62914 100644
--- a/src/specificClass.js
+++ b/src/specificClass.js
@@ -76,9 +76,11 @@ class Reactor {
const Cs = isArray(this.state.at(-1)) ? this.state.at(-1) : this.state;
const effluent = [{ topic: "Fluent", payload: { inlet: 0, F: math.sum(this.Fs), C: Cs }, timestamp: this.currentTime }];
if (this.returnPump) {
- const recirculationFlow = this.returnPump.measurements.type("flow").variant("measured").position("atEquipement").getCurrentValue();
- effluent[0].F -= recirculationFlow || 0;
- effluent.push({ topic: "Fluent", payload: { inlet: 1, F: recirculationFlow, C: Cs }, timestamp: this.currentTime });
+ const recirculationFlow = this.returnPump.measurements.type("flow").variant("measured").position("atequipment").getCurrentValue();
+ const F_main = Math.max(effluent[0].payload.F - recirculationFlow, 0);
+ const F_side_constrained = effluent[0].payload.F < recirculationFlow ? effluent[0].payload.F : recirculationFlow;
+ effluent[0].payload.F = F_main;
+ effluent.push({ topic: "Fluent", payload: { inlet: 1, F: F_side_constrained, C: Cs }, timestamp: this.currentTime });
}
return effluent;
}
--
2.49.1
From 6de4f9ec3e3eae0d1926adad6e4629fdc765e54b Mon Sep 17 00:00:00 2001
From: HorriblePerson555 <47578455+HorriblePerson555@users.noreply.github.com>
Date: Tue, 21 Oct 2025 13:02:41 +0200
Subject: [PATCH 4/8] Fix recirculation flow calculation to prevent negative
flow rates and improve variable naming
---
src/specificClass.js | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/specificClass.js b/src/specificClass.js
index 3f62914..75edd08 100644
--- a/src/specificClass.js
+++ b/src/specificClass.js
@@ -76,11 +76,12 @@ class Reactor {
const Cs = isArray(this.state.at(-1)) ? this.state.at(-1) : this.state;
const effluent = [{ topic: "Fluent", payload: { inlet: 0, F: math.sum(this.Fs), C: Cs }, timestamp: this.currentTime }];
if (this.returnPump) {
- const recirculationFlow = this.returnPump.measurements.type("flow").variant("measured").position("atequipment").getCurrentValue();
+ const recirculationFlow = this.returnPump.measurements.type("flow").variant("measured").position("atEquipment").getCurrentValue();
+ // constrain flow to prevent negatives
const F_main = Math.max(effluent[0].payload.F - recirculationFlow, 0);
- const F_side_constrained = effluent[0].payload.F < recirculationFlow ? effluent[0].payload.F : recirculationFlow;
+ const F_sidestream = effluent[0].payload.F < recirculationFlow ? effluent[0].payload.F : recirculationFlow;
effluent[0].payload.F = F_main;
- effluent.push({ topic: "Fluent", payload: { inlet: 1, F: F_side_constrained, C: Cs }, timestamp: this.currentTime });
+ effluent.push({ topic: "Fluent", payload: { inlet: 1, F: F_sidestream, C: Cs }, timestamp: this.currentTime });
}
return effluent;
}
--
2.49.1
From eb787ec47f96cdfa967b570c60e32bb0e4232dda Mon Sep 17 00:00:00 2001
From: "p.vanderwilt"
Date: Wed, 22 Oct 2025 14:40:56 +0200
Subject: [PATCH 5/8] Minor bug fix and change in report level when
encountering invalid children
---
src/specificClass.js | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/specificClass.js b/src/specificClass.js
index 75edd08..c53d76d 100644
--- a/src/specificClass.js
+++ b/src/specificClass.js
@@ -132,7 +132,7 @@ class Reactor {
_connectMeasurement(measurementChild) {
if (!measurementChild) {
- this.logger.warn("Invalid measurement provided.");
+ this.logger.error("Invalid measurement provided.");
return;
}
@@ -158,7 +158,7 @@ class Reactor {
_connectReactor(reactorChild) {
if (!reactorChild) {
- this.logger.warn("Invalid reactor provided.");
+ this.logger.error("Invalid reactor provided.");
return;
}
@@ -182,11 +182,12 @@ class Reactor {
_connectRotatingMachine(rotatingMachineChild) {
if (!rotatingMachineChild) {
- this.logger.warn("Invalid rotating machine provided.");
+ this.logger.error("Invalid rotating machine provided.");
return;
}
if (rotatingMachineChild.config.functionality.positionVsParent == "downstream") {
+ rotatingMachineChild.upstreamReactor = this;
this.returnPump = rotatingMachineChild;
}
}
--
2.49.1
From 4680b984181be1a98f38b87ec8e9e88b7ce626f8 Mon Sep 17 00:00:00 2001
From: "p.vanderwilt"
Date: Thu, 23 Oct 2025 17:16:10 +0200
Subject: [PATCH 6/8] minor variable name changes
---
src/specificClass.js | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/specificClass.js b/src/specificClass.js
index c53d76d..ae8025e 100644
--- a/src/specificClass.js
+++ b/src/specificClass.js
@@ -121,8 +121,8 @@ class Reactor {
this._connectReactor(child);
break;
case "machine":
- this.logger.debug(`Registering rotating machine child...`);
- this._connectRotatingMachine(child);
+ this.logger.debug(`Registering machine child...`);
+ this._connectMachine(child);
break;
default:
@@ -174,21 +174,21 @@ class Reactor {
this.upstreamReactor = reactorChild;
reactorChild.downstreamReactor = this;
- reactorChild.emitter.on("stateChange", (data) => {
+ reactorChild.emitter.on("stateChange", (eventData) => {
this.logger.debug(`State change of upstream reactor detected.`);
- this.updateState(data);
+ this.updateState(eventData);
});
}
- _connectRotatingMachine(rotatingMachineChild) {
- if (!rotatingMachineChild) {
+ _connectMachine(machineChild) {
+ if (!machineChild) {
this.logger.error("Invalid rotating machine provided.");
return;
}
- if (rotatingMachineChild.config.functionality.positionVsParent == "downstream") {
- rotatingMachineChild.upstreamReactor = this;
- this.returnPump = rotatingMachineChild;
+ if (machineChild.config.functionality.positionVsParent == "downstream") {
+ machineChild.upstreamReactor = this;
+ this.returnPump = machineChild;
}
}
--
2.49.1
From e6923f2916380785a1b63c46af7c1f8fcd011a4e Mon Sep 17 00:00:00 2001
From: "p.vanderwilt"
Date: Fri, 31 Oct 2025 11:54:28 +0100
Subject: [PATCH 7/8] Refactor child registration and connection methods to
handle invalid inputs and improve readability
---
src/specificClass.js | 28 ++++++++--------------------
1 file changed, 8 insertions(+), 20 deletions(-)
diff --git a/src/specificClass.js b/src/specificClass.js
index ae8025e..1966d56 100644
--- a/src/specificClass.js
+++ b/src/specificClass.js
@@ -14,6 +14,7 @@ const S_O_INDEX = 0;
const NUM_SPECIES = 13;
const BC_PADDING = 2;
const DEBUG = false;
+const DAY2MS = 1000 * 60 * 60 * 24;
class Reactor {
/**
@@ -28,7 +29,6 @@ class Reactor {
this.measurements = new MeasurementContainer();
this.upstreamReactor = null;
this.childRegistrationUtils = new childRegistrationUtils(this); // Child registration utility
- this.parent = []; // Gets assigned via child registration
this.upstreamReactor = null;
this.downstreamReactor = null;
@@ -111,6 +111,11 @@ class Reactor {
}
registerChild(child, softwareType) {
+ if(!child) {
+ this.logger.error(`Invalid ${softwareType} child provided.`);
+ return;
+ }
+
switch (softwareType) {
case "measurement":
this.logger.debug(`Registering measurement child...`);
@@ -131,11 +136,6 @@ class Reactor {
}
_connectMeasurement(measurementChild) {
- if (!measurementChild) {
- this.logger.error("Invalid measurement provided.");
- return;
- }
-
const position = measurementChild.config.functionality.positionVsParent;
const measurementType = measurementChild.config.asset.type;
const eventName = `${measurementType}.measured.${position}`;
@@ -157,11 +157,6 @@ class Reactor {
_connectReactor(reactorChild) {
- if (!reactorChild) {
- this.logger.error("Invalid reactor provided.");
- return;
- }
-
if (reactorChild.config.functionality.positionVsParent != "upstream") {
this.logger.warn("Reactor children of reactors should always be upstream.");
}
@@ -181,11 +176,6 @@ class Reactor {
}
_connectMachine(machineChild) {
- if (!machineChild) {
- this.logger.error("Invalid rotating machine provided.");
- return;
- }
-
if (machineChild.config.functionality.positionVsParent == "downstream") {
machineChild.upstreamReactor = this;
this.returnPump = machineChild;
@@ -211,20 +201,18 @@ class Reactor {
* @param {number} newTime - New time to update reactor state to, in milliseconds since epoch.
*/
updateState(newTime = Date.now()) { // expect update with timestamp
- const day2ms = 1000 * 60 * 60 * 24;
-
if (this.upstreamReactor) {
this.setInfluent = this.upstreamReactor.getEffluent[0]; // grab main effluent upstream reactor
}
- let n_iter = Math.floor(this.speedUpFactor * (newTime-this.currentTime) / (this.timeStep*day2ms));
+ let n_iter = Math.floor(this.speedUpFactor * (newTime-this.currentTime) / (this.timeStep*DAY2MS));
if (n_iter) {
let n = 0;
while (n < n_iter) {
this.tick(this.timeStep);
n += 1;
}
- this.currentTime += n_iter * this.timeStep * day2ms / this.speedUpFactor;
+ this.currentTime += n_iter * this.timeStep * DAY2MS / this.speedUpFactor;
this.emitter.emit("stateChange", this.currentTime);
}
}
--
2.49.1
From 3828e43c12562e14703cbf49e829ab9ad16ce5b1 Mon Sep 17 00:00:00 2001
From: "p.vanderwilt"
Date: Thu, 6 Nov 2025 14:51:06 +0100
Subject: [PATCH 8/8] Refactor reactor node configuration to remove n_inlets
and simplify inlet handling
---
reactor.html | 13 -------------
src/nodeClass.js | 1 -
src/specificClass.js | 20 +++++++++++++-------
3 files changed, 13 insertions(+), 21 deletions(-)
diff --git a/reactor.html b/reactor.html
index 9d1574f..cdca7c7 100644
--- a/reactor.html
+++ b/reactor.html
@@ -11,7 +11,6 @@
length: { value: 0.},
resolution_L: { value: 0.},
alpha: {value: 0},
- n_inlets: { value: 1, required: true},
kla: { value: null },
S_O_init: { value: 0., required: true },
@@ -58,10 +57,6 @@
type:"num",
types:["num"]
});
- $("#node-input-n_inlets").typedInput({
- type:"num",
- types:["num"]
- });
$("#node-input-length").typedInput({
type:"num",
types:["num"]
@@ -128,10 +123,6 @@
if (isNaN(volume) || volume <= 0) {
RED.notify("Fluid volume not set correctly", {type: "error"});
}
- let n_inlets = parseInt($("#node-input-n_inlets").typedInput("value"));
- if (isNaN(n_inlets) || n_inlets < 1) {
- RED.notify("Number of inlets not set correctly", {type: "error"});
- }
}
});
@@ -165,10 +156,6 @@
-
-
-
-
Internal mass transfer calculation (optional)
diff --git a/src/nodeClass.js b/src/nodeClass.js
index a9e53d3..3abe037 100644
--- a/src/nodeClass.js
+++ b/src/nodeClass.js
@@ -88,7 +88,6 @@ class nodeClass {
length: parseFloat(uiConfig.length),
resolution_L: parseInt(uiConfig.resolution_L),
alpha: parseFloat(uiConfig.alpha),
- n_inlets: parseInt(uiConfig.n_inlets),
kla: parseFloat(uiConfig.kla),
initialState: [
parseFloat(uiConfig.S_O_init),
diff --git a/src/specificClass.js b/src/specificClass.js
index 1966d56..18ac54a 100644
--- a/src/specificClass.js
+++ b/src/specificClass.js
@@ -1,5 +1,5 @@
const ASM3 = require('./reaction_modules/asm3_class.js');
-const { create, all, isArray } = require('mathjs');
+const { create, all, isArray, i } = require('mathjs');
const { assertNoNaN } = require('./utils.js');
const { childRegistrationUtils, logger, MeasurementContainer } = require('generalFunctions');
const EventEmitter = require('events');
@@ -38,8 +38,8 @@ class Reactor {
this.volume = config.volume; // fluid volume reactor [m3]
- this.Fs = Array(config.n_inlets).fill(0); // fluid debits per inlet [m3 d-1]
- this.Cs_in = Array.from(Array(config.n_inlets), () => new Array(NUM_SPECIES).fill(0)); // composition influents
+ this.Fs = [0]; // fluid debits per inlet [m3 d-1]
+ this.Cs_in = [Array(NUM_SPECIES).fill(0)]; // composition influents
this.OTR = 0.0; // oxygen transfer rate [g O2 d-1 m-3]
this.temperature = 20; // temperature [C]
@@ -55,9 +55,15 @@ class Reactor {
* @param {object} input - Input object (msg) containing payload with inlet index, flow rate, and concentrations.
*/
set setInfluent(input) {
- let index_in = input.payload.inlet;
- this.Fs[index_in] = input.payload.F;
- this.Cs_in[index_in] = input.payload.C;
+ const i_in = input.payload.inlet;
+ if (this.Fs.length <= i_in) {
+ this.logger.debug(`Adding new inlet index ${i_in}.`);
+ this.Fs.push(0);
+ this.Cs_in.push(Array(NUM_SPECIES).fill(0));
+ this.setInfluent = input;
+ }
+ this.Fs[i_in] = input.payload.F;
+ this.Cs_in[i_in] = input.payload.C;
}
/**
@@ -177,7 +183,7 @@ class Reactor {
_connectMachine(machineChild) {
if (machineChild.config.functionality.positionVsParent == "downstream") {
- machineChild.upstreamReactor = this;
+ machineChild.upstreamSource = this;
this.returnPump = machineChild;
}
}
--
2.49.1