diff --git a/src/control/control_rod.cpp b/src/control/control_rod.cpp new file mode 100644 index 0000000..164d26a --- /dev/null +++ b/src/control/control_rod.cpp @@ -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; +} + diff --git a/src/control/control_rod.hpp b/src/control/control_rod.hpp new file mode 100644 index 0000000..202bb09 --- /dev/null +++ b/src/control/control_rod.hpp @@ -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); +}; + +} + diff --git a/src/coolant/pipe.cpp b/src/coolant/pipe.cpp new file mode 100644 index 0000000..df8a646 --- /dev/null +++ b/src/coolant/pipe.cpp @@ -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; +} + diff --git a/src/coolant/pipe.hpp b/src/coolant/pipe.hpp new file mode 100644 index 0000000..94ec5d4 --- /dev/null +++ b/src/coolant/pipe.hpp @@ -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); +}; + +} + diff --git a/src/display.cpp b/src/display.cpp new file mode 100644 index 0000000..b92ec98 --- /dev/null +++ b/src/display.cpp @@ -0,0 +1,49 @@ + +#include "display.hpp" + +#include + +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('+'); +} diff --git a/src/display.hpp b/src/display.hpp new file mode 100644 index 0000000..be126e3 --- /dev/null +++ b/src/display.hpp @@ -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); + +} + diff --git a/src/fuel/fuel_rod.cpp b/src/fuel/fuel_rod.cpp new file mode 100644 index 0000000..7c63860 --- /dev/null +++ b/src/fuel/fuel_rod.cpp @@ -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); +} + diff --git a/src/fuel/fuel_rod.hpp b/src/fuel/fuel_rod.hpp new file mode 100644 index 0000000..8d52313 --- /dev/null +++ b/src/fuel/fuel_rod.hpp @@ -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); +}; + +} + diff --git a/src/half_life.hpp b/src/fuel/half_life.hpp similarity index 89% rename from src/half_life.hpp rename to src/fuel/half_life.hpp index a2a1ee5..c326e2b 100644 --- a/src/half_life.hpp +++ b/src/fuel/half_life.hpp @@ -3,7 +3,7 @@ #include -namespace sim::half_life +namespace sim::fuel::half_life { const double Te_135 = 19; diff --git a/src/sample.cpp b/src/fuel/sample.cpp similarity index 95% rename from src/sample.cpp rename to src/fuel/sample.cpp index 3757651..98e1611 100644 --- a/src/sample.cpp +++ b/src/fuel/sample.cpp @@ -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; diff --git a/src/sample.hpp b/src/fuel/sample.hpp similarity index 87% rename from src/sample.hpp rename to src/fuel/sample.hpp index 3a190e4..98e95e2 100644 --- a/src/sample.hpp +++ b/src/fuel/sample.hpp @@ -5,12 +5,12 @@ #include -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: } }; - } diff --git a/src/waste.cpp b/src/fuel/waste.cpp similarity index 96% rename from src/waste.cpp rename to src/fuel/waste.cpp index 2750b4b..367f9dd 100644 --- a/src/waste.cpp +++ b/src/fuel/waste.cpp @@ -2,7 +2,7 @@ #include "waste.hpp" #include "half_life.hpp" -using namespace sim; +using namespace sim::fuel; void waste::update(double secs) { diff --git a/src/waste.hpp b/src/fuel/waste.hpp similarity index 93% rename from src/waste.hpp rename to src/fuel/waste.hpp index 5cd4bd1..3bd4a8e 100644 --- a/src/waste.hpp +++ b/src/fuel/waste.hpp @@ -1,7 +1,7 @@ #pragma once -namespace sim +namespace sim::fuel { class waste diff --git a/src/fuel_rod.cpp b/src/fuel_rod.cpp deleted file mode 100644 index 07b1320..0000000 --- a/src/fuel_rod.cpp +++ /dev/null @@ -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"; -} - diff --git a/src/fuel_rod.hpp b/src/fuel_rod.hpp deleted file mode 100644 index 8e6055b..0000000 --- a/src/fuel_rod.hpp +++ /dev/null @@ -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; - } -}; - -}; - diff --git a/src/main.cpp b/src/main.cpp index d50bbf3..77c1661 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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 #include #include -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(); diff --git a/src/reactor.cpp b/src/reactor.cpp deleted file mode 100644 index ad28291..0000000 --- a/src/reactor.cpp +++ /dev/null @@ -1,58 +0,0 @@ - -#include "reactor.hpp" - -#include -#include - -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)]; -} - diff --git a/src/reactor.hpp b/src/reactor.hpp index 3fa7673..87aa5ad 100644 --- a/src/reactor.hpp +++ b/src/reactor.hpp @@ -1,30 +1,58 @@ #pragma once -#include "fuel_rod.hpp" +#include "rod.hpp" -#include +#include namespace sim { -class reactor +template +struct reactor { - std::vector rods; + const static int width = W; + const static int height = H; + + std::array, W> rods; - int size; - long update_count = 0; + reactor(std::array 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); + } + } }; } diff --git a/src/rod.cpp b/src/rod.cpp new file mode 100644 index 0000000..2300f7b --- /dev/null +++ b/src/rod.cpp @@ -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 +{ + +} + diff --git a/src/rod.hpp b/src/rod.hpp new file mode 100644 index 0000000..c8f06a8 --- /dev/null +++ b/src/rod.hpp @@ -0,0 +1,52 @@ + +#pragma once + +#include + +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(); +}; + +} +