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_LE(m->quantity(), 5.0) <<
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.19</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.125kg.
303  // Q * (e_p - e_f)/(e_f - e_t) = 0.5 * (0.04 - 0.007)/(0.007 - 0.003) = 4.125
304  EXPECT_EQ(2, qr.rows.size());
305 
306  cyclus::SqlStatement::Ptr stmt = sim.db().db().Prepare(
307  "SELECT SUM(r.Quantity) FROM Transactions AS t"
308  " INNER JOIN Resources AS r ON r.ResourceId = t.ResourceId"
309  " WHERE t.Commodity = ?;"
310  );
311 
312  stmt->BindText(1, "tails");
313  stmt->Step();
314  EXPECT_NEAR(8.25,stmt->GetDouble(0), 0.01) <<
315  "Not providing the requested quantity" ;
316 }
317 
318 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
319 TEST_F(EnrichmentTest, BidPrefs) {
320  // This tests that natu sources are preference-ordered by
321  // U235 content
322 
323  std::string config =
324  " <feed_commod>natu</feed_commod> "
325  " <feed_recipe>natu1</feed_recipe> "
326  " <product_commod>enr_u</product_commod> "
327  " <tails_commod>tails</tails_commod> "
328  " <tails_assay>0.003</tails_assay> "
329  " <max_feed_inventory>1.0</max_feed_inventory> ";
330 
331  int simdur = 1;
332  cyclus::MockSim sim(cyclus::AgentSpec
333  (":cycamore:Enrichment"), config, simdur);
334  sim.AddRecipe("natu1", c_natu1());
335  sim.AddRecipe("natu2", c_natu2());
336 
337  sim.AddSource("natu")
338  .recipe("natu1")
339  .capacity(1)
340  .Finalize();
341 
342  sim.AddSource("natu")
343  .recipe("natu2")
344  .capacity(1)
345  .Finalize();
346 
347  int id = sim.Run();
348 
349  std::vector<Cond> conds;
350  conds.push_back(Cond("Commodity", "==", std::string("natu")));
351  QueryResult qr = sim.db().Query("Transactions", &conds);
352 
353  // should trade only with #2 since it has higher U235
354  EXPECT_EQ(1, qr.rows.size());
355 
356  Material::Ptr m = sim.GetMaterial(qr.GetVal<int>("ResourceId"));
357  CompMap got = m->comp()->mass();
358  CompMap want = c_natu2()->mass();
359  cyclus::compmath::Normalize(&got);
360  cyclus::compmath::Normalize(&want);
361 
362  CompMap::iterator it;
363  for (it = want.begin(); it != want.end(); ++it) {
364  EXPECT_DOUBLE_EQ(it->second, got[it->first]) <<
365  "nuclide qty off: " << pyne::nucname::name(it->first);
366  }
367 
368 }
369 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
370  TEST_F(EnrichmentTest, NoBidPrefs) {
371  // This tests that preference-ordering for sources
372  // turns off correctly if flag is used
373 
374  std::string config =
375  " <feed_commod>natu</feed_commod> "
376  " <feed_recipe>natu1</feed_recipe> "
377  " <product_commod>enr_u</product_commod> "
378  " <tails_commod>tails</tails_commod> "
379  " <tails_assay>0.003</tails_assay> "
380  " <max_feed_inventory>2.0</max_feed_inventory> "
381  " <order_prefs>0</order_prefs> ";
382 
383  int simdur = 1;
384  cyclus::MockSim sim(cyclus::AgentSpec
385  (":cycamore:Enrichment"), config, simdur);
386  sim.AddRecipe("natu1", c_natu1());
387  sim.AddRecipe("natu2", c_natu2());
388 
389  sim.AddSource("natu")
390  .recipe("natu1")
391  .capacity(1)
392  .Finalize();
393 
394  sim.AddSource("natu")
395  .recipe("natu2")
396  .capacity(1)
397  .Finalize();
398 
399  int id = sim.Run();
400 
401  std::vector<Cond> conds;
402  conds.push_back(Cond("Commodity", "==", std::string("natu")));
403  QueryResult qr = sim.db().Query("Transactions", &conds);
404 
405  // should trade with both to meet its capacity limit
406  EXPECT_EQ(2, qr.rows.size());
407  }
408 
409 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
410 TEST_F(EnrichmentTest, ZeroU235) {
411  // Test that offers of natu with no u235 content are rejected
412 
413  std::string config =
414  " <feed_commod>natu</feed_commod> "
415  " <feed_recipe>natu1</feed_recipe> "
416  " <product_commod>enr_u</product_commod> "
417  " <tails_commod>tails</tails_commod> "
418  " <tails_assay>0.003</tails_assay> "
419  " <max_feed_inventory>1.0</max_feed_inventory> ";
420 
421  int simdur = 1;
422  cyclus::MockSim sim(cyclus::AgentSpec
423  (":cycamore:Enrichment"), config, simdur);
424  sim.AddRecipe("no_u235", c_nou235());
425  sim.AddRecipe("natu1", c_natu1());
426 
427  sim.AddSource("natu")
428  .recipe("no_u235")
429  .capacity(1)
430  .Finalize();
431 
432  int id = sim.Run();
433 
434  std::vector<Cond> conds;
435  conds.push_back(Cond("Commodity", "==", std::string("natu")));
436  // DB table should be empty since there are no transactions
437  EXPECT_THROW(sim.db().Query("Transactions", &conds),
438  std::exception);
439 }
440 
441 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
442 void EnrichmentTest::SetUp() {
443  cyclus::Env::SetNucDataPath();
444  cyclus::Context* ctx = tc_.get();
445  src_facility = new Enrichment(ctx);
446  trader = tc_.trader();
447  InitParameters();
448  SetUpSource();
449 }
450 
451 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
453  delete src_facility;
454 }
455 
456 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
458  cyclus::Context* ctx = tc_.get();
459 
460  feed_commod = "incommod";
461  product_commod = "outcommod";
462  tails_commod = "tailscommod";
463 
464  feed_recipe = "recipe";
465  feed_assay = 0.0072;
466 
467  cyclus::CompMap v;
468  v[922350000] = feed_assay;
469  v[922380000] = 1 - feed_assay;
470  recipe = cyclus::Composition::CreateFromMass(v);
471  ctx->AddRecipe(feed_recipe, recipe);
472 
473  tails_assay = 0.002;
474  swu_capacity = 100; //**
475  inv_size = 5;
476 
477  reserves = 105.5;
478 }
479 
480 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
491 }
492 
493 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
494 cyclus::Material::Ptr EnrichmentTest::GetMat(double qty) {
495  return cyclus::Material::CreateUntracked(qty,
496  tc_.get()->GetRecipe(feed_recipe));
497 }
498 
499 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
500 void EnrichmentTest::DoAddMat(cyclus::Material::Ptr mat) {
501  src_facility->AddMat_(mat);
502 }
503 
504 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
505 cyclus::Material::Ptr EnrichmentTest::DoRequest() {
506  return src_facility->Request_();
507 }
508 
509 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
510 cyclus::Material::Ptr
511 EnrichmentTest::DoOffer(cyclus::Material::Ptr mat) {
512  return src_facility->Offer_(mat);
513 }
514 
515 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
516 cyclus::Material::Ptr
517 EnrichmentTest::DoEnrich(cyclus::Material::Ptr mat, double qty) {
518  return src_facility->Enrich_(mat, qty);
519 }
520 
521 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
522 TEST_F(EnrichmentTest, Request) {
523  // Tests that quantity in material request is accurate
524  double req = inv_size;
525  double add = 0;
526  cyclus::Material::Ptr mat = DoRequest();
527  EXPECT_DOUBLE_EQ(mat->quantity(), req);
528  EXPECT_EQ(mat->comp(), tc_.get()->GetRecipe(feed_recipe));
529 
530  add = 2 * inv_size / 3;
531  req -= add;
532  DoAddMat(GetMat(add));
533  mat = DoRequest();
534  EXPECT_DOUBLE_EQ(mat->quantity(), req);
535  EXPECT_EQ(mat->comp(), tc_.get()->GetRecipe(feed_recipe));
536 
537  add = inv_size / 3;
538  req = 0;
539  DoAddMat(GetMat(add));
540  mat = DoRequest();
541  EXPECT_DOUBLE_EQ(mat->quantity(), req);
542  EXPECT_EQ(mat->comp(), tc_.get()->GetRecipe(feed_recipe));
543 }
544 
545 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
546 TEST_F(EnrichmentTest, ValidReq) {
547  // Tests that material requests have U235/(U235+U238) > tails assay
548  using cyclus::CompMap;
549  using cyclus::Composition;
550  using cyclus::Material;
551 
552  double qty = 4.5; // some magic number
553 
554  cyclus::CompMap v1;
555  v1[922350000] = 1;
556  Material::Ptr mat = Material::CreateUntracked
557  (qty,Composition::CreateFromAtom(v1));
558  EXPECT_FALSE(src_facility->ValidReq(mat)); // u238 = 0
559 
560  cyclus::CompMap v2;
561  v2[922350000] = tails_assay;
562  v2[922380000] = 1 - tails_assay;
563  mat = Material::CreateUntracked(qty, Composition::CreateFromAtom(v2));
564  // u235 / (u235 + u238) <= tails_assay
565  EXPECT_FALSE(src_facility->ValidReq(mat));
566 
567  cyclus::CompMap v3;
568  v3[922350000] = 1;
569  v3[922380000] = 1;
570  mat = Material::CreateUntracked(qty, Composition::CreateFromAtom(v3));
571  EXPECT_TRUE(src_facility->ValidReq(mat)); // valid
572 }
573 
574 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
575  TEST_F(EnrichmentTest, ConstraintConverters) {
576  // Tests the SWU and NatU converters to make sure that amount of
577  // feed and SWU required are correct to fulfill the enrichment request.
578  using cyclus::CompMap;
579  using cyclus::Material;
580  using cyclus::toolkit::MatQuery;
581  using cyclus::Composition;
582  using cyclus::toolkit::Assays;
583  using cyclus::toolkit::UraniumAssayMass;
584  using cyclus::toolkit::SwuRequired;
585  using cyclus::toolkit::FeedQty;
586  using cyclus::toolkit::MatQuery;
587  cyclus::Env::SetNucDataPath();
588 
589  double qty = 5; // 5 kg
590  double product_assay = 0.05; // of 5 w/o enriched U
591  CompMap v;
592  v[922350000] = product_assay;
593  v[922380000] = 1 - product_assay;
594  v[94239] = 0.5; // 94239 shouldn't be taken into account
595  Material::Ptr target = Material::CreateUntracked(
596  qty, Composition::CreateFromMass(v));
597 
598  std::set<cyclus::Nuc> nucs;
599  nucs.insert(922350000);
600  nucs.insert(922380000);
601 
602  MatQuery mq(target);
603  double mass_frac = mq.mass_frac(nucs);
604 
605  SWUConverter swuc(feed_assay, tails_assay);
606  NatUConverter natuc(feed_assay, tails_assay);
607 
608  Material::Ptr offer = DoOffer(target);
609 
610  EXPECT_NEAR(swuc.convert(target), swuc.convert(offer), 0.001);
611  EXPECT_NEAR(natuc.convert(target) * mass_frac, natuc.convert(offer), 0.001);
612 }
613 
614 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
615 TEST_F(EnrichmentTest, Enrich) {
616  // this test asks the facility to enrich a material that results in an amount
617  // of natural uranium required that is exactly its inventory level. that
618  // inventory will be comprised of two materials to test the manifest/absorb
619  // strategy employed in Enrich_.
620  using cyclus::CompMap;
621  using cyclus::Material;
622  using cyclus::toolkit::MatQuery;
623  using cyclus::Composition;
624  using cyclus::toolkit::Assays;
625  using cyclus::toolkit::UraniumAssayMass;
626  using cyclus::toolkit::SwuRequired;
627  using cyclus::toolkit::FeedQty;
628 
629  double qty = 5; // kg
630  double product_assay = 0.05; // of 5 w/o enriched U
631  cyclus::CompMap v;
632  v[922350000] = product_assay;
633  v[922380000] = 1 - product_assay;
634  // target qty need not be = to request qty
635  Material::Ptr target = cyclus::Material::CreateUntracked(
636  qty + 10, cyclus::Composition::CreateFromMass(v));
637 
638  Assays assays(feed_assay, UraniumAssayMass(target), tails_assay);
639  double swu_req = SwuRequired(qty, assays);
640  double natu_req = FeedQty(qty, assays);
641  double tails_qty = TailsQty(qty, assays);
642 
643  double swu_cap = swu_req * 5;
644  src_facility->SwuCapacity(swu_cap);
646  DoAddMat(GetMat(natu_req / 2));
647  DoAddMat(GetMat(natu_req / 2));
648 
649  Material::Ptr response;
650  EXPECT_NO_THROW(response = DoEnrich(target, qty));
651  EXPECT_DOUBLE_EQ(src_facility->Tails().quantity(), tails_qty);
652 
653  MatQuery q(response);
654  EXPECT_EQ(response->quantity(), qty);
655  EXPECT_EQ(q.mass_frac(922350000), product_assay);
656  EXPECT_EQ(q.mass_frac(922380000), 1 - product_assay);
657 
658  // test too much natu request
659  DoAddMat(GetMat(natu_req - 1));
660  EXPECT_THROW(response = DoEnrich(target, qty), cyclus::Error);
661 }
662 
663 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
664 TEST_F(EnrichmentTest, Response) {
665  // this test asks the facility to respond to multiple requests for enriched
666  // uranium. two requests are provided, whose total equals the swu capacity of
667  // the facility while not exceeding its inventory capacity (that's taken care
668  // of in the Enrich tests).
669  //
670  // note that response quantity and quality need not be tested, because they
671  // are covered by the Enrich and RequestEnrich tests
672  using cyclus::Bid;
673  using cyclus::CompMap;
674  using cyclus::Material;
675  using cyclus::Request;
676  using cyclus::Trade;
677  using cyclus::toolkit::Assays;
678  using cyclus::toolkit::FeedQty;
679  using cyclus::toolkit::SwuRequired;
680  using cyclus::toolkit::UraniumAssayMass;
681 
682  // problem set up
683  std::vector< cyclus::Trade<cyclus::Material> > trades;
684  std::vector<std::pair<cyclus::Trade<cyclus::Material>,
685  cyclus::Material::Ptr> > responses;
686 
687  double qty = 5; // kg
688  double trade_qty = qty / 3;
689  double product_assay = 0.05; // of 5 w/o enriched U
690 
691  cyclus::CompMap v;
692  v[922350000] = product_assay;
693  v[922380000] = 1 - product_assay;
694  // target qty need not be = to request qty
695  Material::Ptr target = cyclus::Material::CreateUntracked(
696  qty + 10, cyclus::Composition::CreateFromMass(v));
697 
698  Assays assays(feed_assay, UraniumAssayMass(target), tails_assay);
699  double swu_req = SwuRequired(qty, assays);
700  double natu_req = FeedQty(qty, assays);
701 
702  src_facility->SetMaxInventorySize(natu_req * 4); // not capacitated by nat
703  src_facility->SwuCapacity(swu_req); // swu capacitated
704 
705  src_facility->GetMatlTrades(trades, responses);
706 
707  // set up state
708  DoAddMat(GetMat(natu_req * 2));
709 
710  src_facility->GetMatlTrades(trades, responses);
711 
712  Request<Material>* req =
713  Request<Material>::Create(target, trader, product_commod);
714  Bid<Material>* bid = Bid<Material>::Create(req, target, src_facility);
715  Trade<Material> trade(req, bid, trade_qty);
716  trades.push_back(trade);
717 
718  // 2 trades, SWU = SWU cap
719  ASSERT_GT(src_facility->SwuCapacity() - 2 * swu_req / 3,
720  -1 * cyclus::eps());
721  trades.push_back(trade);
722  responses.clear();
723  EXPECT_NO_THROW(src_facility->GetMatlTrades(trades, responses));
724  EXPECT_EQ(responses.size(), 2);
725 }
726 
727 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
728 TEST_F(EnrichmentTest, PositionInitialize) {
729  // this tests verifies the initialization of the latitude variable
730 
731  std::string config =
732  " <feed_commod>natu</feed_commod> "
733  " <feed_recipe>natu1</feed_recipe> "
734  " <product_commod>enr_u</product_commod> "
735  " <tails_commod>tails</tails_commod> "
736  " <max_feed_inventory>1.0</max_feed_inventory> "
737  " <tails_assay>0.003</tails_assay> ";
738 
739  int simdur = 1;
740  cyclus::MockSim sim(cyclus::AgentSpec
741  (":cycamore:Enrichment"), config, simdur);
742  sim.AddRecipe("natu1", c_natu1());
743 
744  sim.AddSource("natu")
745  .recipe("natu1")
746  .Finalize();
747 
748  int id = sim.Run();
749 
750  QueryResult qr = sim.db().Query("AgentPosition", NULL);
751  EXPECT_EQ(qr.GetVal<double>("Latitude"), 0.0);
752  EXPECT_EQ(qr.GetVal<double>("Longitude"), 0.0);
753 }
754 
755 TEST_F(EnrichmentTest, PositionInitialize2) {
756  // this tests verifies the initialization of the longitude
757  // variable
758 
759  std::string config =
760  " <feed_commod>natu</feed_commod> "
761  " <feed_recipe>natu1</feed_recipe> "
762  " <product_commod>enr_u</product_commod> "
763  " <tails_commod>tails</tails_commod> "
764  " <max_feed_inventory>1.0</max_feed_inventory> "
765  " <tails_assay>0.003</tails_assay> "
766  " <latitude>50.0</latitude> "
767  " <longitude>35.0</longitude> ";
768 
769  int simdur = 1;
770  cyclus::MockSim sim(cyclus::AgentSpec
771  (":cycamore:Enrichment"), config, simdur);
772  sim.AddRecipe("natu1", c_natu1());
773 
774  sim.AddSource("natu")
775  .recipe("natu1")
776  .Finalize();
777 
778  int id = sim.Run();
779 
780  QueryResult qr = sim.db().Query("AgentPosition", NULL);
781  EXPECT_EQ(qr.GetVal<double>("Latitude"), 50.0);
782  EXPECT_EQ(qr.GetVal<double>("Longitude"), 35.0);
783 }
784 
785 
786 } // namespace cycamore
787 
788 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
789 cyclus::Agent* EnrichmentConstructor(cyclus::Context* ctx) {
790  return new cycamore::Enrichment(ctx);
791 }
792 
793 // required to get functionality in cyclus agent unit tests library
794 #ifndef CYCLUS_AGENT_TESTS_CONNECTED
795 int ConnectAgentTests();
797 #define CYCLUS_AGENT_TESTS_CONNECTED cyclus_agent_tests_connected
798 #endif // CYCLUS_AGENT_TESTS_CONNECTED
799 
800 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
801 INSTANTIATE_TEST_CASE_P(EnrichmentFac, FacilityTests,
802  Values(&EnrichmentConstructor));
803 INSTANTIATE_TEST_CASE_P(EnrichmentFac, AgentTests,
804  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.
const cyclus::toolkit::ResBuf< cyclus::Material > & Tails() const
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)
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)