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;