diff --git a/assets/model/primary_coolant_pump_switch.glb b/assets/model/primary_coolant_pump_switch.glb new file mode 100644 index 0000000..7ce8622 --- /dev/null +++ b/assets/model/primary_coolant_pump_switch.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4344c73249a535c6472aaa177e75ecd94daef875444e9216fa3d03d50a9c8b2b +size 2300 diff --git a/assets/model/primary_coolant_pump_switch.stl b/assets/model/primary_coolant_pump_switch.stl new file mode 100644 index 0000000..f8bead3 --- /dev/null +++ b/assets/model/primary_coolant_pump_switch.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:578b9844f451434d7439918972840abe9734e0e681a6714b4880994f221feda2 +size 1384 diff --git a/assets/model/secondary_coolant_pump_switch.glb b/assets/model/secondary_coolant_pump_switch.glb new file mode 100644 index 0000000..217e781 --- /dev/null +++ b/assets/model/secondary_coolant_pump_switch.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b78531b28fd2aa3a4187910a9d3e12589ce90bf618f1c6a06ba9dd87289eea4 +size 2304 diff --git a/assets/model/secondary_coolant_pump_switch.stl b/assets/model/secondary_coolant_pump_switch.stl new file mode 100644 index 0000000..bbee054 --- /dev/null +++ b/assets/model/secondary_coolant_pump_switch.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08cb689a2e9589f2cf900dda401a4050c4a7ca0df9dec993fb0b95194cf44152 +size 1384 diff --git a/assets/scene-baked.glb b/assets/scene-baked.glb index 5264c0c..f179956 100644 --- a/assets/scene-baked.glb +++ b/assets/scene-baked.glb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ed870c17367c0bb8858bb68fbc5277f56e47c3ffa650591b11d703e3052da9f -size 59404508 +oid sha256:28b515def72bcb7c1fb46ca68443b510565e9538032fd9320016953154f902f9 +size 59501212 diff --git a/assets/unbaked/scene.blend b/assets/unbaked/scene.blend index 2334421..cabd2ba 100644 --- a/assets/unbaked/scene.blend +++ b/assets/unbaked/scene.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ba3be1ad135735ed6ac111c2229004e8eb7d2d9442a873a5f49bd4cbc905f40 -size 10146216 +oid sha256:617293315153b7993db7beeaba58d2c30e5fc77e75b1d2447907541070357320 +size 12058488 diff --git a/assets/unbaked/scene/labels.png b/assets/unbaked/scene/labels.png index 7ae9d7b..3e2cb14 100644 --- a/assets/unbaked/scene/labels.png +++ b/assets/unbaked/scene/labels.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22b0bcb35c11d4da7718d85136baadbc5801d9823661e1feecd8851d384ef290 -size 26579 +oid sha256:9387fc6ea27299ea12fcc2b27240e9443c168989d5a642740567a4a4b5680745 +size 48112 diff --git a/assets/unbaked/scene/labels.xcf b/assets/unbaked/scene/labels.xcf index c6d49ea..7f87dd0 100644 Binary files a/assets/unbaked/scene/labels.xcf and b/assets/unbaked/scene/labels.xcf differ diff --git a/src/coolant/fluid_holder.cpp b/src/coolant/fluid_holder.cpp index 145aab1..e58454f 100644 --- a/src/coolant/fluid_holder.cpp +++ b/src/coolant/fluid_holder.cpp @@ -1,6 +1,6 @@ #include "fluid_holder.hpp" -#include "../constants.hpp" +#include "../util/constants.hpp" #include "../conversions/temperature.hpp" #include "../reactor/fuel/half_life.hpp" @@ -86,7 +86,7 @@ double fluid_holder::get_pressure() const if(V == 0) { - return NAN; + return 0; } return (n * T * constants::R) / V; @@ -95,7 +95,7 @@ double fluid_holder::get_pressure() const double fluid_holder::get_steam_density() const { double v = get_steam_volume(); - return v > 0 ? steam / v : NAN; + return v > 0 ? steam / v : 0; } void fluid_holder::update(double secs) diff --git a/src/coolant/pump.cpp b/src/coolant/pump.cpp index 8e92414..8291b94 100644 --- a/src/coolant/pump.cpp +++ b/src/coolant/pump.cpp @@ -6,15 +6,20 @@ using namespace sim::coolant; -pump::pump(fluid_holder* src, fluid_holder* dst, double mass, double radius, double l_per_rev, double friction) : +pump::pump(fluid_holder* src, fluid_holder* dst, double mass, double radius, double power, double l_per_rev, double friction) : src(src), dst(dst), mass(mass), radius(radius), l_per_rev(l_per_rev), friction(friction) { - power = 1e8; + this->power = power; } double pump::get_flow() const { - return src->fluid.l_to_g(l_per_rev * get_rpm() / 60); + return l_per_rev * get_rpm() * 60; +} + +double pump::get_flow_mass() const +{ + return src->fluid.l_to_g(get_flow()); } double pump::get_rpm() const @@ -56,40 +61,38 @@ static double calc_work(double j, double mass) void pump::update(double dt) { + idling = false; + if(powered && !idling) { velocity += calc_work(dt * power, mass); } + fluid_holder fh_src(*src); + fluid_holder fh_dst(*dst); + double src_heat = src->get_heat(); double p_diff_1 = dst->get_pressure() - src->get_pressure(); - double src_volume = src->extract_fluid(get_flow() * dt); - double dst_volume = dst->add_fluid(src_volume, src_heat); + double src_volume = fh_src.extract_fluid(get_flow() * dt); + double dst_volume = fh_dst.add_fluid(src_volume, src_heat); - if(dst_volume < src_volume) - { - src->add_fluid(src_volume - dst_volume, src_heat); - } + src->extract_fluid(dst_volume); + dst->add_fluid(dst_volume, src_heat); double p_diff_2 = dst->get_pressure() - src->get_pressure(); double p_diff = (p_diff_1 + p_diff_2) / 2; - double work = p_diff * dst_volume + get_rpm() * 60 * dt * friction; + double work = p_diff * dst_volume * 0.001 + get_rpm() * 60 * dt * friction; velocity -= calc_work(work, mass); if(dst->get_level() > 400 || src->get_level() < 10) { - idling = true; +// idling = true; } else { - idling = false; +// idling = false; } - - std::cout << "RPM: " << get_rpm() << "\t"; - std::cout << "Flow: " << get_flow() << std::endl; - std::cout << "Work Done: " << work << " J\n"; - std::cout << "Src Volume: " << src_volume << "\n"; } diff --git a/src/coolant/pump.hpp b/src/coolant/pump.hpp index 526d8af..30fda18 100644 --- a/src/coolant/pump.hpp +++ b/src/coolant/pump.hpp @@ -21,12 +21,13 @@ class pump public: - bool powered = true; + bool powered = false; bool idling = false; - pump(fluid_holder* src, fluid_holder* dst, double mass, double radius, double l_per_rev, double friction); + pump(fluid_holder* src, fluid_holder* dst, double mass, double radius, double power, double l_per_rev, double friction); - double get_flow() const; // g/s + double get_flow() const; // L/s + double get_flow_mass() const; // g/s double get_rpm() const; // rev/min const char* get_state_string(); diff --git a/src/coolant/valve.cpp b/src/coolant/valve.cpp index ee793ea..53cb9a9 100644 --- a/src/coolant/valve.cpp +++ b/src/coolant/valve.cpp @@ -1,7 +1,7 @@ #include "valve.hpp" #include "../conversions/temperature.hpp" -#include "../constants.hpp" +#include "../util/constants.hpp" #include #include diff --git a/src/graphics/monitor/core.cpp b/src/graphics/monitor/core.cpp index 12054b1..1cbe0a1 100644 --- a/src/graphics/monitor/core.cpp +++ b/src/graphics/monitor/core.cpp @@ -73,16 +73,14 @@ struct core_monitor : public focus::focus_t struct core_joystick : public focus::focus_t { - double ypos = 0; - virtual void on_cursor_pos(double x, double y) { - ypos += y; + sim::system::active.reactor->add_rod_speed(y * 1e-6); } - virtual void update(double dt) + virtual ~core_joystick() { - sim::system::active.reactor->add_rod_speed(ypos * dt * 1e-6); + sim::system::active.reactor->reset_rod_speed(); } virtual void on_mouse_button(int button, int action, int mods) diff --git a/src/graphics/monitor/primary_loop.cpp b/src/graphics/monitor/primary_loop.cpp index 8b36649..961eb8b 100644 --- a/src/graphics/monitor/primary_loop.cpp +++ b/src/graphics/monitor/primary_loop.cpp @@ -54,6 +54,15 @@ primary_loop::primary_loop() } +void primary_loop::toggle_primary_pump() +{ + system& sys = sim::system::active; + bool state; + + sys.primary_pump->powered = state = !sys.primary_pump->powered; + gm_switch_primary.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, state ? 0.07 : 0, 0)); +} + void primary_loop::init() { mesh1.model_matrix = locations::monitors[3]; @@ -85,8 +94,18 @@ void primary_loop::init() mesh1.bind(); mesh1.set(rmesh, GL_STATIC_DRAW); + rmesh.load_model("../assets/model", "primary_coolant_pump_switch.glb"); + gm_switch_primary.bind(); + gm_switch_primary.set(rmesh, GL_STATIC_DRAW); + + rmesh.load_model("../assets/model", "secondary_coolant_pump_switch.glb"); + gm_switch_secondary.bind(); + gm_switch_secondary.set(rmesh, GL_STATIC_DRAW); + m_joystick_turbine_bypass.load_model("../assets/model", "turbine_valve_bypass_joystick.stl"); m_joystick_turbine_inlet.load_model("../assets/model", "turbine_valve_inlet_joystick.stl"); + m_switch_primary.load_model("../assets/model", "primary_coolant_pump_switch.stl"); + m_switch_secondary.load_model("../assets/model", "secondary_coolant_pump_switch.stl"); } void primary_loop::update() @@ -104,7 +123,7 @@ void primary_loop::update() ss << "\n\n\n"; ss << sys.primary_pump->get_state_string() << "\n"; ss << show( sys.primary_pump->get_rpm() ) << " r/min\n"; - ss << show( sys.primary_pump->get_flow() / 1000 ) << " kg/s\n"; + ss << show( sys.primary_pump->get_flow_mass() / 1000 ) << " kg/s\n"; ss << "\n\n\n"; ss << show( sys.condenser->get_heat() ) << " C\n"; ss << show( sys.condenser->get_steam() ) << " g\n"; @@ -114,11 +133,13 @@ void primary_loop::update() rmesh.load_text(ss.str().c_str(), 0.04); mesh2.bind(); mesh2.set(rmesh, GL_DYNAMIC_DRAW); - + if(m_joystick_turbine_bypass.check_focus()) focus::set(std::make_unique(sys.turbine_bypass_valve.get())); if(m_joystick_turbine_inlet.check_focus()) focus::set(std::make_unique(sys.turbine_inlet_valve.get())); + if(m_switch_primary.check_focus()) + toggle_primary_pump(); } void primary_loop::render() @@ -130,5 +151,13 @@ void primary_loop::render() mesh2.bind(); mesh2.uniform(); mesh2.render(); + + gm_switch_primary.bind(); + gm_switch_primary.uniform(); + gm_switch_primary.render(); + + gm_switch_secondary.bind(); + gm_switch_secondary.uniform(); + gm_switch_secondary.render(); } diff --git a/src/graphics/monitor/primary_loop.hpp b/src/graphics/monitor/primary_loop.hpp index 5982126..eb56eab 100644 --- a/src/graphics/monitor/primary_loop.hpp +++ b/src/graphics/monitor/primary_loop.hpp @@ -9,9 +9,16 @@ namespace sim::graphics::monitor class primary_loop { sim::graphics::glmesh mesh1, mesh2; + + sim::graphics::glmesh gm_switch_primary; + sim::graphics::glmesh gm_switch_secondary; sim::graphics::mesh m_joystick_turbine_bypass; sim::graphics::mesh m_joystick_turbine_inlet; + sim::graphics::mesh m_switch_primary; + sim::graphics::mesh m_switch_secondary; + + void toggle_primary_pump(); public: diff --git a/src/reactor/coolant/vessel.cpp b/src/reactor/coolant/vessel.cpp index 494baf5..a3dcc96 100644 --- a/src/reactor/coolant/vessel.cpp +++ b/src/reactor/coolant/vessel.cpp @@ -1,6 +1,6 @@ #include "vessel.hpp" -#include "../../constants.hpp" +#include "../../util/constants.hpp" #include "../../conversions/temperature.hpp" #include "../fuel/half_life.hpp" diff --git a/src/reactor/reactor.cpp b/src/reactor/reactor.cpp index ced8e84..db5448c 100644 --- a/src/reactor/reactor.cpp +++ b/src/reactor/reactor.cpp @@ -1,6 +1,6 @@ #include "reactor.hpp" -#include "../random.hpp" +#include "../util/random.hpp" #include diff --git a/src/system.cpp b/src/system.cpp index 215a535..0805a3f 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -37,12 +37,12 @@ system::system() vessel = std::make_unique(sim::coolant::WATER, 8, 10, 6e6, 300); reactor = std::make_unique(sim::reactor::builder(19, 19, 1.0 / 4.0, 4, reactor::fuel::fuel_rod(0.5), vessel.get(), layout)); - condenser = std::make_unique(sim::coolant::WATER, 8, 6, 3e6, 0); + condenser = std::make_unique(sim::coolant::WATER, 8, 6, 3e6, 200); turbine = std::make_unique(sim::coolant::WATER, condenser.get(), 6, 3, 2e6); turbine_inlet_valve = std::make_unique(vessel.get(), turbine.get(), 0, 1e-2); turbine_bypass_valve = std::make_unique(vessel.get(), condenser.get(), 0, 1e-2); - primary_pump = std::make_unique(condenser.get(), vessel.get(), 1e6, 1, 1, 0); + primary_pump = std::make_unique(condenser.get(), vessel.get(), 1e6, 1, 1e6, 1, 10); } system::system(system&& o) diff --git a/src/constants.hpp b/src/util/constants.hpp similarity index 100% rename from src/constants.hpp rename to src/util/constants.hpp diff --git a/src/util/pid.cpp b/src/util/pid.cpp new file mode 100644 index 0000000..a5b9ca8 --- /dev/null +++ b/src/util/pid.cpp @@ -0,0 +1,112 @@ +/** + * Copyright 2019 Bradley J. Snyder + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include "pid.hpp" + +using namespace std; + +class PIDImpl +{ + public: + PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki ); + ~PIDImpl(); + double calculate( double setpoint, double pv ); + + private: + double _dt; + double _max; + double _min; + double _Kp; + double _Kd; + double _Ki; + double _pre_error; + double _integral; +}; + + +PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki ) +{ + pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki); +} +double PID::calculate( double setpoint, double pv ) +{ + return pimpl->calculate(setpoint,pv); +} +PID::~PID() +{ + delete pimpl; +} + + +/** + * Implementation + */ +PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki ) : + _dt(dt), + _max(max), + _min(min), + _Kp(Kp), + _Kd(Kd), + _Ki(Ki), + _pre_error(0), + _integral(0) +{ +} + +double PIDImpl::calculate( double setpoint, double pv ) +{ + + // Calculate error + double error = setpoint - pv; + + // Proportional term + double Pout = _Kp * error; + + // Integral term + _integral += error * _dt; + double Iout = _Ki * _integral; + + // Derivative term + double derivative = (error - _pre_error) / _dt; + double Dout = _Kd * derivative; + + // Calculate total output + double output = Pout + Iout + Dout; + + // Restrict to max/min + if( output > _max ) + output = _max; + else if( output < _min ) + output = _min; + + // Save error to previous error + _pre_error = error; + + return output; +} + +PIDImpl::~PIDImpl() +{ +} + diff --git a/src/util/pid.hpp b/src/util/pid.hpp new file mode 100644 index 0000000..c537f20 --- /dev/null +++ b/src/util/pid.hpp @@ -0,0 +1,44 @@ +/** + * Copyright 2019 Bradley J. Snyder + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +class PIDImpl; +class PID +{ + public: + // Kp - proportional gain + // Ki - Integral gain + // Kd - derivative gain + // dt - loop interval time + // max - maximum value of manipulated variable + // min - minimum value of manipulated variable + PID( double dt, double max, double min, double Kp, double Kd, double Ki ); + + // Returns the manipulated variable given a setpoint and current process value + double calculate( double setpoint, double pv ); + ~PID(); + + private: + PIDImpl *pimpl; +}; + diff --git a/src/random.cpp b/src/util/random.cpp similarity index 100% rename from src/random.cpp rename to src/util/random.cpp diff --git a/src/random.hpp b/src/util/random.hpp similarity index 100% rename from src/random.hpp rename to src/util/random.hpp