10#include <boost/lexical_cast.hpp>
12using cyclus::Material;
18 : cyclus::Facility(ctx),
33Enrichment::~Enrichment() {}
36std::string Enrichment::str() {
38 ss << cyclus::Facility::str() <<
" with enrichment facility parameters:"
39 <<
" * SWU capacity: " << SwuCapacity()
40 <<
" * Tails assay: " << tails_assay <<
" * Feed assay: " << FeedAssay()
41 <<
" * Input cyclus::Commodity: " << feed_commod
42 <<
" * Output cyclus::Commodity: " << product_commod
43 <<
" * Tails cyclus::Commodity: " << tails_commod;
48void Enrichment::Build(cyclus::Agent* parent) {
49 Facility::Build(parent);
50 if (initial_feed > 0) {
51 inventory.Push(Material::Create(
this, initial_feed,
52 context()->GetRecipe(feed_recipe)));
55 LOG(cyclus::LEV_DEBUG2,
"EnrFac") <<
"Enrichment "
56 <<
" entering the simuluation: ";
57 LOG(cyclus::LEV_DEBUG2,
"EnrFac") << str();
62void Enrichment::Tick() {
63 current_swu_capacity = SwuCapacity();
68void Enrichment::Tock() {
69 using cyclus::toolkit::RecordTimeSeries;
70 LOG(cyclus::LEV_INFO4,
"EnrFac") << prototype() <<
" used "
71 << intra_timestep_swu_ <<
" SWU";
72 RecordTimeSeries<cyclus::toolkit::ENRICH_SWU>(
this, intra_timestep_swu_);
73 LOG(cyclus::LEV_INFO4,
"EnrFac") << prototype() <<
" used "
74 << intra_timestep_feed_ <<
" feed";
75 RecordTimeSeries<cyclus::toolkit::ENRICH_FEED>(
this, intra_timestep_feed_);
76 RecordTimeSeries<double>(
"demand"+feed_commod,
this, intra_timestep_feed_);
80std::set<cyclus::RequestPortfolio<Material>::Ptr>
81Enrichment::GetMatlRequests() {
82 using cyclus::RequestPortfolio;
84 std::set<RequestPortfolio<Material>::Ptr> ports;
85 RequestPortfolio<Material>::Ptr port(
new RequestPortfolio<Material>());
86 Material::Ptr mat = Request_();
87 double amt = mat->quantity();
89 if (amt > cyclus::eps_rsrc()) {
90 port->AddRequest(mat,
this, feed_commod);
98bool SortBids(cyclus::Bid<Material>* i,
99 cyclus::Bid<Material>* j) {
100 Material::Ptr mat_i = i->offer();
101 Material::Ptr mat_j = j->offer();
103 cyclus::toolkit::MatQuery mq_i(mat_i);
104 cyclus::toolkit::MatQuery mq_j(mat_j);
106 return ((mq_i.mass(922350000) / mq_i.qty()) <=
107 (mq_j.mass(922350000) / mq_j.qty()));
112void Enrichment::AdjustMatlPrefs(
113 cyclus::PrefMap<Material>::type& prefs) {
116 if (order_prefs ==
false) {
120 cyclus::PrefMap<Material>::type::iterator reqit;
123 for (reqit = prefs.begin(); reqit != prefs.end(); ++reqit) {
124 std::vector<Bid<Material>*> bids_vector;
125 std::map<Bid<Material>*,
double>::iterator mit;
126 for (mit = reqit->second.begin(); mit != reqit->second.end(); ++mit) {
127 Bid<Material>* bid = mit->first;
128 bids_vector.push_back(bid);
130 std::sort(bids_vector.begin(), bids_vector.end(), SortBids);
133 double n_bids = bids_vector.size();
136 for (
int bidit = 0; bidit < bids_vector.size(); bidit++) {
137 int new_pref = bidit + 1;
141 Material::Ptr mat = bids_vector[bidit]->offer();
142 cyclus::toolkit::MatQuery mq(mat);
143 if (mq.mass(922350000) == 0) {
149 (reqit->second)[bids_vector[bidit]] = new_pref;
155void Enrichment::AcceptMatlTrades(
156 const std::vector<std::pair<cyclus::Trade<Material>,
157 Material::Ptr> >& responses) {
160 std::vector<std::pair<cyclus::Trade<Material>,
161 Material::Ptr> >::const_iterator it;
162 for (it = responses.begin(); it != responses.end(); ++it) {
168std::set<cyclus::BidPortfolio<Material>::Ptr> Enrichment::GetMatlBids(
169 cyclus::CommodMap<Material>::type& out_requests) {
170 using cyclus::BidPortfolio;
171 using cyclus::CapacityConstraint;
172 using cyclus::Converter;
173 using cyclus::Request;
174 using cyclus::toolkit::MatVec;
175 using cyclus::toolkit::RecordTimeSeries;
177 std::set<BidPortfolio<Material>::Ptr> ports;
179 RecordTimeSeries<double>(
"supply" + tails_commod,
this, tails.quantity());
180 RecordTimeSeries<double>(
"supply" + product_commod,
this, inventory.quantity());
181 if ((out_requests.count(tails_commod) > 0) && (tails.quantity() > 0)) {
182 BidPortfolio<Material>::Ptr tails_port(
new BidPortfolio<Material>());
184 std::vector<Request<Material>*>& tails_requests =
185 out_requests[tails_commod];
186 std::vector<Request<Material>*>::iterator it;
187 for (it = tails_requests.begin(); it != tails_requests.end(); ++it) {
190 MatVec mats = tails.PopN(tails.count());
192 for (
int k = 0; k < mats.size(); k++) {
193 Material::Ptr m = mats[k];
194 Request<Material>* req = *it;
195 tails_port->AddBid(req, m,
this);
200 CapacityConstraint<Material> tails_constraint(tails.quantity());
201 tails_port->AddConstraint(tails_constraint);
202 LOG(cyclus::LEV_INFO5,
"EnrFac") << prototype()
203 <<
" adding tails capacity constraint of "
205 ports.insert(tails_port);
208 if ((out_requests.count(product_commod) > 0) && (inventory.quantity() > 0)) {
209 BidPortfolio<Material>::Ptr commod_port(
new BidPortfolio<Material>());
211 std::vector<Request<Material>*>& commod_requests =
212 out_requests[product_commod];
213 std::vector<Request<Material>*>::iterator it;
214 for (it = commod_requests.begin(); it != commod_requests.end(); ++it) {
215 Request<Material>* req = *it;
216 Material::Ptr mat = req->target();
217 double request_enrich = cyclus::toolkit::UraniumAssayMass(mat);
218 if (ValidReq(req->target()) &&
219 ((request_enrich < max_enrich) ||
220 (cyclus::AlmostEq(request_enrich, max_enrich)))) {
221 Material::Ptr offer = Offer_(req->target());
222 commod_port->AddBid(req, offer,
this);
226 Converter<Material>::Ptr sc(
new SWUConverter(FeedAssay(), tails_assay));
227 Converter<Material>::Ptr nc(
new NatUConverter(FeedAssay(), tails_assay));
228 CapacityConstraint<Material> swu(swu_capacity, sc);
229 CapacityConstraint<Material> natu(inventory.quantity(), nc);
230 commod_port->AddConstraint(swu);
231 commod_port->AddConstraint(natu);
233 LOG(cyclus::LEV_INFO5,
"EnrFac")
234 << prototype() <<
" adding a swu constraint of " << swu.capacity();
235 LOG(cyclus::LEV_INFO5,
"EnrFac")
236 << prototype() <<
" adding a natu constraint of " << natu.capacity();
237 ports.insert(commod_port);
243bool Enrichment::ValidReq(
const Material::Ptr mat) {
244 cyclus::toolkit::MatQuery q(mat);
245 double u235 = q.atom_frac(922350000);
246 double u238 = q.atom_frac(922380000);
247 return (u238 > 0 && u235 / (u235 + u238) > tails_assay);
251void Enrichment::GetMatlTrades(
252 const std::vector<cyclus::Trade<Material> >& trades,
253 std::vector<std::pair<cyclus::Trade<Material>,
254 Material::Ptr> >& responses) {
257 intra_timestep_swu_ = 0;
258 intra_timestep_feed_ = 0;
260 std::vector<Trade<Material>>::const_iterator it;
261 for (it = trades.begin(); it != trades.end(); ++it) {
262 double qty = it->amt;
263 std::string commod_type = it->bid->request()->commodity();
264 Material::Ptr response;
267 if (commod_type == tails_commod) {
268 LOG(cyclus::LEV_INFO5,
"EnrFac")
269 << prototype() <<
" just received an order"
270 <<
" for " << it->amt <<
" of " << tails_commod;
271 double pop_qty = std::min(qty, tails.quantity());
272 response = tails.Pop(pop_qty, cyclus::eps_rsrc());
274 LOG(cyclus::LEV_INFO5,
"EnrFac")
275 << prototype() <<
" just received an order"
276 <<
" for " << it->amt <<
" of " << product_commod;
277 response = Enrich_(it->bid->offer(), qty);
279 responses.push_back(std::make_pair(*it, response));
282 if (cyclus::IsNegative(tails.quantity())) {
283 std::stringstream ss;
284 ss <<
"is being asked to provide more than its current inventory.";
285 throw cyclus::ValueError(Agent::InformErrorMsg(ss.str()));
287 if (cyclus::IsNegative(current_swu_capacity)) {
288 throw cyclus::ValueError(
"EnrFac " + prototype() +
289 " is being asked to provide more than" +
290 " its SWU capacity.");
295void Enrichment::AddMat_(Material::Ptr mat) {
297 cyclus::CompMap cm = mat->comp()->atom();
298 bool extra_u =
false;
299 bool other_elem =
false;
300 for (cyclus::CompMap::const_iterator it = cm.begin(); it != cm.end(); ++it) {
301 if (pyne::nucname::znum(it->first) == 92) {
302 if (pyne::nucname::anum(it->first) != 235 &&
303 pyne::nucname::anum(it->first) != 238 && it->second > 0) {
306 }
else if (it->second > 0) {
311 cyclus::Warn<cyclus::VALUE_WARNING>(
312 "More than 2 isotopes of U. "
313 "Istopes other than U-235, U-238 are sent directly to tails.");
316 cyclus::Warn<cyclus::VALUE_WARNING>(
317 "Non-uranium elements are "
318 "sent directly to tails.");
321 LOG(cyclus::LEV_INFO5,
"EnrFac") << prototype() <<
" is initially holding "
322 << inventory.quantity() <<
" total.";
326 }
catch (cyclus::Error& e) {
327 e.msg(Agent::InformErrorMsg(e.msg()));
331 LOG(cyclus::LEV_INFO5,
"EnrFac")
332 << prototype() <<
" added " << mat->quantity() <<
" of " << feed_commod
333 <<
" to its inventory, which is holding " << inventory.quantity()
338Material::Ptr Enrichment::Request_() {
339 double qty = std::max(0.0, inventory.capacity() - inventory.quantity());
340 return Material::CreateUntracked(qty,
341 context()->GetRecipe(feed_recipe));
345Material::Ptr Enrichment::Offer_(Material::Ptr mat) {
346 cyclus::toolkit::MatQuery q(mat);
347 cyclus::CompMap comp;
348 comp[922350000] = q.atom_frac(922350000);
349 comp[922380000] = q.atom_frac(922380000);
350 return Material::CreateUntracked(
351 mat->quantity(), cyclus::Composition::CreateFromAtom(comp));
354Material::Ptr Enrichment::Enrich_(Material::Ptr mat,
356 using cyclus::toolkit::Assays;
357 using cyclus::toolkit::UraniumAssayMass;
358 using cyclus::toolkit::SwuRequired;
359 using cyclus::toolkit::FeedQty;
360 using cyclus::toolkit::TailsQty;
363 Assays assays(FeedAssay(), UraniumAssayMass(mat), tails_assay);
364 double swu_req = SwuRequired(qty, assays);
365 double natu_req = FeedQty(qty, assays);
369 double pop_qty = inventory.quantity();
370 Material::Ptr natu_matl = inventory.Pop(pop_qty, cyclus::eps_rsrc());
371 inventory.Push(natu_matl);
373 cyclus::toolkit::MatQuery mq(natu_matl);
374 std::set<cyclus::Nuc> nucs;
375 nucs.insert(922350000);
376 nucs.insert(922380000);
377 double natu_frac = mq.mass_frac(nucs);
378 double feed_req = natu_req / natu_frac;
384 if (cyclus::AlmostEq(feed_req, inventory.quantity())) {
385 r = cyclus::toolkit::Squash(inventory.PopN(inventory.count()));
387 r = inventory.Pop(feed_req, cyclus::eps_rsrc());
389 }
catch (cyclus::Error& e) {
390 NatUConverter nc(FeedAssay(), tails_assay);
391 std::stringstream ss;
392 ss <<
" tried to remove " << feed_req <<
" from its inventory of size "
393 << inventory.quantity()
394 <<
" and the conversion of the material into natu is "
396 throw cyclus::ValueError(Agent::InformErrorMsg(ss.str()));
401 cyclus::Composition::Ptr comp = mat->comp();
402 Material::Ptr response = r->ExtractComp(qty, comp);
405 current_swu_capacity -= swu_req;
407 intra_timestep_swu_ += swu_req;
408 intra_timestep_feed_ += feed_req;
409 RecordEnrichment_(feed_req, swu_req);
411 LOG(cyclus::LEV_INFO5,
"EnrFac") << prototype()
412 <<
" has performed an enrichment: ";
413 LOG(cyclus::LEV_INFO5,
"EnrFac") <<
" * Feed Qty: " << feed_req;
414 LOG(cyclus::LEV_INFO5,
"EnrFac") <<
" * Feed Assay: "
415 << assays.Feed() * 100;
416 LOG(cyclus::LEV_INFO5,
"EnrFac") <<
" * Product Qty: " << qty;
417 LOG(cyclus::LEV_INFO5,
"EnrFac") <<
" * Product Assay: "
418 << assays.Product() * 100;
419 LOG(cyclus::LEV_INFO5,
"EnrFac") <<
" * Tails Qty: "
420 << TailsQty(qty, assays);
421 LOG(cyclus::LEV_INFO5,
"EnrFac") <<
" * Tails Assay: "
422 << assays.Tails() * 100;
423 LOG(cyclus::LEV_INFO5,
"EnrFac") <<
" * SWU: " << swu_req;
424 LOG(cyclus::LEV_INFO5,
"EnrFac") <<
" * Current SWU capacity: "
425 << current_swu_capacity;
431void Enrichment::RecordEnrichment_(
double natural_u,
double swu) {
432 using cyclus::Context;
435 LOG(cyclus::LEV_DEBUG1,
"EnrFac") << prototype()
436 <<
" has enriched a material:";
437 LOG(cyclus::LEV_DEBUG1,
"EnrFac") <<
" * Amount: " << natural_u;
438 LOG(cyclus::LEV_DEBUG1,
"EnrFac") <<
" * SWU: " << swu;
440 Context* ctx = Agent::context();
441 ctx->NewDatum(
"Enrichments")
442 ->AddVal(
"AgentId",
id())
443 ->AddVal(
"Time", ctx->time())
444 ->AddVal(
"Natural_Uranium", natural_u)
449double Enrichment::FeedAssay() {
450 if (inventory.empty()) {
453 double pop_qty = inventory.quantity();
454 Material::Ptr fission_matl =
455 inventory.Pop(pop_qty, cyclus::eps_rsrc());
456 inventory.Push(fission_matl);
457 return cyclus::toolkit::UraniumAssayMass(fission_matl);
461void Enrichment::RecordPosition() {
462 std::string specification = this->spec();
464 ->NewDatum(
"AgentPosition")
465 ->AddVal(
"Spec", specification)
466 ->AddVal(
"Prototype", this->prototype())
467 ->AddVal(
"AgentId",
id())
468 ->AddVal(
"Latitude", latitude)
469 ->AddVal(
"Longitude", longitude)
475 return new Enrichment(ctx);
Enrichment(cyclus::Context *ctx)
Constructor for the Enrichment class.
void RecordPosition()
Records an agent's latitude and longitude to the output db.
cyclus::Agent * ConstructEnrichment(cyclus::Context *ctx)
cyclus::toolkit::Position coordinates
bool SortBids(cyclus::Bid< Material > *i, cyclus::Bid< Material > *j)