added some primary coolant loop gui stuff

This commit is contained in:
Jay Robson 2024-02-03 18:12:18 +11:00
parent d222599836
commit 1306dd43ca
33 changed files with 317 additions and 136 deletions

View File

@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.25)
project(FastNuclearSim VERSION 1.0) project(FastNuclearSim VERSION 1.0)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS "-O3 -lncurses -I/usr/include/freetype2") set(CMAKE_CXX_FLAGS "-g -O3 -I/usr/include/freetype2")
file(GLOB_RECURSE SOURCES src/*.cpp) file(GLOB_RECURSE SOURCES src/*.cpp)

Binary file not shown.

Binary file not shown.

BIN
assets/scene-baked.glb (Stored with Git LFS)

Binary file not shown.

BIN
assets/unbaked/scene.blend (Stored with Git LFS)

Binary file not shown.

BIN
assets/unbaked/scene/labels.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/unbaked/scene/labels.xcf (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -26,14 +26,6 @@ double condenser::get_bubble_hl()
void condenser::update(double secs) void condenser::update(double secs)
{ {
std::cout << "Condenser:\n\n";
std::cout << "Level: " << level << "\n";
std::cout << "Volume: " << volume << "\n";
std::cout << "Height: " << height << "\n";
std::cout << "Diameter: " << diameter << "\n";
std::cout << "Pressure: " << get_pressure() << "\n";
std::cout << "Teperature: " << heat << "\n\n";
((sim::coolant::fluid_holder*)this)->update(secs); ((sim::coolant::fluid_holder*)this)->update(secs);
} }

View File

@ -6,8 +6,8 @@
using namespace sim::coolant; 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 l_per_rev, double friction) :
src(&src), dst(&dst), mass(mass), radius(radius), l_per_rev(l_per_rev), friction(friction) src(src), dst(dst), mass(mass), radius(radius), l_per_rev(l_per_rev), friction(friction)
{ {
power = 1e3; power = 1e3;
} }

View File

@ -22,7 +22,7 @@ public:
double power = 0; // watts double power = 0; // watts
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 l_per_rev, double friction);
double get_flow() const; // L/s double get_flow() const; // L/s
double get_rpm() const; // rev/min double get_rpm() const; // rev/min

View File

@ -3,25 +3,25 @@
using namespace sim::coolant; using namespace sim::coolant;
valve::valve(fluid_holder& src, fluid_holder& dst, double max) : src(&src), dst(&dst), max(max) valve::valve(fluid_holder* src, fluid_holder* dst, double max) : src(src), dst(dst), max(max)
{ {
} }
void valve::set_state(double v) void valve::add_open_speed(double v)
{ {
if(v > 1) v = 1; open_speed += v;
if(v < 0) v = 0;
state = v;
} }
void valve::open(double v) void valve::clear_open_speed()
{ {
set_state(state + v); open_speed = 0;
} }
void valve::update(double dt) void valve::update(double dt)
{ {
// rate = a->extract_steam(dt, state * max, pressure) / dt; TODO state += open_speed * dt;
if(state > 1) state = 1;
if(state < 0) state = 0;
} }

View File

@ -13,15 +13,16 @@ class valve
fluid_holder* const src; fluid_holder* const src;
fluid_holder* const dst; fluid_holder* const dst;
double open_speed = 0;
double state = 0; double state = 0;
public: public:
valve(fluid_holder& src, fluid_holder& dst, double max); valve(fluid_holder* src, fluid_holder* dst, double max);
void open(double v);
void update(double secs); void update(double secs);
void set_state(double v); void add_open_speed(double v);
void clear_open_speed();
constexpr double get_state() const { return state; } constexpr double get_state() const { return state; }
}; };

View File

@ -1,54 +0,0 @@
#include "display.hpp"
#include <curses.h>
#include <string.h>
#include <stdlib.h>
void display::draw_text(int x, int y, const char* at)
{
for(int i = 0;; i++)
{
const char* start = at;
char c = (at++)[0];
while(c != '\n' && c != '\0')
{
c = (at++)[0];
}
mvaddnstr(x + i, y, start, (size_t)(at - start));
if(c == '\0')
{
return;
}
}
}
void display::draw_box(int x, int y, int h, int w)
{
mvaddch(x, y, '+');
for(int i = 0; i < w - 2; i++)
{
addch('-');
}
addch('+');
for(int i = 0; i < h - 2; i++)
{
mvaddch(x + i + 1, y, '|');
mvaddch(x + i + 1, y + w - 1, '|');
}
mvaddch(x + h - 1, y, '+');
for(int i = 0; i < w - 2; i++)
{
addch('-');
}
addch('+');
}

View File

@ -1,11 +0,0 @@
#pragma once
namespace display
{
void draw_text(int x, int y, const char* str);
void draw_box(int x, int y, int h, int w);
}

View File

@ -0,0 +1,32 @@
#include "turbine.hpp"
#include <cmath>
#include <iostream>
using namespace sim::electric;
constexpr static double calc_cylinder(double h, double d)
{
double r = d / 2;
return M_PI * r * r * h;
}
turbine::turbine(coolant::fluid_t type, double height, double diameter, double level) :
height(height), diameter(diameter), sim::coolant::fluid_holder(type, calc_cylinder(height, diameter))
{
this->level = level;
}
double turbine::get_bubble_hl()
{
return (level / volume) * diameter * 0.5 / fluid.bubble_speed;
}
void turbine::update(double secs)
{
((sim::coolant::fluid_holder*)this)->update(secs);
}

View File

@ -1,10 +1,24 @@
#pragma once #pragma once
#include "../coolant/fluid_holder.hpp"
namespace sim::electric namespace sim::electric
{ {
class turbine : public sim::coolant::fluid_holder
{
const double height;
const double diameter;
virtual double get_bubble_hl();
public:
turbine(coolant::fluid_t type, double height, double diameter, double level);
void update(double dt);
};
}; };

View File

@ -3,9 +3,11 @@
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include "core.hpp" #include "core.hpp"
#include "helpers.hpp"
#include "../locations.hpp" #include "../locations.hpp"
#include "../input/focus.hpp" #include "../input/focus.hpp"
#include "../mesh/arrays.hpp" #include "../mesh/arrays.hpp"
#include "../../system.hpp"
#include <glm/ext/matrix_transform.hpp> #include <glm/ext/matrix_transform.hpp>
@ -15,6 +17,60 @@
using namespace sim::graphics; using namespace sim::graphics;
using namespace sim::graphics::monitor; using namespace sim::graphics::monitor;
static void set_all(bool state)
{
for(int i = 0; i < sim::system::active.reactor->rods.size(); i++)
{
sim::reactor::rod* r = sim::system::active.reactor->rods[i].get();
if(r->should_select())
{
r->selected = state;
}
}
}
struct core_monitor : public focus::focus_t
{
virtual void on_keypress(int key, int sc, int action, int mods)
{
if(action != GLFW_PRESS)
{
return;
}
sim::system& sys = sim::system::active;
switch(key)
{
case GLFW_KEY_KP_7:
set_all(true);
break;
case GLFW_KEY_KP_8:
sys.reactor->move_cursor(-sys.reactor->height);
break;
case GLFW_KEY_KP_9:
set_all(false);
break;
case GLFW_KEY_KP_4:
sys.reactor->move_cursor(-1);
break;
case GLFW_KEY_KP_5:
sys.reactor->toggle_selected();
break;
case GLFW_KEY_KP_6:
sys.reactor->move_cursor(1);
break;
case GLFW_KEY_KP_1:
sys.reactor->reset_rod_speed();
break;
case GLFW_KEY_KP_2:
sys.reactor->move_cursor(sys.reactor->height);
break;
}
}
};
struct core_joystick : public focus::focus_t struct core_joystick : public focus::focus_t
{ {
virtual void on_cursor_pos(double x, double y) virtual void on_cursor_pos(double x, double y)
@ -40,19 +96,6 @@ core::core()
{ {
} }
static void set_all(bool state)
{
for(int i = 0; i < sim::system::active.reactor->rods.size(); i++)
{
sim::reactor::rod* r = sim::system::active.reactor->rods[i].get();
if(r->should_select())
{
r->selected = state;
}
}
}
void core::init() void core::init()
{ {
mesh1.model_matrix = locations::monitors[2]; mesh1.model_matrix = locations::monitors[2];
@ -80,6 +123,7 @@ void core::init()
m_buttons[7].load_model("../assets/model/", "reactor_core_button8.stl"); m_buttons[7].load_model("../assets/model/", "reactor_core_button8.stl");
m_buttons[8].load_model("../assets/model/", "reactor_core_button9.stl"); m_buttons[8].load_model("../assets/model/", "reactor_core_button9.stl");
m_joystick.load_model("../assets/model/", "reactor_core_joystick.stl"); m_joystick.load_model("../assets/model/", "reactor_core_joystick.stl");
m_monitor.load_model("../assets/model/", "reactor_core_input.stl");
m_scram.load_model("../assets/model/", "reactor_core_scram.stl"); m_scram.load_model("../assets/model/", "reactor_core_scram.stl");
} }
@ -87,28 +131,28 @@ void core::update()
{ {
sim::system& sys = sim::system::active; sim::system& sys = sim::system::active;
if(m_monitor.check_focus())
focus::set(std::make_unique<core_monitor>());
if(m_joystick.check_focus()) if(m_joystick.check_focus())
focus::set(std::make_unique<core_joystick>()); focus::set(std::make_unique<core_joystick>());
if(m_scram.check_focus()) if(m_scram.check_focus())
sim::system::active.reactor->scram(); sys.reactor->scram();
if(m_buttons[0].check_focus()) if(m_buttons[0].check_focus())
set_all(true); set_all(true);
if(m_buttons[1].check_focus()) if(m_buttons[1].check_focus())
sys.reactor->move_cursor(-sim::system::active.reactor->height); sys.reactor->move_cursor(-sys.reactor->height);
if(m_buttons[2].check_focus()) if(m_buttons[2].check_focus())
set_all(false); set_all(false);
if(m_buttons[3].check_focus()) if(m_buttons[3].check_focus())
sys.reactor->move_cursor(-1); sys.reactor->move_cursor(-1);
if(m_buttons[4].check_focus()) if(m_buttons[4].check_focus())
sys.reactor->move_cursor(sim::system::active.reactor->height); sys.reactor->toggle_selected();
if(m_buttons[5].check_focus()) if(m_buttons[5].check_focus())
sys.reactor->move_cursor(1); sys.reactor->move_cursor(1);
if(m_buttons[6].check_focus()) if(m_buttons[6].check_focus())
sim::system::active.reactor->toggle_selected(); sys.reactor->reset_rod_speed();
if(m_buttons[7].check_focus()) if(m_buttons[7].check_focus())
sim::system::active.reactor->reset_rod_speed(); sys.reactor->move_cursor(sys.reactor->height);
// if(m_buttons[8].check_focus())
//
} }
void core::render() void core::render()

View File

@ -2,7 +2,6 @@
#pragma once #pragma once
#include "../mesh/glmesh.hpp" #include "../mesh/glmesh.hpp"
#include "../../system.hpp"
namespace sim::graphics::monitor namespace sim::graphics::monitor
{ {
@ -11,6 +10,7 @@ class core
{ {
sim::graphics::glmesh mesh1, mesh2; sim::graphics::glmesh mesh1, mesh2;
sim::graphics::mesh m_monitor;
sim::graphics::mesh m_buttons[9]; sim::graphics::mesh m_buttons[9];
sim::graphics::mesh m_joystick; sim::graphics::mesh m_joystick;
sim::graphics::mesh m_scram; sim::graphics::mesh m_scram;

View File

@ -0,0 +1,14 @@
#pragma once
#include <cmath>
constexpr double show(double v, double m)
{
return std::round(v * m) / m;
}
constexpr double show(double v)
{
return std::round(v * 1e3) * 1e-3;
}

View File

@ -0,0 +1,113 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "helpers.hpp"
#include "primary_loop.hpp"
#include "../locations.hpp"
#include "../../system.hpp"
#include "../../coolant/valve.hpp"
#include "../input/focus.hpp"
#include <glm/ext/matrix_transform.hpp>
using namespace sim::graphics;
using namespace sim::graphics::monitor;
struct valve_joystick : public focus::focus_t
{
sim::coolant::valve* active;
valve_joystick(sim::coolant::valve* v) : active(v)
{
}
virtual ~valve_joystick()
{
active->clear_open_speed();
}
virtual void on_cursor_pos(double x, double y)
{
active->add_open_speed(y * 1e-5);
}
virtual void on_mouse_button(int button, int action, int mods)
{
if(button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE)
{
focus::clear_focus();
}
}
virtual bool cursor_is_visible()
{
return false;
}
};
primary_loop::primary_loop()
{
}
void primary_loop::init()
{
mesh1.model_matrix = locations::monitors[3];
mesh2.model_matrix = glm::translate(mesh1.model_matrix, glm::vec3(0.5, 0, 0));
mesh1.colour_matrix = mesh2.colour_matrix = {
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
std::stringstream ss;
sim::graphics::mesh rmesh;
ss << "Turbine Valves\n\n";
ss << "Inlet\n";
ss << "Bypass\n";
rmesh.load_text(ss.str().c_str(), 0.04);
mesh1.bind();
mesh1.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");
}
void primary_loop::update()
{
std::stringstream ss;
sim::graphics::mesh rmesh;
system& sys = sim::system::active;
ss << "\n\n";
ss << show( sys.turbine_inlet_valve->get_state() * 100 ) << " %\n";
ss << show( sys.turbine_bypass_valve->get_state() * 100 ) << " %\n";
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<valve_joystick>(sys.turbine_bypass_valve.get()));
if(m_joystick_turbine_inlet.check_focus())
focus::set(std::make_unique<valve_joystick>(sys.turbine_inlet_valve.get()));
}
void primary_loop::render()
{
mesh1.bind();
mesh1.uniform();
mesh1.render();
mesh2.bind();
mesh2.uniform();
mesh2.render();
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "../mesh/glmesh.hpp"
namespace sim::graphics::monitor
{
class primary_loop
{
sim::graphics::glmesh mesh1, mesh2;
sim::graphics::mesh m_joystick_turbine_bypass;
sim::graphics::mesh m_joystick_turbine_inlet;
public:
primary_loop();
void init();
void update();
void render();
};
};

View File

@ -3,9 +3,11 @@
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include "vessel.hpp" #include "vessel.hpp"
#include "helpers.hpp"
#include "../../reactor/rod.hpp" #include "../../reactor/rod.hpp"
#include "../../reactor/control/boron_rod.hpp" #include "../../reactor/control/boron_rod.hpp"
#include "../locations.hpp" #include "../locations.hpp"
#include "../../system.hpp"
#include <glm/ext/matrix_transform.hpp> #include <glm/ext/matrix_transform.hpp>
#include <sstream> #include <sstream>
@ -49,16 +51,6 @@ void vessel::init()
mesh1.set(rmesh, GL_STATIC_DRAW); mesh1.set(rmesh, GL_STATIC_DRAW);
} }
static double show(double v, double m)
{
return std::round(v * m) / m;
}
static double show(double v)
{
return std::round(v * 1e3) * 1e-3;
}
void vessel::update() void vessel::update()
{ {
sim::system& sys = sim::system::active; sim::system& sys = sim::system::active;

View File

@ -2,7 +2,6 @@
#pragma once #pragma once
#include "../mesh/glmesh.hpp" #include "../mesh/glmesh.hpp"
#include "../../system.hpp"
namespace sim::graphics::monitor namespace sim::graphics::monitor
{ {

View File

@ -20,6 +20,7 @@
#include "locations.hpp" #include "locations.hpp"
#include "monitor/vessel.hpp" #include "monitor/vessel.hpp"
#include "monitor/core.hpp" #include "monitor/core.hpp"
#include "monitor/primary_loop.hpp"
#include "mesh/texture.hpp" #include "mesh/texture.hpp"
#include "ui.hpp" #include "ui.hpp"
@ -31,6 +32,7 @@ static bool win_should_close = false;
static glmesh MeshScene; static glmesh MeshScene;
static monitor::vessel MonitorVessel; static monitor::vessel MonitorVessel;
static monitor::core MonitorCore; static monitor::core MonitorCore;
static monitor::primary_loop MonitorPrimaryLoop;
glm::mat4 window::projection_matrix; glm::mat4 window::projection_matrix;
@ -113,6 +115,7 @@ void window::create()
MonitorCore.init(); MonitorCore.init();
MonitorVessel.init(); MonitorVessel.init();
MonitorPrimaryLoop.init();
glfwShowWindow(win); glfwShowWindow(win);
glViewport(0, 0, 800, 600); glViewport(0, 0, 800, 600);
@ -124,6 +127,7 @@ void window::update(double dt)
MonitorCore.update(); MonitorCore.update();
MonitorVessel.update(); MonitorVessel.update();
MonitorPrimaryLoop.update();
ui::update(dt); ui::update(dt);
} }
@ -145,6 +149,7 @@ void window::render()
MonitorCore.render(); MonitorCore.render();
MonitorVessel.render(); MonitorVessel.render();
MonitorPrimaryLoop.render();
ui::render(); ui::render();

View File

@ -7,7 +7,7 @@
using namespace sim::reactor; using namespace sim::reactor;
sim::reactor::reactor sim::reactor::builder(const int W, const int H, const double CW, const double CH, fuel::fuel_rod fr, coolant::vessel& v, const char** lines) sim::reactor::reactor sim::reactor::builder(const int W, const int H, const double CW, const double CH, fuel::fuel_rod fr, coolant::vessel* v, const char** lines)
{ {
std::vector<std::unique_ptr<rod>> arr(W * H); std::vector<std::unique_ptr<rod>> arr(W * H);

View File

@ -13,7 +13,7 @@
namespace sim::reactor namespace sim::reactor
{ {
reactor builder(const int W, const int H, const double CW, const double CH, fuel::fuel_rod fr, coolant::vessel& v, const char** lines); reactor builder(const int W, const int H, const double CW, const double CH, fuel::fuel_rod fr, coolant::vessel* v, const char** lines);
}; };

View File

@ -9,7 +9,7 @@ constexpr double boron_density = 2340000; // g/m^3
constexpr double boron_molar_mass = 10; // g/mol constexpr double boron_molar_mass = 10; // g/mol
constexpr double boron_molar_density = boron_density / boron_molar_mass; // mol/m^3 constexpr double boron_molar_density = boron_density / boron_molar_mass; // mol/m^3
boron_rod::boron_rod(coolant::vessel& v) : coolant::pipe(v) boron_rod::boron_rod(coolant::vessel* v) : coolant::pipe(v)
{ {
} }

View File

@ -18,7 +18,7 @@ class boron_rod : public coolant::pipe
public: public:
boron_rod(coolant::vessel& v); boron_rod(coolant::vessel* v);
virtual void update(double secs); virtual void update(double secs);
void set_reactivity(double a); void set_reactivity(double a);

View File

@ -4,9 +4,9 @@
using namespace sim::reactor::coolant; using namespace sim::reactor::coolant;
pipe::pipe(coolant::vessel& v) pipe::pipe(coolant::vessel* v)
{ {
this->vessel = &v; this->vessel = v;
this->steam = 0; this->steam = 0;
} }

View File

@ -22,7 +22,7 @@ protected:
public: public:
pipe(coolant::vessel& v); pipe(coolant::vessel* v);
virtual std::unique_ptr<rod> clone() const { return std::make_unique<pipe>(*this); } virtual std::unique_ptr<rod> clone() const { return std::make_unique<pipe>(*this); }
virtual bool should_display() const { return true; } virtual bool should_display() const { return true; }

View File

@ -36,11 +36,13 @@ system::system()
}; };
vessel = std::make_unique<reactor::coolant::vessel>(sim::coolant::WATER, 8, 10, 300); vessel = std::make_unique<reactor::coolant::vessel>(sim::coolant::WATER, 8, 10, 300);
reactor = std::make_unique<reactor::reactor>(sim::reactor::builder(19, 19, 1.0 / 4.0, 4, reactor::fuel::fuel_rod(0.5), *vessel.get(), layout)); reactor = std::make_unique<reactor::reactor>(sim::reactor::builder(19, 19, 1.0 / 4.0, 4, reactor::fuel::fuel_rod(0.5), vessel.get(), layout));
condenser = std::make_unique<coolant::condenser>(sim::coolant::WATER, 8, 6, 200); condenser = std::make_unique<coolant::condenser>(sim::coolant::WATER, 8, 6, 200);
turbine = std::make_unique<electric::turbine>(sim::coolant::WATER, 6, 3, 20);
turbine_bypass_valve = std::make_unique<coolant::valve>(*vessel.get(), *condenser.get(), 1); turbine_inlet_valve = std::make_unique<coolant::valve>(vessel.get(), turbine.get(), 1);
core_pump = std::make_unique<coolant::pump>(*condenser.get(), *vessel.get(), 1e6, 1, 100, 100); turbine_bypass_valve = std::make_unique<coolant::valve>(vessel.get(), condenser.get(), 1);
core_pump = std::make_unique<coolant::pump>(condenser.get(), vessel.get(), 1e6, 1, 100, 100);
} }
system::system(system&& o) system::system(system&& o)
@ -48,7 +50,9 @@ system::system(system&& o)
vessel = std::move(o.vessel); vessel = std::move(o.vessel);
reactor = std::move(o.reactor); reactor = std::move(o.reactor);
condenser = std::move(o.condenser); condenser = std::move(o.condenser);
turbine = std::move(o.turbine);
turbine_bypass_valve = std::move(o.turbine_bypass_valve); turbine_bypass_valve = std::move(o.turbine_bypass_valve);
turbine_inlet_valve = std::move(o.turbine_inlet_valve);
core_pump = std::move(o.core_pump); core_pump = std::move(o.core_pump);
} }
@ -57,8 +61,10 @@ void system::update(double dt)
dt *= speed; dt *= speed;
vessel->update(dt); vessel->update(dt);
reactor->update(dt); reactor->update(dt);
// condenser->update(dt); condenser->update(dt);
// turbine_bypass_valve->update(dt); turbine->update(dt);
turbine_inlet_valve->update(dt);
turbine_bypass_valve->update(dt);
// core_pump->update(dt); // core_pump->update(dt);
} }

View File

@ -8,6 +8,7 @@
#include "coolant/pump.hpp" #include "coolant/pump.hpp"
#include "coolant/valve.hpp" #include "coolant/valve.hpp"
#include "coolant/condenser.hpp" #include "coolant/condenser.hpp"
#include "electric/turbine.hpp"
#include "graphics/mesh/mesh.hpp" #include "graphics/mesh/mesh.hpp"
namespace sim namespace sim
@ -20,8 +21,10 @@ struct system
std::unique_ptr<sim::reactor::reactor> reactor; std::unique_ptr<sim::reactor::reactor> reactor;
std::unique_ptr<sim::reactor::coolant::vessel> vessel; std::unique_ptr<sim::reactor::coolant::vessel> vessel;
std::unique_ptr<sim::coolant::condenser> condenser; std::unique_ptr<sim::coolant::condenser> condenser;
std::unique_ptr<sim::electric::turbine> turbine;
std::unique_ptr<sim::coolant::pump> core_pump; std::unique_ptr<sim::coolant::pump> core_pump;
std::unique_ptr<sim::coolant::valve> turbine_bypass_valve; std::unique_ptr<sim::coolant::valve> turbine_bypass_valve;
std::unique_ptr<sim::coolant::valve> turbine_inlet_valve;
sim::graphics::mesh scene; sim::graphics::mesh scene;
double speed = 1; double speed = 1;