CYCAMORE
src/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 
7 using pyne::nucname::id;
8 using cyclus::Composition;
9 using cyclus::Material;
10 using cyclus::QueryResult;
11 using cyclus::Cond;
12 using cyclus::toolkit::MatQuery;
13 
14 namespace cycamore {
15 namespace reactortests {
16 
17 Composition::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 
24 Composition::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 
32 Composition::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 
40 Composition::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 
48 Composition::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.
58 TEST(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.
85 TEST(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.
112 TEST(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.
142 TEST(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.
181 TEST(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.
214 TEST(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.
243 TEST(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.
279 TEST(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.
309 TEST(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.
341 TEST(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.
390 TEST(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.
424 TEST(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.
464 TEST(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 
493 TEST(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 
565 TEST(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 
623 TEST(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 
649 TEST(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 
677 TEST(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 
714 TEST(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 
cycamore::GrowthRegion string
TEST(ReactorTests, JustInTimeOrdering)