diff --git a/advanced-reactor.html b/advanced-reactor.html index a18e6a3..a1a7ea7 100644 --- a/advanced-reactor.html +++ b/advanced-reactor.html @@ -5,6 +5,7 @@ defaults: { name: { value: "" }, volume: { value: 0., required: true}, + n_inlets: { value: 1, required: true}, S_O_init: { value: 0., required: true }, S_I_init: { value: 30., required: true }, S_S_init: { value: 100., required: true }, @@ -31,6 +32,10 @@ type:"num", types:["num"] }); + $("#node-input-n_inlets").typedInput({ + type:"num", + types:["num"] + }); $(".concentrations").typedInput({ type:"num", types:["num"] @@ -41,6 +46,10 @@ 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"}); + } } }); @@ -55,6 +64,10 @@ +
+ + +

Dissolved components

diff --git a/advanced-reactor.js b/advanced-reactor.js index 0a0bbcd..15369ec 100644 --- a/advanced-reactor.js +++ b/advanced-reactor.js @@ -8,7 +8,8 @@ module.exports = function(RED) { const Reactor = require('./dependencies/reactor_class'); const reactor = new Reactor( - config.volume, + parseFloat(config.volume), + parseInt(config.n_inlets), [ parseFloat(config.S_O_init), parseFloat(config.S_I_init), @@ -29,13 +30,11 @@ module.exports = function(RED) { node.on('input', function(msg, send, done) { switch (msg.topic) { case "clock": - reactor.updateState(msg); + reactor.updateState(msg.timestamp); break; - case "Influent": - reactor.setInflux = msg; - break; - case "Effluent": - reactor.setInflux = msg; + case "Fluent": + reactor.setInfluent = msg; + reactor.updateState(msg.timestamp); break; case "OTR": reactor.setOTR = msg; diff --git a/dependencies/reactor_class.js b/dependencies/reactor_class.js index 29a3111..fd459d2 100644 --- a/dependencies/reactor_class.js +++ b/dependencies/reactor_class.js @@ -3,36 +3,37 @@ const math = require('mathjs') class Reactor_CSTR { - constructor(volume, initial_state) { + constructor(volume, n_inlets, initial_state) { this.state = initial_state; console.log(this.state); this.asm = new ASM3(); this.Vl = volume; // fluid volume reactor [m3] - this.F = 0.0; // fluid debit [m3 d-1] - this.C_in = Array(13).fill(0.0); // composition influent + this.Fs = Array(n_inlets).fill(0.0); // fluid debits per inlet [m3 d-1] + this.Cs_in = Array.from(Array(n_inlets), () => new 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 setInfluent(input) { // setter for C_in (WIP) + let index_in = input.payload.inlet; + this.Fs[index_in] = input.payload.F; + this.Cs_in[index_in] = input.payload.C; } set setOTR(input) { // setter for OTR (WIP) [g O2 d-1] this.OTR = input.payload; } - get getEffluent() { - return {topic: "Effluent", payload: {F: this.F, C_in:this.state}}; + get getEffluent() { // getter for Effluent, defaults to inlet 0 + return {topic: "Fluent", payload: {inlet: 0, F: math.sum(this.Fs), C:this.state}, timestamp: this.currentTime}; } // expect update with timestamp - updateState(input) { - let newTime = input.payload; + updateState(timestamp) { + let newTime = timestamp; const day2ms = 1000 * 60 * 60 * 24; @@ -50,8 +51,8 @@ class Reactor_CSTR { tick_fe(time_step) { // tick reactor state using forward Euler method const r = this.asm.compute_dC(this.state); - const dC_in = math.multiply(this.C_in, this.F/this.Vl); - const dC_out = math.multiply(this.state, this.F/this.Vl); + const dC_in = math.multiply(this.Cs_in, this.Fs/this.Vl)[0]; + const dC_out = math.multiply(this.state, math.sum(this.Fs)/this.Vl); const T_O = Array(13).fill(0.0); T_O[0] = this.OTR;