added basic reactor components

This commit is contained in:
Jay Robson 2024-01-14 16:57:13 +11:00
parent 6d4a1b298a
commit eb1dabfe82
20 changed files with 435 additions and 237 deletions

View File

@ -0,0 +1,54 @@
#include "control_rod.hpp"
using namespace sim::control;
control_rod::control_rod(double limit)
{
this->limit = limit;
}
const char* control_rod::get_name() const
{
return "Control Rod";
}
void control_rod::display(std::ostream& o) const
{
o << "Inserted: " << (inserted * 100) << "%\n";
o << "Absorbed: " << absorbed << " / " << limit << "\n";
};
double control_rod::get_k(val_t type) const
{
switch(type)
{
case val_t::HEAT:
return 1.0 / 16.0;
case val_t::N_SLOW:
return 1.0 / 4.0;
case val_t::N_FAST:
return 1.0 / 2.0;
}
return 0;
}
void control_rod::set_reactivity(double a)
{
inserted = 1 - a;
}
void control_rod::update(double secs)
{
update_rod();
double m = (1 - absorbed / limit) * inserted;
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;
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "../rod.hpp"
namespace sim::control
{
class control_rod : public sim::rod
{
double inserted = 1;
double absorbed = 0;
double limit;
virtual const char* get_name() const;
virtual double get_k(sim::rod::val_t type) const;
virtual void display(std::ostream& o) const;
public:
control_rod(double limit);
virtual void update(double secs);
void set_reactivity(double a);
};
}

34
src/coolant/pipe.cpp Normal file
View File

@ -0,0 +1,34 @@
#include "pipe.hpp"
using namespace sim::coolant;
const char* pipe::get_name() const
{
return "Coolant Pipe";
}
double pipe::get_k(sim::rod::val_t type) const
{
switch(type)
{
case val_t::HEAT:
return 1.0 / 16.0;
case val_t::N_SLOW:
return 1.0 / 4.0;
case val_t::N_FAST:
return 1.0 / 2.0;
}
return 0;
}
void pipe::update(double secs)
{
update_rod();
double v = vals[val_t::N_FAST] * 0.25;
vals[val_t::N_FAST] -= v;
vals[val_t::N_SLOW] += v;
}

20
src/coolant/pipe.hpp Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include "../rod.hpp"
namespace sim::coolant
{
class pipe : public sim::rod
{
virtual const char* get_name() const;
virtual double get_k(sim::rod::val_t type) const;
public:
virtual void update(double secs);
};
}

49
src/display.cpp Normal file
View File

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

11
src/display.hpp Normal file
View File

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

49
src/fuel/fuel_rod.cpp Normal file
View File

@ -0,0 +1,49 @@
#include "fuel_rod.hpp"
using namespace sim::fuel;
fuel_rod::fuel_rod(double fuel, double mass) : s(fuel, mass)
{
}
void fuel_rod::display(std::ostream& o) const
{
o << "Fuel: " << s.get_fuel() << " / " << s.get_mass() << "\n";
o << "Energy: " << s.get_energy() << "\n";
}
const char* fuel_rod::get_name() const
{
return "Fuel";
}
double fuel_rod::get_k(sim::rod::val_t type) const
{
switch(type)
{
case val_t::HEAT:
return 1.0 / 16.0;
case val_t::N_SLOW:
return 1.0 / 4.0;
case val_t::N_FAST:
return 1.0 / 2.0;
}
return 0;
}
void fuel_rod::update(double secs)
{
update_rod();
s.add_slow_neutrons(vals[val_t::N_SLOW]);
vals[val_t::HEAT] += s.extract_energy() / s.get_mass();
vals[val_t::N_FAST] += s.extract_fast_neutrons();
vals[val_t::N_SLOW] = 0;
s.update(secs);
}

26
src/fuel/fuel_rod.hpp Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#include "sample.hpp"
#include "../rod.hpp"
namespace sim::fuel
{
class fuel_rod : public sim::rod
{
sample s;
virtual const char* get_name() const;
virtual double get_k(sim::rod::val_t type) const;
virtual void display(std::ostream& o) const;
public:
fuel_rod(double fuel, double mass);
virtual void update(double secs);
};
}

View File

@ -3,7 +3,7 @@
#include <cmath>
namespace sim::half_life
namespace sim::fuel::half_life
{
const double Te_135 = 19;

View File

@ -2,7 +2,7 @@
#include "sample.hpp"
#include "half_life.hpp"
using namespace sim;
using namespace sim::fuel;
static const double Xe_135_M = 1e4;
static const double NEUTRON_BG = 1e-10;
@ -17,7 +17,7 @@ void sample::update(double secs)
{
double m;
// simulate waste and extract products
// sim::fuelulate waste and extract products
waste.update(secs);
fast_neutrons += waste.extract_neutrons();
energy += waste.extract_energy();
@ -49,7 +49,7 @@ void sample::update(double secs)
if(neutrons_xenon > xe_135) neutrons_xenon = xe_135;
if(neutrons_iodine > i_135) neutrons_iodine = i_135;
// simulate fuel use
// sim::fuelulate fuel use
fuel -= neutrons_fuel;
energy += neutrons_fuel;
fast_neutrons += neutrons_fuel * 3;

View File

@ -5,12 +5,12 @@
#include <ostream>
namespace sim
namespace sim::fuel
{
class sample
{
sim::waste waste;
sim::fuel::waste waste;
double fuel = 0;
double i_135 = 0;
@ -35,6 +35,7 @@ public:
constexpr double get_fuel() const { return fuel; }
constexpr double get_mass() const { return mass; }
constexpr double get_energy() const { return energy; }
double get_volume() const;
@ -45,6 +46,5 @@ public:
}
};
}

View File

@ -2,7 +2,7 @@
#include "waste.hpp"
#include "half_life.hpp"
using namespace sim;
using namespace sim::fuel;
void waste::update(double secs)
{

View File

@ -1,7 +1,7 @@
#pragma once
namespace sim
namespace sim::fuel
{
class waste

View File

@ -1,61 +0,0 @@
#include "fuel_rod.hpp"
using namespace sim;
fuel_rod::fuel_rod(double f, double m) : fuel(f, m)
{
}
void fuel_rod::update(double secs)
{
double n = fuel.extract_fast_neutrons();
double n_slow = n * 0.5 * reactivity;
fuel.add_slow_neutrons(n_slow);
neutrons_absorbed += n * 0.5 * (1 - reactivity);
neutrons_free += n_slow;
fuel.update(secs);
temperature += fuel.extract_energy() / fuel.get_mass();
}
void fuel_rod::add_neutrons(double amount)
{
fuel.add_slow_neutrons(amount);
}
double fuel_rod::extract_free_neutrons()
{
double v = neutrons_free;
neutrons_free = 0;
return v;
}
double fuel_rod::extract_heat(double k, double o)
{
double v = k * (temperature - o);
temperature -= v;
return v;
}
void fuel_rod::add_heat(double amount)
{
temperature += amount;
}
void fuel_rod::set_reactivity(double v)
{
reactivity = v;
}
void fuel_rod::display(std::ostream& o) const
{
o << "Temperature: " << temperature << "\n";
o << "Reactivity: " << reactivity << "\n";
o << "Fuel: " << fuel.get_fuel() << " / " << fuel.get_mass() << "\n";
o << "Neutrons:\n Absorbed: " << neutrons_absorbed << "\n Free: " << neutrons_free << "\n";
}

View File

@ -1,44 +0,0 @@
#pragma once
#include "sample.hpp"
namespace sim
{
class fuel_rod
{
sample fuel;
double reactivity = 0;
double temperature = 0;
double neutrons_absorbed = 0;
double neutrons_free = 0;
void display(std::ostream& o) const;
public:
fuel_rod(double fuel, double mass);
fuel_rod() : fuel_rod(0, 0) {};
void update(double secs);
void set_reactivity(double amount);
void add_neutrons(double amount);
void add_heat(double amount);
constexpr double get_temperature() const { return temperature; }
constexpr double get_reactivity() const { return reactivity; }
double extract_free_neutrons();
double extract_heat(double k, double o);
friend std::ostream& operator<<(std::ostream& o, const fuel_rod& fr)
{
fr.display(o);
return o;
}
};
};

View File

@ -1,55 +1,14 @@
#include "reactor.hpp"
#include "control/control_rod.hpp"
#include "fuel/fuel_rod.hpp"
#include "coolant/pipe.hpp"
#include "display.hpp"
#include <sstream>
#include <unistd.h>
#include <curses.h>
void draw_text(int x, int y, const char* str)
{
for(int i = 0;; i++)
{
const char* start = str;
char c = (str++)[0];
while(c != '\n' && c != '\0')
{
c = (str++)[0];
}
mvaddnstr(x + i, y, start, (size_t)(str - start));
if(c == '\0') return;
}
}
void draw_box(int x, int y, int h, int w)
{
mvaddch(x, y, '+');
for(int i = 0; i < w - 2; i++)
{
addch('-');
}
addch('+');
for(int i = 0; i < h - 2; i++)
{
mvaddch(x + i + 1, y, '|');
mvaddch(x + i + 1, y + w - 1, '|');
}
mvaddch(x + h - 1, y, '+');
for(int i = 0; i < w - 2; i++)
{
addch('-');
}
addch('+');
}
int main()
{
initscr();
@ -59,7 +18,12 @@ int main()
nodelay(stdscr, TRUE);
curs_set(0);
sim::reactor reactor(5, {100, 200});
sim::reactor<2, 2> reactor({
new sim::fuel::fuel_rod(100, 400), new sim::fuel::fuel_rod(100, 400),
new sim::control::control_rod(1000), new sim::coolant::pipe()
});
((sim::control::control_rod*)reactor.rods[0][1])->set_reactivity(0.99);
for(;;)
{
@ -69,22 +33,22 @@ int main()
}
erase();
draw_text(1, 0, "Reactor Core:");
display::draw_text(1, 0, "Reactor Core:");
const int X = 3, Y = 4;
const int W = 32, H = 8;
for(int x = 0; x < reactor.get_size(); x++)
for(int y = 0; y < reactor.get_size(); y++)
for(int x = 0; x < reactor.width; x++)
for(int y = 0; y < reactor.height; y++)
{
std::stringstream ss;
reactor.display(ss, x, y);
ss << *reactor.rods[x][y];
int px = X + (H - 1) * y;
int py = Y + (W - 1) * x;
draw_text(px + 1, py + 2, ss.str().c_str());
draw_box(px, py, H, W);
display::draw_text(px + 1, py + 2, ss.str().c_str());
display::draw_box(px, py, H, W);
}
refresh();

View File

@ -1,58 +0,0 @@
#include "reactor.hpp"
#include <iostream>
#include <iomanip>
using namespace sim;
reactor::reactor(int size, fuel_rod fr)
{
this->size = size;
rods.resize(size * size, fr);
rods[2].set_reactivity(1);
}
static const double HEAT_K = 1.0/64.0;
void reactor::update(double secs)
{
for(int y = 0; y < size; y++)
for(int x = 0; x < size; x++)
{
fuel_rod& fr = rods[get_id(x, y)];
fr.update(secs);
const int id_os[] = {
get_id(x - 1, y),
get_id(x, y - 1),
get_id(x + 1, y),
get_id(x, y + 1)
};
const double neutrons = fr.extract_free_neutrons();
for(const int id_o : id_os)
{
if(id_o == -1) continue;
fuel_rod& fr_o = rods[id_o];
fr_o.add_heat(fr.extract_heat(HEAT_K * secs, fr_o.get_temperature()));
fr_o.add_neutrons(neutrons / 4);
}
}
}
int reactor::get_id(int x, int y) const
{
if(x < 0 || y < 0 || x >= size || y >= size) return -1;
return y * size + x;
}
void reactor::display(std::ostream& o, int x, int y) const
{
o << rods[get_id(x, y)];
}

View File

@ -1,30 +1,58 @@
#pragma once
#include "fuel_rod.hpp"
#include "rod.hpp"
#include <vector>
#include <array>
namespace sim
{
class reactor
template <int W, int H>
struct reactor
{
std::vector<fuel_rod> rods;
const static int width = W;
const static int height = H;
std::array<std::array<sim::rod*, H>, W> rods;
int size;
long update_count = 0;
reactor(std::array<sim::rod*, W * H> rods)
{
for(int y = 0; y < H; y++)
for(int x = 0; x < W; x++)
{
this->rods[x][y] = rods[y * W + x];
}
}
int get_id(int x, int y) const;
void update(double secs)
{
// do interactions
for(int x = 1; x < W; x++)
{
rods[x][0]->interact(rods[x - 1][0]);
}
public:
for(int y = 1; y < H; y++)
{
rods[0][y]->interact(rods[0][y - 1]);
}
reactor(int radius, fuel_rod fr);
for(int y = 1; y < H; y++)
for(int x = 1; x < W; x++)
{
rod* r = rods[x][y];
r->interact(rods[x - 1][y]);
r->interact(rods[x][y - 1]);
}
void update(double secs);
void display(std::ostream& o, int x, int y) const;
constexpr int get_size() const { return size; }
// do updates
for(int y = 0; y < H; y++)
for(int x = 0; x < W; x++)
{
rods[x][y]->update(secs);
}
}
};
}

46
src/rod.cpp Normal file
View File

@ -0,0 +1,46 @@
#include "rod.hpp"
using namespace sim;
double rod::get(val_t type) const
{
return vals[type];
}
void rod::add(val_t type, double v)
{
vals_in[type] += v;
}
double rod::extract(val_t type, double k, double o)
{
double v = k * get_k(type) * 0.5 * (get(type) - o);
vals_in[type] -= v;
return v;
}
void rod::interact(rod* o)
{
for(int i = 0; i < rod::VAL_N; i++)
{
val_t v = (val_t)i;
add(v, o->extract(v, get_k(v), get(v)));
}
}
void rod::update_rod()
{
for(int i = 0; i < rod::VAL_N; i++)
{
val_t v = (val_t)i;
vals[v] += vals_in[v];
vals_in[v] = 0;
}
}
void rod::display(std::ostream& o) const
{
}

52
src/rod.hpp Normal file
View File

@ -0,0 +1,52 @@
#pragma once
#include <ostream>
namespace sim
{
class rod
{
public:
static const int VAL_N = 3;
enum val_t
{
HEAT = 0,
N_SLOW = 1,
N_FAST = 2
};
virtual void interact(rod* o);
virtual void update(double secs) = 0;
virtual void add(val_t type, double v);
virtual double extract(val_t type, double k, double o);
virtual double get(val_t type) const;
friend std::ostream& operator<<(std::ostream& o, const rod& r)
{
o << "Name: " << r.get_name() << "\n";
r.display(o);
o << "Heat: " << r.get(val_t::HEAT) << "\n";
o << "Fast: " << r.get(val_t::N_FAST) << "\n";
o << "Slow: " << r.get(val_t::N_SLOW) << "\n";
return o;
}
protected:
double vals_in[VAL_N] = {0};
double vals[VAL_N] = {0};
virtual void display(std::ostream& o) const;
virtual double get_k(val_t type) const = 0;
virtual const char* get_name() const = 0;
void update_rod();
};
}