CYCAMORE
src/mixer.cc
Go to the documentation of this file.
1 #include <sstream>
2 
3 #include "mixer.h"
4 
5 namespace cycamore {
6 
7 Mixer::Mixer(cyclus::Context* ctx)
8  : cyclus::Facility(ctx),
9  throughput(0),
10  latitude(0.0),
11  longitude(0.0),
13  cyclus::Warn<cyclus::EXPERIMENTAL_WARNING>(
14  "the Mixer archetype is experimental");
16 }
17 
18 cyclus::Inventories Mixer::SnapshotInv() {
19  cyclus::Inventories invs;
20 
21  // these inventory names are intentionally convoluted so as to not clash
22  // with the user-specified stream commods that are used as the Mixer
23  // streams inventory names.
24  invs["output-inv-name"] = output.PopNRes(output.count());
25  output.Push(invs["output-inv-name"]);
26 
27  std::map<std::string, cyclus::toolkit::ResBuf<cyclus::Material> >::iterator
28  it;
29  for (it = streambufs.begin(); it != streambufs.end(); ++it) {
30  invs[it->first] = it->second.PopNRes(it->second.count());
31  it->second.Push(invs[it->first]);
32  }
33  return invs;
34 }
35 
36 void Mixer::InitInv(cyclus::Inventories& inv) {
37  inv["output-inv-name"] = output.PopNRes(output.count());
38  output.Push(inv["output-inv-name"]);
39 
40  cyclus::Inventories::iterator it;
41  for (it = inv.begin(); it != inv.end(); ++it) {
42  streambufs[it->first].Push(it->second);
43  }
44 }
45 
46 void Mixer::EnterNotify() {
47  cyclus::Facility::EnterNotify();
48 
49  mixing_ratios.clear();
50  in_buf_sizes.clear();
51  in_commods.clear();
52 
53  // initialisation internal variable
54  for (int i = 0; i < streams_.size(); i++) {
55  mixing_ratios.push_back(streams_[i].first.first);
56  in_buf_sizes.push_back(streams_[i].first.second);
57 
58  std::string name = "in_stream_" + std::to_string(i);
59  double cap = in_buf_sizes[i];
60  if (cap >= 0) {
61  streambufs[name].capacity(cap);
62  }
63  in_commods.push_back(streams_[i].second);
64  }
65 
66  // ratio normalisation
67  if (mixing_ratios.size() != in_commods.size()) {
68  std::stringstream ss;
69  ss << "prototype '" << prototype() << "' has " << mixing_ratios.size()
70  << " commodity fraction values, expected " << in_commods.size();
71  throw cyclus::ValidationError(ss.str());
72 
73  } else {
74  double frac_sum = 0.0;
75  for (int i = 0; i < mixing_ratios.size(); i++) frac_sum += mixing_ratios[i];
76 
77  if (frac_sum != 1.0) {
78  std::stringstream ss;
79  ss << "prototype '" << prototype() << "': the sum of mixing fractions is "
80  "not 1, renormalization will be "
81  "done.";
82  cyclus::Warn<cyclus::VALUE_WARNING>(ss.str());
83  }
84  if (frac_sum != 0) {
85  for (int i = 0; i < mixing_ratios.size(); i++) {
86  mixing_ratios[i] *= 1.0 / frac_sum;
87  }
88  } else {
89  for (int i = 0; i < mixing_ratios.size(); i++) {
90  mixing_ratios[i] = 1.0 / (mixing_ratios.size());
91  }
92  }
93  }
94 
95  sell_policy.Init(this, &output, "output").Set(out_commod).Start();
96 }
97 
98 void Mixer::Tick() {
99  using cyclus::toolkit::RecordTimeSeries;
100  if (output.quantity() < output.capacity()) {
101  double tgt_qty = output.space();
102 
103  for (int i = 0; i < mixing_ratios.size(); i++) {
104  std::string name = "in_stream_" + std::to_string(i);
105  tgt_qty =
106  std::min(tgt_qty, streambufs[name].quantity() / mixing_ratios[i]);
107  }
108 
109  tgt_qty = std::min(tgt_qty, throughput);
110 
111  if (tgt_qty > 0) {
112  cyclus::Material::Ptr m;
113  for (int i = 0; i < mixing_ratios.size(); i++) {
114  std::string name = "in_stream_" + std::to_string(i);
115  double pop_qty = mixing_ratios[i] * tgt_qty;
116  if (i == 0) {
117  m = streambufs[name].Pop(pop_qty, cyclus::eps_rsrc());
118  } else {
119  cyclus::Material::Ptr m_ =
120  streambufs[name].Pop(pop_qty, cyclus::eps_rsrc());
121  m->Absorb(m_);
122  }
123  }
124  output.Push(m);
125  }
126  }
127  cyclus::toolkit::RecordTimeSeries<double>("supply"+out_commod, this, output.quantity());
128 }
129 
130 std::set<cyclus::RequestPortfolio<cyclus::Material>::Ptr>
132  using cyclus::RequestPortfolio;
133  using cyclus::toolkit::RecordTimeSeries;
134 
135  for (int i = 0; i < mixing_ratios.size(); i++)
136  {
137  std::string name = "in_stream_" + std::to_string(i);
138  std::map<std::string, double>::iterator it;
139  std::map<std::string, double>::iterator max_it = in_commods[i].begin();
140  double prev_pref = 0;
141  for (it = in_commods[i].begin(); it != in_commods[i].end(); it++)
142  {
143  cyclus::toolkit::RecordTimeSeries<double>("demand" + it->first, this,
144  streambufs[name].space());
145  }
146  }
147 
148  std::set<RequestPortfolio<cyclus::Material>::Ptr> ports;
149 
150  for (int i = 0; i < in_commods.size(); i++) {
151  std::string name = "in_stream_" + std::to_string(i);
152 
153  if (streambufs[name].space() > cyclus::eps_rsrc()) {
154  RequestPortfolio<cyclus::Material>::Ptr port(
155  new RequestPortfolio<cyclus::Material>());
156 
157  cyclus::Material::Ptr m;
158  m = cyclus::NewBlankMaterial(streambufs[name].space());
159 
160  std::vector<cyclus::Request<cyclus::Material>*> reqs;
161 
162  std::map<std::string, double>::iterator it;
163  for (it = in_commods[i].begin() ; it != in_commods[i].end(); it++) {
164  std::string commod = it->first;
165  double pref = it->second;
166  reqs.push_back(port->AddRequest(m, this, commod , pref, false));
167  req_inventories_[reqs.back()] = name;
168  }
169  port->AddMutualReqs(reqs);
170  ports.insert(port);
171  }
172  }
173  return ports;
174 }
175 
177  const std::vector<std::pair<cyclus::Trade<cyclus::Material>,
178  cyclus::Material::Ptr> >& responses) {
179  std::vector<std::pair<cyclus::Trade<cyclus::Material>,
180  cyclus::Material::Ptr> >::const_iterator trade;
181 
182  for (trade = responses.begin(); trade != responses.end(); ++trade) {
183  cyclus::Request<cyclus::Material>* req = trade->first.request;
184  cyclus::Material::Ptr m = trade->second;
185 
186  std::string name = req_inventories_[req];
187  bool assigned = false;
188  std::map<std::string, cyclus::toolkit::ResBuf<cyclus::Material> >::iterator
189  it;
190 
191  for (it = streambufs.begin(); it != streambufs.end(); it++) {
192  if (name == it->first) {
193  it->second.Push(m);
194  assigned = true;
195  break;
196  }
197  }
198  if (!assigned) {
199  throw cyclus::ValueError("cycamore::Mixer was overmatched on requests");
200  }
201  }
202 
203  req_inventories_.clear();
204 }
205 
206 void Mixer::RecordPosition() {
207  std::string specification = spec();
208  context()
209  ->NewDatum("AgentPosition")
210  ->AddVal("Spec", specification)
211  ->AddVal("Prototype", this->prototype())
212  ->AddVal("AgentId", id())
213  ->AddVal("Latitude", latitude)
214  ->AddVal("Longitude", longitude)
215  ->Record();
216 }
217 
218 extern "C" cyclus::Agent* ConstructMixer(cyclus::Context* ctx) {
219  return new Mixer(ctx);
220 }
221 }
virtual std::set< cyclus::RequestPortfolio< cyclus::Material >::Ptr > GetMatlRequests()
std::vector< double > in_buf_sizes
virtual void AcceptMatlTrades(const std::vector< std::pair< cyclus::Trade< cyclus::Material >, cyclus::Material::Ptr > > &responses)
cyclus::Agent * ConstructMixer(cyclus::Context *ctx)
void RecordPosition()
Records an agent&#39;s latitude and longitude to the output db.
virtual cyclus::Inventories SnapshotInv()
std::map< cyclus::Request< cyclus::Material > *, std::string > req_inventories_
double longitude
cycamore::GrowthRegion string
cyclus::toolkit::ResBuf< cyclus::Material > output
cyclus::toolkit::Position coordinates
cyclus::toolkit::MatlSellPolicy sell_policy
Mixer(cyclus::Context *ctx)
void RecordPosition()
Records an agent&#39;s latitude and longitude to the output db.
std::vector< double > mixing_ratios
virtual void InitInv(cyclus::Inventories &inv)
std::map< std::string, cyclus::toolkit::ResBuf< cyclus::Material > > streambufs
std::vector< std::pair< std::pair< double, double >, std::map< std::string, double > > > streams_
std::vector< std::map< std::string, double > > in_commods