9 : cyclus::Facility(ctx),
13 inventory_tracker.Init({&inventory, &stocks, &ready, &processing}, cyclus::CY_LARGE_DOUBLE);
14 cyclus::Warn<cyclus::EXPERIMENTAL_WARNING>(
15 "The Storage Facility is experimental.");};
20#pragma cyclus def schema cycamore::Storage
22#pragma cyclus def annotations cycamore::Storage
24#pragma cyclus def initinv cycamore::Storage
26#pragma cyclus def snapshotinv cycamore::Storage
28#pragma cyclus def infiletodb cycamore::Storage
30#pragma cyclus def snapshot cycamore::Storage
32#pragma cyclus def clone cycamore::Storage
35void Storage::InitFrom(Storage* m) {
36#pragma cyclus impl initfromcopy cycamore::Storage
37 cyclus::toolkit::CommodityProducer::Copy(m);
41void Storage::InitFrom(cyclus::QueryableBackend* b) {
42#pragma cyclus impl initfromdb cycamore::Storage
44 cyclus::toolkit::Commodity commod = cyclus::toolkit::Commodity(out_commods.front());
45 cyclus::toolkit::CommodityProducer::Add(commod);
46 cyclus::toolkit::CommodityProducer::SetCapacity(commod, throughput);
49void Storage::InitBuyPolicyParameters() {
51 if (active_buying_min > active_buying_max) {
52 throw cyclus::ValueError(
"Active min larger than max.");
54 if (dormant_buying_min > dormant_buying_max) {
55 throw cyclus::ValueError(
"Dormant min larger than max.");
57 if (buying_size_min > buying_size_max) {
58 throw cyclus::ValueError(
"Buying size min larger than max.");
61 if (active_buying_frequency_type ==
"Fixed") {
62 active_dist_ = cyclus::FixedIntDist::Ptr (
new cyclus::FixedIntDist(active_buying_val));
64 else if (active_buying_frequency_type ==
"Uniform") {
65 if ((active_buying_min == -1) || (active_buying_max == -1)) {
66 throw cyclus::ValueError(
"Invalid active buying frequency range. Please provide both a min and max value.");
68 active_dist_ = cyclus::UniformIntDist::Ptr (
new cyclus::UniformIntDist(active_buying_min, active_buying_max));
70 else if (active_buying_frequency_type ==
"Normal") {
71 if ((active_buying_mean == -1) || (active_buying_stddev == -1)) {
72 throw cyclus::ValueError(
"Invalid active buying frequency range. Please provide both a mean and standard deviation value.");
74 if (active_buying_min == -1) {active_buying_min = 1;}
75 if (active_buying_max == -1) {
76 active_buying_max = std::numeric_limits<int>::max();}
78 active_dist_ = cyclus::NormalIntDist::Ptr (
new cyclus::NormalIntDist(active_buying_mean, active_buying_stddev,
79 active_buying_min, active_buying_max));
82 throw cyclus::ValueError(
"Invalid active buying frequency type");}
85 if (dormant_buying_frequency_type ==
"Fixed") {
86 dormant_dist_ = cyclus::FixedIntDist::Ptr (
new cyclus::FixedIntDist(dormant_buying_val));
88 else if (dormant_buying_frequency_type ==
"Uniform") {
89 if ((dormant_buying_min == -1) || (dormant_buying_max == -1)) {
90 throw cyclus::ValueError(
"Invalid dormant buying frequency range. Please provide both a min and max value.");
92 dormant_dist_ = cyclus::UniformIntDist::Ptr (
new cyclus::UniformIntDist(dormant_buying_min, dormant_buying_max));
94 else if (dormant_buying_frequency_type ==
"Normal") {
95 if ((dormant_buying_mean == -1) || (dormant_buying_stddev == -1)) {
96 throw cyclus::ValueError(
"Invalid dormant buying frequency range. Please provide both a mean and standard deviation value.");
98 if (dormant_buying_min == -1) {dormant_buying_min = 1;}
99 if (dormant_buying_max == -1) {
100 dormant_buying_max = std::numeric_limits<int>::max();}
101 dormant_dist_ = cyclus::NormalIntDist::Ptr (
new cyclus::NormalIntDist(dormant_buying_mean, dormant_buying_stddev,
102 dormant_buying_min, dormant_buying_max));
105 throw cyclus::ValueError(
"Invalid dormant buying frequency type");}
108 if (buying_size_type ==
"Fixed") {
109 size_dist_ = cyclus::FixedDoubleDist::Ptr (
new cyclus::FixedDoubleDist(buying_size_val));
111 else if (buying_size_type ==
"Uniform") {
112 if ((buying_size_min == -1) || (buying_size_max == -1)) {
113 throw cyclus::ValueError(
"Invalid buying size range. Please provide both a min and max value.");
115 size_dist_ = cyclus::UniformDoubleDist::Ptr (
new cyclus::UniformDoubleDist(buying_size_min, buying_size_max));
117 else if (buying_size_type ==
"Normal") {
118 if ((buying_size_mean == -1) || (buying_size_stddev == -1)) {
119 throw cyclus::ValueError(
"Invalid buying size range. Please provide both a mean and standard deviation value.");
121 if (buying_size_min == -1) {buying_size_min = 0;}
122 if (buying_size_max == -1) {buying_size_max = 1;}
123 size_dist_ = cyclus::NormalDoubleDist::Ptr (
new cyclus::NormalDoubleDist(buying_size_mean, buying_size_stddev,
124 buying_size_min, buying_size_max));
127 throw cyclus::ValueError(
"Invalid buying size type");}
131void Storage::EnterNotify() {
132 cyclus::Facility::EnterNotify();
134 inventory_tracker.set_capacity(max_inv_size);
135 if (reorder_point < 0 && cumulative_cap <= 0) {
136 InitBuyPolicyParameters();
137 buy_policy.Init(
this, &inventory, std::string(
"inventory"),
138 &inventory_tracker, throughput, active_dist_,
139 dormant_dist_, size_dist_);
141 else if (cumulative_cap > 0) {
142 InitBuyPolicyParameters();
143 buy_policy.Init(
this, &inventory, std::string(
"inventory"),
144 &inventory_tracker, throughput, cumulative_cap,
147 else if (reorder_quantity > 0) {
148 if (reorder_point + reorder_quantity > max_inv_size) {
149 throw cyclus::ValueError(
150 "reorder_point + reorder_quantity must be less than or equal to max_inv_size");
152 buy_policy.Init(
this, &inventory, std::string(
"inventory"),
153 &inventory_tracker, throughput,
"RQ",
154 reorder_quantity, reorder_point);
157 buy_policy.Init(
this, &inventory, std::string(
"inventory"),
158 &inventory_tracker, throughput,
"sS",
159 max_inv_size, reorder_point);
164 cyclus::Composition::Ptr comp = cyclus::Composition::CreateFromAtom(v);
165 if (in_recipe !=
"") {
166 comp = context()->GetRecipe(in_recipe);
169 if (in_commod_prefs.size() == 0) {
170 for (
int i = 0; i < in_commods.size(); ++i) {
171 in_commod_prefs.push_back(cyclus::kDefaultPref);
173 }
else if (in_commod_prefs.size() != in_commods.size()) {
174 std::stringstream ss;
175 ss <<
"in_commod_prefs has " << in_commod_prefs.size()
176 <<
" values, expected " << in_commods.size();
177 throw cyclus::ValueError(ss.str());
180 for (
int i = 0; i != in_commods.size(); ++i) {
181 buy_policy.Set(in_commods[i], comp, in_commod_prefs[i]);
185 std::string package_name_ = context()->GetPackage(package)->name();
186 std::string tu_name_ = context()->GetTransportUnit(transport_unit)->name();
187 if (out_commods.size() == 1) {
188 sell_policy.Init(
this, &stocks, std::string(
"stocks"), cyclus::CY_LARGE_DOUBLE,
false,
189 sell_quantity, package_name_, tu_name_)
190 .Set(out_commods.front())
194 std::stringstream ss;
195 ss <<
"out_commods has " << out_commods.size() <<
" values, expected 1.";
196 throw cyclus::ValueError(ss.str());
202std::string Storage::str() {
203 std::stringstream ss;
204 std::string ans, out_str;
205 if (out_commods.size() == 1) {
206 out_str = out_commods.front();
210 if (cyclus::toolkit::CommodityProducer::Produces(
211 cyclus::toolkit::Commodity(out_str))) {
216 ss << cyclus::Facility::str();
217 ss <<
" has facility parameters {"
219 <<
" Output Commodity = " << out_str <<
",\n"
220 <<
" Residence Time = " << residence_time <<
",\n"
221 <<
" Throughput = " << throughput <<
",\n"
222 <<
" commod producer members: "
223 <<
" produces " << out_str <<
"?:" << ans <<
"'}";
228void Storage::Tick() {
231 LOG(cyclus::LEV_INFO3,
"ComCnv") << prototype() <<
" is ticking {";
233 LOG(cyclus::LEV_INFO5,
"ComCnv") <<
"Processing = " << processing.quantity() <<
", ready = " << ready.quantity() <<
", stocks = " << stocks.quantity() <<
" and max inventory = " << max_inv_size;
235 LOG(cyclus::LEV_INFO4,
"ComCnv") <<
"current capacity " << max_inv_size <<
" - " << processing.quantity() <<
" - " << ready.quantity() <<
" - " << stocks.quantity() <<
" = " << current_capacity();
237 if (current_capacity() > cyclus::eps_rsrc()) {
238 LOG(cyclus::LEV_INFO4,
"ComCnv")
239 <<
" has capacity for " << current_capacity() <<
".";
241 LOG(cyclus::LEV_INFO3,
"ComCnv") <<
"}";
245void Storage::Tock() {
246 LOG(cyclus::LEV_INFO3,
"ComCnv") << prototype() <<
" is tocking {";
250 LOG(cyclus::LEV_INFO4,
"ComCnv") <<
"processing currently holds " << processing.quantity() <<
". ready currently holds " << ready.quantity() <<
".";
252 if (ready_time() >= 0 || residence_time == 0 && !inventory.empty()) {
253 ReadyMatl_(ready_time());
256 LOG(cyclus::LEV_INFO5,
"ComCnv") <<
"Ready now holds " << ready.quantity() <<
" kg.";
258 if (ready.quantity() > throughput) {
259 LOG(cyclus::LEV_INFO5,
"ComCnv") <<
"Up to " << throughput <<
" kg will be placed in stocks based on throughput limits. ";
262 ProcessMat_(throughput);
264 std::vector<double>::iterator result;
265 result = std::max_element(in_commod_prefs.begin(), in_commod_prefs.end());
266 int maxindx = std::distance(in_commod_prefs.begin(), result);
268 demand = current_capacity();
270 cyclus::toolkit::RecordTimeSeries<double>(
"demand"+in_commods[maxindx],
this, demand);
274 cyclus::toolkit::RecordTimeSeries<double>(
"supply"+out_commods[0],
this,
277 LOG(cyclus::LEV_INFO4,
"ComCnv") <<
"process has "
278 << processing.quantity() <<
". Ready has " << ready.quantity() <<
". Stocks has " << stocks.quantity() <<
".";
279 LOG(cyclus::LEV_INFO3,
"ComCnv") <<
"}";
283void Storage::AddMat_(cyclus::Material::Ptr mat) {
284 LOG(cyclus::LEV_INFO5,
"ComCnv") << prototype() <<
" is initially holding "
285 << inventory.quantity() <<
" total.";
289 }
catch (cyclus::Error& e) {
290 e.msg(Agent::InformErrorMsg(e.msg()));
294 LOG(cyclus::LEV_INFO5,
"ComCnv")
295 << prototype() <<
" added " << mat->quantity()
296 <<
" of material to its inventory, which is holding "
297 << inventory.quantity() <<
" total.";
301void Storage::BeginProcessing_() {
302 while (inventory.count() > 0) {
304 processing.Push(inventory.Pop());
305 entry_times.push_back(context()->time());
307 LOG(cyclus::LEV_DEBUG2,
"ComCnv")
308 <<
"Storage " << prototype()
309 <<
" added resources to processing at t= " << context()->time();
310 }
catch (cyclus::Error& e) {
311 e.msg(Agent::InformErrorMsg(e.msg()));
318void Storage::ProcessMat_(
double cap) {
319 if (!ready.empty()) {
321 double max_pop = std::min(cap, ready.quantity());
323 if (discrete_handling) {
324 if (max_pop == ready.quantity()) {
325 stocks.Push(ready.PopN(ready.count()));
327 double cap_pop = ready.Peek()->quantity();
328 while (cap_pop <= max_pop && !ready.empty()) {
329 stocks.Push(ready.Pop());
330 cap_pop += ready.empty() ? 0 : ready.Peek()->quantity();
334 stocks.Push(ready.Pop(max_pop, cyclus::eps_rsrc()));
337 LOG(cyclus::LEV_INFO4,
"ComCnv") <<
"Storage " << prototype()
338 <<
" moved resources"
339 <<
" from ready to stocks"
340 <<
" at t= " << context()->time();
341 }
catch (cyclus::Error& e) {
342 e.msg(Agent::InformErrorMsg(e.msg()));
349void Storage::ReadyMatl_(
int time) {
350 LOG(cyclus::LEV_INFO5,
"ComCnv") <<
"Placing material into ready";
354 while (!entry_times.empty() && entry_times.front() <= time) {
355 entry_times.pop_front();
359 ready.Push(processing.PopN(to_ready));
362void Storage::RecordPosition() {
363 std::string specification = this->spec();
365 ->NewDatum(
"AgentPosition")
366 ->AddVal(
"Spec", specification)
367 ->AddVal(
"Prototype", this->prototype())
368 ->AddVal(
"AgentId",
id())
369 ->AddVal(
"Latitude", latitude)
370 ->AddVal(
"Longitude", longitude)
377 return new Storage(ctx);
Storage(cyclus::Context *ctx)
void RecordPosition()
Records an agent's latitude and longitude to the output db.
cyclus::Agent * ConstructStorage(cyclus::Context *ctx)
cyclus::toolkit::Position coordinates