2#line 1 "/cycamore/src/fuel_fab.cc"
8using cyclus::Composition;
11#define SHOW(X) std::cout << std::setprecision(17) << __FILE__ << ":" << __LINE__ << ": " #X " = " << X << "\n"
12#line 12 "/cycamore/src/fuel_fab.cc"
19 Composition::Ptr c_topup, std::string spectrum)
29 Material::Ptr m, cyclus::Arc
const* a = NULL,
30 cyclus::ExchangeTranslationContext<Material>
const* ctx =
42 return cyclus::CY_LARGE_DOUBLE;
59 Composition::Ptr c_topup, std::string spectrum)
69 Material::Ptr m, cyclus::Arc
const* a = NULL,
70 cyclus::ExchangeTranslationContext<Material>
const* ctx =
81 return cyclus::CY_LARGE_DOUBLE;
98 Composition::Ptr c_topup, std::string spectrum)
108 Material::Ptr m, cyclus::Arc
const* a = NULL,
109 cyclus::ExchangeTranslationContext<Material>
const* ctx =
120 return cyclus::CY_LARGE_DOUBLE;
135 : cyclus::Facility(ctx),
144 cyclus::Facility::EnterNotify();
151 std::stringstream ss;
153 <<
" fiss_commod_prefs vals, expected " <<
fiss_commods.size();
154 throw cyclus::ValidationError(ss.str());
162 std::stringstream ss;
164 <<
" fill_commod_prefs vals, expected " <<
fill_commods.size();
165 throw cyclus::ValidationError(ss.str());
171 using cyclus::RequestPortfolio;
173 std::set<RequestPortfolio<Material>::Ptr> ports;
175 bool exclusive =
false;
177 if (
fiss.space() > cyclus::eps_rsrc()) {
178 RequestPortfolio<Material>::Ptr port(
new RequestPortfolio<Material>());
180 Material::Ptr m = cyclus::NewBlankMaterial(
fiss.space());
182 Composition::Ptr c = context()->GetRecipe(
fiss_recipe);
183 m = Material::CreateUntracked(
fiss.space(), c);
186 std::vector<cyclus::Request<Material>*> reqs;
190 reqs.push_back(port->AddRequest(m,
this, commod, pref, exclusive));
193 port->AddMutualReqs(reqs);
197 if (
fill.space() > cyclus::eps_rsrc()) {
198 RequestPortfolio<Material>::Ptr port(
new RequestPortfolio<Material>());
200 Material::Ptr m = cyclus::NewBlankMaterial(
fill.space());
202 Composition::Ptr c = context()->GetRecipe(
fill_recipe);
203 m = Material::CreateUntracked(
fill.space(), c);
206 std::vector<cyclus::Request<Material>*> reqs;
210 reqs.push_back(port->AddRequest(m,
this, commod, pref, exclusive));
213 port->AddMutualReqs(reqs);
217 if (
topup.space() > cyclus::eps_rsrc()) {
218 RequestPortfolio<Material>::Ptr port(
new RequestPortfolio<Material>());
220 Material::Ptr m = cyclus::NewBlankMaterial(
topup.space());
222 Composition::Ptr c = context()->GetRecipe(
topup_recipe);
223 m = Material::CreateUntracked(
topup.space(), c);
225 cyclus::Request<Material>* r =
234bool Contains(std::vector<std::string> vec, std::string s) {
235 for (
int i = 0; i < vec.size(); i++) {
244 const std::vector<std::pair<cyclus::Trade<Material>, Material::Ptr> >&
246 std::vector<std::pair<cyclus::Trade<Material>,
247 Material::Ptr> >::const_iterator trade;
249 for (trade = responses.begin(); trade != responses.end(); ++trade) {
250 std::string commod = trade->first.request->commodity();
251 double req_qty = trade->first.request->target()->quantity();
252 cyclus::Request<Material>* req = trade->first.request;
253 Material::Ptr m = trade->second;
261 throw cyclus::ValueError(
"cycamore::FuelFab was overmatched on requests");
269 if (
fill.count() > 1) {
270 fill.Push(cyclus::toolkit::Squash(
fill.PopN(
fill.count())));
272 if (
fiss.count() > 1) {
273 fiss.Push(cyclus::toolkit::Squash(
fiss.PopN(
fiss.count())));
275 if (
topup.count() > 1) {
281 cyclus::CommodMap<Material>::type& commod_requests) {
282 using cyclus::BidPortfolio;
284 std::set<BidPortfolio<Material>::Ptr> ports;
285 std::vector<cyclus::Request<Material>*>& reqs = commod_requests[
outcommod];
289 }
else if (reqs.size() == 0) {
296 if (
fill.count() > 0) {
297 c_fill =
fill.Peek()->comp();
305 Composition::Ptr c_topup = c_fill;
306 if (
topup.count() > 0) {
307 c_topup =
topup.Peek()->comp();
316 Composition::Ptr c_fiss = c_fill;
317 if (
fiss.count() > 0) {
318 c_fiss =
fiss.Peek()->comp();
325 BidPortfolio<Material>::Ptr port(
new BidPortfolio<Material>());
326 for (
int j = 0; j < reqs.size(); j++) {
327 cyclus::Request<Material>* req = reqs[j];
329 Composition::Ptr tgt = req->target()->comp();
331 double tgt_qty = req->target()->quantity();
333 double fiss_frac =
HighFrac(w_fill, w_tgt, w_fiss);
334 double fill_frac = 1 - fiss_frac;
337 Material::Ptr m1 = Material::CreateUntracked(fiss_frac * tgt_qty, c_fiss);
338 Material::Ptr m2 = Material::CreateUntracked(fill_frac * tgt_qty, c_fill);
341 bool exclusive =
false;
342 port->AddBid(req, m1,
this, exclusive);
347 double topup_frac =
HighFrac(w_fiss, w_tgt, w_topup);
348 double fiss_frac = 1 - topup_frac;
352 Material::CreateUntracked(topup_frac * tgt_qty, c_topup);
353 Material::Ptr m2 = Material::CreateUntracked(fiss_frac * tgt_qty, c_fiss);
356 bool exclusive =
false;
357 port->AddBid(req, m1,
this, exclusive);
358 }
else if (
fiss.count() > 0 &&
fill.count() > 0 ||
363 std::stringstream ss;
364 ss <<
"prototype '" << prototype()
365 <<
"': Input stream weights/reactivity do not span "
366 "the requested material weight.";
367 cyclus::Warn<cyclus::VALUE_WARNING>(ss.str());
371 cyclus::Converter<Material>::Ptr fissconv(
372 new FissConverter(c_fill, c_fiss, c_topup,
spectrum));
373 cyclus::Converter<Material>::Ptr fillconv(
374 new FillConverter(c_fill, c_fiss, c_topup,
spectrum));
375 cyclus::Converter<Material>::Ptr topupconv(
376 new TopupConverter(c_fill, c_fiss, c_topup,
spectrum));
379 cyclus::CapacityConstraint<Material> fissc(std::max(
fiss.quantity(), cyclus::CY_NEAR_ZERO),
381 cyclus::CapacityConstraint<Material> fillc(std::max(
fill.quantity(), cyclus::CY_NEAR_ZERO),
383 cyclus::CapacityConstraint<Material> topupc(std::max(
topup.quantity(), cyclus::CY_NEAR_ZERO),
385 port->AddConstraint(fillc);
386 port->AddConstraint(fissc);
387 port->AddConstraint(topupc);
389 cyclus::CapacityConstraint<Material> cc(
throughput);
390 port->AddConstraint(cc);
396 const std::vector<cyclus::Trade<Material> >& trades,
397 std::vector<std::pair<cyclus::Trade<Material>, Material::Ptr> >&
404 if (
fill.count() > 0) {
408 if (
topup.count() > 0) {
412 if (
fiss.count() > 0) {
416 std::vector<cyclus::Trade<Material> >::const_iterator it;
418 for (
int i = 0; i < trades.size(); i++) {
419 Material::Ptr tgt = trades[i].request->target();
422 double qty = trades[i].amt;
423 double wfiss = w_fiss;
427 std::stringstream ss;
428 ss <<
"FuelFab was matched above throughput limit: " << tot <<
" > "
430 throw cyclus::ValueError(ss.str());
433 if (
fiss.count() == 0) {
435 double fillqty = qty;
436 if (std::abs(fillqty -
fill.quantity()) < cyclus::eps_rsrc()) {
437 fillqty = std::min(
fill.quantity(), qty);
440 std::make_pair(trades[i],
fill.Pop(fillqty, cyclus::eps_rsrc())));
443 double fissqty = qty;
444 if (std::abs(fissqty -
fiss.quantity()) < cyclus::eps_rsrc()) {
445 fissqty = std::min(
fiss.quantity(), qty);
448 std::make_pair(trades[i],
fiss.Pop(fissqty, cyclus::eps_rsrc())));
450 double fiss_frac =
HighFrac(w_fill, w_tgt, w_fiss);
451 double fill_frac =
LowFrac(w_fill, w_tgt, w_fiss);
457 double fissqty = fiss_frac * qty;
458 if (std::abs(fissqty -
fiss.quantity()) < cyclus::eps_rsrc()) {
459 fissqty = std::min(
fiss.quantity(), fiss_frac * qty);
461 double fillqty = fill_frac * qty;
462 if (std::abs(fillqty -
fill.quantity()) < cyclus::eps_rsrc()) {
463 fillqty = std::min(
fill.quantity(), fill_frac * qty);
466 Material::Ptr m =
fiss.Pop(fissqty, cyclus::eps_rsrc());
469 m->Absorb(
fill.Pop(fillqty, cyclus::eps_rsrc()));
471 responses.push_back(std::make_pair(trades[i], m));
473 double topup_frac =
HighFrac(w_fiss, w_tgt, w_topup);
474 double fiss_frac = 1 - topup_frac;
480 double fissqty = fiss_frac * qty;
481 if (std::abs(fissqty -
fiss.quantity()) < cyclus::eps_rsrc()) {
482 fissqty = std::min(
fiss.quantity(), fiss_frac * qty);
484 double topupqty = topup_frac * qty;
485 if (std::abs(topupqty -
topup.quantity()) < cyclus::eps_rsrc()) {
486 topupqty = std::min(
topup.quantity(), topup_frac * qty);
489 Material::Ptr m =
fiss.Pop(fissqty, cyclus::eps_rsrc());
491 if (topup_frac > 0) {
492 m->Absorb(
topup.Pop(topupqty, cyclus::eps_rsrc()));
494 responses.push_back(std::make_pair(trades[i], m));
500 std::string specification = this->spec();
502 ->NewDatum(
"AgentPosition")
503 ->AddVal(
"Spec", specification)
504 ->AddVal(
"Prototype", this->prototype())
505 ->AddVal(
"AgentId",
id())
528double CosiWeight(Composition::Ptr c,
const std::string& spectrum) {
529 cyclus::CompMap cm = c->atom();
530 cyclus::compmath::Normalize(&cm);
532 if (spectrum ==
"thermal") {
533 double nu_pu239 = 2.85;
534 double nu_u233 = 2.5;
535 double nu_u235 = 2.43;
537 double nu_pu241 = nu_pu239;
539 static std::map<int, double> absorb_xs;
540 static std::map<int, double> fiss_xs;
541 static double p_u238 = 0;
542 static double p_pu239 = 0;
544 double fiss_u238 = simple_xs(922380000,
"fission",
"thermal");
545 double absorb_u238 = simple_xs(922380000,
"absorption",
"thermal");
546 p_u238 = nu_u238 * fiss_u238 - absorb_u238;
548 double fiss_pu239 = simple_xs(942390000,
"fission",
"thermal");
549 double absorb_pu239 = simple_xs(942390000,
"absorption",
"thermal");
550 p_pu239 = nu_pu239 * fiss_pu239 - absorb_pu239;
553 cyclus::CompMap::iterator it;
555 for (it = cm.begin(); it != cm.end(); ++it) {
556 cyclus::Nuc nuc = it->first;
558 if (nuc == 922350000) {
560 }
else if (nuc == 922330000) {
562 }
else if (nuc == 942390000) {
564 }
else if (nuc == 942410000) {
570 if (absorb_xs.count(nuc) == 0) {
572 fiss = simple_xs(nuc,
"fission",
"thermal");
573 absorb = simple_xs(nuc,
"absorption",
"thermal");
574 absorb_xs[nuc] = absorb;
576 }
catch (pyne::InvalidSimpleXS err) {
582 absorb = absorb_xs[nuc];
585 double p = nu * fiss - absorb;
586 w += it->second * (p - p_u238) / (p_pu239 - p_u238);
589 }
else if (spectrum ==
"fission_spectrum_ave") {
590 double nu_pu239 = 3.1;
591 double nu_u233 = 2.63;
592 double nu_u235 = 2.58;
594 double nu_pu241 = nu_pu239;
596 static std::map<int, double> absorb_xs;
597 static std::map<int, double> fiss_xs;
598 static double p_u238 = 0;
599 static double p_pu239 = 0;
602 simple_xs(922380000,
"fission",
"fission_spectrum_ave");
604 simple_xs(922380000,
"absorption",
"fission_spectrum_ave");
605 p_u238 = nu_u238 * fiss_u238 - absorb_u238;
608 simple_xs(942390000,
"fission",
"fission_spectrum_ave");
609 double absorb_pu239 =
610 simple_xs(942390000,
"absorption",
"fission_spectrum_ave");
611 p_pu239 = nu_pu239 * fiss_pu239 - absorb_pu239;
614 cyclus::CompMap::iterator it;
616 for (it = cm.begin(); it != cm.end(); ++it) {
617 cyclus::Nuc nuc = it->first;
619 if (nuc == 922350000) {
621 }
else if (nuc == 922330000) {
623 }
else if (nuc == 942390000) {
625 }
else if (nuc == 942410000) {
631 if (absorb_xs.count(nuc) == 0) {
633 fiss = simple_xs(nuc,
"fission",
"fission_spectrum_ave");
634 absorb = simple_xs(nuc,
"absorption",
"fission_spectrum_ave");
635 absorb_xs[nuc] = absorb;
637 }
catch (pyne::InvalidSimpleXS err) {
643 absorb = absorb_xs[nuc];
646 double p = nu * fiss - absorb;
647 w += it->second * (p - p_u238) / (p_pu239 - p_u238);
651 double nu_pu239 = 3.1;
652 double nu_u233 = 2.63;
653 double nu_u235 = 2.58;
655 double nu_pu241 = nu_pu239;
657 double fiss_u238 = simple_xs(922380000,
"fission", spectrum);
658 double absorb_u238 = simple_xs(922380000,
"absorption", spectrum);
659 double p_u238 = nu_u238 * fiss_u238 - absorb_u238;
661 double fiss_pu239 = simple_xs(942390000,
"fission", spectrum);
662 double absorb_pu239 = simple_xs(942390000,
"absorption", spectrum);
663 double p_pu239 = nu_pu239 * fiss_pu239 - absorb_pu239;
665 cyclus::CompMap::iterator it;
667 for (it = cm.begin(); it != cm.end(); ++it) {
668 cyclus::Nuc nuc = it->first;
670 if (nuc == 922350000) {
672 }
else if (nuc == 922330000) {
674 }
else if (nuc == 942390000) {
676 }
else if (nuc == 942410000) {
683 fiss = simple_xs(nuc,
"fission", spectrum);
684 absorb = simple_xs(nuc,
"absorption", spectrum);
685 }
catch (pyne::InvalidSimpleXS err) {
690 double p = nu * fiss - absorb;
691 w += it->second * (p - p_u238) / (p_pu239 - p_u238);
700 Composition::Ptr c2) {
701 cyclus::CompMap n1 = c1->atom();
702 cyclus::CompMap n2 = c2->atom();
703 cyclus::compmath::Normalize(&n1, atomfrac);
704 cyclus::compmath::Normalize(&n2, 1 - atomfrac);
706 cyclus::CompMap::iterator it;
709 for (it = n1.begin(); it != n1.end(); ++it) {
710 mass1 += it->second * pyne::atomic_mass(it->first);
714 for (it = n2.begin(); it != n2.end(); ++it) {
715 mass2 += it->second * pyne::atomic_mass(it->first);
718 return mass1 / (mass1 + mass2);
721double HighFrac(
double w_low,
double w_target,
double w_high,
double eps) {
723 throw cyclus::ValueError(
"low and high weights cannot meet target");
724 }
else if (w_low == w_high && w_target == w_low) {
727 double f = std::abs((w_target - w_low) / (w_high - w_low));
730 }
else if (f < eps) {
736double LowFrac(
double w_low,
double w_target,
double w_high,
double eps) {
737 return 1 -
HighFrac(w_low, w_target, w_high, eps);
745 return w_low <= w_target && w_target <= w_high;
FillConverter(Composition::Ptr c_fill, Composition::Ptr c_fiss, Composition::Ptr c_topup, std::string spectrum)
Composition::Ptr c_topup_
virtual double convert(Material::Ptr m, cyclus::Arc const *a=NULL, cyclus::ExchangeTranslationContext< Material > const *ctx=NULL) const
FissConverter(Composition::Ptr c_fill, Composition::Ptr c_fiss, Composition::Ptr c_topup, std::string spectrum)
virtual double convert(Material::Ptr m, cyclus::Arc const *a=NULL, cyclus::ExchangeTranslationContext< Material > const *ctx=NULL) const
Composition::Ptr c_topup_
FuelFab takes in 2 streams of material and mixes them in ratios in order to supply material that matc...
FuelFab(cyclus::Context *ctx)
void RecordPosition()
Records an agent's latitude and longitude to the output db.
virtual void EnterNotify()
virtual void AcceptMatlTrades(const std::vector< std::pair< cyclus::Trade< cyclus::Material >, cyclus::Material::Ptr > > &responses)
cyclus::toolkit::ResBuf< cyclus::Material > fill
std::map< cyclus::Request< cyclus::Material > *, std::string > req_inventories_
virtual void GetMatlTrades(const std::vector< cyclus::Trade< cyclus::Material > > &trades, std::vector< std::pair< cyclus::Trade< cyclus::Material >, cyclus::Material::Ptr > > &responses)
virtual std::set< cyclus::RequestPortfolio< cyclus::Material >::Ptr > GetMatlRequests()
std::vector< double > fill_commod_prefs
virtual std::set< cyclus::BidPortfolio< cyclus::Material >::Ptr > GetMatlBids(cyclus::CommodMap< cyclus::Material >::type &commod_requests)
cyclus::toolkit::ResBuf< cyclus::Material > topup
cyclus::toolkit::ResBuf< cyclus::Material > fiss
std::vector< std::string > fiss_commods
std::vector< std::string > fill_commods
std::vector< double > fiss_commod_prefs
virtual double convert(Material::Ptr m, cyclus::Arc const *a=NULL, cyclus::ExchangeTranslationContext< Material > const *ctx=NULL) const
Composition::Ptr c_topup_
virtual ~TopupConverter()
TopupConverter(Composition::Ptr c_fill, Composition::Ptr c_fiss, Composition::Ptr c_topup, std::string spectrum)
double HighFrac(double w_low, double w_target, double w_high, double eps)
double CosiWeight(Composition::Ptr c, const std::string &spectrum)
cyclus::Agent * ConstructFuelFab(cyclus::Context *ctx)
bool ValidWeights(double w_low, double w_target, double w_high)
double AtomToMassFrac(double atomfrac, Composition::Ptr c1, Composition::Ptr c2)
bool Contains(std::vector< std::string > vec, std::string s)
double LowFrac(double w_low, double w_target, double w_high, double eps)
cyclus::toolkit::Position coordinates