steam flow sort of works

This commit is contained in:
Jay Robson 2024-02-04 23:22:15 +11:00
parent 711f2e9924
commit 67b9f29745
16 changed files with 178 additions and 84 deletions

View File

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

View File

@ -18,7 +18,7 @@ double fluid_holder::add_heat(double m1, double t1)
{
double t2 = get_heat();
double t = t1 - t2;
double m2 = (fluid.l_to_g(level) + steam) * fluid.jPgk;
double m2 = get_mass() * fluid.jPgk;
double m = m1 + m2;
if(m1 == 0 || m2 == 0)
@ -62,33 +62,24 @@ double fluid_holder::extract_fluid(double amount)
return amount;
}
double fluid_holder::extract_steam(double dt, double a, double p2)
void fluid_holder::add_steam(double m2, double t2)
{
// calculate the mass moved
double p1 = get_pressure();
double p = (p1 - p2) * 0.001; // mPa or g/m/s^2
double m1 = steam;
double t1 = heat;
double m = m1 + m2;
if(p == 0)
if(m > 0)
{
return 0;
heat = (t1 * m1 + t2 * m2) / m;
}
double V = (volume - level) * 0.001; // m^3
double mass = std::min(dt * a * p / std::sqrt( V * std::abs(p) / steam ), steam);
if(std::isnan(mass))
{
return 0;
}
steam -= mass;
return mass;
steam = m;
}
double fluid_holder::get_pressure() const
{
double T = conversions::temperature::c_to_k(heat);
double V = (volume - level) * 0.001;
double V = get_steam_volume() * 0.001;
double n = fluid.g_to_mol(steam);
return (n * T * constants::R) / V;
@ -96,38 +87,36 @@ double fluid_holder::get_pressure() const
void fluid_holder::update(double secs)
{
double V = (volume - level) * 0.001;
double P = fluid.vapor_pressure.calc_p(heat);
double T = conversions::temperature::c_to_k(heat);
double n = fluid.mol_to_g((V * P) / (T * constants::R)) - steam;
double mass = get_mass();
double s = steam + n;
double l = fluid.l_to_g(level) - n;
double v = fluid.l_to_g(volume);
if(l < 0)
if(mass > 0)
{
s += l;
l = 0;
double V = get_steam_volume() * 0.001;
double P = fluid.vapor_pressure.calc_p(heat);
double T = conversions::temperature::c_to_k(heat);
double n = fluid.mol_to_g((V * P) / (T * constants::R)) - steam;
double s = steam + n;
double l = fluid.l_to_g(level) - n;
double v = fluid.l_to_g(volume);
if(l < 0)
{
s += l;
l = 0;
}
if(l > v)
{
l = v;
s = 0;
}
double diff = s - steam;
steam = s;
level = fluid.g_to_l(l);
heat -= diff * fluid.jPg / mass / fluid.jPgk;
}
if(s > v)
{
s = v;
l = 0;
}
if(l > v)
{
l = v;
s = 0;
}
double diff = s - steam;
steam = s;
level = fluid.g_to_l(l);
heat -= diff * fluid.jPg / (fluid.l_to_g(level) + steam) / fluid.jPgk;
}

View File

@ -23,15 +23,16 @@ public:
double add_heat(double m, double t);
double add_fluid(double amount, double heat);
double extract_steam(double dt, double a, double p2);
double extract_fluid(double amount);
virtual void add_steam(double amount, double t);
constexpr double get_volume() const { return volume; } // litres
constexpr double get_level() const { return level; } // litres
constexpr double get_heat() const { return heat; } // celsius
constexpr double get_steam() const { return steam; } // grams
constexpr double get_steam_volume() const { return volume - level; } // litres
constexpr double get_steam_density() const { return steam / get_steam_volume(); } // g/L
constexpr double get_mass() const { return fluid.l_to_g(level) + steam; } // grams
constexpr double get_steam_density() const { return steam / (volume - level); } // g/L
double get_pressure() const; // pascals
void update(double dt);

View File

@ -1,6 +1,9 @@
#include "valve.hpp"
#include <cmath>
#include <iostream>
using namespace sim::coolant;
valve::valve(fluid_holder* src, fluid_holder* dst, double max) : src(src), dst(dst), max(max)
@ -10,18 +13,46 @@ valve::valve(fluid_holder* src, fluid_holder* dst, double max) : src(src), dst(d
void valve::add_open_speed(double v)
{
open_speed += v;
speed += v;
}
void valve::clear_open_speed()
{
open_speed = 0;
speed = 0;
}
void valve::update(double dt)
{
state += open_speed * dt;
state += speed * dt;
if(state > 1) state = 1;
if(state < 0) state = 0;
double r = max * state; // L
double m = r * dt;//1 - std::pow(0.5, dt * -std::log2(1 - r));
double pressure1 = src->get_pressure();
double pressure2 = dst->get_pressure();
double density1 = src->get_steam_density(); // g/L
double density2 = dst->get_steam_density(); // g/L
double diff = (pressure1 - pressure2) * m;
double temp, mass;
if(diff > 0)
{
temp = src->get_heat();
mass = diff * src->get_steam_density();
}
else
{
temp = dst->get_heat();
mass = diff * dst->get_steam_density();
}
src->add_steam(-mass, temp);
dst->add_steam(mass, temp);
this->flow = mass / dt;
}

View File

@ -13,8 +13,9 @@ class valve
fluid_holder* const src;
fluid_holder* const dst;
double open_speed = 0;
double speed = 0;
double state = 0;
double flow = 0; // L/s
public:
@ -25,6 +26,7 @@ public:
void clear_open_speed();
constexpr double get_state() const { return state; }
constexpr double get_flow() const { return flow; }
};
};

View File

@ -1,5 +1,6 @@
#include "turbine.hpp"
#include "../system.hpp"
#include <cmath>
#include <iostream>
@ -21,7 +22,24 @@ turbine::turbine(coolant::fluid_t type, double height, double diameter, double l
void turbine::update(double secs)
{
sim::system& sys = sim::system::active;
auto& o = *sys.turbine.get();
((sim::coolant::fluid_holder*)this)->update(secs);
/* if(level + o.level > o.volume)
{
level += o.level - o.volume;
o.level = o.volume;
}
else
{
o.level += level;
level = 0;
}
balance_steam(o);*/
}

View File

@ -12,12 +12,14 @@
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
#include <vector>
using namespace sim::graphics;
static glm::vec<3, double> trigger_near;
static glm::vec<3, double> trigger_far;
static std::vector<std::unique_ptr<focus::focus_t>> stack;
static std::unique_ptr<focus::focus_t> state = nullptr;
static bool mouse_visible = false;
static bool mouse_locked = false;
@ -51,11 +53,9 @@ void focus::on_mouse_button(int button, int action, int mods)
state->on_mouse_button(button, action, mods);
}
else if(button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
if(button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
{
triggered = true;
if(is_mouse_locked())
if(is_mouse_locked() && mouse_visible)
{
double mx, my;
mouse::get(mx, my);
@ -66,12 +66,14 @@ void focus::on_mouse_button(int button, int action, int mods)
trigger_near = glm::unProject(glm::vec3(mouse, -1), camera::get_matrix(), window::projection_matrix, viewport);
trigger_far = glm::unProject(glm::vec3(mouse, 1), camera::get_matrix(), window::projection_matrix, viewport);
triggered = true;
}
else
else if(!mouse_visible)
{
trigger_near = camera::get_pos();
trigger_far = trigger_near + camera::get_normal();
triggered = true;
}
}
}
@ -102,7 +104,7 @@ glm::vec<3, double> focus::get_trigger_far()
return trigger_far;
}
void focus::update()
void focus::update(double dt)
{
triggered = false;
@ -130,7 +132,7 @@ void focus::update()
if(state)
{
state->update();
state->update(dt);
}
}
@ -142,6 +144,12 @@ bool focus::is_focused()
void focus::clear_focus()
{
state = nullptr;
if(stack.size() != 0)
{
state = std::move(stack.back());
stack.pop_back();
}
}
bool focus::is_mouse_locked()
@ -152,11 +160,16 @@ bool focus::is_mouse_locked()
void focus::clear_mouse_locked()
{
mouse_locked = false;
state = nullptr;
clear_focus();
}
void focus::set(std::unique_ptr<focus_t> f)
{
if(state != nullptr)
{
stack.push_back(std::move(state));
}
state = std::move(f);
}

View File

@ -16,7 +16,7 @@ struct focus_t
virtual void on_mouse_button(int button, int action, int mods) { }
virtual void on_cursor_pos(double x, double y) { }
virtual void on_charcode(unsigned int c) { }
virtual void update() { }
virtual void update(double dt) { }
};
bool is_focused();
@ -31,7 +31,7 @@ void on_keypress(int key, int sc, int action, int mods);
void on_mouse_button(int button, int action, int mods);
void on_cursor_pos(double x, double y);
void on_charcode(unsigned int c);
void update();
void update(double dt);
};

View File

@ -61,7 +61,7 @@ static void cb_charcode(GLFWwindow* win, unsigned int code)
bool keyboard::is_pressed(int key)
{
if(focus::is_focused())
if(focus::is_mouse_locked())
{
return false;
}

View File

@ -73,9 +73,16 @@ 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)
{
sim::system::active.reactor->add_rod_speed(y * 1e-6);
ypos += y;
}
virtual void update(double dt)
{
sim::system::active.reactor->add_rod_speed(ypos * dt * 1e-6);
}
virtual void on_mouse_button(int button, int action, int mods)

View File

@ -8,7 +8,8 @@ constexpr double show(double v, double m)
return std::round(v * m) / m;
}
constexpr double show(double v)
constexpr double show(double a)
{
return std::round(v * 1e3) * 1e-3;
double b = std::round(a * 1e3) * 1e-3;
return b == 0 ? 0 : b;
}

View File

@ -10,6 +10,7 @@
#include "../input/focus.hpp"
#include <glm/ext/matrix_transform.hpp>
#include <iostream>
using namespace sim::graphics;
using namespace sim::graphics::monitor;
@ -30,7 +31,7 @@ struct valve_joystick : public focus::focus_t
virtual void on_cursor_pos(double x, double y)
{
active->add_open_speed(y * 1e-5);
active->add_open_speed(-y * 1e-6);
}
virtual void on_mouse_button(int button, int action, int mods)
@ -68,9 +69,20 @@ void primary_loop::init()
std::stringstream ss;
sim::graphics::mesh rmesh;
ss << "Turbine Valves\n\n";
ss << "Inlet\n";
ss << "Bypass\n";
ss << "Turbine Bypass Valve\n\n";
ss << "Opened\nFlow\n\n";
ss << "Turbine Inlet Valve\n\n";
ss << "Opened\nFlow\n\n";
ss << "Turbine\n\n";
ss << "Heat\n";
ss << "Steam\n";
ss << "Pressure\n";
ss << "Level\n\n";
ss << "Condenser\n\n";
ss << "Heat\n";
ss << "Steam\n";
ss << "Pressure\n";
ss << "Level\n\n";
rmesh.load_text(ss.str().c_str(), 0.04);
mesh1.bind();
@ -87,8 +99,21 @@ void primary_loop::update()
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";
ss << show( sys.turbine_bypass_valve->get_flow() ) << " g/s\n";
ss << "\n\n\n";
ss << show( sys.turbine_inlet_valve->get_state() * 100 ) << " %\n";
ss << show( sys.turbine_inlet_valve->get_flow() ) << " g/s\n";
ss << "\n\n\n";
ss << show( sys.turbine->get_heat() ) << " C\n";
ss << show( sys.turbine->get_steam() ) << " g\n";
ss << show( sys.turbine->get_pressure() / 1000 ) << " kPa\n";
ss << sys.turbine->get_level() << " / " << show( sys.turbine->get_volume() ) << " L\n";
ss << "\n\n\n";
ss << show( sys.condenser->get_heat() ) << " C\n";
ss << show( sys.condenser->get_steam() ) << " g\n";
ss << show( sys.condenser->get_pressure() / 1000 ) << " kPa\n";
ss << sys.condenser->get_level() << " / " << show( sys.condenser->get_volume() ) << " L\n";
rmesh.load_text(ss.str().c_str(), 0.04);
mesh2.bind();

View File

@ -47,7 +47,7 @@ int main()
graphics::camera::update(dt);
graphics::window::update(dt);
graphics::focus::update();
graphics::focus::update(dt);
graphics::window::render();
}

View File

@ -30,14 +30,22 @@ double vessel::get_steam_suspended() const
double vessel::get_void_ratio() const
{
double s = steam_suspended / get_steam_density();
if(s == 0)
double density = get_steam_density();
if(density == 0)
{
return 0;
}
return s / (level + s);
double s = steam_suspended / density;
double m = level + s;
if(m == 0)
{
return 0;
}
return s / m;
}
double vessel::get_bubble_hl() const

View File

@ -31,7 +31,6 @@ double rod::extract(val_t type, double s, double k, double o)
m = 1 - std::pow(0.5, s * -std::log2(k));
}
double v = m * 0.5 * (get(type) - o);
vals[type] -= v;

View File

@ -37,11 +37,11 @@ system::system()
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));
condenser = std::make_unique<coolant::condenser>(sim::coolant::WATER, 8, 6, 20);
turbine = std::make_unique<electric::turbine>(sim::coolant::WATER, 6, 3, 20);
condenser = std::make_unique<coolant::condenser>(sim::coolant::WATER, 8, 6, 0);
turbine = std::make_unique<electric::turbine>(sim::coolant::WATER, 6, 3, 0);
turbine_inlet_valve = std::make_unique<coolant::valve>(vessel.get(), turbine.get(), 1);
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(), 1e-7);
turbine_bypass_valve = std::make_unique<coolant::valve>(vessel.get(), condenser.get(), 1e-7);
core_pump = std::make_unique<coolant::pump>(condenser.get(), vessel.get(), 1e6, 1, 100, 100);
}