CYCAMORE
Loading...
Searching...
No Matches
build/cycamore/reactor_tests.cc
Go to the documentation of this file.
1#include <gtest/gtest.h>
2
3#include <sstream>
4
5#include "cyclus.h"
6
7using pyne::nucname::id;
8using cyclus::Composition;
9using cyclus::Material;
10using cyclus::QueryResult;
11using cyclus::Cond;
12using cyclus::toolkit::MatQuery;
13
14namespace cycamore {
15namespace reactortests {
16
17Composition::Ptr c_uox() {
18 cyclus::CompMap m;
19 m[id("u235")] = 0.04;
20 m[id("u238")] = 0.96;
21 return Composition::CreateFromMass(m);
22};
23
24Composition::Ptr c_mox() {
25 cyclus::CompMap m;
26 m[id("u235")] = .7;
27 m[id("u238")] = 100;
28 m[id("pu239")] = 3.3;
29 return Composition::CreateFromMass(m);
30};
31
32Composition::Ptr c_spentuox() {
33 cyclus::CompMap m;
34 m[id("u235")] = .8;
35 m[id("u238")] = 100;
36 m[id("pu239")] = 1;
37 return Composition::CreateFromMass(m);
38};
39
40Composition::Ptr c_spentmox() {
41 cyclus::CompMap m;
42 m[id("u235")] = .2;
43 m[id("u238")] = 100;
44 m[id("pu239")] = .9;
45 return Composition::CreateFromMass(m);
46};
47
48Composition::Ptr c_water() {
49 cyclus::CompMap m;
50 m[id("O16")] = 1;
51 m[id("H1")] = 2;
52 return Composition::CreateFromAtom(m);
53};
54
55// Test that with a zero refuel_time and a zero capacity fresh fuel buffer
56// (the default), fuel can be ordered and the cycle started with no time step
57// delay.
58TEST(ReactorTests, JustInTimeOrdering) {
59 std::string config =
60 " <fuel_inrecipes> <val>lwr_fresh</val> </fuel_inrecipes> "
61 " <fuel_outrecipes> <val>lwr_spent</val> </fuel_outrecipes> "
62 " <fuel_incommods> <val>enriched_u</val> </fuel_incommods> "
63 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
64 " <fuel_prefs> <val>1.0</val> </fuel_prefs> "
65 ""
66 " <cycle_time>1</cycle_time> "
67 " <refuel_time>0</refuel_time> "
68 " <assem_size>300</assem_size> "
69 " <n_assem_core>1</n_assem_core> "
70 " <n_assem_batch>1</n_assem_batch> ";
71
72 int simdur = 50;
73 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
74 sim.AddSource("enriched_u").Finalize();
75 sim.AddRecipe("lwr_fresh", c_uox());
76 sim.AddRecipe("lwr_spent", c_spentuox());
77 int id = sim.Run();
78
79 QueryResult qr = sim.db().Query("Transactions", NULL);
80 EXPECT_EQ(simdur, qr.rows.size()) << "failed to order+run on fresh fuel inside 1 time step";
81}
82
83// tests that the correct number of assemblies are popped from the core each
84// cycle.
85TEST(ReactorTests, BatchSizes) {
86 std::string config =
87 " <fuel_inrecipes> <val>uox</val> </fuel_inrecipes> "
88 " <fuel_outrecipes> <val>spentuox</val> </fuel_outrecipes> "
89 " <fuel_incommods> <val>uox</val> </fuel_incommods> "
90 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
91 ""
92 " <cycle_time>1</cycle_time> "
93 " <refuel_time>0</refuel_time> "
94 " <assem_size>1</assem_size> "
95 " <n_assem_core>7</n_assem_core> "
96 " <n_assem_batch>3</n_assem_batch> ";
97
98 int simdur = 50;
99 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
100 sim.AddSource("uox").Finalize();
101 sim.AddRecipe("uox", c_uox());
102 sim.AddRecipe("spentuox", c_spentuox());
103 int id = sim.Run();
104
105 QueryResult qr = sim.db().Query("Transactions", NULL);
106 // 7 for initial core, 3 per time step for each new batch for remainder
107 EXPECT_EQ(7+3*(simdur-1), qr.rows.size());
108}
109
110// tests that the refueling period between cycle end and start of the next
111// cycle is honored.
112TEST(ReactorTests, RefuelTimes) {
113 std::string config =
114 " <fuel_inrecipes> <val>uox</val> </fuel_inrecipes> "
115 " <fuel_outrecipes> <val>spentuox</val> </fuel_outrecipes> "
116 " <fuel_incommods> <val>uox</val> </fuel_incommods> "
117 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
118 ""
119 " <cycle_time>4</cycle_time> "
120 " <refuel_time>3</refuel_time> "
121 " <assem_size>1</assem_size> "
122 " <n_assem_core>1</n_assem_core> "
123 " <n_assem_batch>1</n_assem_batch> ";
124
125 int simdur = 49;
126 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
127 sim.AddSource("uox").Finalize();
128 sim.AddRecipe("uox", c_uox());
129 sim.AddRecipe("spentuox", c_spentuox());
130 int id = sim.Run();
131
132 QueryResult qr = sim.db().Query("Transactions", NULL);
133 int cyclet = 4;
134 int refuelt = 3;
135 int n_assem_want = simdur/(cyclet+refuelt)+1; // +1 for initial core
136 EXPECT_EQ(n_assem_want, qr.rows.size());
137}
138
139
140// tests that a reactor decommissions on time without producing
141// power at the end of its lifetime.
142TEST(ReactorTests, DecomTimes) {
143 std::string config =
144 " <fuel_inrecipes> <val>uox</val> </fuel_inrecipes> "
145 " <fuel_outrecipes> <val>spentuox</val> </fuel_outrecipes> "
146 " <fuel_incommods> <val>uox</val> </fuel_incommods> "
147 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
148 ""
149 " <cycle_time>2</cycle_time> "
150 " <refuel_time>2</refuel_time> "
151 " <assem_size>1</assem_size> "
152 " <n_assem_core>3</n_assem_core> "
153 " <power_cap>1000</power_cap> "
154 " <n_assem_batch>1</n_assem_batch> ";
155
156 int simdur = 12;
157 int lifetime = 7;
158 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur, lifetime);
159 sim.AddSource("uox").Finalize();
160 sim.AddRecipe("uox", c_uox());
161 sim.AddRecipe("spentuox", c_spentuox());
162 int id = sim.Run();
163
164 // operating for 2+2 months and shutdown for 2+1
165 int on_time = 4;
166 std::vector<Cond> conds;
167 conds.push_back(Cond("Value", "==", 1000));
168 QueryResult qr = sim.db().Query("TimeSeriesPower", &conds);
169 EXPECT_EQ(on_time, qr.rows.size());
170
171 int off_time = 3;
172 conds.clear();
173 conds.push_back(Cond("Value", "==", 0));
174 qr = sim.db().Query("TimeSeriesPower", &conds);
175 EXPECT_EQ(off_time, qr.rows.size());
176}
177
178
179// Tests if a reactor produces power at the time of its decommission
180// given a refuel_time of zero.
181TEST(ReactorTests, DecomZeroRefuel) {
182 std::string config =
183 " <fuel_inrecipes> <val>uox</val> </fuel_inrecipes> "
184 " <fuel_outrecipes> <val>spentuox</val> </fuel_outrecipes> "
185 " <fuel_incommods> <val>uox</val> </fuel_incommods> "
186 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
187 ""
188 " <cycle_time>2</cycle_time> "
189 " <refuel_time>0</refuel_time> "
190 " <assem_size>1</assem_size> "
191 " <n_assem_core>3</n_assem_core> "
192 " <power_cap>1000</power_cap> "
193 " <n_assem_batch>1</n_assem_batch> ";
194
195 int simdur = 8;
196 int lifetime = 6;
197 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur, lifetime);
198 sim.AddSource("uox").Finalize();
199 sim.AddRecipe("uox", c_uox());
200 sim.AddRecipe("spentuox", c_spentuox());
201 int id = sim.Run();
202
203 // operating for 2+2 months and shutdown for 2+1
204 int on_time = 6;
205 std::vector<Cond> conds;
206 conds.push_back(Cond("Value", "==", 1000));
207 QueryResult qr = sim.db().Query("TimeSeriesPower", &conds);
208 EXPECT_EQ(on_time, qr.rows.size());
209}
210
211// tests that new fuel is ordered immediately following cycle end - at the
212// start of the refueling period - not before and not after. - thie is subtly
213// different than RefuelTimes test and is not a duplicate of it.
214TEST(ReactorTests, OrderAtRefuelStart) {
215 std::string config =
216 " <fuel_inrecipes> <val>uox</val> </fuel_inrecipes> "
217 " <fuel_outrecipes> <val>spentuox</val> </fuel_outrecipes> "
218 " <fuel_incommods> <val>uox</val> </fuel_incommods> "
219 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
220 ""
221 " <cycle_time>4</cycle_time> "
222 " <refuel_time>3</refuel_time> "
223 " <assem_size>1</assem_size> "
224 " <n_assem_core>1</n_assem_core> "
225 " <n_assem_batch>1</n_assem_batch> ";
226
227 int simdur = 7;
228 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
229 sim.AddSource("uox").Finalize();
230 sim.AddRecipe("uox", c_uox());
231 sim.AddRecipe("spentuox", c_spentuox());
232 int id = sim.Run();
233
234 QueryResult qr = sim.db().Query("Transactions", NULL);
235 int cyclet = 4;
236 int refuelt = 3;
237 int n_assem_want = simdur/(cyclet+refuelt)+1; // +1 for initial core
238 EXPECT_EQ(n_assem_want, qr.rows.size());
239}
240
241// tests that the reactor handles requesting multiple types of fuel correctly
242// - with proper inventory constraint honoring, etc.
243TEST(ReactorTests, MultiFuelMix) {
244 std::string config =
245 " <fuel_inrecipes> <val>uox</val> <val>mox</val> </fuel_inrecipes> "
246 " <fuel_outrecipes> <val>spentuox</val> <val>spentmox</val> </fuel_outrecipes> "
247 " <fuel_incommods> <val>uox</val> <val>mox</val> </fuel_incommods> "
248 " <fuel_outcommods> <val>waste</val> <val>waste</val> </fuel_outcommods> "
249 ""
250 " <cycle_time>1</cycle_time> "
251 " <refuel_time>0</refuel_time> "
252 " <assem_size>1</assem_size> "
253 " <n_assem_fresh>3</n_assem_fresh> "
254 " <n_assem_core>3</n_assem_core> "
255 " <n_assem_batch>3</n_assem_batch> ";
256
257 // it is important that the sources have cumulative capacity greater than
258 // the reactor can take on a single time step - to test that inventory
259 // capacity constraints are being set properly. It is also important that
260 // each source is smaller capacity thatn the reactor orders on each time
261 // step to make it easy to compute+check the number of transactions.
262 int simdur = 50;
263 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
264 sim.AddSource("uox").capacity(2).Finalize();
265 sim.AddSource("mox").capacity(2).Finalize();
266 sim.AddRecipe("uox", c_uox());
267 sim.AddRecipe("spentuox", c_spentuox());
268 sim.AddRecipe("mox", c_spentuox());
269 sim.AddRecipe("spentmox", c_spentuox());
270 int id = sim.Run();
271
272 QueryResult qr = sim.db().Query("Transactions", NULL);
273 // +3 is for fresh fuel inventory
274 EXPECT_EQ(3*simdur+3, qr.rows.size());
275}
276
277// tests that the reactor halts operation when it has no more room in its
278// spent fuel inventory buffer.
279TEST(ReactorTests, FullSpentInventory) {
280 std::string config =
281 " <fuel_inrecipes> <val>uox</val> </fuel_inrecipes> "
282 " <fuel_outrecipes> <val>spentuox</val> </fuel_outrecipes> "
283 " <fuel_incommods> <val>uox</val> </fuel_incommods> "
284 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
285 ""
286 " <cycle_time>1</cycle_time> "
287 " <refuel_time>0</refuel_time> "
288 " <assem_size>1</assem_size> "
289 " <n_assem_core>1</n_assem_core> "
290 " <n_assem_batch>1</n_assem_batch> "
291 " <n_assem_spent>3</n_assem_spent> ";
292
293 int simdur = 10;
294 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
295 sim.AddSource("uox").Finalize();
296 sim.AddRecipe("uox", c_uox());
297 sim.AddRecipe("spentuox", c_spentuox());
298 int id = sim.Run();
299
300 QueryResult qr = sim.db().Query("Transactions", NULL);
301 int n_assem_spent = 3;
302
303 // +1 is for the assembly in the core + the three in spent
304 EXPECT_EQ(n_assem_spent+1, qr.rows.size());
305}
306
307// tests that the reactor shuts down, ie., does not generate power, when the
308// spent fuel inventory is full and the core cannot be unloaded.
309TEST(ReactorTests, FullSpentInventoryShutdown) {
310 std::string config =
311 " <fuel_inrecipes> <val>uox</val> </fuel_inrecipes> "
312 " <fuel_outrecipes> <val>spentuox</val> </fuel_outrecipes> "
313 " <fuel_incommods> <val>uox</val> </fuel_incommods> "
314 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
315 ""
316 " <cycle_time>1</cycle_time> "
317 " <refuel_time>0</refuel_time> "
318 " <assem_size>1</assem_size> "
319 " <n_assem_core>1</n_assem_core> "
320 " <n_assem_batch>1</n_assem_batch> "
321 " <n_assem_spent>1</n_assem_spent> "
322 " <power_cap>100</power_cap> ";
323
324 int simdur = 3;
325 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
326 sim.AddSource("uox").Finalize();
327 sim.AddRecipe("uox", c_uox());
328 sim.AddRecipe("spentuox", c_spentuox());
329 int id = sim.Run();
330
331 QueryResult qr = sim.db().Query("TimeSeriesPower", NULL);
332 EXPECT_EQ(0, qr.GetVal<double>("Value", simdur - 1));
333
334}
335
336// tests that the reactor cycle is delayed as expected when it is unable to
337// acquire fuel in time for the next cycle start. This checks that after a
338// cycle is delayed past an original scheduled start time, as soon as enough fuel is
339// received, a new cycle pattern is established starting from the delayed
340// start time.
341TEST(ReactorTests, FuelShortage) {
342 std::string config =
343 " <fuel_inrecipes> <val>uox</val> </fuel_inrecipes> "
344 " <fuel_outrecipes> <val>spentuox</val> </fuel_outrecipes> "
345 " <fuel_incommods> <val>uox</val> </fuel_incommods> "
346 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
347 ""
348 " <cycle_time>7</cycle_time> "
349 " <refuel_time>0</refuel_time> "
350 " <assem_size>1</assem_size> "
351 " <n_assem_core>3</n_assem_core> "
352 " <n_assem_batch>3</n_assem_batch> ";
353
354 int simdur = 50;
355 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
356 sim.AddSource("uox").lifetime(1).Finalize(); // provide initial full batch
357 sim.AddSource("uox").start(9).lifetime(1).capacity(2).Finalize(); // provide partial batch post cycle-end
358 sim.AddSource("uox").start(15).Finalize(); // provide remainder of batch much later
359 sim.AddRecipe("uox", c_uox());
360 sim.AddRecipe("spentuox", c_spentuox());
361 int id = sim.Run();
362
363 // check that we never got a full refueled batch during refuel period
364 std::vector<Cond> conds;
365 conds.push_back(Cond("Time", "<", 15));
366 QueryResult qr = sim.db().Query("Transactions", &conds);
367 EXPECT_EQ(5, qr.rows.size());
368
369 // after being delayed past original scheduled start of new cycle, we got
370 // final assembly for core.
371 conds.clear();
372 conds.push_back(Cond("Time", "==", 15));
373 qr = sim.db().Query("Transactions", &conds);
374 EXPECT_EQ(1, qr.rows.size());
375
376 // all during the next (delayed) cycle we shouldn't be requesting any new fuel
377 conds.clear();
378 conds.push_back(Cond("Time", "<", 21));
379 qr = sim.db().Query("Transactions", &conds);
380 EXPECT_EQ(6, qr.rows.size());
381
382 // as soon as this delayed cycle ends, we should be requesting/getting 3 new batches
383 conds.clear();
384 conds.push_back(Cond("Time", "==", 22));
385 qr = sim.db().Query("Transactions", &conds);
386 EXPECT_EQ(3, qr.rows.size());
387}
388
389// tests that discharged fuel is transmuted properly immediately at cycle end.
390TEST(ReactorTests, DischargedFuelTransmute) {
391 std::string config =
392 " <fuel_inrecipes> <val>uox</val> </fuel_inrecipes> "
393 " <fuel_outrecipes> <val>spentuox</val> </fuel_outrecipes> "
394 " <fuel_incommods> <val>uox</val> </fuel_incommods> "
395 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
396 ""
397 " <cycle_time>4</cycle_time> "
398 " <refuel_time>3</refuel_time> "
399 " <assem_size>1</assem_size> "
400 " <n_assem_core>1</n_assem_core> "
401 " <n_assem_batch>1</n_assem_batch> ";
402
403 int simdur = 7;
404 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
405 sim.AddSource("uox").Finalize();
406 sim.AddSink("waste").Finalize();
407 sim.AddRecipe("uox", c_uox());
408 Composition::Ptr spentuox = c_spentuox();
409 sim.AddRecipe("spentuox", spentuox);
410 int id = sim.Run();
411
412 std::vector<Cond> conds;
413 conds.push_back(Cond("SenderId", "==", id));
414 int resid = sim.db().Query("Transactions", &conds).GetVal<int>("ResourceId");
415 Material::Ptr m = sim.GetMaterial(resid);
416 MatQuery mq(m);
417 EXPECT_EQ(spentuox->id(), m->comp()->id());
418 EXPECT_TRUE(mq.mass(942390000) > 0) << "transmuted spent fuel doesn't have Pu239";
419}
420
421// tests that spent fuel is offerred on correct commods according to the
422// incommod it was received on - esp when dealing with multiple fuel commods
423// simultaneously.
424TEST(ReactorTests, SpentFuelProperCommodTracking) {
425 std::string config =
426 " <fuel_inrecipes> <val>uox</val> <val>mox</val> </fuel_inrecipes> "
427 " <fuel_outrecipes> <val>spentuox</val> <val>spentmox</val> </fuel_outrecipes> "
428 " <fuel_incommods> <val>uox</val> <val>mox</val> </fuel_incommods> "
429 " <fuel_outcommods> <val>waste1</val> <val>waste2</val> </fuel_outcommods> "
430 ""
431 " <cycle_time>1</cycle_time> "
432 " <refuel_time>0</refuel_time> "
433 " <assem_size>1</assem_size> "
434 " <n_assem_core>3</n_assem_core> "
435 " <n_assem_batch>3</n_assem_batch> ";
436
437 int simdur = 7;
438 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
439 sim.AddSource("uox").capacity(1).Finalize();
440 sim.AddSource("mox").capacity(2).Finalize();
441 sim.AddSink("waste1").Finalize();
442 sim.AddSink("waste2").Finalize();
443 sim.AddRecipe("uox", c_uox());
444 sim.AddRecipe("spentuox", c_spentuox());
445 sim.AddRecipe("mox", c_mox());
446 sim.AddRecipe("spentmox", c_spentmox());
447 int id = sim.Run();
448
449 std::vector<Cond> conds;
450 conds.push_back(Cond("SenderId", "==", id));
451 conds.push_back(Cond("Commodity", "==", std::string("waste1")));
452 QueryResult qr = sim.db().Query("Transactions", &conds);
453 EXPECT_EQ(simdur-1, qr.rows.size());
454
455 conds[1] = Cond("Commodity", "==", std::string("waste2"));
456 qr = sim.db().Query("Transactions", &conds);
457 EXPECT_EQ(2*(simdur-1), qr.rows.size());
458}
459
460// The user can optionally omit fuel preferences. In the case where
461// preferences are adjusted, the ommitted preference vector must be populated
462// with default values - if it wasn't then preferences won't be adjusted
463// correctly and the reactor could segfault. Check that this doesn't happen.
464TEST(ReactorTests, PrefChange) {
465 // it is important that the fuel_prefs not be present in the config below.
466 std::string config =
467 " <fuel_inrecipes> <val>lwr_fresh</val> </fuel_inrecipes> "
468 " <fuel_outrecipes> <val>lwr_spent</val> </fuel_outrecipes> "
469 " <fuel_incommods> <val>enriched_u</val> </fuel_incommods> "
470 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
471 ""
472 " <cycle_time>1</cycle_time> "
473 " <refuel_time>0</refuel_time> "
474 " <assem_size>300</assem_size> "
475 " <n_assem_core>1</n_assem_core> "
476 " <n_assem_batch>1</n_assem_batch> "
477 ""
478 " <pref_change_times> <val>25</val> </pref_change_times>"
479 " <pref_change_commods> <val>enriched_u</val> </pref_change_commods>"
480 " <pref_change_values> <val>-1</val> </pref_change_values>";
481
482 int simdur = 50;
483 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
484 sim.AddSource("enriched_u").Finalize();
485 sim.AddRecipe("lwr_fresh", c_uox());
486 sim.AddRecipe("lwr_spent", c_spentuox());
487 int id = sim.Run();
488
489 QueryResult qr = sim.db().Query("Transactions", NULL);
490 EXPECT_EQ(25, qr.rows.size()) << "failed to adjust preferences properly";
491}
492
493TEST(ReactorTests, RecipeChange) {
494 // it is important that the fuel_prefs not be present in the config below.
495 std::string config =
496 " <fuel_inrecipes> <val>lwr_fresh</val> </fuel_inrecipes> "
497 " <fuel_outrecipes> <val>lwr_spent</val> </fuel_outrecipes> "
498 " <fuel_incommods> <val>enriched_u</val> </fuel_incommods> "
499 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
500 ""
501 " <cycle_time>1</cycle_time> "
502 " <refuel_time>0</refuel_time> "
503 " <assem_size>300</assem_size> "
504 " <n_assem_core>1</n_assem_core> "
505 " <n_assem_batch>1</n_assem_batch> "
506 ""
507 " <recipe_change_times> <val>25</val> <val>35</val> </recipe_change_times>"
508 " <recipe_change_commods> <val>enriched_u</val> <val>enriched_u</val> </recipe_change_commods>"
509 " <recipe_change_in> <val>water</val> <val>water</val> </recipe_change_in>"
510 " <recipe_change_out> <val>lwr_spent</val> <val>water</val> </recipe_change_out>";
511
512 int simdur = 50;
513 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
514 sim.AddSource("enriched_u").Finalize();
515 sim.AddSink("waste").Finalize();
516 sim.AddRecipe("lwr_fresh", c_uox());
517 sim.AddRecipe("lwr_spent", c_spentuox());
518 sim.AddRecipe("water", c_water());
519 int aid = sim.Run();
520
521 std::vector<Cond> conds;
522 QueryResult qr;
523
524 // check that received recipe is not water
525 conds.clear();
526 conds.push_back(Cond("Time", "==", 24));
527 conds.push_back(Cond("ReceiverId", "==", aid));
528 qr = sim.db().Query("Transactions", &conds);
529 MatQuery mq = MatQuery(sim.GetMaterial(qr.GetVal<int>("ResourceId")));
530
531 EXPECT_TRUE(0 < mq.qty());
532 EXPECT_TRUE(0 == mq.mass(id("H1")));
533
534 // check that received recipe changed to water
535 conds.clear();
536 conds.push_back(Cond("Time", "==", 26));
537 conds.push_back(Cond("ReceiverId", "==", aid));
538 qr = sim.db().Query("Transactions", &conds);
539 mq = MatQuery(sim.GetMaterial(qr.GetVal<int>("ResourceId")));
540
541 EXPECT_TRUE(0 < mq.qty());
542 EXPECT_TRUE(0 < mq.mass(id("H1")));
543
544 // check that sent recipe is not water
545 conds.clear();
546 conds.push_back(Cond("Time", "==", 34));
547 conds.push_back(Cond("SenderId", "==", aid));
548 qr = sim.db().Query("Transactions", &conds);
549 mq = MatQuery(sim.GetMaterial(qr.GetVal<int>("ResourceId")));
550
551 EXPECT_TRUE(0 < mq.qty());
552 EXPECT_TRUE(0 == mq.mass(id("H1")));
553
554 // check that sent recipe changed to water
555 conds.clear();
556 conds.push_back(Cond("Time", "==", 36));
557 conds.push_back(Cond("SenderId", "==", aid));
558 qr = sim.db().Query("Transactions", &conds);
559 mq = MatQuery(sim.GetMaterial(qr.GetVal<int>("ResourceId")));
560
561 EXPECT_TRUE(0 < mq.qty());
562 EXPECT_TRUE(0 < mq.mass(id("H1")));
563}
564
565TEST(ReactorTests, Retire) {
566 std::string config =
567 " <fuel_inrecipes> <val>lwr_fresh</val> </fuel_inrecipes> "
568 " <fuel_outrecipes> <val>lwr_spent</val> </fuel_outrecipes> "
569 " <fuel_incommods> <val>enriched_u</val> </fuel_incommods> "
570 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
571 ""
572 " <cycle_time>7</cycle_time> "
573 " <refuel_time>0</refuel_time> "
574 " <assem_size>300</assem_size> "
575 " <n_assem_fresh>1</n_assem_fresh> "
576 " <n_assem_core>3</n_assem_core> "
577 " <n_assem_batch>1</n_assem_batch> "
578 " <power_cap>1</power_cap> "
579 "";
580
581 int dur = 50;
582 int life = 36;
583 int cycle_time = 7;
584 int refuel_time = 0;
585 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, dur, life);
586 sim.AddSource("enriched_u").Finalize();
587 sim.AddSink("waste").Finalize();
588 sim.AddRecipe("lwr_fresh", c_uox());
589 sim.AddRecipe("lwr_spent", c_spentuox());
590 int id = sim.Run();
591
592 int ncore = 3;
593 int nbatch = 1;
594
595 // reactor should stop requesting new fresh fuel as it approaches retirement
596 int nassem_recv =
597 static_cast<int>(ceil(static_cast<double>(life) / 7.0)) * nbatch +
598 (ncore - nbatch);
599
600 std::vector<Cond> conds;
601 conds.push_back(Cond("ReceiverId", "==", id));
602 QueryResult qr = sim.db().Query("Transactions", &conds);
603 EXPECT_EQ(nassem_recv, qr.rows.size())
604 << "failed to stop ordering near retirement";
605
606 // reactor should discharge all fuel before/by retirement
607 conds.clear();
608 conds.push_back(Cond("SenderId", "==", id));
609 qr = sim.db().Query("Transactions", &conds);
610 EXPECT_EQ(nassem_recv, qr.rows.size())
611 << "failed to discharge all material by retirement time";
612
613 // reactor should record power entry on the time step it retires if operating
614 int time_online = life / (cycle_time + refuel_time) * cycle_time + std::min(life % (cycle_time + refuel_time), cycle_time);
615 conds.clear();
616 conds.push_back(Cond("AgentId", "==", id));
617 conds.push_back(Cond("Value", ">", 0));
618 qr = sim.db().Query("TimeSeriesPower", &conds);
619 EXPECT_EQ(time_online, qr.rows.size())
620 << "failed to generate power for the correct number of time steps";
621}
622
623TEST(ReactorTests, PositionInitialize) {
624 std::string config =
625 " <fuel_inrecipes> <val>lwr_fresh</val> </fuel_inrecipes> "
626 " <fuel_outrecipes> <val>lwr_spent</val> </fuel_outrecipes> "
627 " <fuel_incommods> <val>enriched_u</val> </fuel_incommods> "
628 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
629 " <fuel_prefs> <val>1.0</val> </fuel_prefs> "
630 ""
631 " <cycle_time>1</cycle_time> "
632 " <refuel_time>0</refuel_time> "
633 " <assem_size>300</assem_size> "
634 " <n_assem_core>1</n_assem_core> "
635 " <n_assem_batch>1</n_assem_batch> ";
636
637 int simdur = 50;
638 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
639 sim.AddSource("enriched_u").Finalize();
640 sim.AddRecipe("lwr_fresh", c_uox());
641 sim.AddRecipe("lwr_spent", c_spentuox());
642 int id = sim.Run();
643
644 QueryResult qr = sim.db().Query("AgentPosition", NULL);
645 EXPECT_EQ(qr.GetVal<double>("Latitude"), 0.0);
646 EXPECT_EQ(qr.GetVal<double>("Longitude"), 0.0);
647}
648
649TEST(ReactorTests, PositionInitialize2) {
650 std::string config =
651 " <fuel_inrecipes> <val>lwr_fresh</val> </fuel_inrecipes> "
652 " <fuel_outrecipes> <val>lwr_spent</val> </fuel_outrecipes> "
653 " <fuel_incommods> <val>enriched_u</val> </fuel_incommods> "
654 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
655 " <fuel_prefs> <val>1.0</val> </fuel_prefs> "
656 ""
657 " <cycle_time>1</cycle_time> "
658 " <refuel_time>0</refuel_time> "
659 " <assem_size>300</assem_size> "
660 " <n_assem_core>1</n_assem_core> "
661 " <n_assem_batch>1</n_assem_batch> "
662 " <longitude>30.0</longitude> "
663 " <latitude>30.0</latitude> ";
664
665 int simdur = 50;
666 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
667 sim.AddSource("enriched_u").Finalize();
668 sim.AddRecipe("lwr_fresh", c_uox());
669 sim.AddRecipe("lwr_spent", c_spentuox());
670 int id = sim.Run();
671
672 QueryResult qr = sim.db().Query("AgentPosition", NULL);
673 EXPECT_EQ(qr.GetVal<double>("Latitude"), 30.0);
674 EXPECT_EQ(qr.GetVal<double>("Longitude"), 30.0);
675}
676
677TEST(ReactorTests, ByProduct) {
678 std::string config =
679 " <fuel_inrecipes> <val>uox</val> </fuel_inrecipes> "
680 " <fuel_outrecipes> <val>spentuox</val> </fuel_outrecipes> "
681 " <fuel_incommods> <val>uox</val> </fuel_incommods> "
682 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
683 ""
684 " <cycle_time>1</cycle_time> "
685 " <refuel_time>1</refuel_time> "
686 " <assem_size>1</assem_size> "
687 " <n_assem_core>7</n_assem_core> "
688 " <n_assem_batch>3</n_assem_batch> "
689 ""
690 " <side_products> <val>process_heat</val> </side_products>"
691 " <side_product_quantity> <val>10</val> </side_product_quantity>";
692
693 int simdur = 10;
694 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
695 sim.AddSource("uox").Finalize();
696 sim.AddRecipe("uox", c_uox());
697 sim.AddRecipe("spentuox", c_spentuox());
698 int id = sim.Run();
699
700 std::vector<Cond> conds;
701 // test if it produces side products only when reactor is running
702 int quantity = 10;
703 conds.push_back(Cond("Value", "==", quantity));
704 QueryResult qr = sim.db().Query("ReactorSideProducts", &conds);
705 EXPECT_EQ(5, qr.rows.size());
706
707 // test if it doesn't produce side products when reactor is refueling
708 conds.clear();
709 conds.push_back(Cond("Value", "==", 0));
710 qr = sim.db().Query("ReactorSideProducts", &conds);
711 EXPECT_EQ(5, qr.rows.size());
712}
713
714TEST(ReactorTests, MultipleByProduct) {
715 std::string config =
716 " <fuel_inrecipes> <val>uox</val> </fuel_inrecipes> "
717 " <fuel_outrecipes> <val>spentuox</val> </fuel_outrecipes> "
718 " <fuel_incommods> <val>uox</val> </fuel_incommods> "
719 " <fuel_outcommods> <val>waste</val> </fuel_outcommods> "
720 ""
721 " <cycle_time>1</cycle_time> "
722 " <refuel_time>1</refuel_time> "
723 " <assem_size>1</assem_size> "
724 " <n_assem_core>7</n_assem_core> "
725 " <n_assem_batch>3</n_assem_batch> "
726 ""
727 " <side_products> <val>process_heat</val> <val>water</val> </side_products>"
728 " <side_product_quantity> <val>10</val> <val>100</val> </side_product_quantity>";
729
730 int simdur = 10;
731 cyclus::MockSim sim(cyclus::AgentSpec(":cycamore:Reactor"), config, simdur);
732 sim.AddSource("uox").Finalize();
733 sim.AddRecipe("uox", c_uox());
734 sim.AddRecipe("spentuox", c_spentuox());
735 int id = sim.Run();
736
737
738 std::vector<Cond> conds;
739 // test if it produces heat when reactor is running
740 int quantity = 10;
741 conds.push_back(Cond("Product", "==", std::string("process_heat")));
742 conds.push_back(Cond("Value", "==", quantity));
743 QueryResult qr = sim.db().Query("ReactorSideProducts", &conds);
744 EXPECT_EQ(5, qr.rows.size());
745
746 // test if it produces water when reactor is running
747 conds.clear();
748 quantity = 100;
749 conds.push_back(Cond("Product", "==", std::string("water")));
750 conds.push_back(Cond("Value", "==", quantity));
751 qr = sim.db().Query("ReactorSideProducts", &conds);
752 EXPECT_EQ(5, qr.rows.size());
753
754 conds.clear();
755 conds.push_back(Cond("Value", "==", 0));
756 qr = sim.db().Query("ReactorSideProducts", &conds);
757 EXPECT_EQ(10, qr.rows.size());
758
759}
760
761} // namespace reactortests
762} // namespace cycamore
763
TEST(ReactorTests, JustInTimeOrdering)