From 2e0a949ab8ea46240ff448ce931fcfa88a3ffbc6 Mon Sep 17 00:00:00 2001 From: Jay Robson Date: Mon, 29 Jan 2024 01:26:07 +1100 Subject: [PATCH] made sim more accurate, fancy displays now show stuff --- src/graphics/mesh/font.cpp | 4 +- src/graphics/mesh/glmesh.cpp | 78 ++++++++++++++++ src/graphics/mesh/glmesh.hpp | 34 +++++++ src/graphics/mesh/mesh.cpp | 89 +++++++------------ src/graphics/mesh/mesh.hpp | 23 ++--- src/graphics/mesh/model.cpp | 7 +- src/graphics/monitor/core.cpp | 63 ++++++++++--- src/graphics/monitor/core.hpp | 7 +- src/graphics/monitor/vessel.cpp | 79 +++++++++++++--- src/graphics/monitor/vessel.hpp | 4 +- src/graphics/window.cpp | 13 +-- src/main.cpp | 2 +- src/reactor/builder.cpp | 17 ++-- src/reactor/builder.hpp | 5 +- src/reactor/control/boron_rod.cpp | 61 +++++++++++++ .../{control_rod.hpp => boron_rod.hpp} | 13 +-- src/reactor/control/control_rod.cpp | 47 ---------- src/reactor/control/graphite_rod.cpp | 6 ++ src/reactor/control/graphite_rod.hpp | 5 +- src/reactor/coolant/heater.hpp | 2 + src/reactor/coolant/pipe.cpp | 6 +- src/reactor/coolant/pipe.hpp | 1 + src/reactor/coolant/vessel.cpp | 6 +- src/reactor/coolant/vessel.hpp | 4 +- src/reactor/fuel/fuel_rod.cpp | 70 +++++++++++++-- src/reactor/fuel/fuel_rod.hpp | 6 +- src/reactor/fuel/sample.cpp | 10 +-- src/reactor/fuel/sample.hpp | 2 +- src/reactor/reactor.cpp | 39 +++++++- src/reactor/reactor.hpp | 7 +- src/reactor/rod.cpp | 7 ++ src/reactor/rod.hpp | 12 ++- src/system.cpp | 78 ++++++++++------ src/system.hpp | 16 ++-- 34 files changed, 588 insertions(+), 235 deletions(-) create mode 100644 src/graphics/mesh/glmesh.cpp create mode 100644 src/graphics/mesh/glmesh.hpp create mode 100644 src/reactor/control/boron_rod.cpp rename src/reactor/control/{control_rod.hpp => boron_rod.hpp} (54%) delete mode 100644 src/reactor/control/control_rod.cpp diff --git a/src/graphics/mesh/font.cpp b/src/graphics/mesh/font.cpp index eebc48b..846e68d 100644 --- a/src/graphics/mesh/font.cpp +++ b/src/graphics/mesh/font.cpp @@ -137,7 +137,7 @@ void mesh::load_text(const char* text, double size) x += ch.advance * size; } - set_vertices(&vertices[0], vertices.size(), GL_DYNAMIC_DRAW); - set_indices(&indices[0], indices.size(), GL_DYNAMIC_DRAW); + set_vertices(&vertices[0], vertices.size()); + set_indices(&indices[0], indices.size()); } diff --git a/src/graphics/mesh/glmesh.cpp b/src/graphics/mesh/glmesh.cpp new file mode 100644 index 0000000..9e9b47e --- /dev/null +++ b/src/graphics/mesh/glmesh.cpp @@ -0,0 +1,78 @@ + +#include +#include + +#include "glmesh.hpp" +#include "arrays.hpp" +#include "../shader.hpp" +#include "../camera.hpp" + +using namespace sim::graphics; + +constexpr static void init(glmesh* m) +{ + if(m->vao != 0) + { + return; + } + + glGenVertexArrays(1, &m->vao); + glGenBuffers(1, &m->vbo); + glGenBuffers(1, &m->ebo); + + glBindVertexArray(m->vao); + glBindBuffer(GL_ARRAY_BUFFER, m->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ebo); + + arrays::vertex_attrib_pointers(); +} + +glmesh::glmesh(glmesh&& o) +{ + vbo = o.vbo; + ebo = o.ebo; + vao = o.vao; + size = o.size; + colour_matrix = o.colour_matrix; + model_matrix = o.model_matrix; + + o.vbo = 0; + o.ebo = 0; + o.vao = 0; +} + +glmesh::~glmesh() +{ + if(vbo) glDeleteBuffers(1, &vbo); + if(ebo) glDeleteBuffers(1, &ebo); + if(vao) glDeleteVertexArrays(1, &vao); +} + +void glmesh::bind() +{ + init(this); + + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); +} + +void glmesh::uniform() +{ + glm::mat4 m = camera::get_matrix() * model_matrix; + glUniformMatrix4fv(shader::gl_model, 1, false, &m[0][0]); + glUniformMatrix4fv(shader::gl_tex_mat, 1, false, &colour_matrix[0][0]); +} + +void glmesh::set(const mesh& m, int mode) +{ + glBufferData(GL_ARRAY_BUFFER, m.vertices.size() * sizeof(m.vertices[0]), &m.vertices[0], mode); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m.indices.size() * sizeof(m.indices[0]), &m.indices[0], mode); + this->size = m.indices.size(); +} + +void glmesh::render() +{ + glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0); +} + diff --git a/src/graphics/mesh/glmesh.hpp b/src/graphics/mesh/glmesh.hpp new file mode 100644 index 0000000..ff04e6d --- /dev/null +++ b/src/graphics/mesh/glmesh.hpp @@ -0,0 +1,34 @@ + +#pragma once + +#include + +#include "arrays.hpp" +#include "mesh.hpp" + +#include + +namespace sim::graphics +{ + +struct glmesh +{ + unsigned int vao = 0, vbo = 0, ebo = 0, size = 0; + + glm::mat4 model_matrix {1.0f}; + glm::mat4 colour_matrix {1.0f}; + + constexpr glmesh() { } + + glmesh(glmesh&& o); + glmesh(const glmesh& o) = delete; + ~glmesh(); + + void bind(); + void uniform(); + void set(const mesh& m, int mode); + void render(); +}; + +}; + diff --git a/src/graphics/mesh/mesh.cpp b/src/graphics/mesh/mesh.cpp index 3a1ed76..a411602 100644 --- a/src/graphics/mesh/mesh.cpp +++ b/src/graphics/mesh/mesh.cpp @@ -1,7 +1,4 @@ -#include -#include - #include "mesh.hpp" #include "arrays.hpp" #include "../shader.hpp" @@ -9,71 +6,47 @@ using namespace sim::graphics; -constexpr static void init(mesh* m) +void mesh::add(const mesh& o, glm::mat4 mat) { - if(m->vao != 0) + unsigned int off = vertices.size(); + glm::mat3 mat3(mat); + + vertices.reserve(vertices.size() + o.vertices.size()); + indices.reserve(indices.size() + o.indices.size()); + + for(unsigned int i = 0; i < o.vertices.size(); i++) { - return; + arrays::vertex v = o.vertices[i]; + v.normal = v.normal * mat3; + v.pos = v.pos * mat; + vertices.push_back(v); } - glGenVertexArrays(1, &m->vao); - glGenBuffers(1, &m->vbo); - glGenBuffers(1, &m->ebo); - - glBindVertexArray(m->vao); - glBindBuffer(GL_ARRAY_BUFFER, m->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ebo); - - arrays::vertex_attrib_pointers(); + for(unsigned int i = 0; i < o.indices.size(); i++) + { + indices.push_back(o.indices[i] + off); + } } -mesh::mesh(mesh&& o) +void mesh::set_vertices(const arrays::vertex* data, size_t size) { - vbo = o.vbo; - ebo = o.ebo; - vao = o.vao; - size = o.size; - colour_matrix = o.colour_matrix; - model_matrix = o.model_matrix; + vertices.clear(); + vertices.reserve(size); - o.vbo = 0; - o.ebo = 0; - o.vao = 0; + for(unsigned int i = 0; i < size; i++) + { + vertices.push_back(data[i]); + } } -mesh::~mesh() +void mesh::set_indices(const unsigned int* data, size_t size) { - if(vbo) glDeleteBuffers(1, &vbo); - if(ebo) glDeleteBuffers(1, &ebo); - if(vao) glDeleteVertexArrays(1, &vao); -} - -void mesh::set_vertices(const arrays::vertex* data, size_t size, int mode) -{ - glBufferData(GL_ARRAY_BUFFER, size * sizeof(data[0]), data, mode); -} - -void mesh::set_indices(const unsigned int* data, size_t size, int mode) -{ - glBufferData(GL_ELEMENT_ARRAY_BUFFER, size * sizeof(data[0]), data, mode); - this->size = size; -} - -void mesh::bind() -{ - init(this); - - glm::mat4 m = camera::get_matrix() * model_matrix; - glUniformMatrix4fv(shader::gl_model, 1, false, &m[0][0]); - glUniformMatrix4fv(shader::gl_tex_mat, 1, false, &colour_matrix[0][0]); - - glBindVertexArray(vao); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); -} - -void mesh::render() -{ - glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0); + indices.clear(); + indices.reserve(size); + + for(unsigned int i = 0; i < size; i++) + { + indices.push_back(data[i]); + } } diff --git a/src/graphics/mesh/mesh.hpp b/src/graphics/mesh/mesh.hpp index dc2aa7c..698cbc1 100644 --- a/src/graphics/mesh/mesh.hpp +++ b/src/graphics/mesh/mesh.hpp @@ -2,35 +2,30 @@ #pragma once #include +#include +#include + +#include #include "arrays.hpp" -#include -#include namespace sim::graphics { struct mesh { - unsigned int vao = 0, vbo = 0, ebo = 0, size = 0; - - glm::mat4 model_matrix {1.0f}; - glm::mat4 colour_matrix {1.0f}; + std::vector vertices; + std::vector indices; constexpr mesh() { } - mesh(mesh&& o); - mesh(const mesh& o) = delete; - ~mesh(); - - void bind(); - void set_vertices(const arrays::vertex* data, size_t size, int mode); - void set_indices(const unsigned int* data, size_t size, int mode); + void set_vertices(const arrays::vertex* data, size_t size); + void set_indices(const unsigned int* data, size_t size); void load_model(std::string base, std::string path); void load_model(std::string path) { load_model(".", path); } void load_text(const char* text, double size); - void render(); + void add(const mesh& o, glm::mat4 mat); template void load_text(const char* header, T& item, double size) diff --git a/src/graphics/mesh/model.cpp b/src/graphics/mesh/model.cpp index f9500a2..949944b 100644 --- a/src/graphics/mesh/model.cpp +++ b/src/graphics/mesh/model.cpp @@ -64,6 +64,7 @@ static void proc_mesh(proc_state& state, glm::mat4 mat, aiMesh* mesh, const aiSc aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; unsigned int handle = proc_texture(state, material, scene); unsigned int offset = state.offset; + glm::mat3 mat3(mat); for(unsigned int i = 0; i < mesh->mNumVertices; i++) { @@ -76,7 +77,7 @@ static void proc_mesh(proc_state& state, glm::mat4 mat, aiMesh* mesh, const aiSc if(mesh->HasNormals()) { auto [x, y, z] = mesh->mNormals[i]; - vertex.normal = glm::vec3(x, y, z) * glm::mat3(mat); + vertex.normal = glm::vec3(x, y, z) * mat3; } if(mesh->mTextureCoords[0]) @@ -165,7 +166,7 @@ void mesh::load_model(std::string base, std::string filename) proc_node(state, glm::mat4(1), scene->mRootNode, scene); - set_vertices(&state.vertices[0], state.vertices.size(), GL_STATIC_DRAW); - set_indices(&state.indices[0], state.indices.size(), GL_STATIC_DRAW); + set_vertices(&state.vertices[0], state.vertices.size()); + set_indices(&state.indices[0], state.indices.size()); } diff --git a/src/graphics/monitor/core.cpp b/src/graphics/monitor/core.cpp index 81d53fd..522760f 100644 --- a/src/graphics/monitor/core.cpp +++ b/src/graphics/monitor/core.cpp @@ -1,4 +1,7 @@ +#include +#include + #include "core.hpp" #include "../locations.hpp" @@ -14,7 +17,7 @@ core::core() void core::init() { - mesh1.model_matrix = mesh2.model_matrix = locations::monitors[2]; + mesh1.model_matrix = locations::monitors[2]; mesh1.colour_matrix = { 1, 1, 1, 1, 0, 0, 0, 0, @@ -22,23 +25,57 @@ void core::init() 0, 0, 0, 0 }; - std::stringstream ss; - - ss << "Reactor Core"; + sim::graphics::mesh rmesh1, rmesh2; + + rmesh1.load_text("Reactor Core", 0.04); + rmesh2.load_model("../assets/model/", "reactor_core_interface_circle.stl"); + rmesh1.add(rmesh2, glm::mat4(1)); mesh1.bind(); - mesh1.load_text(ss.str().c_str(), 0.05); + mesh1.set(rmesh1, GL_STATIC_DRAW); + rmesh2.load_model("../assets/model/", "reactor_core_interface_cell.stl"); mesh2.bind(); - mesh2.load_model("../assets/model/", "reactor_core_interface.stl"); + mesh2.set(rmesh2, GL_STATIC_DRAW); } -void core::update(sim::system& sys) +void core::render(sim::system& sys) { -} - -void core::render() -{ - mesh1.bind(); mesh1.render(); - mesh2.bind(); mesh2.render(); + double step = 1 / (sys.vessel->diameter / sys.reactor->cell_width * 0.8); + double sx = 0.5 - (sys.reactor->width - 1) * step / 2.0; + double sy = 0.5 - (sys.reactor->height - 1) * step / 2.0; + + glm::mat4 mat_scale = glm::scale(glm::mat4(1), glm::vec3(step * 0.5, step * 0.5, 1)); + + mesh1.bind(); + mesh1.uniform(); + mesh1.render(); + mesh2.bind(); + + for(int i = 0; i < sys.reactor->size; i++) + { + int x = i % sys.reactor->width; + int y = i / sys.reactor->width; + double ox = sx + x * step; + double oy = sy + y * step; + + reactor::rod* r = sys.reactor->rods[i].get(); + glm::vec4 colour = r->get_colour(); + + if(!r->should_display() || colour[3] == 0) + { + continue; + } + + mesh2.model_matrix = mesh1.model_matrix * glm::translate(glm::mat4(1), glm::vec3(ox, oy, 0)) * mat_scale; + mesh2.colour_matrix = glm::mat4({ + colour[0], colour[1], colour[2], colour[3], + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }); + + mesh2.uniform(); + mesh2.render(); + } } diff --git a/src/graphics/monitor/core.hpp b/src/graphics/monitor/core.hpp index 1142ee0..09908f2 100644 --- a/src/graphics/monitor/core.hpp +++ b/src/graphics/monitor/core.hpp @@ -1,7 +1,7 @@ #pragma once -#include "../mesh/mesh.hpp" +#include "../mesh/glmesh.hpp" #include "../../system.hpp" namespace sim::graphics::monitor @@ -9,14 +9,13 @@ namespace sim::graphics::monitor class core { - sim::graphics::mesh mesh1, mesh2; + sim::graphics::glmesh mesh1, mesh2; public: core(); void init(); - void update(sim::system& sys); - void render(); + void render(sim::system& sys); }; }; diff --git a/src/graphics/monitor/vessel.cpp b/src/graphics/monitor/vessel.cpp index 5dded40..8c985fe 100644 --- a/src/graphics/monitor/vessel.cpp +++ b/src/graphics/monitor/vessel.cpp @@ -1,5 +1,10 @@ +#include +#include + #include "vessel.hpp" +#include "../../reactor/rod.hpp" +#include "../../reactor/control/boron_rod.hpp" #include "../locations.hpp" #include @@ -15,7 +20,7 @@ vessel::vessel() void vessel::init() { mesh1.model_matrix = locations::monitors[1]; - mesh2.model_matrix = glm::translate(mesh1.model_matrix, glm::vec3(3.0 / 8.0, 0, 0)); + mesh2.model_matrix = glm::translate(mesh1.model_matrix, glm::vec3(0.5, 0, 0)); mesh1.colour_matrix = mesh2.colour_matrix = { 1, 1, 1, 1, @@ -25,36 +30,88 @@ void vessel::init() }; std::stringstream ss; + sim::graphics::mesh rmesh; ss << "Reactor Vessel\n\n"; ss << "Heat\n"; ss << "Steam\n"; ss << "Pressure\n"; ss << "Level\n"; - ss << "Void Ratio\n"; + ss << "Void Ratio\n\n\n\n"; + ss << "Reactor Core\n\n"; + ss << "Temperature\nMin\nMax\n\n"; + ss << "Neutron Flux\nSlow\nFast\n\n"; + ss << "Control Rods\nMin\nMax\n\n"; + rmesh.load_text(ss.str().c_str(), 0.04); mesh1.bind(); - mesh1.load_text(ss.str().c_str(), 0.05); + mesh1.set(rmesh, GL_STATIC_DRAW); +} + +static double show(double v) +{ + return std::round(v * 1e3) * 1e-3; } void vessel::update(sim::system& sys) { std::stringstream ss; + sim::graphics::mesh rmesh; + + double temp_min, temp_max; + double crod_min = INFINITY, crod_max = -INFINITY; + + sys.reactor->get_stats(sim::reactor::rod::val_t::HEAT, temp_min, temp_max); + + for(int i = 0; i < sys.reactor->size; i++) + { + sim::reactor::rod* r = sys.reactor->rods[i].get(); + + if(r->get_id() != 5) + { + continue; + } + + auto br = (sim::reactor::control::boron_rod*)r; + double v = br->get_inserted(); + + if(v > crod_max) + { + crod_max = v; + } + + if(v < crod_min) + { + crod_min = v; + } + } ss << "\n\n"; - ss << sys.vessel.get_heat() << " C\n"; - ss << sys.vessel.get_steam() << " g\n"; - ss << (sys.vessel.get_pressure() * 0.001) << " kPa\n"; - ss << sys.vessel.get_level() << " / " << sys.vessel.get_volume() << " L\n"; - ss << (sys.vessel.get_void_ratio() * 100) << " %\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"; + ss << show( sys.vessel->get_level() ) << " / " << show( sys.vessel->get_volume() ) << " L\n"; + ss << show( sys.vessel->get_void_ratio() * 100 ) << " %\n\n\n\n\n\n\n"; + ss << show( temp_min ) << " C\n"; + ss << show( temp_max ) << " C\n\n\n"; + ss << sys.reactor->get_total(sim::reactor::rod::val_t::N_SLOW) << " mol\n"; + ss << sys.reactor->get_total(sim::reactor::rod::val_t::N_FAST) << " mol\n\n\n"; + ss << show( crod_min * 100 ) << " %\n"; + ss << show( crod_max * 100 ) << " %\n"; + rmesh.load_text(ss.str().c_str(), 0.04); mesh2.bind(); - mesh2.load_text(ss.str().c_str(), 0.05); + mesh2.set(rmesh, GL_DYNAMIC_DRAW); } void vessel::render() { - mesh1.bind(); mesh1.render(); - mesh2.bind(); mesh2.render(); + mesh1.bind(); + mesh1.uniform(); + mesh1.render(); + + mesh2.bind(); + mesh2.uniform(); + mesh2.render(); } diff --git a/src/graphics/monitor/vessel.hpp b/src/graphics/monitor/vessel.hpp index b173e77..016bd08 100644 --- a/src/graphics/monitor/vessel.hpp +++ b/src/graphics/monitor/vessel.hpp @@ -1,7 +1,7 @@ #pragma once -#include "../mesh/mesh.hpp" +#include "../mesh/glmesh.hpp" #include "../../system.hpp" namespace sim::graphics::monitor @@ -9,7 +9,7 @@ namespace sim::graphics::monitor class vessel { - sim::graphics::mesh mesh1, mesh2; + sim::graphics::glmesh mesh1, mesh2; public: diff --git a/src/graphics/window.cpp b/src/graphics/window.cpp index fc3f503..b09996a 100644 --- a/src/graphics/window.cpp +++ b/src/graphics/window.cpp @@ -28,7 +28,7 @@ using namespace sim::graphics; static GLFWwindow* win; static bool win_should_close = false; -static mesh MeshScene; +static glmesh MeshScene; static monitor::vessel MonitorVessel; static monitor::core MonitorCore; @@ -96,9 +96,11 @@ void window::create() font::init(); shader::init_program(); + mesh rmesh; + rmesh.load_model("../assets", "scene-baked.glb"); MeshScene.bind(); - MeshScene.load_model("../assets", "scene-baked.glb"); + MeshScene.set(rmesh, GL_STATIC_DRAW); MonitorCore.init(); MonitorVessel.init(); @@ -109,7 +111,6 @@ void window::create() void window::loop(sim::system& sys) { - MonitorCore.update(sys); MonitorVessel.update(sys); glm::mat4 mat_projection = glm::perspective(glm::radians(80.0f), resize::get_aspect(), 0.01f, 20.f); @@ -118,9 +119,11 @@ void window::loop(sim::system& sys) glClearColor(0, 0, 0, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - MeshScene.bind(); MeshScene.render(); + MeshScene.bind(); + MeshScene.uniform(); + MeshScene.render(); - MonitorCore.render(); + MonitorCore.render(sys); MonitorVessel.render(); glfwSwapBuffers(win); diff --git a/src/main.cpp b/src/main.cpp index 79e1d88..2dffe43 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,7 +27,7 @@ unsigned long get_now() int main() { graphics::window::create(); - sim::system sys(system::generate()); + sim::system sys; long clock = get_now(); diff --git a/src/reactor/builder.cpp b/src/reactor/builder.cpp index 58e9cf3..53495b4 100644 --- a/src/reactor/builder.cpp +++ b/src/reactor/builder.cpp @@ -1,11 +1,14 @@ #include "builder.hpp" +#include +#include + using namespace sim::reactor; -sim::reactor::reactor sim::reactor::builder(const int W, const int H, fuel::fuel_rod fr, control::control_rod cr, coolant::pipe p, 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, control::boron_rod br, coolant::vessel& v, const char** lines) { - std::unique_ptr arr[W * H]; + std::vector> arr(W * H); for(int y = 0; y < H; y++) for(int x = 0; x < W; x++) @@ -19,7 +22,7 @@ sim::reactor::reactor sim::reactor::builder(const int W, const int H, fuel::fuel r = new fuel::fuel_rod(fr); break; case 'C': - r = new control::control_rod(cr); + r = new control::boron_rod(br); break; case 'G': r = new control::graphite_rod(); @@ -27,10 +30,10 @@ sim::reactor::reactor sim::reactor::builder(const int W, const int H, fuel::fuel case 'H': r = new coolant::heater(); break; - case ' ': - r = new coolant::pipe(p); + case 'P': + r = new coolant::pipe(v); break; - case '#': + case ' ': r = new rod(); break; } @@ -38,6 +41,6 @@ sim::reactor::reactor sim::reactor::builder(const int W, const int H, fuel::fuel arr[y * W + x] = std::unique_ptr(std::move(r)); } - return reactor(arr, W, H); + return reactor(&arr[0], W, H, CW, CH); } diff --git a/src/reactor/builder.hpp b/src/reactor/builder.hpp index 79ba7ba..8bfa264 100644 --- a/src/reactor/builder.hpp +++ b/src/reactor/builder.hpp @@ -3,16 +3,17 @@ #include "rod.hpp" #include "fuel/fuel_rod.hpp" -#include "control/control_rod.hpp" +#include "control/boron_rod.hpp" #include "control/graphite_rod.hpp" #include "coolant/pipe.hpp" #include "coolant/heater.hpp" +#include "coolant/vessel.hpp" #include "reactor.hpp" namespace sim::reactor { -reactor builder(const int W, const int H, fuel::fuel_rod fr, control::control_rod cr, coolant::pipe p, const char** lines); +reactor builder(const int W, const int H, const double CW, const double CH, fuel::fuel_rod fr, control::boron_rod br, coolant::vessel& v, const char** lines); }; diff --git a/src/reactor/control/boron_rod.cpp b/src/reactor/control/boron_rod.cpp new file mode 100644 index 0000000..7a9e6e8 --- /dev/null +++ b/src/reactor/control/boron_rod.cpp @@ -0,0 +1,61 @@ + +#include "boron_rod.hpp" + +#include + +using namespace sim::reactor::control; + +constexpr double boron_density = 2340000; // g/m^3 +constexpr double boron_molar_mass = 10; // g/mol +constexpr double boron_molar_density = boron_density / boron_molar_mass; // mol/m^3 + +boron_rod::boron_rod(coolant::vessel& v, double max) : coolant::pipe(v), max(max) +{ + +} + +void boron_rod::display(std::ostream& o) const +{ + double limit = get_volume() * boron_molar_density; + + o << "Inserted: " << (inserted * 100) << "%\n"; + o << "Use: " << (absorbed * limit) << " / " << limit << "\n"; +}; + +void boron_rod::set_reactivity(double a) +{ + inserted = 1 - a; +} + +glm::vec4 boron_rod::get_colour() const +{ + double v = inserted * 0.75 + 0.25; + return {v, v, v, 1}; +} + +void boron_rod::update(double secs) +{ + double limit = get_volume() * boron_molar_density; + + update_rod(secs); + + double k = (1 - absorbed) * inserted * max; + double m = 1 - std::pow(0.5, secs * -std::log2(1 - k)); + double r_fast = vals[val_t::N_FAST] * m; + double r_slow = vals[val_t::N_SLOW] * m; + + vals[val_t::N_FAST] -= r_fast; + vals[val_t::N_SLOW] -= r_slow; + absorbed += (r_fast + r_slow) / limit; + + update_pipe(secs); +} + +void boron_rod::update_selected(double a) +{ + inserted += a; + + if(inserted > 1) inserted = 1; + if(inserted < 0) inserted = 0; +} + diff --git a/src/reactor/control/control_rod.hpp b/src/reactor/control/boron_rod.hpp similarity index 54% rename from src/reactor/control/control_rod.hpp rename to src/reactor/control/boron_rod.hpp index 655b74d..a5b59bf 100644 --- a/src/reactor/control/control_rod.hpp +++ b/src/reactor/control/boron_rod.hpp @@ -6,25 +6,26 @@ namespace sim::reactor::control { -class control_rod : public sim::reactor::coolant::pipe +class boron_rod : public sim::reactor::coolant::pipe { - const double limit; const double max; double inserted = 1; double absorbed = 0; virtual void display(std::ostream& o) const; - - virtual const char* get_name() const { return "Control Rod"; } - virtual rod* clone() const { return new control_rod(*this); }; + virtual const char* get_name() const { return "Boron Control Rod"; } + virtual rod* clone() const { return new boron_rod(*this); } + virtual glm::vec4 get_colour() const; + virtual int get_id() const { return 5; } public: - control_rod(coolant::vessel& v, double limit, double max); + boron_rod(coolant::vessel& v, double max); virtual void update(double secs); void set_reactivity(double a); + double get_inserted() { return inserted; } virtual bool should_display() const { return true; } virtual bool should_select() const { return true; } diff --git a/src/reactor/control/control_rod.cpp b/src/reactor/control/control_rod.cpp deleted file mode 100644 index e955b98..0000000 --- a/src/reactor/control/control_rod.cpp +++ /dev/null @@ -1,47 +0,0 @@ - -#include "control_rod.hpp" - -#include - -using namespace sim::reactor::control; - -control_rod::control_rod(coolant::vessel& v, double limit, double max) : coolant::pipe(v), limit(limit), max(max) -{ - -} - -void control_rod::display(std::ostream& o) const -{ - o << "Inserted: " << (inserted * 100) << "%\n"; - o << "Use: " << absorbed << " / " << limit << " mol\n"; -}; - -void control_rod::set_reactivity(double a) -{ - inserted = 1 - a; -} - -void control_rod::update(double secs) -{ - update_rod(secs); - - double k = (1 - absorbed / limit) * inserted * max; - double m = 1 - std::pow(0.5, secs * -std::log2(1 - k)); - double r_fast = vals[val_t::N_FAST] * m; - double r_slow = vals[val_t::N_SLOW] * m; - - vals[val_t::N_FAST] -= r_fast; - vals[val_t::N_SLOW] -= r_slow; - absorbed += r_fast + r_slow; - - update_pipe(secs); -} - -void control_rod::update_selected(double a) -{ - inserted += a; - - if(inserted > 1) inserted = 1; - if(inserted < 0) inserted = 0; -} - diff --git a/src/reactor/control/graphite_rod.cpp b/src/reactor/control/graphite_rod.cpp index 19f8907..7c87b9d 100644 --- a/src/reactor/control/graphite_rod.cpp +++ b/src/reactor/control/graphite_rod.cpp @@ -10,6 +10,12 @@ void graphite_rod::display(std::ostream& o) const o << "Inserted: " << (inserted * 100) << "%\n"; }; +glm::vec4 graphite_rod::get_colour() const +{ + double v = inserted * 0.75 + 0.25; + return {v, v, v, 1}; +} + double graphite_rod::get_k(val_t type) const { if(type == val_t::HEAT) return 0.5; diff --git a/src/reactor/control/graphite_rod.hpp b/src/reactor/control/graphite_rod.hpp index 698f742..a77b63e 100644 --- a/src/reactor/control/graphite_rod.hpp +++ b/src/reactor/control/graphite_rod.hpp @@ -11,10 +11,13 @@ class graphite_rod : public sim::reactor::rod double inserted = 0; virtual void display(std::ostream& o) const; - virtual const char* get_name() const { return "Graphite Rod"; } virtual rod* clone() const { return new graphite_rod(*this); }; virtual double get_k(val_t type) const; + virtual glm::vec4 get_colour() const; + virtual int get_id() const { return 4; } + + double get_inserted() { return inserted; } public: diff --git a/src/reactor/coolant/heater.hpp b/src/reactor/coolant/heater.hpp index f9fa1a4..c906335 100644 --- a/src/reactor/coolant/heater.hpp +++ b/src/reactor/coolant/heater.hpp @@ -12,9 +12,11 @@ class heater : public sim::reactor::rod virtual void display(std::ostream& o) const; + virtual bool has_sensors(val_t t) const { return true; } virtual const char* get_name() const { return "Heater"; } virtual double get_k(val_t type) const { return 0.5; } virtual rod* clone() const { return new heater(*this); }; + virtual int get_id() const { return 3; } public: diff --git a/src/reactor/coolant/pipe.cpp b/src/reactor/coolant/pipe.cpp index e78810e..7bcd4e0 100644 --- a/src/reactor/coolant/pipe.cpp +++ b/src/reactor/coolant/pipe.cpp @@ -1,5 +1,6 @@ #include "pipe.hpp" +#include "../reactor.hpp" using namespace sim::reactor::coolant; @@ -22,7 +23,10 @@ void pipe::update(double secs) void pipe::update_pipe(double secs) { - vals[val_t::HEAT] = vessel->add_heat(vals[val_t::HEAT]); + sim::reactor::reactor* r = (sim::reactor::reactor*)reactor; + double m = r->cell_width * r->cell_width * r->cell_height * 1e6; + + vals[val_t::HEAT] = vessel->add_heat(m, vals[val_t::HEAT]); vals[val_t::N_SLOW] += vals[val_t::N_FAST]; vals[val_t::N_FAST] = 0; } diff --git a/src/reactor/coolant/pipe.hpp b/src/reactor/coolant/pipe.hpp index b184bec..46deb5f 100644 --- a/src/reactor/coolant/pipe.hpp +++ b/src/reactor/coolant/pipe.hpp @@ -17,6 +17,7 @@ protected: virtual double get_k(sim::reactor::rod::val_t type) const; virtual const char* get_name() const { return "Coolant"; } virtual rod* clone() const { return new pipe(*this); }; + virtual int get_id() const { return 2; } void update_pipe(double secs); diff --git a/src/reactor/coolant/vessel.cpp b/src/reactor/coolant/vessel.cpp index 5cbd1ad..0c82ffe 100644 --- a/src/reactor/coolant/vessel.cpp +++ b/src/reactor/coolant/vessel.cpp @@ -65,15 +65,15 @@ void vessel::update(double secs) steam_suspended *= fuel::half_life::get(secs, bubble_hl); } -double vessel::add_heat(double t1) +double vessel::add_heat(double m1, double t1) { double t2 = get_heat(); double t = t1 - t2; - double m1 = 1e6; double m2 = (fluid.l_to_g(level) + steam) * fluid.jPgk; double m = m1 + m2; - return heat = t1 - t * m2 / m; + heat = t1 - t * m2 / m; + return heat; } double vessel::add_fluid(double m2, double t2) diff --git a/src/reactor/coolant/vessel.hpp b/src/reactor/coolant/vessel.hpp index f95a59d..99ddcac 100644 --- a/src/reactor/coolant/vessel.hpp +++ b/src/reactor/coolant/vessel.hpp @@ -11,7 +11,7 @@ namespace sim::reactor::coolant class vessel { double level; // litres - double heat = 0; // celcius + double heat = 0; // celsius double steam = 0; // grams double steam_suspended = 0; // grams @@ -27,7 +27,7 @@ public: vessel(double height, double diameter, double level, sim::coolant::fluid_t fluid); void update(double secs); - double add_heat(double amount); + double add_heat(double m, double t); double add_fluid(double amount, double heat); double extract_steam(double dt, double a, double p2); diff --git a/src/reactor/fuel/fuel_rod.cpp b/src/reactor/fuel/fuel_rod.cpp index fc96c2d..6951be9 100644 --- a/src/reactor/fuel/fuel_rod.cpp +++ b/src/reactor/fuel/fuel_rod.cpp @@ -1,33 +1,87 @@ #include "fuel_rod.hpp" +#include + using namespace sim::reactor::fuel; -fuel_rod::fuel_rod(double fuel, double mass) : s(fuel, mass) +constexpr double fuel_density = 19100000; // g/m^3 +constexpr double fuel_molar_mass = 238.029; // g/mol +constexpr double fuel_molar_density = fuel_density / fuel_molar_mass; // mol/m^3 +constexpr double energy_density = 165e11; // J/mol + +fuel_rod::fuel_rod(double fuel) : s(fuel) { } void fuel_rod::display(std::ostream& o) const { - o << "Fuel: " << s.get_fuel() << " / " << s.get_mass() << " mol\n"; + double mol = fuel_molar_density * get_volume(); + + o << "Fuel: " << (s.get_fuel() * mol) << " / " << (s.get_mass() * mol) << " mol\n"; o << "Efficiency: " << (s.get_efficiency() * 100) << " %\n"; - o << "Output: " << s.get_energy() << " W/s\n"; - o << "Iodine: " << s.get_i_135() << " mol\n"; - o << "Xenon: " << s.get_xe_135() << " mol\n"; + o << "Output: " << (s.get_energy() * mol * energy_density) << " W/s\n"; + o << "Iodine: " << (s.get_i_135() * mol) << " mol\n"; + o << "Xenon: " << (s.get_xe_135() * mol) << " mol\n"; +} + +static float map(float v, float imin, float imax, float omin, float omax) +{ + return (v - imin) * (omax - omin) / (imax - imin) + omin; +} + +glm::vec4 fuel_rod::get_colour() const +{ + double temp = vals[val_t::HEAT]; + + if(temp < 0) + { + temp = 0; + } + + // this should not happen + if(std::isnan(temp)) + { + return {1, 0, 1, 1}; + } + + if(temp < 120) + { + return {0, map(temp, 0, 120, 0, 1), 1, 1}; + } + + if(temp < 240) + { + return {0, 1, map(temp, 120, 240, 1, 0), 1}; + } + + if(temp < 280) + { + return {map(temp, 240, 280, 0, 1), 1, 0, 1}; + } + + if(temp < 320) + { + return {1, map(temp, 280, 320, 1, 0), 0, 1}; + } + + return {1, 0, 0, 1}; } void fuel_rod::update(double secs) { update_rod(secs); + double mol = fuel_molar_density * get_volume(); + s.clear_energy(); s.clear_fast_neutrons(); - s.add_slow_neutrons(vals[val_t::N_SLOW]); + s.add_slow_neutrons(vals[val_t::N_SLOW] / mol); s.update(secs); - vals[val_t::HEAT] += s.get_energy() * secs; - vals[val_t::N_FAST] += s.get_fast_neutrons(); + vals[val_t::HEAT] += s.get_energy() * mol * energy_density * secs; + vals[val_t::N_FAST] += s.get_fast_neutrons() * mol; vals[val_t::N_SLOW] = 0; } diff --git a/src/reactor/fuel/fuel_rod.hpp b/src/reactor/fuel/fuel_rod.hpp index 68a6635..1e1b12d 100644 --- a/src/reactor/fuel/fuel_rod.hpp +++ b/src/reactor/fuel/fuel_rod.hpp @@ -14,15 +14,17 @@ class fuel_rod : public sim::reactor::rod virtual double get_k(val_t type) const { return 0.5; } virtual void display(std::ostream& o) const; + virtual bool has_sensors(val_t t) const { return true; } virtual const char* get_name() const { return "Fuel"; } virtual rod* clone() const { return new fuel_rod(*this); }; + virtual int get_id() const { return 1; } + virtual glm::vec4 get_colour() const; public: - fuel_rod(double fuel, double mass); + fuel_rod(double fuel); virtual bool should_display() const { return true; } - virtual void update(double secs); }; diff --git a/src/reactor/fuel/sample.cpp b/src/reactor/fuel/sample.cpp index 8ded7d5..8021191 100644 --- a/src/reactor/fuel/sample.cpp +++ b/src/reactor/fuel/sample.cpp @@ -6,12 +6,12 @@ using namespace sim::reactor::fuel; -static const double NEUTRON_BG = 1e-10; +static const double NEUTRON_BG = 1e-25; -sample::sample(double fuel, double mass) +sample::sample(double fuel) { this->fuel = fuel; - this->mass = mass; + this->mass = 1; } void sample::update(double secs) @@ -21,7 +21,7 @@ void sample::update(double secs) // decay waste and extract products waste.update(secs); fast_neutrons += waste.extract_neutrons(); - energy += waste.extract_energy(); + energy += waste.extract_energy() * (1.0 / 30.0); // decay Xe-135 m = half_life::get(secs, half_life::Xe_135); @@ -59,7 +59,7 @@ void sample::update(double secs) efficiency = neutrons_fuel / neutrons_total; // simulate fuel use - energy += neutrons_fuel / secs; + energy += neutrons_fuel / secs * 0.8; waste.add_fissile(neutrons_fuel * 6); } diff --git a/src/reactor/fuel/sample.hpp b/src/reactor/fuel/sample.hpp index c69cacc..4579c0c 100644 --- a/src/reactor/fuel/sample.hpp +++ b/src/reactor/fuel/sample.hpp @@ -31,7 +31,7 @@ class sample public: - sample(double fuel, double mass); + sample(double fuel); void update(double secs); diff --git a/src/reactor/reactor.cpp b/src/reactor/reactor.cpp index 32ee09d..73b2a22 100644 --- a/src/reactor/reactor.cpp +++ b/src/reactor/reactor.cpp @@ -6,24 +6,25 @@ using namespace sim::reactor; -reactor::reactor(std::unique_ptr* rods, int width, int height) : width(width), height(height), size(width * height) +reactor::reactor(std::unique_ptr* rods, int w, int h, double cw, double ch) : cell_width(cw), cell_height(ch), width(w), height(h), size(w * h) { this->rods = new std::unique_ptr[width * height]; for(int i = 0; i < size; i++) { this->rods[i] = std::move(rods[i]); + this->rods[i]->reactor = this; } } -reactor::reactor(reactor&& o) : width(o.width), height(o.height), size(o.size) +reactor::reactor(reactor&& o) : cell_width(o.cell_width), cell_height(o.cell_height), width(o.width), height(o.height), size(o.size) { rods = o.rods; cursor = o.cursor; o.rods = nullptr; } -reactor::reactor(const reactor& o) : width(o.width), height(o.height), size(o.size) +reactor::reactor(const reactor& o) : cell_width(o.cell_width), cell_height(o.cell_height), width(o.width), height(o.height), size(o.size) { rods = new std::unique_ptr[width * height]; @@ -132,3 +133,35 @@ void reactor::update_interactions(int* rods_lookup, double secs) } } } + +double reactor::get_total(rod::val_t type) +{ + double v = 0; + + for(int i = 0; i < size; i++) + { + v += rods[i]->get(type); + } + + return v; +} + +void reactor::get_stats(rod::val_t type, double& min, double& max) +{ + min = INFINITY; + max = -INFINITY; + + for(int i = 0; i < size; i++) + { + if(!rods[i]->has_sensors(type)) + { + continue; + } + + double v = rods[i]->get(type); + + if(v > max) max = v; + if(v < min) min = v; + } +} + diff --git a/src/reactor/reactor.hpp b/src/reactor/reactor.hpp index 0a64139..55e7e38 100644 --- a/src/reactor/reactor.hpp +++ b/src/reactor/reactor.hpp @@ -12,6 +12,8 @@ namespace sim::reactor struct reactor { + const double cell_width; + const double cell_height; const int width; const int height; const int size; @@ -19,13 +21,16 @@ struct reactor std::unique_ptr* rods; int cursor = 0; - reactor(std::unique_ptr* rods, int width, int height); + reactor(std::unique_ptr* rods, int width, int height, double cell_width, double cell_height); reactor(const reactor& r); reactor(reactor&& r); ~reactor(); void update(double secs); void update_selected(int v); + void get_stats(rod::val_t type, double& min, double& max); + void get_rod_stats(int type, double& min, double& max); + double get_total(rod::val_t type); int move_cursor(int d); void toggle_selected(); diff --git a/src/reactor/rod.cpp b/src/reactor/rod.cpp index 75b02c5..d744e5d 100644 --- a/src/reactor/rod.cpp +++ b/src/reactor/rod.cpp @@ -1,5 +1,6 @@ #include "rod.hpp" +#include "reactor.hpp" #include @@ -48,6 +49,12 @@ double rod::get_speed() const return motion == 0 ? 0 : (std::pow(10, std::abs(motion)) * 1e-6 * m); } +double rod::get_volume() const +{ + auto r = (sim::reactor::reactor*)reactor; + return r->cell_width * r->cell_width * r->cell_height; +} + void rod::update_rod(double secs) { // decay the free neutrons diff --git a/src/reactor/rod.hpp b/src/reactor/rod.hpp index 685cb86..755e896 100644 --- a/src/reactor/rod.hpp +++ b/src/reactor/rod.hpp @@ -2,6 +2,7 @@ #pragma once #include +#include namespace sim::reactor { @@ -9,7 +10,8 @@ namespace sim::reactor class rod { public: - + + void* reactor = nullptr; static const int VAL_N = 3; enum val_t @@ -20,15 +22,19 @@ public: }; virtual void interact(rod* o, double secs); - virtual void update(double secs) { }; + virtual void update(double secs) { } virtual void add(val_t type, double v); virtual double extract(val_t type, double s, double k, double o); virtual double get(val_t type) const; - virtual rod* clone() const { return new rod(*this); }; + virtual rod* clone() const { return new rod(*this); } + virtual glm::vec4 get_colour() const { return {0, 0, 0, 0}; } + virtual int get_id() const { return 0; } + virtual bool has_sensors(val_t t) const { return false; } virtual bool should_display() const { return false; } virtual bool should_select() const { return false; } void update_rod_selected(int m); + double get_volume() const; constexpr void toggle_selected() { selected = !selected; } constexpr bool is_selected() const { return selected; } diff --git a/src/system.cpp b/src/system.cpp index 748f4ad..c2e1759 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -2,46 +2,74 @@ #include "system.hpp" #include "reactor/builder.hpp" -#include "reactor/control/control_rod.hpp" +#include "reactor/control/boron_rod.hpp" #include "reactor/fuel/fuel_rod.hpp" #include "reactor/coolant/pipe.hpp" #include "reactor/coolant/heater.hpp" using namespace sim; -sim::system sim::system::generate() +system::system() { const char* layout[] = { - "#C#C#", - "CFCFC", - "#C#C#", - "CFCFC", - "#C#C#" + " C C C C ", + " C CFCFCFCFC C ", + " CFCFCFCFCFCFCFC ", + " CFCFCFCFCFCFCFCFC ", + " CFCFCFCFCFCFCFC ", + " CFCFCFCFCFCFCFCFC ", + "CFCFCFCFCFCFCFCFCFC", + " CFCFCFCFCFCFCFCFC ", + "CFCFCFCFCFCFCFCFCFC", + " CFCFCFCFCFCFCFCFC ", + "CFCFCFCFCFCFCFCFCFC", + " CFCFCFCFCFCFCFCFC ", + "CFCFCFCFCFCFCFCFCFC", + " CFCFCFCFCFCFCFCFC ", + " CFCFCFCFCFCFCFC ", + " CFCFCFCFCFCFCFCFC ", + " CFCFCFCFCFCFCFC ", + " C CFCFCFCFC C ", + " C C C C " }; - reactor::coolant::vessel vessel(8, 10, 300, sim::coolant::WATER); - sim::reactor::reactor reactor(sim::reactor::builder(5, 5, - reactor::fuel::fuel_rod(2000, 4000), - reactor::control::control_rod(vessel, 10000, 1), - reactor::coolant::pipe(vessel), - layout)); + vessel = new reactor::coolant::vessel(8, 10, 300, sim::coolant::WATER); + reactor = new sim::reactor::reactor(sim::reactor::builder(19, 19, 0.25, 8, + reactor::fuel::fuel_rod(0.5), + reactor::control::boron_rod(*vessel, 1), + *vessel, layout)); - coolant::valve valve(vessel, 1, 500); - coolant::pump pump(vessel, 1e4, 15); + valve = new coolant::valve(*vessel, 1, 500); + pump = new coolant::pump(*vessel, 1e4, 15); +} - return { - .reactor = reactor, - .vessel = vessel, - .valve = valve, - .pump = pump - }; +system::system(system&& o) +{ + vessel = o.vessel; + reactor = o.reactor; + valve = o.valve; + pump = o.pump; + + o.vessel = nullptr; + o.reactor = nullptr; + o.valve = nullptr; + o.pump = nullptr; +} + +system::~system() +{ + if(vessel != nullptr) delete vessel; + if(reactor != nullptr) delete reactor; + if(valve != nullptr) delete valve; + if(pump != nullptr) delete pump; } void system::update(double dt) { - vessel.update(dt); - reactor.update(dt); - valve.update(dt); - pump.update(dt); + dt *= 10; + vessel->update(dt); + reactor->update(dt); + valve->update(dt); + pump->update(dt); } diff --git a/src/system.hpp b/src/system.hpp index b52d872..a8154b1 100644 --- a/src/system.hpp +++ b/src/system.hpp @@ -1,6 +1,8 @@ #pragma once +#include + #include "reactor/coolant/vessel.hpp" #include "reactor/reactor.hpp" #include "coolant/pump.hpp" @@ -11,13 +13,17 @@ namespace sim struct system { - sim::reactor::reactor reactor; - sim::reactor::coolant::vessel vessel; - sim::coolant::valve valve; - sim::coolant::pump pump; + sim::reactor::reactor* reactor; + sim::reactor::coolant::vessel* vessel; + sim::coolant::valve* valve; + sim::coolant::pump* pump; + + system(); + system(system&& o); + system(const system& o) = delete; + ~system(); void update(double dt); - static system generate(); }; };