From 05d33b7f39db40a7e595faa56edc1141948b2d28 Mon Sep 17 00:00:00 2001 From: "p.vanderwilt" Date: Fri, 13 Jun 2025 12:56:30 +0200 Subject: [PATCH 1/3] Add fluid volume and initial component inputs to advanced-reactor node edit dialogue --- advanced-reactor.html | 85 +++++++++++++++++++++++++++++++++++ advanced-reactor.js | 19 +++++++- dependencies/reactor_class.js | 4 +- 3 files changed, 105 insertions(+), 3 deletions(-) diff --git a/advanced-reactor.html b/advanced-reactor.html index f6bedc9..d63f531 100644 --- a/advanced-reactor.html +++ b/advanced-reactor.html @@ -4,12 +4,38 @@ color: '#c4cce0', defaults: { name: { value: "" }, + volume: { value: 0., required: true}, + S_O_init: { value: 0., required: true }, + S_I_init: { value: 30., required: true }, + S_S_init: { value: 100., required: true }, + S_NH_init: { value: 16., required: true }, + S_N2_init: { value: 0., required: true }, + S_NO_init: { value: 0., required: true }, + S_HCO_init: { value: 5., required: true }, + X_I_init: { value: 25., required: true }, + X_S_init: { value: 75., required: true }, + X_H_init: { value: 30., required: true }, + X_STO_init: { value: 0., required: true }, + X_A_init: { value: 0.001, required: true }, + X_TS_init: { value: 125., required: true } }, inputs: 1, outputs: 1, icon: "font-awesome/fa-recycle", label: function() { return this.name||"advanced-reactor"; + }, + oneditprepare: function() { + $(".typed-num").typedInput({ + type:"num", + types:["num"] + }); + }, + oneditsave: function() { + let volume = parseFloat($("#node-input-volume").typedInput("value")); + if (isNaN(volume) || volume <= 0) { + RED.notify("Fluid volume not set correctly", {type: "error"}); + } } }); @@ -19,6 +45,65 @@ +

Reactor properties

+
+ + +
+

Dissolved components

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+

Particulate components

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
diff --git a/advanced-reactor.js b/advanced-reactor.js index 20d6081..bd364c8 100644 --- a/advanced-reactor.js +++ b/advanced-reactor.js @@ -10,25 +10,35 @@ module.exports = function(RED) { const reactor = new Reactor( config.volume, [ - config.S_O_init, - config.S_I_init, - config.S_S_init, - config.S_NH_init, - config.S_N2_init, - config.S_NO_init, - config.S_HCO_init, - config.X_I_init, - config.X_S_init, - config.X_H_init, - config.X_STO_init, - config.X_A_init, - config.X_TS_init + parseFloat(config.S_O_init), + parseFloat(config.S_I_init), + parseFloat(config.S_S_init), + parseFloat(config.S_NH_init), + parseFloat(config.S_N2_init), + parseFloat(config.S_NO_init), + parseFloat(config.S_HCO_init), + parseFloat(config.X_I_init), + parseFloat(config.X_S_init), + parseFloat(config.X_H_init), + parseFloat(config.X_STO_init), + parseFloat(config.X_A_init), + parseFloat(config.X_TS_init) ] ); node.on('input', function(msg, send, done) { - if (msg.topic == "clock") { - reactor.updateState(msg); + switch (msg.topic) { + case "clock": + reactor.updateState(msg); + break; + case "Influx": + reactor.setInflux = msg; + break; + case "OTR": + reactor.setOTR = msg; + break; + default: + console.log("Unknown topic: " + msg.topic) } if (done) { diff --git a/dependencies/reactor_class.js b/dependencies/reactor_class.js index 80aa3b6..a50ca23 100644 --- a/dependencies/reactor_class.js +++ b/dependencies/reactor_class.js @@ -9,14 +9,23 @@ class Reactor_CSTR { this.asm = new ASM3(); this.Vl = volume; // fluid volume reactor [m3] - this.F = 1.0; // fluid debit [m3 d-1] - this.C_in = [0., 30., 100., 16., 0., 0., 5., 25., 75., 30., 0., 0., 125.]; // composition influent - this.OTR = 100.0; // oxygen transfer rate [g O2 d-1] + this.F = 0.0; // fluid debit [m3 d-1] + this.C_in = Array(13).fill(0.0); // composition influent + this.OTR = 0.0; // oxygen transfer rate [g O2 d-1] this.currentTime = Date.now(); // milliseconds since epoch [ms] this.timeStep = 1/(24*60*15) // time step [d] } + set setInflux(input) { // setter for C_in (WIP) + this.F = input.payload.F; + this.C_in = input.payload.C_in; + } + + set setOTR(input) { // setter for OTR (WIP) [g O2 d-1] + this.OTR = input.payload; + } + // expect update with timestamp updateState(input) { let newTime = input.payload; From 5b7f7a3cef78960a0d2462df03f8ded0491f906b Mon Sep 17 00:00:00 2001 From: "p.vanderwilt" Date: Fri, 13 Jun 2025 15:31:31 +0200 Subject: [PATCH 3/3] Add effluent output handling --- advanced-reactor.html | 1 + advanced-reactor.js | 9 +++++++-- dependencies/reactor_class.js | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/advanced-reactor.html b/advanced-reactor.html index d63f71b..a18e6a3 100644 --- a/advanced-reactor.html +++ b/advanced-reactor.html @@ -21,6 +21,7 @@ }, inputs: 1, outputs: 1, + outputLabels: "Effluent", icon: "font-awesome/fa-recycle", label: function() { return this.name || "advanced-reactor"; diff --git a/advanced-reactor.js b/advanced-reactor.js index bd364c8..0a0bbcd 100644 --- a/advanced-reactor.js +++ b/advanced-reactor.js @@ -31,16 +31,21 @@ module.exports = function(RED) { case "clock": reactor.updateState(msg); break; - case "Influx": + case "Influent": + reactor.setInflux = msg; + break; + case "Effluent": reactor.setInflux = msg; break; case "OTR": reactor.setOTR = msg; break; default: - console.log("Unknown topic: " + msg.topic) + console.log("Unknown topic: " + msg.topic); } + send(reactor.getEffluent); + if (done) { done(); } diff --git a/dependencies/reactor_class.js b/dependencies/reactor_class.js index a50ca23..29a3111 100644 --- a/dependencies/reactor_class.js +++ b/dependencies/reactor_class.js @@ -26,6 +26,10 @@ class Reactor_CSTR { this.OTR = input.payload; } + get getEffluent() { + return {topic: "Effluent", payload: {F: this.F, C_in:this.state}}; + } + // expect update with timestamp updateState(input) { let newTime = input.payload;