CYCAMORE
src/enrichment_tests.cc
Go to the documentation of this file.
1 #include <gtest/gtest.h>
2 
3 #include <sstream>
4 
5 #include "facility_tests.h"
6 #include "toolkit/mat_query.h"
7 #include "agent_tests.h"
8 #include "resource_helpers.h"
9 #include "infile_tree.h"
10 #include "env.h"
11 
12 #include "enrichment_tests.h"
13 
14 using cyclus::QueryResult;
15 using cyclus::Cond;
16 using cyclus::CompMap;
17 using cyclus::toolkit::MatQuery;
18 using pyne::nucname::id;
19 using cyclus::Material;
20 
21 namespace cycamore {
22 
23 Composition::Ptr c_nou235() {
24  cyclus::CompMap m;
25  m[922380000] = 1.0;
26  return Composition::CreateFromMass(m);
27 };
28 Composition::Ptr c_natu1() {
29  cyclus::CompMap m;
30  m[922350000] = 0.007;
31  m[922380000] = 0.993;
32  return Composition::CreateFromMass(m);
33 };
34 Composition::Ptr c_natu2() {
35  cyclus::CompMap m;
36  m[922350000] = 0.01;
37  m[922380000] = 0.99;
38  return Composition::CreateFromMass(m);
39 };
40 Composition::Ptr c_leu() {
41  cyclus::CompMap m;
42  m[922350000] = 0.04;
43  m[922380000] = 0.96;
44  return Composition::CreateFromMass(m);
45 };
46 Composition::Ptr c_heu() {
47  cyclus::CompMap m;
48  m[922350000] = 0.20;
49  m[922380000] = 0.80;
50  return Composition::CreateFromMass(m);
51 };
52 
53 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
54 TEST_F(EnrichmentTest, RequestQty) {
55  // this tests verifies that requests for input material are fulfilled
56  // without providing any extra
57 
58  std::string config =
59  " <feed_commod>natu</feed_commod> "
60  " <feed_recipe>natu1</feed_recipe> "
61  " <product_commod>enr_u</product_commod> "
62  " <tails_commod>tails</tails_commod> "
63  " <max_feed_inventory>1.0</max_feed_inventory> "
64  " <tails_assay>0.003</tails_assay> ";
65 
66  int simdur = 1;
67  cyclus::MockSim sim(cyclus::AgentSpec
68  (":cycamore:Enrichment"), config, simdur);
69  sim.AddRecipe("natu1", c_natu1());
70 
71  sim.AddSource("natu")
72  .recipe("natu1")
73  .Finalize();
74 
75  int id = sim.Run();
76 
77  std::vector<Cond> conds;
78  conds.push_back(Cond("Commodity", "==", std::string("natu")));
79  QueryResult qr = sim.db().Query("Transactions", &conds);
80  Material::Ptr m = sim.GetMaterial(qr.GetVal<int>("ResourceId"));
81 
82  // Should be only one transaction into the EF,
83  // and it should be exactly 1kg of natu
84  EXPECT_EQ(1.0, qr.rows.size());
85  EXPECT_NEAR(1.0, m->quantity(), 1e-10) <<
86  "matched trade provides the wrong quantity of material";
87 }
88 
89 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
90 TEST_F(EnrichmentTest, CheckSWUConstraint) {
91  // Tests that request for enrichment that exceeds the SWU constraint
92  // fulfilled only up to the available SWU.
93  // Also confirms that initial_feed flag works.
94  // 388 SWU = 10kg 80% enriched HEU from 486kg feed matl
95 
96  std::string config =
97  " <feed_commod>natu</feed_commod> "
98  " <feed_recipe>natu1</feed_recipe> "
99  " <product_commod>enr_u</product_commod> "
100  " <tails_commod>tails</tails_commod> "
101  " <tails_assay>0.003</tails_assay> "
102  " <initial_feed>1000</initial_feed> "
103  " <swu_capacity>195</swu_capacity> ";
104 
105  int simdur = 1;
106 
107  cyclus::MockSim sim(cyclus::AgentSpec
108  (":cycamore:Enrichment"), config, simdur);
109 
110  sim.AddRecipe("natu1", c_natu1());
111  sim.AddRecipe("heu", c_heu());
112 
113  sim.AddSink("enr_u")
114  .recipe("heu")
115  .capacity(10)
116  .Finalize();
117 
118  int id = sim.Run();
119 
120  std::vector<Cond> conds;
121  conds.push_back(Cond("Commodity", "==", std::string("enr_u")));
122  QueryResult qr = sim.db().Query("Transactions", &conds);
123  Material::Ptr m = sim.GetMaterial(qr.GetVal<int>("ResourceId"));
124 
125  EXPECT_EQ(1.0, qr.rows.size());
126  EXPECT_NEAR(5.0, m->quantity(), 0.1) <<
127  "traded quantity exceeds SWU constraint";
128 }
129 
130 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
131 TEST_F(EnrichmentTest, CheckCapConstraint) {
132  // Tests that a request for more material than is available in
133  // inventory is partially filled with only the inventory quantity.
134 
135  std::string config =
136  " <feed_commod>natu</feed_commod> "
137  " <feed_recipe>natu1</feed_recipe> "
138  " <product_commod>enr_u</product_commod> "
139  " <tails_commod>tails</tails_commod> "
140  " <tails_assay>0.003</tails_assay> "
141  " <initial_feed>243</initial_feed> ";
142 
143  int simdur = 1;
144 
145  cyclus::MockSim sim(cyclus::AgentSpec
146  (":cycamore:Enrichment"), config, simdur);
147 
148 
149  sim.AddRecipe("natu1", c_natu1());
150  sim.AddRecipe("heu", c_heu());
151 
152  sim.AddSink("enr_u")
153  .recipe("heu")
154  .capacity(10)
155  .Finalize();
156 
157  int id = sim.Run();
158 
159  std::vector<Cond> conds;
160  conds.push_back(Cond("Commodity", "==", std::string("enr_u")));
161  QueryResult qr = sim.db().Query("Transactions", &conds);
162  Material::Ptr m = sim.GetMaterial(qr.GetVal<int>("ResourceId"));
163 
164  EXPECT_EQ(1.0, qr.rows.size());
165  EXPECT_NEAR(5.0, m->quantity(), 0.01) <<
166  "traded quantity exceeds capacity constraint";
167 }
168 
169 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
170 TEST_F(EnrichmentTest, RequestEnrich) {
171  // this tests verifies that requests for output material exceeding
172  // the maximum allowed enrichment are not fulfilled.
173 
174  std::string config =
175  " <feed_commod>natu</feed_commod> "
176  " <feed_recipe>natu1</feed_recipe> "
177  " <product_commod>enr_u</product_commod> "
178  " <tails_commod>tails</tails_commod> "
179  " <tails_assay>0.003</tails_assay> "
180  " <max_enrich>0.20</max_enrich> ";
181 
182  int simdur = 2;
183  cyclus::MockSim sim(cyclus::AgentSpec
184  (":cycamore:Enrichment"), config, simdur);
185  sim.AddRecipe("natu1", c_natu1());
186  sim.AddRecipe("leu", c_leu());
187  sim.AddRecipe("heu", c_heu());
188 
189  sim.AddSource("natu")
190  .recipe("natu1")
191  .Finalize();
192  sim.AddSink("enr_u")
193  .recipe("leu")
194  .capacity(1.0)
195  .Finalize();
196  sim.AddSink("enr_u")
197  .recipe("heu")
198  .Finalize();
199 
200  int id = sim.Run();
201 
202  std::vector<Cond> conds;
203  conds.push_back(Cond("Commodity", "==", std::string("enr_u")));
204  QueryResult qr = sim.db().Query("Transactions", &conds);
205  Material::Ptr m = sim.GetMaterial(qr.GetVal<int>("ResourceId"));
206 
207  // Should be only one transaction out of the EF,
208  // and it should be 1kg of LEU
209  EXPECT_EQ(1.0, qr.rows.size());
210  EXPECT_NEAR(1.0, m->quantity(), 0.01) <<
211  "Not providing the requested quantity" ;
212 
213  CompMap got = m->comp()->mass();
214  CompMap want = c_leu()->mass();
215  cyclus::compmath::Normalize(&got);
216  cyclus::compmath::Normalize(&want);
217 
218  CompMap::iterator it;
219  for (it = want.begin(); it != want.end(); ++it) {
220  EXPECT_DOUBLE_EQ(it->second, got[it->first]) <<
221  "nuclide qty off: " << pyne::nucname::name(it->first);
222  }
223 }
224 
225 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
226 TEST_F(EnrichmentTest, TradeTails) {
227  // this tests whether tails are being traded.
228 
229  std::string config =
230  " <feed_commod>natu</feed_commod> "
231  " <feed_recipe>natu1</feed_recipe> "
232  " <product_commod>enr_u</product_commod> "
233  " <tails_commod>tails</tails_commod> "
234  " <tails_assay>0.003</tails_assay> ";
235 
236  // time 1-source to EF, 2-Enrich, add to tails, 3-tails avail. for trade
237  int simdur = 3;
238  cyclus::MockSim sim(cyclus::AgentSpec
239  (":cycamore:Enrichment"), config, simdur);
240  sim.AddRecipe("natu1", c_natu1());
241  sim.AddRecipe("leu", c_leu());
242 
243  sim.AddSource("natu")
244  .recipe("natu1")
245  .Finalize();
246  sim.AddSink("enr_u")
247  .recipe("leu")
248  .Finalize();
249  sim.AddSink("tails")
250  .Finalize();
251 
252  int id = sim.Run();
253 
254  std::vector<Cond> conds;
255  conds.push_back(Cond("Commodity", "==", std::string("tails")));
256  QueryResult qr = sim.db().Query("Transactions", &conds);
257 
258  // Should be exactly one tails transaction
259  EXPECT_EQ(1, qr.rows.size());
260 
261 }
262 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
263  TEST_F(EnrichmentTest, TailsQty) {
264  // this tests whether tails are being traded at correct quantity when
265  // requested amount is larger than qty in a single tails-buffer element
266 
267  std::string config =
268  " <feed_commod>natu</feed_commod> "
269  " <feed_recipe>natu1</feed_recipe> "
270  " <product_commod>enr_u</product_commod> "
271  " <tails_commod>tails</tails_commod> "
272  " <tails_assay>0.003</tails_assay> ";
273 
274  // time 1-source to EF, 2-Enrich, add to tails, 3-tails avail. for trade
275  int simdur = 3;
276  cyclus::MockSim sim(cyclus::AgentSpec
277  (":cycamore:Enrichment"), config, simdur);
278  sim.AddRecipe("natu1", c_natu1());
279  sim.AddRecipe("leu", c_leu());
280 
281  sim.AddSource("natu")
282  .recipe("natu1")
283  .Finalize();
284  sim.AddSink("enr_u")
285  .recipe("leu")
286  .capacity(0.5)
287  .Finalize();
288  sim.AddSink("enr_u")
289  .recipe("leu")
290  .capacity(0.5)
291  .Finalize();
292  sim.AddSink("tails")
293  .Finalize();
294 
295  int id = sim.Run();
296 
297  std::vector<Cond> conds;
298  conds.push_back(Cond("Commodity", "==", std::string("tails")));
299  QueryResult qr = sim.db().Query("Transactions", &conds);
300  Material::Ptr m = sim.GetMaterial(qr.GetVal<int>("ResourceId"));
301 
302  // Should be 2 tails transactions, one from each LEU sink, each 4.084kg.
303  EXPECT_EQ(2, qr.rows.size());
304 
305  cyclus::SqlStatement::Ptr stmt = sim.db().db().Prepare(
306  "SELECT SUM(r.Quantity) FROM Transactions AS t"
307  " INNER JOIN Resources AS r ON r.ResourceId = t.ResourceId"
308  " WHERE t.Commodity = ?;"
309  );
310 
311  stmt->BindText(1, "tails");
312  stmt->Step();
313  EXPECT_NEAR(8.168,stmt->GetDouble(0), 0.01) <<
314  "Not providing the requested quantity" ;
315 }
316 
317 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
318 TEST_F(EnrichmentTest, BidPrefs) {
319  // This tests that natu sources are preference-ordered by
320  // U235 content
321 
322  std::string config =
323  " <feed_commod>natu</feed_commod> "
324  " <feed_recipe>natu1</feed_recipe> "
325  " <product_commod>enr_u</product_commod> "
326  " <tails_commod>tails</tails_commod> "
327  " <tails_assay>0.003</tails_assay> "
328  " <max_feed_inventory>1.0</max_feed_inventory> ";
329 
330  int simdur = 1;
331  cyclus::MockSim sim(cyclus::AgentSpec
332  (":cycamore:Enrichment"), config, simdur);
333  sim.AddRecipe("natu1", c_natu1());
334  sim.AddRecipe("natu2", c_natu2());
335 
336  sim.AddSource("natu")
337  .recipe("natu1")
338  .capacity(1)
339  .Finalize();
340 
341  sim.AddSource("natu")
342  .recipe("natu2")
343  .capacity(1)
344  .Finalize();
345 
346  int id = sim.Run();
347 
348  std::vector<Cond> conds;
349  conds.push_back(Cond("Commodity", "==", std::string("natu")));
350  QueryResult qr = sim.db().Query("Transactions", &conds);
351 
352  // should trade only with #2 since it has higher U235
353  EXPECT_EQ(1, qr.rows.size());
354 
355  Material::Ptr m = sim.GetMaterial(qr.GetVal<int>("ResourceId"));
356  CompMap got = m->comp()->mass();
357  CompMap want = c_natu2()->mass();
358  cyclus::compmath::Normalize(&got);
359  cyclus::compmath::Normalize(&want);
360 
361  CompMap::iterator it;
362  for (it = want.begin(); it != want.end(); ++it) {
363  EXPECT_DOUBLE_EQ(it->second, got[it->first]) <<
364  "nuclide qty off: " << pyne::nucname::name(it->first);
365  }
366 
367 }
368 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
369  TEST_F(EnrichmentTest, NoBidPrefs) {
370  // This tests that preference-ordering for sources
371  // turns off correctly if flag is used
372 
373  std::string config =
374  " <feed_commod>natu</feed_commod> "
375  " <feed_recipe>natu1</feed_recipe> "
376  " <product_commod>enr_u</product_commod> "
377  " <tails_commod>tails</tails_commod> "
378  " <tails_assay>0.003</tails_assay> "
379  " <max_feed_inventory>2.0</max_feed_inventory> "
380  " <order_prefs>0</order_prefs> ";
381 
382  int simdur = 1;
383  cyclus::MockSim sim(cyclus::AgentSpec
384  (":cycamore:Enrichment"), config, simdur);
385  sim.AddRecipe("natu1", c_natu1());
386  sim.AddRecipe("natu2", c_natu2());
387 
388  sim.AddSource("natu")
389  .recipe("natu1")
390  .capacity(1)
391  .Finalize();
392 
393  sim.AddSource("natu")
394  .recipe("natu2")
395  .capacity(1)
396  .Finalize();
397 
398  int id = sim.Run();
399 
400  std::vector<Cond> conds;
401  conds.push_back(Cond("Commodity", "==", std::string("natu")));
402  QueryResult qr = sim.db().Query("Transactions", &conds);
403 
404  // should trade with both to meet its capacity limit
405  EXPECT_EQ(2, qr.rows.size());
406  }
407 
408 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
409 TEST_F(EnrichmentTest, ZeroU235) {
410  // Test that offers of natu with no u235 content are rejected
411 
412  std::string config =
413  " <feed_commod>natu</feed_commod> "
414  " <feed_recipe>natu1</feed_recipe> "
415  " <product_commod>enr_u</product_commod> "
416  " <tails_commod>tails</tails_commod> "
417  " <tails_assay>0.003</tails_assay> "
418  " <max_feed_inventory>1.0</max_feed_inventory> ";
419 
420  int simdur = 1;
421  cyclus::MockSim sim(cyclus::AgentSpec
422  (":cycamore:Enrichment"), config, simdur);
423  sim.AddRecipe("no_u235", c_nou235());
424  sim.AddRecipe("natu1", c_natu1());
425 
426  sim.AddSource("natu")
427  .recipe("no_u235")
428  .capacity(1)
429  .Finalize();
430 
431  int id = sim.Run();
432 
433  std::vector<Cond> conds;
434  conds.push_back(Cond("Commodity", "==", std::string("natu")));
435  // DB table should be empty since there are no transactions
436  EXPECT_THROW(sim.db().Query("Transactions", &conds),
437  std::exception);
438 }
439 
440 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
441 void EnrichmentTest::SetUp() {
442  cyclus::Env::SetNucDataPath();
443  cyclus::Context* ctx = tc_.get();
444  src_facility = new Enrichment(ctx);
445  trader = tc_.trader();
446  InitParameters();
447  SetUpSource();
448 }
449 
450 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
452  delete src_facility;
453 }
454 
455 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
457  cyclus::Context* ctx = tc_.get();
458 
459  feed_commod = "incommod";
460  product_commod = "outcommod";
461  tails_commod = "tailscommod";
462 
463  feed_recipe = "recipe";
464  feed_assay = 0.0072;
465 
466  cyclus::CompMap v;
467  v[922350000] = feed_assay;
468  v[922380000] = 1 - feed_assay;
469  recipe = cyclus::Composition::CreateFromAtom(v);
470  ctx->AddRecipe(feed_recipe, recipe);
471 
472  tails_assay = 0.002;
473  swu_capacity = 100; //**
474  inv_size = 5;
475 
476  reserves = 105.5;
477 }
478 
479 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
490 }
491 
492 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
493 cyclus::Material::Ptr EnrichmentTest::GetMat(double qty) {
494  return cyclus::Material::CreateUntracked(qty,
495  tc_.get()->GetRecipe(feed_recipe));
496 }
497 
498 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
499 void EnrichmentTest::DoAddMat(cyclus::Material::Ptr mat) {
500  src_facility->AddMat_(mat);
501 }
502 
503 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
504 cyclus::Material::Ptr EnrichmentTest::DoRequest() {
505  return src_facility->Request_();
506 }
507 
508 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
509 cyclus::Material::Ptr
510 EnrichmentTest::DoOffer(cyclus::Material::Ptr mat) {
511  return src_facility->Offer_(mat);
512 }
513 
514 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
515 cyclus::Material::Ptr
516 EnrichmentTest::DoEnrich(cyclus::Material::Ptr mat, double qty) {
517  return src_facility->Enrich_(mat, qty);
518 }
519 
520 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
521 TEST_F(EnrichmentTest, Request) {
522  // Tests that quantity in material request is accurate
523  double req = inv_size;
524  double add = 0;
525  cyclus::Material::Ptr mat = DoRequest();
526  EXPECT_DOUBLE_EQ(mat->quantity(), req);
527  EXPECT_EQ(mat->comp(), tc_.get()->GetRecipe(feed_recipe));
528 
529  add = 2 * inv_size / 3;
530  req -= add;
531  DoAddMat(GetMat(add));
532  mat = DoRequest();
533  EXPECT_DOUBLE_EQ(mat->quantity(), req);
534  EXPECT_EQ(mat->comp(), tc_.get()->GetRecipe(feed_recipe));
535 
536  add = inv_size / 3;
537  req = 0;
538  DoAddMat(GetMat(add));
539  mat = DoRequest();
540  EXPECT_DOUBLE_EQ(mat->quantity(), req);
541  EXPECT_EQ(mat->comp(), tc_.get()->GetRecipe(feed_recipe));
542 }
543 
544 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
545 TEST_F(EnrichmentTest, ValidReq) {
546  // Tests that material requests have U235/(U235+U238) > tails assay
547  using cyclus::CompMap;
548  using cyclus::Composition;
549  using cyclus::Material;
550 
551  double qty = 4.5; // some magic number
552 
553  cyclus::CompMap v1;
554  v1[922350000] = 1;
555  Material::Ptr mat = Material::CreateUntracked
556  (qty,Composition::CreateFromAtom(v1));
557  EXPECT_FALSE(src_facility->ValidReq(mat)); // u238 = 0
558 
559  cyclus::CompMap v2;
560  v2[922350000] = tails_assay;
561  v2[922380000] = 1 - tails_assay;
562  mat = Material::CreateUntracked(qty, Composition::CreateFromAtom(v2));
563  // u235 / (u235 + u238) <= tails_assay
564  EXPECT_FALSE(src_facility->ValidReq(mat));
565 
566  cyclus::CompMap v3;
567  v3[922350000] = 1;
568  v3[922380000] = 1;
569  mat = Material::CreateUntracked(qty, Composition::CreateFromAtom(v3));
570  EXPECT_TRUE(src_facility->ValidReq(mat)); // valid
571 }
572 
573 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
574  TEST_F(EnrichmentTest, ConstraintConverters) {
575  // Tests the SWU and NatU converters to make sure that amount of
576  // feed and SWU required are correct to fulfill the enrichment request.
577  using cyclus::CompMap;
578  using cyclus::Material;
579  using cyclus::toolkit::MatQuery;
580  using cyclus::Composition;
581  using cyclus::toolkit::Assays;
582  using cyclus::toolkit::UraniumAssay;
583  using cyclus::toolkit::SwuRequired;
584  using cyclus::toolkit::FeedQty;
585  using cyclus::toolkit::MatQuery;
586  cyclus::Env::SetNucDataPath();
587 
588  double qty = 5; // 5 kg
589  double product_assay = 0.05; // of 5 w/o enriched U
590  CompMap v;
591  v[922350000] = product_assay;
592  v[922380000] = 1 - product_assay;
593  v[94239] = 0.5; // 94239 shouldn't be taken into account
594  Material::Ptr target = Material::CreateUntracked(
595  qty, Composition::CreateFromMass(v));
596 
597  std::set<cyclus::Nuc> nucs;
598  nucs.insert(922350000);
599  nucs.insert(922380000);
600 
601  MatQuery mq(target);
602  double mass_frac = mq.mass_frac(nucs);
603 
604  SWUConverter swuc(feed_assay, tails_assay);
605  NatUConverter natuc(feed_assay, tails_assay);
606 
607  Material::Ptr offer = DoOffer(target);
608 
609  EXPECT_NEAR(swuc.convert(target), swuc.convert(offer), 0.001);
610  EXPECT_NEAR(natuc.convert(target) * mass_frac, natuc.convert(offer), 0.001);
611 }
612 
613 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
614 TEST_F(EnrichmentTest, Enrich) {
615  // this test asks the facility to enrich a material that results in an amount
616  // of natural uranium required that is exactly its inventory level. that
617  // inventory will be comprised of two materials to test the manifest/absorb
618  // strategy employed in Enrich_.
619  using cyclus::CompMap;
620  using cyclus::Material;
621  using cyclus::toolkit::MatQuery;
622  using cyclus::Composition;
623  using cyclus::toolkit::Assays;
624  using cyclus::toolkit::UraniumAssay;
625  using cyclus::toolkit::SwuRequired;
626  using cyclus::toolkit::FeedQty;
627 
628  double qty = 5; // kg
629  double product_assay = 0.05; // of 5 w/o enriched U
630  cyclus::CompMap v;
631  v[922350000] = product_assay;
632  v[922380000] = 1 - product_assay;
633  // target qty need not be = to request qty
634  Material::Ptr target = cyclus::Material::CreateUntracked(
635  qty + 10, cyclus::Composition::CreateFromMass(v));
636 
637  Assays assays(feed_assay, UraniumAssay(target), tails_assay);
638  double swu_req = SwuRequired(qty, assays);
639  double natu_req = FeedQty(qty, assays);
640  double tails_qty = TailsQty(qty, assays);
641 
642  double swu_cap = swu_req * 5;
643  src_facility->SwuCapacity(swu_cap);
645  DoAddMat(GetMat(natu_req / 2));
646  DoAddMat(GetMat(natu_req / 2));
647 
648  Material::Ptr response;
649  EXPECT_NO_THROW(response = DoEnrich(target, qty));
650  EXPECT_DOUBLE_EQ(src_facility->Tails().quantity(), tails_qty);
651 
652  MatQuery q(response);
653  EXPECT_EQ(response->quantity(), qty);
654  EXPECT_EQ(q.mass_frac(922350000), product_assay);
655  EXPECT_EQ(q.mass_frac(922380000), 1 - product_assay);
656 
657  // test too much natu request
658  DoAddMat(GetMat(natu_req - 1));
659  EXPECT_THROW(response = DoEnrich(target, qty), cyclus::Error);
660 }
661 
662 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
663 TEST_F(EnrichmentTest, Response) {
664  // this test asks the facility to respond to multiple requests for enriched
665  // uranium. two requests are provided, whose total equals the swu capacity of
666  // the facility while not exceeding its inventory capacity (that's taken care
667  // of in the Enrich tests).
668  //
669  // note that response quantity and quality need not be tested, because they
670  // are covered by the Enrich and RequestEnrich tests
671  using cyclus::Bid;
672  using cyclus::CompMap;
673  using cyclus::Material;
674  using cyclus::Request;
675  using cyclus::Trade;
676  using cyclus::toolkit::Assays;
677  using cyclus::toolkit::FeedQty;
678  using cyclus::toolkit::SwuRequired;
679  using cyclus::toolkit::UraniumAssay;
680 
681  // problem set up
682  std::vector< cyclus::Trade<cyclus::Material> > trades;
683  std::vector<std::pair<cyclus::Trade<cyclus::Material>,
684  cyclus::Material::Ptr> > responses;
685 
686  double qty = 5; // kg
687  double trade_qty = qty / 3;
688  double product_assay = 0.05; // of 5 w/o enriched U
689 
690  cyclus::CompMap v;
691  v[922350000] = product_assay;
692  v[922380000] = 1 - product_assay;
693  // target qty need not be = to request qty
694  Material::Ptr target = cyclus::Material::CreateUntracked(
695  qty + 10, cyclus::Composition::CreateFromMass(v));
696 
697  Assays assays(feed_assay, UraniumAssay(target), tails_assay);
698  double swu_req = SwuRequired(qty, assays);
699  double natu_req = FeedQty(qty, assays);
700 
701  src_facility->SetMaxInventorySize(natu_req * 4); // not capacitated by nat
702  src_facility->SwuCapacity(swu_req); // swu capacitated
703 
704  src_facility->GetMatlTrades(trades, responses);
705 
706  // set up state
707  DoAddMat(GetMat(natu_req * 2));
708 
709  src_facility->GetMatlTrades(trades, responses);
710 
711  Request<Material>* req =
712  Request<Material>::Create(target, trader, product_commod);
713  Bid<Material>* bid = Bid<Material>::Create(req, target, src_facility);
714  Trade<Material> trade(req, bid, trade_qty);
715  trades.push_back(trade);
716 
717  // 2 trades, SWU = SWU cap
718  ASSERT_GT(src_facility->SwuCapacity() - 2 * swu_req / 3,
719  -1 * cyclus::eps());
720  trades.push_back(trade);
721  responses.clear();
722  EXPECT_NO_THROW(src_facility->GetMatlTrades(trades, responses));
723  EXPECT_EQ(responses.size(), 2);
724 }
725 
726 } // namespace cycamore
727 
728 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
729 cyclus::Agent* EnrichmentConstructor(cyclus::Context* ctx) {
730  return new cycamore::Enrichment(ctx);
731 }
732 
733 // required to get functionality in cyclus agent unit tests library
734 #ifndef CYCLUS_AGENT_TESTS_CONNECTED
735 int ConnectAgentTests();
737 #define CYCLUS_AGENT_TESTS_CONNECTED cyclus_agent_tests_connected
738 #endif // CYCLUS_AGENT_TESTS_CONNECTED
739 
740 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
741 INSTANTIATE_TEST_CASE_P(EnrichmentFac, FacilityTests,
742  Values(&EnrichmentConstructor));
743 INSTANTIATE_TEST_CASE_P(EnrichmentFac, AgentTests,
744  Values(&EnrichmentConstructor));
int ConnectAgentTests()
cyclus::Material::Ptr Offer_(cyclus::Material::Ptr req)
Generates a material offer for a given request.
cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat)
bool ValidReq(const cyclus::Material::Ptr mat)
Determines if a particular material is a valid request to respond to.
cyclus::Material::Ptr Request_()
generates a request for this facility given its current state.
static int cyclus_agent_tests_connected
cyclus::Material::Ptr Enrich_(cyclus::Material::Ptr mat, double qty)
cycamore::GrowthRegion string
cyclus::Agent * EnrichmentConstructor(cyclus::Context *ctx)
const cyclus::toolkit::ResBuf< cyclus::Material > & Tails() const
cyclus::Material::Ptr GetMat(double qty)
void AddMat_(cyclus::Material::Ptr mat)
adds a material into the natural uranium inventory
The Enrichment facility is a simple Agent that enriches natural uranium in a Cyclus simulation...
INSTANTIATE_TEST_CASE_P(EnrichmentFac, FacilityTests, Values(&EnrichmentConstructor))
void DoAddMat(cyclus::Material::Ptr mat)
virtual void GetMatlTrades(const std::vector< cyclus::Trade< cyclus::Material > > &trades, std::vector< std::pair< cyclus::Trade< cyclus::Material >, cyclus::Material::Ptr > > &responses)
respond to each trade with a material enriched to the appropriate level given this facility&#39;s invento...
cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty)
TEST_F(EnrichmentTest, RequestQty)