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));
81 else if (active_buying_frequency_type ==
"Binomial") {
82 if (active_buying_end_probability < 0 || active_buying_end_probability > 1) {
83 throw cyclus::ValueError(
"Active buying end probability must be between 0 and 1");
86 active_dist_ = cyclus::NegativeBinomialIntDist::Ptr (
new cyclus::NegativeBinomialIntDist(success, active_buying_end_probability));
87 }
else if (active_buying_frequency_type ==
"FixedWithDisruption") {
88 if (active_buying_disruption < 0) {
89 throw cyclus::ValueError(
"Disruption must be greater than or equal to 0");
91 active_dist_ = cyclus::BinaryIntDist::Ptr (
92 new cyclus::BinaryIntDist(active_buying_disruption_probability,
93 active_buying_disruption, active_buying_val));
96 throw cyclus::ValueError(
"Invalid active buying frequency type");}
99 if (dormant_buying_frequency_type ==
"Fixed") {
100 dormant_dist_ = cyclus::FixedIntDist::Ptr (
new cyclus::FixedIntDist(dormant_buying_val));
102 else if (dormant_buying_frequency_type ==
"Uniform") {
103 if ((dormant_buying_min == -1) || (dormant_buying_max == -1)) {
104 throw cyclus::ValueError(
"Invalid dormant buying frequency range. Please provide both a min and max value.");
106 dormant_dist_ = cyclus::UniformIntDist::Ptr (
new cyclus::UniformIntDist(dormant_buying_min, dormant_buying_max));
108 else if (dormant_buying_frequency_type ==
"Normal") {
109 if ((dormant_buying_mean == -1) || (dormant_buying_stddev == -1)) {
110 throw cyclus::ValueError(
"Invalid dormant buying frequency range. Please provide both a mean and standard deviation value.");
112 if (dormant_buying_min == -1) {dormant_buying_min = 1;}
113 if (dormant_buying_max == -1) {
114 dormant_buying_max = std::numeric_limits<int>::max();}
115 dormant_dist_ = cyclus::NormalIntDist::Ptr (
new cyclus::NormalIntDist(dormant_buying_mean, dormant_buying_stddev,
116 dormant_buying_min, dormant_buying_max));
118 else if (dormant_buying_frequency_type ==
"Binomial") {
119 if (dormant_buying_end_probability < 0 || dormant_buying_end_probability > 1) {
120 throw cyclus::ValueError(
"Dormant buying end probability must be between 0 and 1");
123 dormant_dist_ = cyclus::NegativeBinomialIntDist::Ptr (
new cyclus::NegativeBinomialIntDist(success, dormant_buying_end_probability));
124 }
else if (dormant_buying_frequency_type ==
"FixedWithDisruption") {
125 if (dormant_buying_disruption < 0) {
126 throw cyclus::ValueError(
"Disruption must be greater than or equal to 0");
128 dormant_dist_ = cyclus::BinaryIntDist::Ptr (
129 new cyclus::BinaryIntDist(dormant_buying_disruption_probability,
130 dormant_buying_disruption, dormant_buying_val));
133 throw cyclus::ValueError(
"Invalid dormant buying frequency type");}
136 if (buying_size_type ==
"Fixed") {
137 size_dist_ = cyclus::FixedDoubleDist::Ptr (
new cyclus::FixedDoubleDist(buying_size_val));
139 else if (buying_size_type ==
"Uniform") {
140 if ((buying_size_min == -1) || (buying_size_max == -1)) {
141 throw cyclus::ValueError(
"Invalid buying size range. Please provide both a min and max value.");
143 size_dist_ = cyclus::UniformDoubleDist::Ptr (
new cyclus::UniformDoubleDist(buying_size_min, buying_size_max));
145 else if (buying_size_type ==
"Normal") {
146 if ((buying_size_mean == -1) || (buying_size_stddev == -1)) {
147 throw cyclus::ValueError(
"Invalid buying size range. Please provide both a mean and standard deviation value.");
149 if (buying_size_min == -1) {buying_size_min = 0;}
150 if (buying_size_max == -1) {buying_size_max = 1;}
151 size_dist_ = cyclus::NormalDoubleDist::Ptr (
new cyclus::NormalDoubleDist(buying_size_mean, buying_size_stddev,
152 buying_size_min, buying_size_max));
155 throw cyclus::ValueError(
"Invalid buying size type");}
159void Storage::EnterNotify() {
160 cyclus::Facility::EnterNotify();
162 inventory_tracker.set_capacity(max_inv_size);
163 if (reorder_point < 0 && cumulative_cap <= 0) {
164 InitBuyPolicyParameters();
165 buy_policy.Init(
this, &inventory, std::string(
"inventory"),
166 &inventory_tracker, throughput, active_dist_,
167 dormant_dist_, size_dist_);
169 else if (cumulative_cap > 0) {
170 InitBuyPolicyParameters();
171 buy_policy.Init(
this, &inventory, std::string(
"inventory"),
172 &inventory_tracker, throughput, cumulative_cap,
175 else if (reorder_quantity > 0) {
176 if (reorder_point + reorder_quantity > max_inv_size) {
177 throw cyclus::ValueError(
178 "reorder_point + reorder_quantity must be less than or equal to max_inv_size");
180 buy_policy.Init(
this, &inventory, std::string(
"inventory"),
181 &inventory_tracker, throughput,
"RQ",
182 reorder_quantity, reorder_point);
185 buy_policy.Init(
this, &inventory, std::string(
"inventory"),
186 &inventory_tracker, throughput,
"sS",
187 max_inv_size, reorder_point);
192 cyclus::Composition::Ptr comp = cyclus::Composition::CreateFromAtom(v);
193 if (in_recipe !=
"") {
194 comp = context()->GetRecipe(in_recipe);
197 if (in_commod_prefs.size() == 0) {
198 for (
int i = 0; i < in_commods.size(); ++i) {
199 in_commod_prefs.push_back(cyclus::kDefaultPref);
201 }
else if (in_commod_prefs.size() != in_commods.size()) {
202 std::stringstream ss;
203 ss <<
"in_commod_prefs has " << in_commod_prefs.size()
204 <<
" values, expected " << in_commods.size();
205 throw cyclus::ValueError(ss.str());
208 for (
int i = 0; i != in_commods.size(); ++i) {
209 buy_policy.Set(in_commods[i], comp, in_commod_prefs[i]);
213 std::string package_name_ = context()->GetPackage(package)->name();
214 std::string tu_name_ = context()->GetTransportUnit(transport_unit)->name();
215 if (out_commods.size() == 1) {
216 sell_policy.Init(
this, &stocks, std::string(
"stocks"), cyclus::CY_LARGE_DOUBLE,
false,
217 sell_quantity, package_name_, tu_name_)
218 .Set(out_commods.front())
222 std::stringstream ss;
223 ss <<
"out_commods has " << out_commods.size() <<
" values, expected 1.";
224 throw cyclus::ValueError(ss.str());
230std::string Storage::str() {
231 std::stringstream ss;
232 std::string ans, out_str;
233 if (out_commods.size() == 1) {
234 out_str = out_commods.front();
238 if (cyclus::toolkit::CommodityProducer::Produces(
239 cyclus::toolkit::Commodity(out_str))) {
244 ss << cyclus::Facility::str();
245 ss <<
" has facility parameters {"
247 <<
" Output Commodity = " << out_str <<
",\n"
248 <<
" Residence Time = " << residence_time <<
",\n"
249 <<
" Throughput = " << throughput <<
",\n"
250 <<
" commod producer members: "
251 <<
" produces " << out_str <<
"?:" << ans <<
"'}";
256void Storage::Tick() {
259 LOG(cyclus::LEV_INFO3,
"ComCnv") << prototype() <<
" is ticking {";
261 LOG(cyclus::LEV_INFO5,
"ComCnv") <<
"Processing = " << processing.quantity() <<
", ready = " << ready.quantity() <<
", stocks = " << stocks.quantity() <<
" and max inventory = " << max_inv_size;
263 LOG(cyclus::LEV_INFO4,
"ComCnv") <<
"current capacity " << max_inv_size <<
" - " << processing.quantity() <<
" - " << ready.quantity() <<
" - " << stocks.quantity() <<
" = " << current_capacity();
265 if (current_capacity() > cyclus::eps_rsrc()) {
266 LOG(cyclus::LEV_INFO4,
"ComCnv")
267 <<
" has capacity for " << current_capacity() <<
".";
269 LOG(cyclus::LEV_INFO3,
"ComCnv") <<
"}";
273void Storage::Tock() {
274 LOG(cyclus::LEV_INFO3,
"ComCnv") << prototype() <<
" is tocking {";
278 LOG(cyclus::LEV_INFO4,
"ComCnv") <<
"processing currently holds " << processing.quantity() <<
". ready currently holds " << ready.quantity() <<
".";
280 if (ready_time() >= 0 || residence_time == 0 && !inventory.empty()) {
281 ReadyMatl_(ready_time());
284 LOG(cyclus::LEV_INFO5,
"ComCnv") <<
"Ready now holds " << ready.quantity() <<
" kg.";
286 if (ready.quantity() > throughput) {
287 LOG(cyclus::LEV_INFO5,
"ComCnv") <<
"Up to " << throughput <<
" kg will be placed in stocks based on throughput limits. ";
290 ProcessMat_(throughput);
292 std::vector<double>::iterator result;
293 result = std::max_element(in_commod_prefs.begin(), in_commod_prefs.end());
294 int maxindx = std::distance(in_commod_prefs.begin(), result);
296 demand = current_capacity();
298 cyclus::toolkit::RecordTimeSeries<double>(
"demand"+in_commods[maxindx],
this, demand);
302 cyclus::toolkit::RecordTimeSeries<double>(
"supply"+out_commods[0],
this,
305 LOG(cyclus::LEV_INFO4,
"ComCnv") <<
"process has "
306 << processing.quantity() <<
". Ready has " << ready.quantity() <<
". Stocks has " << stocks.quantity() <<
".";
307 LOG(cyclus::LEV_INFO3,
"ComCnv") <<
"}";
311void Storage::AddMat_(cyclus::Material::Ptr mat) {
312 LOG(cyclus::LEV_INFO5,
"ComCnv") << prototype() <<
" is initially holding "
313 << inventory.quantity() <<
" total.";
317 }
catch (cyclus::Error& e) {
318 e.msg(Agent::InformErrorMsg(e.msg()));
322 LOG(cyclus::LEV_INFO5,
"ComCnv")
323 << prototype() <<
" added " << mat->quantity()
324 <<
" of material to its inventory, which is holding "
325 << inventory.quantity() <<
" total.";
329void Storage::BeginProcessing_() {
330 while (inventory.count() > 0) {
332 processing.Push(inventory.Pop());
333 entry_times.push_back(context()->time());
335 LOG(cyclus::LEV_DEBUG2,
"ComCnv")
336 <<
"Storage " << prototype()
337 <<
" added resources to processing at t= " << context()->time();
338 }
catch (cyclus::Error& e) {
339 e.msg(Agent::InformErrorMsg(e.msg()));
346void Storage::ProcessMat_(
double cap) {
347 if (!ready.empty()) {
349 double max_pop = std::min(cap, ready.quantity());
351 if (discrete_handling) {
352 if (max_pop == ready.quantity()) {
353 stocks.Push(ready.PopN(ready.count()));
355 double cap_pop = ready.Peek()->quantity();
356 while (cap_pop <= max_pop && !ready.empty()) {
357 stocks.Push(ready.Pop());
358 cap_pop += ready.empty() ? 0 : ready.Peek()->quantity();
362 stocks.Push(ready.Pop(max_pop, cyclus::eps_rsrc()));
365 LOG(cyclus::LEV_INFO4,
"ComCnv") <<
"Storage " << prototype()
366 <<
" moved resources"
367 <<
" from ready to stocks"
368 <<
" at t= " << context()->time();
369 }
catch (cyclus::Error& e) {
370 e.msg(Agent::InformErrorMsg(e.msg()));
377void Storage::ReadyMatl_(
int time) {
378 LOG(cyclus::LEV_INFO5,
"ComCnv") <<
"Placing material into ready";
382 while (!entry_times.empty() && entry_times.front() <= time) {
383 entry_times.pop_front();
387 ready.Push(processing.PopN(to_ready));
390void Storage::RecordPosition() {
391 std::string specification = this->spec();
393 ->NewDatum(
"AgentPosition")
394 ->AddVal(
"Spec", specification)
395 ->AddVal(
"Prototype", this->prototype())
396 ->AddVal(
"AgentId",
id())
397 ->AddVal(
"Latitude", latitude)
398 ->AddVal(
"Longitude", longitude)
405 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