fix turbine issues, fix save loading issue

This commit is contained in:
Jay Robson 2024-02-18 16:46:09 +11:00
parent 0e924656fd
commit d101e6470a
23 changed files with 270 additions and 102 deletions

View File

@ -21,9 +21,9 @@ void main()
vec4 pos = camera * model * aPos;
vec3 cNormal = vec3(0.f, 0.f, 1.f) * mat3(camera * model);
float brightness = dot(normalize(aNormal), normalize(cNormal)) * 0.25f + 0.75f;
// float brightness = dot(normalize(aNormal), normalize(cNormal)) * 0.25f + 0.75f;
colour = aColour * vec4(vec3(brightness), 1);
colour = aColour;// * vec4(vec3(brightness), 1);
gl_Position = projection * pos;
texPos = aTexPos;
tex = aTex;

View File

@ -71,7 +71,7 @@ void Pump::update(double dt)
break;
}
velocity += Util::calc_work(dt * power * max_power, mass);
velocity += Util::Math::j_to_ms2(dt * power * max_power, mass);
}
else
@ -90,7 +90,7 @@ void Pump::update(double dt)
double p_diff = (p_diff_1 + p_diff_2) / 2;
double work = p_diff * dst_volume * 0.001 + get_rpm() / 60 * dt * friction;
velocity = std::max(velocity - Util::calc_work(work, mass), 0.0);
velocity = std::max(velocity - Util::Math::j_to_ms2(work, mass), 0.0);
flow = dst_volume / dt;
}

View File

@ -2,6 +2,7 @@
#include "turbine.hpp"
#include "../system.hpp"
#include "../util/math.hpp"
#include "../util/streams.hpp"
#include <cmath>
#include <iostream>
@ -32,33 +33,79 @@ Turbine::Turbine(const Json::Value& node, Coolant::Condenser* condenser) :
velocity = node["velocity"].asDouble();
phase = node["phase"].asDouble();
breaker_closed = node["breaker_closed"].asBool();
energy_input = node["energy_input"].asDouble();
energy_generated = node["energy_generated"].asDouble();
}
void Turbine::update(double dt)
{
double work = get_rpm() / 60 * dt * friction;
phase = std::fmod(phase + Util::map( get_rpm(), 0, 60, 0, 2 * M_PI ) * dt, 2 * M_PI);
double energy_friction = get_rpm() / 60 * dt * friction;
double work = Util::Math::j_to_ms2(energy_input - energy_friction, extra_mass);
phase = std::fmod(phase + Util::Math::map( get_rpm(), 0, 60, 0, 2 * M_PI ) * dt, 2 * M_PI);
// do energy transfer stuff here
if(breaker_closed)
{
double r_diff = Util::map(get_phase_diff(), -M_PI, M_PI, -30, 30);
double w = r_diff * 1e6;
double a = get_phase_diff();
double dist_extra = 0.1;
double v2 = Util::mod((velocity - 3600) / 60 + 30, 60) - 30;
double w2 = w * w * v2;
if(is_stable || (a < 1e-5 && std::abs(get_rpm() - 3600) < 1e-3))
{
is_stable = true;
energy_generated = (energy_input - energy_friction) / dt;
energy_input = 0;
phase -= a;
set_rpm(3600);
return;
}
energy_generated = w2 * extra_mass;
work += w * dt;
glm::vec<2, double> point(std::cos(a), std::sin(a));
glm::vec<2, double> diff1 = point - glm::vec<2, double>(dist_extra + 1, 0);
glm::vec<2, double> diff2 = point - glm::vec<2, double>(-dist_extra - 1, 0);
double strength = 1e10;
double dist1 = glm::length(diff1);
double dist2 = glm::length(diff2);
double force1_len = -strength / (4 * M_PI * dist1 * dist1);
double force2_len = strength / (4 * M_PI * dist2 * dist2);
glm::vec<2, double> force1 = diff1 / dist1 * force1_len;
glm::vec<2, double> force2 = diff2 / dist2 * force2_len;
// calc the projected force vector
double t1 = std::tan(a);
double t2 = std::tan(a + M_PI/2);
glm::vec<2, double> proj1, proj2;
proj1.x = ((point.x + force1.x) * t1 - point.x * t2 - force1.y) / (t1 - t2);
proj2.x = ((point.x + force2.x) * t1 - point.x * t2 - force2.y) / (t1 - t2);
proj1.y = (proj1.x - point.x) * t2 + point.y;
proj2.y = (proj2.x - point.x) * t2 + point.y;
glm::mat<2, 2, double> rot_mat = {
point.x, -point.y,
point.y, point.x,
};
double eddy = (get_rpm() - 3600) * dt * 1e5;
// calc the amount of actual work (in change in m/s) done
glm::vec<2, double> proj = rot_mat * (proj1 + proj2) * 0.5;
double work_done = proj.y / (extra_mass * 0.001) * dt - eddy;
work += work_done;
energy_generated = -Util::Math::ms2_to_j(work_done / dt, extra_mass) / dt;
}
else
{
energy_generated = 0;
is_stable = false;
}
velocity = std::max(velocity - work, 0.0);
velocity = std::max(velocity + work, 0.0);
energy_input = 0;
}
double Turbine::get_rpm() const
@ -66,16 +113,20 @@ double Turbine::get_rpm() const
return velocity / (M_PI * extra_mass * 0.001 * diameter * diameter * 0.25);
}
void Turbine::set_rpm(double rpm)
{
velocity = rpm * (M_PI * extra_mass * 0.001 * diameter * diameter * 0.25);
}
double Turbine::get_phase_diff() const
{
double phase_g = std::fmod(System::active.clock * 60, 1) * 2 * M_PI;
return Util::mod(phase - phase_g + M_PI, 2*M_PI) - M_PI;
double phase_g = System::active.clock * 120 * M_PI;
return Util::Math::mod(phase - phase_g + M_PI, 2*M_PI) - M_PI;
}
void Turbine::add_gas(double steam, double air, double t)
{
double joules = (steam + air) * fluid.jPg;
velocity = std::max(velocity + Util::calc_work(joules, extra_mass), 0.0);
energy_input += (steam + air) * fluid.jPg; // J
condenser->add_gas(steam, air, t);
}
@ -88,6 +139,8 @@ Turbine::operator Json::Value() const
node["velocity"] = velocity;
node["friction"] = friction;
node["breaker_closed"] = breaker_closed;
node["energy_input"] = energy_input;
node["energy_generated"] = energy_generated;
node["phase"] = phase;
return node;

View File

@ -13,15 +13,19 @@ class Turbine : public Sim::Coolant::FluidHolder
const double length;
const double diameter;
const double friction = 1;
const double friction = 1e5; // J/rev
double energy_input = 0; // J
double energy_generated = 0; // W
double velocity = 0; // m/s
double phase = 0;
void set_rpm(double rpm);
public:
bool breaker_closed = false;
bool is_stable = false;
Turbine(Coolant::Fluid type, Coolant::Condenser* condenser, double length, double diameter, double mass);
Turbine(const Json::Value& node, Coolant::Condenser* condenser);

View File

@ -139,6 +139,16 @@ void Camera::update(double dt)
camera_mat = glm::translate(camera_mat, glm::vec3(-pos.x, -pos.y, -pos.z));
}
double Camera::get_pitch()
{
return pitch;
}
double Camera::get_yaw()
{
return yaw;
}
glm::mat4 Camera::get_matrix()
{
return camera_mat;

View File

@ -9,9 +9,11 @@
namespace Sim::Graphics::Camera
{
glm::mat4 get_matrix();
glm::vec<3, double> get_normal();
glm::vec<3, double> get_pos();
glm::mat4 get_matrix();
double get_pitch();
double get_yaw();
Json::Value serialize();
void load(const Json::Value& node);

View File

@ -43,9 +43,6 @@ static void cb_keypress(GLFWwindow* win, int key, int sc, int action, int mods)
case GLFW_KEY_5:
Sim::System::active.speed = 3600; // 1 h/s
break;
case GLFW_KEY_6:
Sim::System::active.speed = 43200; // 12 h/s
break;
case GLFW_KEY_O:
Sim::System::save();
break;

View File

@ -3,12 +3,12 @@
#include <GLFW/glfw3.h>
#include "core.hpp"
#include "helpers.hpp"
#include "../locations.hpp"
#include "../input/focus.hpp"
#include "../mesh/arrays.hpp"
#include "../mesh/texture.hpp"
#include "../../system.hpp"
#include "../../util/streams.hpp"
#include <glm/ext/matrix_transform.hpp>
@ -17,6 +17,7 @@
using namespace Sim::Graphics;
using namespace Sim::Graphics::Monitor;
using namespace Sim::Util::Streams;
static void set_all(bool state)
{

View File

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

View File

@ -2,18 +2,19 @@
#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 "../../util/streams.hpp"
#include <glm/ext/matrix_transform.hpp>
#include <iostream>
using namespace Sim::Graphics;
using namespace Sim::Graphics::Monitor;
using namespace Sim::Util::Streams;
struct ValveJoystick : public Focus::FocusType
{
@ -117,7 +118,7 @@ void PrimaryLoop::update(double dt)
ss << "\n\n";
ss << show( sys.turbine_bypass_valve->get_state() * 100 ) << " %\n";
ss << show( sys.turbine_bypass_valve->get_flow() / 1000 ) << " kg/s\n";
show_units( ss, sys.turbine_bypass_valve->get_flow() ) << "g/s\n";
if(sys.turbine_bypass_valve->get_auto())
{
@ -131,7 +132,7 @@ void PrimaryLoop::update(double dt)
ss << "\n\n\n";
ss << show( sys.turbine_inlet_valve->get_state() * 100 ) << " %\n";
ss << show( sys.turbine_inlet_valve->get_flow() / 1000 ) << " kg/s\n";
show_units( ss, sys.turbine_inlet_valve->get_flow() ) << "g/s\n";
if(sys.turbine_inlet_valve->get_auto())
{
@ -146,11 +147,11 @@ void PrimaryLoop::update(double dt)
ss << "\n\n\n";
ss << show( sys.primary_pump->get_power() * 100 ) << " %\n";
ss << show( sys.primary_pump->get_rpm() ) << " r/min\n";
ss << show( sys.primary_pump->get_flow_mass() / 1000 ) << " kg/s\n";
show_units( ss, sys.primary_pump->get_flow_mass() ) << "g/s\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";
show_units( ss, sys.condenser->get_steam() ) << "g\n";
show_units( ss, sys.condenser->get_pressure() ) << "Pa\n";
ss << show( sys.condenser->get_level() / 1000 ) << " / " << show( sys.condenser->get_volume() / 1000 ) << " kL\n";
rmesh.load_text(ss.str().c_str(), 0.04);

View File

@ -2,18 +2,19 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "helpers.hpp"
#include "secondary_loop.hpp"
#include "../locations.hpp"
#include "../../system.hpp"
#include "../../coolant/valve.hpp"
#include "../input/focus.hpp"
#include "../../util/streams.hpp"
#include <glm/ext/matrix_transform.hpp>
#include <iostream>
using namespace Sim::Graphics;
using namespace Sim::Graphics::Monitor;
using namespace Sim::Util::Streams;
SecondaryLoop::SecondaryLoop()
{
@ -73,17 +74,17 @@ void SecondaryLoop::update(double dt)
ss << "\n\n";
ss << show( sys.evaporator->get_heat() ) << " C\n";
ss << show( sys.evaporator->get_steam_output() ) << " g/s\n";
ss << show( sys.evaporator->get_pressure() / 1000 ) << " kPa\n";
show_units( ss, sys.evaporator->get_steam_output() ) << "g/s\n";
show_units( ss, sys.evaporator->get_pressure() ) << "Pa\n";
ss << show( sys.evaporator->get_level() / 1000 ) << " / " << show( sys.evaporator->get_volume() / 1000 ) << " kL\n";
ss << "\n\n\n";
ss << show( sys.secondary_pump->get_power() * 100 ) << " %\n";
ss << show( sys.secondary_pump->get_rpm() ) << " r/min\n";
ss << show( sys.secondary_pump->get_flow_mass() / 1000 ) << " kg/s\n";
show_units( ss, sys.secondary_pump->get_flow_mass() ) << "g/s\n";
ss << "\n\n\n";
ss << show( sys.freight_pump->get_power() * 100 ) << " %\n";
ss << show( sys.freight_pump->get_rpm() ) << " r/min\n";
ss << show( sys.freight_pump->get_flow_mass() / 1000 ) << " kg/s\n";
show_units( ss, sys.freight_pump->get_flow_mass() ) << "g/s\n";
rmesh.load_text(ss.str().c_str(), 0.04);
mesh2.bind();

View File

@ -2,18 +2,19 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "helpers.hpp"
#include "turbine.hpp"
#include "../locations.hpp"
#include "../../system.hpp"
#include "../../coolant/valve.hpp"
#include "../input/focus.hpp"
#include "../../util/streams.hpp"
#include <glm/ext/matrix_transform.hpp>
#include <iostream>
using namespace Sim::Graphics;
using namespace Sim::Graphics::Monitor;
using namespace Sim::Util::Streams;
Turbine::Turbine()
{
@ -77,7 +78,7 @@ void Turbine::update(double dt)
ss << "Local\n\n";
ss << show( sys.turbine->get_rpm() / 60 ) << " Hz\n";
ss << show( sys.turbine->get_energy_generated() ) << " W\n";
Util::Streams::show_units( ss, sys.turbine->get_energy_generated() ) << "W\n";
rmesh2.load_text(ss.str().c_str(), 0.04);
rmesh.add(rmesh2, glm::translate(glm::mat4(1), glm::vec3(0.4, 0.7, 0)));

View File

@ -3,16 +3,17 @@
#include <GLFW/glfw3.h>
#include "vessel.hpp"
#include "helpers.hpp"
#include "../../reactor/rod.hpp"
#include "../../reactor/control/boron_rod.hpp"
#include "../locations.hpp"
#include "../../system.hpp"
#include "../../util/streams.hpp"
#include <glm/ext/matrix_transform.hpp>
#include <sstream>
using namespace Sim::Graphics::Monitor;
using namespace Sim::Util::Streams;
Vessel::Vessel()
{
@ -94,11 +95,11 @@ void Vessel::update(double dt)
ss << "\n\n";
ss << show( sys.vessel->get_heat() ) << " C\n";
ss << show( sys.vessel->get_steam() ) << " g\n";
ss << show( sys.vessel->get_pressure() * 0.001 ) << " kPa\n";
show_units( ss, sys.vessel->get_steam() ) << "g\n";
show_units( ss, sys.vessel->get_pressure() ) << "Pa\n";
ss << show( sys.vessel->get_level() / 1000 ) << " / " << show( sys.vessel->get_volume() / 1000 ) << " kL\n";
ss << show( sys.vessel->get_void_ratio() * 100 ) << " %\n\n\n\n";
ss << show( sys.reactor->get_flux() ) << " n/cm2/s\n\n\n";
show_units( ss, sys.reactor->get_flux() ) << "n/cm2/s\n\n\n";
// ss << show( sys.reactor->flux_rate * 100 ) << " %/s\n\n\n";
ss << show( temp_min ) << " C\n";
ss << show( temp_max ) << " C\n\n\n";

View File

@ -112,6 +112,22 @@ void Window::create()
Mesh m, m2;
m.load_model("../assets", "scene-baked.glb");
// find the floor parts of the model and set them slightly transparent
for(int i = 0; i < m.indices.size(); i += 3)
{
Arrays::Vertex& v1 = m.vertices[m.indices[i]];
Arrays::Vertex& v2 = m.vertices[m.indices[i + 1]];
Arrays::Vertex& v3 = m.vertices[m.indices[i + 2]];
if(v1.pos.z <= 0 && v2.pos.z <= 0 && v3.pos.z <= 0)
{
v1.colour.w = 0.95;
v2.colour.w = 0.95;
v3.colour.w = 0.95;
}
}
m2.load_model("../assets/model", "monitor_graphics.stl");
m.add(m2, glm::mat4(1));
@ -141,17 +157,8 @@ void Window::update(double dt)
UI::update(dt);
}
void Window::render()
void render_scene()
{
glm::mat4 mat_camera = Camera::get_matrix();
glm::mat4 mat_projection = glm::perspective(glm::radians(90.0f), Resize::get_aspect(), 0.01f, 20.f);
glUniformMatrix4fv(Shader::gl_projection, 1, false, &mat_projection[0][0]);
glUniformMatrix4fv(Shader::gl_camera, 1, false, &mat_camera[0][0]);
projection_matrix = mat_projection;
glClearColor(0, 0, 0, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
mesh_scene.bind();
mesh_scene.uniform();
mesh_scene.render();
@ -163,6 +170,31 @@ void Window::render()
monitor_turbine.render();
Focus::render();
}
void Window::render()
{
glm::mat4 mat_camera = Camera::get_matrix();
mat_camera = glm::scale(mat_camera, {1, 1, -1});
glm::mat4 mat_projection = glm::perspective(glm::radians(90.0f), Resize::get_aspect(), 0.01f, 20.f);
glUniformMatrix4fv(Shader::gl_projection, 1, false, &mat_projection[0][0]);
glUniformMatrix4fv(Shader::gl_camera, 1, false, &mat_camera[0][0]);
projection_matrix = mat_projection;
glClearColor(0, 0, 0, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT);
glFrontFace(GL_CW);
render_scene();
mat_camera = Camera::get_matrix();
glUniformMatrix4fv(Shader::gl_camera, 1, false, &mat_camera[0][0]);
glClear(GL_DEPTH_BUFFER_BIT);
glFrontFace(GL_CCW);
render_scene();
UI::render();
Focus::render_ui();

View File

@ -28,7 +28,7 @@ int main()
feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
#endif
// tests::run();
// Tests::run();
// return 0;
Graphics::Window::create();

View File

@ -10,7 +10,7 @@ Pipe::Pipe(Coolant::Vessel* v)
this->steam = 0;
}
Pipe::Pipe(const Json::Value& node, Coolant::Vessel* v) : vessel(v)
Pipe::Pipe(const Json::Value& node, Coolant::Vessel* v) : Rod(node), vessel(v)
{
steam = node["steam"].asDouble();
}

View File

@ -2,6 +2,7 @@
#include "rod.hpp"
#include "reactor.hpp"
#include "../util/math.hpp"
#include "../util/streams.hpp"
#include <cmath>
@ -69,22 +70,22 @@ glm::vec4 Rod::get_heat_colour() const
if(temp < 120)
{
return {0, Util::map(temp, 0, 120, 0, 1), 1, 1};
return {0, Util::Math::map(temp, 0, 120, 0, 1), 1, 1};
}
if(temp < 240)
{
return {0, 1, Util::map(temp, 120, 240, 1, 0), 1};
return {0, 1, Util::Math::map(temp, 120, 240, 1, 0), 1};
}
if(temp < 280)
{
return {Util::map(temp, 240, 280, 0, 1), 1, 0, 1};
return {Util::Math::map(temp, 240, 280, 0, 1), 1, 0, 1};
}
if(temp < 320)
{
return {1, Util::map(temp, 280, 320, 1, 0), 0, 1};
return {1, Util::Math::map(temp, 280, 320, 1, 0), 0, 1};
}
return {1, 0, 0, 1};

View File

@ -114,7 +114,7 @@ System::operator Json::Value() const
return node;
}
void System::save()
void System::save(const char* path)
{
Json::Value root(active);
root["camera"] = Graphics::Camera::serialize();
@ -124,15 +124,15 @@ void System::save()
builder["indentation"] = "";
std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
std::ofstream savefile("savefile.json");
std::ofstream savefile(path);
writer->write(root, &savefile);
savefile.close();
}
void System::load()
void System::load(const char* path)
{
Json::Value root;
std::ifstream savefile("savefile.json");
std::ifstream savefile(path);
savefile >> root;
savefile.close();
@ -141,3 +141,13 @@ void System::load()
active = std::move(sys);
}
void System::save()
{
save("savefile.json");
}
void System::load()
{
load("savefile.json");
}

View File

@ -45,6 +45,8 @@ struct System
void update(double dt);
static void save(const char* path);
static void load(const char* path);
static void save();
static void load();

View File

@ -1,5 +1,6 @@
#include "tests.hpp"
#include "system.hpp"
#include <unistd.h>
#include <iostream>
@ -8,8 +9,13 @@ using namespace Sim;
void Tests::run()
{
// fluid_system fs(WATER, 1000, 10);
// std::cout << "Volume: " << fs.volume << "\n";
std::cout << "Load savefile.json:\n";
System::load("savefile.json");
std::cout << "Save savefile2.json:\n";
System::save("savefile2.json");
std::cout << "Load savefile2.json:\n";
System::load("savefile2.json");
std::cout << "Save savefile3.json:\n";
System::save("savefile3.json");
}

View File

@ -1,36 +1,21 @@
#pragma once
#include <glm/matrix.hpp>
#include <ostream>
#include <cmath>
template <int N, typename T>
std::ostream& operator<<(std::ostream& o, const glm::vec<N, T>& v)
namespace Sim::Util::Math
{
o << "{";
for(int i = 0; i < N - 1; i++)
constexpr double ms2_to_j(double v, double mass)
{
o << v[i] << ", ";
double m = (v < 0) ? -1 : 1;
return m*std::pow(m * v / (mass * 0.001), 2);
}
o << v[N - 1] << "}";
return o;
}
namespace Sim::Util
constexpr double j_to_ms2(double j, double mass)
{
constexpr double calc_work(double j, double mass)
{
double m = 1;
if(j < 0)
{
m = -1;
}
double m = (j < 0) ? -1 : 1;
return m*std::sqrt(m * j / (mass * 0.001));
}

38
src/util/streams.cpp Normal file
View File

@ -0,0 +1,38 @@
#include "streams.hpp"
using namespace Sim::Util;
std::ostream& Streams::show_units(std::ostream& o, double v)
{
const char* PREFIXES[] = {
" ",
" k",
" M",
" G",
" T",
" P",
" E",
" Z",
" Y",
" R",
" Q"
};
int unit_id = 0;
while(std::abs(v) > 10000)
{
unit_id++;
v *= 0.001;
}
if(unit_id > 10)
{
unit_id = 10;
}
o << show(v) << PREFIXES[unit_id];
return o;
}

38
src/util/streams.hpp Normal file
View File

@ -0,0 +1,38 @@
#pragma once
#include <cmath>
#include <ostream>
#include <glm/matrix.hpp>
namespace Sim::Util::Streams
{
constexpr double show(double v, double m)
{
return (v == 0 ? 0 : std::round(v * m) / m);
}
constexpr double show(double v)
{
return show(v, 1e3);
}
std::ostream& show_units(std::ostream& o, double v);
};
template <int N, typename T>
std::ostream& operator<<(std::ostream& o, const glm::vec<N, T>& v)
{
o << "{";
for(int i = 0; i < N - 1; i++)
{
o << v[i] << ", ";
}
o << v[N - 1] << "}";
return o;
}