made sim more accurate, fancy displays now show stuff

This commit is contained in:
Jay Robson 2024-01-29 01:26:07 +11:00
parent 3c0dbabf16
commit 853c8dde3d
34 changed files with 588 additions and 235 deletions

View File

@ -137,7 +137,7 @@ void mesh::load_text(const char* text, double size)
x += ch.advance * size; x += ch.advance * size;
} }
set_vertices(&vertices[0], vertices.size(), GL_DYNAMIC_DRAW); set_vertices(&vertices[0], vertices.size());
set_indices(&indices[0], indices.size(), GL_DYNAMIC_DRAW); set_indices(&indices[0], indices.size());
} }

View File

@ -0,0 +1,78 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#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);
}

View File

@ -0,0 +1,34 @@
#pragma once
#include <string>
#include "arrays.hpp"
#include "mesh.hpp"
#include <glm/matrix.hpp>
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();
};
};

View File

@ -1,7 +1,4 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "mesh.hpp" #include "mesh.hpp"
#include "arrays.hpp" #include "arrays.hpp"
#include "../shader.hpp" #include "../shader.hpp"
@ -9,71 +6,47 @@
using namespace sim::graphics; 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); for(unsigned int i = 0; i < o.indices.size(); i++)
glGenBuffers(1, &m->vbo); {
glGenBuffers(1, &m->ebo); indices.push_back(o.indices[i] + off);
}
glBindVertexArray(m->vao);
glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ebo);
arrays::vertex_attrib_pointers();
} }
mesh::mesh(mesh&& o) void mesh::set_vertices(const arrays::vertex* data, size_t size)
{ {
vbo = o.vbo; vertices.clear();
ebo = o.ebo; vertices.reserve(size);
vao = o.vao;
size = o.size;
colour_matrix = o.colour_matrix;
model_matrix = o.model_matrix;
o.vbo = 0; for(unsigned int i = 0; i < size; i++)
o.ebo = 0; {
o.vao = 0; vertices.push_back(data[i]);
}
} }
mesh::~mesh() void mesh::set_indices(const unsigned int* data, size_t size)
{ {
if(vbo) glDeleteBuffers(1, &vbo); indices.clear();
if(ebo) glDeleteBuffers(1, &ebo); indices.reserve(size);
if(vao) glDeleteVertexArrays(1, &vao);
} for(unsigned int i = 0; i < size; i++)
{
void mesh::set_vertices(const arrays::vertex* data, size_t size, int mode) indices.push_back(data[i]);
{ }
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);
} }

View File

@ -2,35 +2,30 @@
#pragma once #pragma once
#include <string> #include <string>
#include <sstream>
#include <vector>
#include <glm/matrix.hpp>
#include "arrays.hpp" #include "arrays.hpp"
#include <glm/matrix.hpp>
#include <sstream>
namespace sim::graphics namespace sim::graphics
{ {
struct mesh struct mesh
{ {
unsigned int vao = 0, vbo = 0, ebo = 0, size = 0; std::vector<arrays::vertex> vertices;
std::vector<unsigned int> indices;
glm::mat4 model_matrix {1.0f};
glm::mat4 colour_matrix {1.0f};
constexpr mesh() { } constexpr mesh() { }
mesh(mesh&& o); void set_vertices(const arrays::vertex* data, size_t size);
mesh(const mesh& o) = delete; void set_indices(const unsigned int* data, size_t size);
~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 load_model(std::string base, std::string path); void load_model(std::string base, std::string path);
void load_model(std::string path) { load_model(".", path); } void load_model(std::string path) { load_model(".", path); }
void load_text(const char* text, double size); void load_text(const char* text, double size);
void render(); void add(const mesh& o, glm::mat4 mat);
template <class T> template <class T>
void load_text(const char* header, T& item, double size) void load_text(const char* header, T& item, double size)

View File

@ -64,6 +64,7 @@ static void proc_mesh(proc_state& state, glm::mat4 mat, aiMesh* mesh, const aiSc
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
unsigned int handle = proc_texture(state, material, scene); unsigned int handle = proc_texture(state, material, scene);
unsigned int offset = state.offset; unsigned int offset = state.offset;
glm::mat3 mat3(mat);
for(unsigned int i = 0; i < mesh->mNumVertices; i++) 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()) if(mesh->HasNormals())
{ {
auto [x, y, z] = mesh->mNormals[i]; 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]) 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); proc_node(state, glm::mat4(1), scene->mRootNode, scene);
set_vertices(&state.vertices[0], state.vertices.size(), GL_STATIC_DRAW); set_vertices(&state.vertices[0], state.vertices.size());
set_indices(&state.indices[0], state.indices.size(), GL_STATIC_DRAW); set_indices(&state.indices[0], state.indices.size());
} }

View File

@ -1,4 +1,7 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "core.hpp" #include "core.hpp"
#include "../locations.hpp" #include "../locations.hpp"
@ -14,7 +17,7 @@ core::core()
void core::init() void core::init()
{ {
mesh1.model_matrix = mesh2.model_matrix = locations::monitors[2]; mesh1.model_matrix = locations::monitors[2];
mesh1.colour_matrix = { mesh1.colour_matrix = {
1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0,
@ -22,23 +25,57 @@ void core::init()
0, 0, 0, 0 0, 0, 0, 0
}; };
std::stringstream ss; sim::graphics::mesh rmesh1, rmesh2;
ss << "Reactor Core"; 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.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.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)
{ {
} double step = 1 / (sys.vessel->diameter / sys.reactor->cell_width * 0.8);
double sx = 0.5 - (sys.reactor->width - 1) * step / 2.0;
void core::render() double sy = 0.5 - (sys.reactor->height - 1) * step / 2.0;
{
mesh1.bind(); mesh1.render(); glm::mat4 mat_scale = glm::scale(glm::mat4(1), glm::vec3(step * 0.5, step * 0.5, 1));
mesh2.bind(); mesh2.render();
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();
}
} }

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "../mesh/mesh.hpp" #include "../mesh/glmesh.hpp"
#include "../../system.hpp" #include "../../system.hpp"
namespace sim::graphics::monitor namespace sim::graphics::monitor
@ -9,14 +9,13 @@ namespace sim::graphics::monitor
class core class core
{ {
sim::graphics::mesh mesh1, mesh2; sim::graphics::glmesh mesh1, mesh2;
public: public:
core(); core();
void init(); void init();
void update(sim::system& sys); void render(sim::system& sys);
void render();
}; };
}; };

View File

@ -1,5 +1,10 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "vessel.hpp" #include "vessel.hpp"
#include "../../reactor/rod.hpp"
#include "../../reactor/control/boron_rod.hpp"
#include "../locations.hpp" #include "../locations.hpp"
#include <glm/ext/matrix_transform.hpp> #include <glm/ext/matrix_transform.hpp>
@ -15,7 +20,7 @@ vessel::vessel()
void vessel::init() void vessel::init()
{ {
mesh1.model_matrix = locations::monitors[1]; 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 = { mesh1.colour_matrix = mesh2.colour_matrix = {
1, 1, 1, 1, 1, 1, 1, 1,
@ -25,36 +30,88 @@ void vessel::init()
}; };
std::stringstream ss; std::stringstream ss;
sim::graphics::mesh rmesh;
ss << "Reactor Vessel\n\n"; ss << "Reactor Vessel\n\n";
ss << "Heat\n"; ss << "Heat\n";
ss << "Steam\n"; ss << "Steam\n";
ss << "Pressure\n"; ss << "Pressure\n";
ss << "Level\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.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) void vessel::update(sim::system& sys)
{ {
std::stringstream ss; 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 << "\n\n";
ss << sys.vessel.get_heat() << " C\n"; ss << show( sys.vessel->get_heat() ) << " C\n";
ss << sys.vessel.get_steam() << " g\n"; ss << show( sys.vessel->get_steam() ) << " g\n";
ss << (sys.vessel.get_pressure() * 0.001) << " kPa\n"; ss << show( sys.vessel->get_pressure() * 0.001 ) << " kPa\n";
ss << sys.vessel.get_level() << " / " << sys.vessel.get_volume() << " L\n"; ss << show( sys.vessel->get_level() ) << " / " << show( sys.vessel->get_volume() ) << " L\n";
ss << (sys.vessel.get_void_ratio() * 100) << " %\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.bind();
mesh2.load_text(ss.str().c_str(), 0.05); mesh2.set(rmesh, GL_DYNAMIC_DRAW);
} }
void vessel::render() void vessel::render()
{ {
mesh1.bind(); mesh1.render(); mesh1.bind();
mesh2.bind(); mesh2.render(); mesh1.uniform();
mesh1.render();
mesh2.bind();
mesh2.uniform();
mesh2.render();
} }

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "../mesh/mesh.hpp" #include "../mesh/glmesh.hpp"
#include "../../system.hpp" #include "../../system.hpp"
namespace sim::graphics::monitor namespace sim::graphics::monitor
@ -9,7 +9,7 @@ namespace sim::graphics::monitor
class vessel class vessel
{ {
sim::graphics::mesh mesh1, mesh2; sim::graphics::glmesh mesh1, mesh2;
public: public:

View File

@ -28,7 +28,7 @@ using namespace sim::graphics;
static GLFWwindow* win; static GLFWwindow* win;
static bool win_should_close = false; static bool win_should_close = false;
static mesh MeshScene; static glmesh MeshScene;
static monitor::vessel MonitorVessel; static monitor::vessel MonitorVessel;
static monitor::core MonitorCore; static monitor::core MonitorCore;
@ -96,9 +96,11 @@ void window::create()
font::init(); font::init();
shader::init_program(); shader::init_program();
mesh rmesh;
rmesh.load_model("../assets", "scene-baked.glb");
MeshScene.bind(); MeshScene.bind();
MeshScene.load_model("../assets", "scene-baked.glb"); MeshScene.set(rmesh, GL_STATIC_DRAW);
MonitorCore.init(); MonitorCore.init();
MonitorVessel.init(); MonitorVessel.init();
@ -109,7 +111,6 @@ void window::create()
void window::loop(sim::system& sys) void window::loop(sim::system& sys)
{ {
MonitorCore.update(sys);
MonitorVessel.update(sys); MonitorVessel.update(sys);
glm::mat4 mat_projection = glm::perspective(glm::radians(80.0f), resize::get_aspect(), 0.01f, 20.f); 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); glClearColor(0, 0, 0, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 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(); MonitorVessel.render();
glfwSwapBuffers(win); glfwSwapBuffers(win);

View File

@ -27,7 +27,7 @@ unsigned long get_now()
int main() int main()
{ {
graphics::window::create(); graphics::window::create();
sim::system sys(system::generate()); sim::system sys;
long clock = get_now(); long clock = get_now();

View File

@ -1,11 +1,14 @@
#include "builder.hpp" #include "builder.hpp"
#include <cmath>
#include <vector>
using namespace sim::reactor; 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<rod> arr[W * H]; std::vector<std::unique_ptr<rod>> arr(W * H);
for(int y = 0; y < H; y++) for(int y = 0; y < H; y++)
for(int x = 0; x < W; x++) 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); r = new fuel::fuel_rod(fr);
break; break;
case 'C': case 'C':
r = new control::control_rod(cr); r = new control::boron_rod(br);
break; break;
case 'G': case 'G':
r = new control::graphite_rod(); 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': case 'H':
r = new coolant::heater(); r = new coolant::heater();
break; break;
case ' ': case 'P':
r = new coolant::pipe(p); r = new coolant::pipe(v);
break; break;
case '#': case ' ':
r = new rod(); r = new rod();
break; 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<rod>(std::move(r)); arr[y * W + x] = std::unique_ptr<rod>(std::move(r));
} }
return reactor(arr, W, H); return reactor(&arr[0], W, H, CW, CH);
} }

View File

@ -3,16 +3,17 @@
#include "rod.hpp" #include "rod.hpp"
#include "fuel/fuel_rod.hpp" #include "fuel/fuel_rod.hpp"
#include "control/control_rod.hpp" #include "control/boron_rod.hpp"
#include "control/graphite_rod.hpp" #include "control/graphite_rod.hpp"
#include "coolant/pipe.hpp" #include "coolant/pipe.hpp"
#include "coolant/heater.hpp" #include "coolant/heater.hpp"
#include "coolant/vessel.hpp"
#include "reactor.hpp" #include "reactor.hpp"
namespace sim::reactor 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);
}; };

View File

@ -0,0 +1,61 @@
#include "boron_rod.hpp"
#include <cmath>
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;
}

View File

@ -6,25 +6,26 @@
namespace sim::reactor::control 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; const double max;
double inserted = 1; double inserted = 1;
double absorbed = 0; double absorbed = 0;
virtual void display(std::ostream& o) const; virtual void display(std::ostream& o) const;
virtual const char* get_name() const { return "Boron Control Rod"; }
virtual const char* get_name() const { return "Control Rod"; } virtual rod* clone() const { return new boron_rod(*this); }
virtual rod* clone() const { return new control_rod(*this); }; virtual glm::vec4 get_colour() const;
virtual int get_id() const { return 5; }
public: public:
control_rod(coolant::vessel& v, double limit, double max); boron_rod(coolant::vessel& v, double max);
virtual void update(double secs); virtual void update(double secs);
void set_reactivity(double a); void set_reactivity(double a);
double get_inserted() { return inserted; }
virtual bool should_display() const { return true; } virtual bool should_display() const { return true; }
virtual bool should_select() const { return true; } virtual bool should_select() const { return true; }

View File

@ -1,47 +0,0 @@
#include "control_rod.hpp"
#include <cmath>
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;
}

View File

@ -10,6 +10,12 @@ void graphite_rod::display(std::ostream& o) const
o << "Inserted: " << (inserted * 100) << "%\n"; 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 double graphite_rod::get_k(val_t type) const
{ {
if(type == val_t::HEAT) return 0.5; if(type == val_t::HEAT) return 0.5;

View File

@ -11,10 +11,13 @@ class graphite_rod : public sim::reactor::rod
double inserted = 0; double inserted = 0;
virtual void display(std::ostream& o) const; virtual void display(std::ostream& o) const;
virtual const char* get_name() const { return "Graphite Rod"; } virtual const char* get_name() const { return "Graphite Rod"; }
virtual rod* clone() const { return new graphite_rod(*this); }; virtual rod* clone() const { return new graphite_rod(*this); };
virtual double get_k(val_t type) const; 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: public:

View File

@ -12,9 +12,11 @@ class heater : public sim::reactor::rod
virtual void display(std::ostream& o) const; 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 const char* get_name() const { return "Heater"; }
virtual double get_k(val_t type) const { return 0.5; } virtual double get_k(val_t type) const { return 0.5; }
virtual rod* clone() const { return new heater(*this); }; virtual rod* clone() const { return new heater(*this); };
virtual int get_id() const { return 3; }
public: public:

View File

@ -1,5 +1,6 @@
#include "pipe.hpp" #include "pipe.hpp"
#include "../reactor.hpp"
using namespace sim::reactor::coolant; using namespace sim::reactor::coolant;
@ -22,7 +23,10 @@ void pipe::update(double secs)
void pipe::update_pipe(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_SLOW] += vals[val_t::N_FAST];
vals[val_t::N_FAST] = 0; vals[val_t::N_FAST] = 0;
} }

View File

@ -17,6 +17,7 @@ protected:
virtual double get_k(sim::reactor::rod::val_t type) const; virtual double get_k(sim::reactor::rod::val_t type) const;
virtual const char* get_name() const { return "Coolant"; } virtual const char* get_name() const { return "Coolant"; }
virtual rod* clone() const { return new pipe(*this); }; virtual rod* clone() const { return new pipe(*this); };
virtual int get_id() const { return 2; }
void update_pipe(double secs); void update_pipe(double secs);

View File

@ -65,15 +65,15 @@ void vessel::update(double secs)
steam_suspended *= fuel::half_life::get(secs, bubble_hl); 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 t2 = get_heat();
double t = t1 - t2; double t = t1 - t2;
double m1 = 1e6;
double m2 = (fluid.l_to_g(level) + steam) * fluid.jPgk; double m2 = (fluid.l_to_g(level) + steam) * fluid.jPgk;
double m = m1 + m2; 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) double vessel::add_fluid(double m2, double t2)

View File

@ -11,7 +11,7 @@ namespace sim::reactor::coolant
class vessel class vessel
{ {
double level; // litres double level; // litres
double heat = 0; // celcius double heat = 0; // celsius
double steam = 0; // grams double steam = 0; // grams
double steam_suspended = 0; // grams double steam_suspended = 0; // grams
@ -27,7 +27,7 @@ public:
vessel(double height, double diameter, double level, sim::coolant::fluid_t fluid); vessel(double height, double diameter, double level, sim::coolant::fluid_t fluid);
void update(double secs); void update(double secs);
double add_heat(double amount); double add_heat(double m, double t);
double add_fluid(double amount, double heat); double add_fluid(double amount, double heat);
double extract_steam(double dt, double a, double p2); double extract_steam(double dt, double a, double p2);

View File

@ -1,33 +1,87 @@
#include "fuel_rod.hpp" #include "fuel_rod.hpp"
#include <cmath>
using namespace sim::reactor::fuel; 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 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 << "Efficiency: " << (s.get_efficiency() * 100) << " %\n";
o << "Output: " << s.get_energy() << " W/s\n"; o << "Output: " << (s.get_energy() * mol * energy_density) << " W/s\n";
o << "Iodine: " << s.get_i_135() << " mol\n"; o << "Iodine: " << (s.get_i_135() * mol) << " mol\n";
o << "Xenon: " << s.get_xe_135() << " 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) void fuel_rod::update(double secs)
{ {
update_rod(secs); update_rod(secs);
double mol = fuel_molar_density * get_volume();
s.clear_energy(); s.clear_energy();
s.clear_fast_neutrons(); 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); s.update(secs);
vals[val_t::HEAT] += s.get_energy() * secs; vals[val_t::HEAT] += s.get_energy() * mol * energy_density * secs;
vals[val_t::N_FAST] += s.get_fast_neutrons(); vals[val_t::N_FAST] += s.get_fast_neutrons() * mol;
vals[val_t::N_SLOW] = 0; vals[val_t::N_SLOW] = 0;
} }

View File

@ -14,15 +14,17 @@ class fuel_rod : public sim::reactor::rod
virtual double get_k(val_t type) const { return 0.5; } virtual double get_k(val_t type) const { return 0.5; }
virtual void display(std::ostream& o) const; 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 const char* get_name() const { return "Fuel"; }
virtual rod* clone() const { return new fuel_rod(*this); }; virtual rod* clone() const { return new fuel_rod(*this); };
virtual int get_id() const { return 1; }
virtual glm::vec4 get_colour() const;
public: public:
fuel_rod(double fuel, double mass); fuel_rod(double fuel);
virtual bool should_display() const { return true; } virtual bool should_display() const { return true; }
virtual void update(double secs); virtual void update(double secs);
}; };

View File

@ -6,12 +6,12 @@
using namespace sim::reactor::fuel; 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->fuel = fuel;
this->mass = mass; this->mass = 1;
} }
void sample::update(double secs) void sample::update(double secs)
@ -21,7 +21,7 @@ void sample::update(double secs)
// decay waste and extract products // decay waste and extract products
waste.update(secs); waste.update(secs);
fast_neutrons += waste.extract_neutrons(); fast_neutrons += waste.extract_neutrons();
energy += waste.extract_energy(); energy += waste.extract_energy() * (1.0 / 30.0);
// decay Xe-135 // decay Xe-135
m = half_life::get(secs, half_life::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; efficiency = neutrons_fuel / neutrons_total;
// simulate fuel use // simulate fuel use
energy += neutrons_fuel / secs; energy += neutrons_fuel / secs * 0.8;
waste.add_fissile(neutrons_fuel * 6); waste.add_fissile(neutrons_fuel * 6);
} }

View File

@ -31,7 +31,7 @@ class sample
public: public:
sample(double fuel, double mass); sample(double fuel);
void update(double secs); void update(double secs);

View File

@ -6,24 +6,25 @@
using namespace sim::reactor; using namespace sim::reactor;
reactor::reactor(std::unique_ptr<rod>* rods, int width, int height) : width(width), height(height), size(width * height) reactor::reactor(std::unique_ptr<rod>* 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<rod>[width * height]; this->rods = new std::unique_ptr<rod>[width * height];
for(int i = 0; i < size; i++) for(int i = 0; i < size; i++)
{ {
this->rods[i] = std::move(rods[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; rods = o.rods;
cursor = o.cursor; cursor = o.cursor;
o.rods = nullptr; 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<rod>[width * height]; rods = new std::unique_ptr<rod>[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;
}
}

View File

@ -12,6 +12,8 @@ namespace sim::reactor
struct reactor struct reactor
{ {
const double cell_width;
const double cell_height;
const int width; const int width;
const int height; const int height;
const int size; const int size;
@ -19,13 +21,16 @@ struct reactor
std::unique_ptr<rod>* rods; std::unique_ptr<rod>* rods;
int cursor = 0; int cursor = 0;
reactor(std::unique_ptr<rod>* rods, int width, int height); reactor(std::unique_ptr<rod>* rods, int width, int height, double cell_width, double cell_height);
reactor(const reactor& r); reactor(const reactor& r);
reactor(reactor&& r); reactor(reactor&& r);
~reactor(); ~reactor();
void update(double secs); void update(double secs);
void update_selected(int v); 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); int move_cursor(int d);
void toggle_selected(); void toggle_selected();

View File

@ -1,5 +1,6 @@
#include "rod.hpp" #include "rod.hpp"
#include "reactor.hpp"
#include <cmath> #include <cmath>
@ -48,6 +49,12 @@ double rod::get_speed() const
return motion == 0 ? 0 : (std::pow(10, std::abs(motion)) * 1e-6 * m); 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) void rod::update_rod(double secs)
{ {
// decay the free neutrons // decay the free neutrons

View File

@ -2,6 +2,7 @@
#pragma once #pragma once
#include <ostream> #include <ostream>
#include <glm/vec4.hpp>
namespace sim::reactor namespace sim::reactor
{ {
@ -9,7 +10,8 @@ namespace sim::reactor
class rod class rod
{ {
public: public:
void* reactor = nullptr;
static const int VAL_N = 3; static const int VAL_N = 3;
enum val_t enum val_t
@ -20,15 +22,19 @@ public:
}; };
virtual void interact(rod* o, double secs); 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 void add(val_t type, double v);
virtual double extract(val_t type, double s, double k, double o); virtual double extract(val_t type, double s, double k, double o);
virtual double get(val_t type) const; 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_display() const { return false; }
virtual bool should_select() const { return false; } virtual bool should_select() const { return false; }
void update_rod_selected(int m); void update_rod_selected(int m);
double get_volume() const;
constexpr void toggle_selected() { selected = !selected; } constexpr void toggle_selected() { selected = !selected; }
constexpr bool is_selected() const { return selected; } constexpr bool is_selected() const { return selected; }

View File

@ -2,46 +2,74 @@
#include "system.hpp" #include "system.hpp"
#include "reactor/builder.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/fuel/fuel_rod.hpp"
#include "reactor/coolant/pipe.hpp" #include "reactor/coolant/pipe.hpp"
#include "reactor/coolant/heater.hpp" #include "reactor/coolant/heater.hpp"
using namespace sim; using namespace sim;
sim::system sim::system::generate() system::system()
{ {
const char* layout[] = { const char* layout[] = {
"#C#C#", " C C C C ",
"CFCFC", " C CFCFCFCFC C ",
"#C#C#", " CFCFCFCFCFCFCFC ",
"CFCFC", " CFCFCFCFCFCFCFCFC ",
"#C#C#" " 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); vessel = new reactor::coolant::vessel(8, 10, 300, sim::coolant::WATER);
sim::reactor::reactor reactor(sim::reactor::builder(5, 5, reactor = new sim::reactor::reactor(sim::reactor::builder(19, 19, 0.25, 8,
reactor::fuel::fuel_rod(2000, 4000), reactor::fuel::fuel_rod(0.5),
reactor::control::control_rod(vessel, 10000, 1), reactor::control::boron_rod(*vessel, 1),
reactor::coolant::pipe(vessel), *vessel, layout));
layout));
coolant::valve<reactor::coolant::vessel> valve(vessel, 1, 500); valve = new coolant::valve<reactor::coolant::vessel>(*vessel, 1, 500);
coolant::pump<reactor::coolant::vessel> pump(vessel, 1e4, 15); pump = new coolant::pump<reactor::coolant::vessel>(*vessel, 1e4, 15);
}
return { system::system(system&& o)
.reactor = reactor, {
.vessel = vessel, vessel = o.vessel;
.valve = valve, reactor = o.reactor;
.pump = pump 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) void system::update(double dt)
{ {
vessel.update(dt); dt *= 10;
reactor.update(dt); vessel->update(dt);
valve.update(dt); reactor->update(dt);
pump.update(dt); valve->update(dt);
pump->update(dt);
} }

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <memory>
#include "reactor/coolant/vessel.hpp" #include "reactor/coolant/vessel.hpp"
#include "reactor/reactor.hpp" #include "reactor/reactor.hpp"
#include "coolant/pump.hpp" #include "coolant/pump.hpp"
@ -11,13 +13,17 @@ namespace sim
struct system struct system
{ {
sim::reactor::reactor reactor; sim::reactor::reactor* reactor;
sim::reactor::coolant::vessel vessel; sim::reactor::coolant::vessel* vessel;
sim::coolant::valve<sim::reactor::coolant::vessel> valve; sim::coolant::valve<sim::reactor::coolant::vessel>* valve;
sim::coolant::pump<sim::reactor::coolant::vessel> pump; sim::coolant::pump<sim::reactor::coolant::vessel>* pump;
system();
system(system&& o);
system(const system& o) = delete;
~system();
void update(double dt); void update(double dt);
static system generate();
}; };
}; };