CYCAMORE
Loading...
Searching...
No Matches
src/storage.cc
Go to the documentation of this file.
1// storage.cc
2// Implements the Storage class
3#include "storage.h"
4
5namespace cycamore {
6
7// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
8Storage::Storage(cyclus::Context* ctx)
9 : cyclus::Facility(ctx) {
10 inventory_tracker.Init({&inventory, &stocks, &ready, &processing}, cyclus::CY_LARGE_DOUBLE);
11 cyclus::Warn<cyclus::EXPERIMENTAL_WARNING>(
12 "The Storage Facility is experimental.");};
13
14// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
15// pragmas
16
17#pragma cyclus def schema cycamore::Storage
18
19#pragma cyclus def annotations cycamore::Storage
20
21#pragma cyclus def initinv cycamore::Storage
22
23#pragma cyclus def snapshotinv cycamore::Storage
24
25#pragma cyclus def infiletodb cycamore::Storage
26
27#pragma cyclus def snapshot cycamore::Storage
28
29#pragma cyclus def clone cycamore::Storage
30
31//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
32void Storage::InitFrom(Storage* m) {
33#pragma cyclus impl initfromcopy cycamore::Storage
34 cyclus::toolkit::CommodityProducer::Copy(m);
35}
36
37//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
38void Storage::InitFrom(cyclus::QueryableBackend* b) {
39#pragma cyclus impl initfromdb cycamore::Storage
40
41 cyclus::toolkit::Commodity commod = cyclus::toolkit::Commodity(out_commods.front());
42 cyclus::toolkit::CommodityProducer::Add(commod);
43 cyclus::toolkit::CommodityProducer::SetCapacity(commod, throughput);
44}
45
46//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
47void Storage::EnterNotify() {
48 cyclus::Facility::EnterNotify();
49
50 inventory_tracker.set_capacity(max_inv_size);
51 if (reorder_point < 0 && cumulative_cap <= 0) {
52 InitBuyPolicyParameters();
53 buy_policy.Init(this, &inventory, std::string("inventory"),
54 &inventory_tracker, throughput, active_dist_,
55 dormant_dist_, size_dist_);
56 }
57 else if (cumulative_cap > 0) {
58 InitBuyPolicyParameters();
59 buy_policy.Init(this, &inventory, std::string("inventory"),
60 &inventory_tracker, throughput, cumulative_cap,
61 dormant_dist_);
62 }
63 else if (reorder_quantity > 0) {
64 if (reorder_point + reorder_quantity > max_inv_size) {
65 throw cyclus::ValueError(
66 "reorder_point + reorder_quantity must be less than or equal to max_inv_size");
67 }
68 buy_policy.Init(this, &inventory, std::string("inventory"),
69 &inventory_tracker, throughput, "RQ",
70 reorder_quantity, reorder_point);
71 }
72 else {
73 buy_policy.Init(this, &inventory, std::string("inventory"),
74 &inventory_tracker, throughput, "sS",
75 max_inv_size, reorder_point);
76 }
77
78 // dummy comp, use in_recipe if provided
79 cyclus::CompMap v;
80 cyclus::Composition::Ptr comp = cyclus::Composition::CreateFromAtom(v);
81 if (in_recipe != "") {
82 comp = context()->GetRecipe(in_recipe);
83 }
84
85 if (in_commod_prefs.size() == 0) {
86 for (int i = 0; i < in_commods.size(); ++i) {
87 in_commod_prefs.push_back(cyclus::kDefaultPref);
88 }
89 } else if (in_commod_prefs.size() != in_commods.size()) {
90 std::stringstream ss;
91 ss << "in_commod_prefs has " << in_commod_prefs.size()
92 << " values, expected " << in_commods.size();
93 throw cyclus::ValueError(ss.str());
94 }
95
96 for (int i = 0; i != in_commods.size(); ++i) {
97 buy_policy.Set(in_commods[i], comp, in_commod_prefs[i]);
98 }
99 buy_policy.Start();
100
101 std::string package_name_ = context()->GetPackage(package)->name();
102 std::string tu_name_ = context()->GetTransportUnit(transport_unit)->name();
103 if (out_commods.size() == 1) {
104 sell_policy.Init(this, &stocks, std::string("stocks"), cyclus::CY_LARGE_DOUBLE, false,
105 sell_quantity, package_name_, tu_name_)
106 .Set(out_commods.front())
107 .Start();
108
109 } else {
110 std::stringstream ss;
111 ss << "out_commods has " << out_commods.size() << " values, expected 1.";
112 throw cyclus::ValueError(ss.str());
113 }
114
115 InitializePosition();
116}
117
118//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
119std::string Storage::str() {
120 std::stringstream ss;
121 std::string ans, out_str;
122 if (out_commods.size() == 1) {
123 out_str = out_commods.front();
124 } else {
125 out_str = "";
126 }
127 if (cyclus::toolkit::CommodityProducer::Produces(
128 cyclus::toolkit::Commodity(out_str))) {
129 ans = "yes";
130 } else {
131 ans = "no";
132 }
133 ss << cyclus::Facility::str();
134 ss << " has facility parameters {"
135 << "\n"
136 << " Output Commodity = " << out_str << ",\n"
137 << " Residence Time = " << residence_time << ",\n"
138 << " Throughput = " << throughput << ",\n"
139 << " commod producer members: "
140 << " produces " << out_str << "?:" << ans << "'}";
141 return ss.str();
142}
143
144//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
145void Storage::Tick() {
146
147
148 LOG(cyclus::LEV_INFO3, "ComCnv") << prototype() << " is ticking {";
149
150 LOG(cyclus::LEV_INFO5, "ComCnv") << "Processing = " << processing.quantity() << ", ready = " << ready.quantity() << ", stocks = " << stocks.quantity() << " and max inventory = " << max_inv_size;
151
152 LOG(cyclus::LEV_INFO4, "ComCnv") << "current capacity " << max_inv_size << " - " << processing.quantity() << " - " << ready.quantity() << " - " << stocks.quantity() << " = " << current_capacity();
153
154 if (current_capacity() > cyclus::eps_rsrc()) {
155 LOG(cyclus::LEV_INFO4, "ComCnv")
156 << " has capacity for " << current_capacity() << ".";
157 }
158 LOG(cyclus::LEV_INFO3, "ComCnv") << "}";
159}
160
161//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
162void Storage::Tock() {
163 LOG(cyclus::LEV_INFO3, "ComCnv") << prototype() << " is tocking {";
164
165 BeginProcessing_(); // place unprocessed inventory into processing
166
167 LOG(cyclus::LEV_INFO4, "ComCnv") << "processing currently holds " << processing.quantity() << ". ready currently holds " << ready.quantity() << ".";
168
169 if (ready_time() >= 0 || residence_time == 0 && !inventory.empty()) {
170 ReadyMatl_(ready_time()); // place processing into ready
171 }
172
173 LOG(cyclus::LEV_INFO5, "ComCnv") << "Ready now holds " << ready.quantity() << " kg.";
174
175 if (ready.quantity() > throughput) {
176 LOG(cyclus::LEV_INFO5, "ComCnv") << "Up to " << throughput << " kg will be placed in stocks based on throughput limits. ";
177 }
178
179 ProcessMat_(throughput); // place ready into stocks
180
181 std::vector<double>::iterator result;
182 result = std::max_element(in_commod_prefs.begin(), in_commod_prefs.end());
183 int maxindx = std::distance(in_commod_prefs.begin(), result);
184 double demand = 0;
185 demand = current_capacity();
186
187 cyclus::toolkit::RecordTimeSeries<double>("demand"+in_commods[maxindx], this, demand);
188
189 // Multiple commodity tracking is not supported, user can only
190 // provide one value for out_commods, despite it being a vector of strings.
191 cyclus::toolkit::RecordTimeSeries<double>("supply"+out_commods[0], this,
192 stocks.quantity());
193
194 LOG(cyclus::LEV_INFO4, "ComCnv") << "process has "
195 << processing.quantity() << ". Ready has " << ready.quantity() << ". Stocks has " << stocks.quantity() << ".";
196 LOG(cyclus::LEV_INFO3, "ComCnv") << "}";
197}
198
199//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
200void Storage::AddMat_(cyclus::Material::Ptr mat) {
201 LOG(cyclus::LEV_INFO5, "ComCnv") << prototype() << " is initially holding "
202 << inventory.quantity() << " total.";
203
204 try {
205 inventory.Push(mat);
206 } catch (cyclus::Error& e) {
207 e.msg(Agent::InformErrorMsg(e.msg()));
208 throw e;
209 }
210
211 LOG(cyclus::LEV_INFO5, "ComCnv")
212 << prototype() << " added " << mat->quantity()
213 << " of material to its inventory, which is holding "
214 << inventory.quantity() << " total.";
215}
216
217//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
218void Storage::BeginProcessing_() {
219 while (inventory.count() > 0) {
220 try {
221 processing.Push(inventory.Pop());
222 entry_times.push_back(context()->time());
223
224 LOG(cyclus::LEV_DEBUG2, "ComCnv")
225 << "Storage " << prototype()
226 << " added resources to processing at t= " << context()->time();
227 } catch (cyclus::Error& e) {
228 e.msg(Agent::InformErrorMsg(e.msg()));
229 throw e;
230 }
231 }
232}
233
234//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
235void Storage::ProcessMat_(double cap) {
236 if (!ready.empty()) {
237 try {
238 double max_pop = std::min(cap, ready.quantity());
239
240 if (discrete_handling) {
241 if (max_pop == ready.quantity()) {
242 stocks.Push(ready.PopN(ready.count()));
243 } else {
244 double cap_pop = ready.Peek()->quantity();
245 while (cap_pop <= max_pop && !ready.empty()) {
246 stocks.Push(ready.Pop());
247 cap_pop += ready.empty() ? 0 : ready.Peek()->quantity();
248 }
249 }
250 } else {
251 stocks.Push(ready.Pop(max_pop, cyclus::eps_rsrc()));
252 }
253
254 LOG(cyclus::LEV_INFO4, "ComCnv") << "Storage " << prototype()
255 << " moved resources"
256 << " from ready to stocks"
257 << " at t= " << context()->time();
258 } catch (cyclus::Error& e) {
259 e.msg(Agent::InformErrorMsg(e.msg()));
260 throw e;
261 }
262 }
263}
264
265//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
266void Storage::ReadyMatl_(int time) {
267 LOG(cyclus::LEV_INFO5, "ComCnv") << "Placing material into ready";
268
269 int to_ready = 0;
270
271 while (!entry_times.empty() && entry_times.front() <= time) {
272 entry_times.pop_front();
273 ++to_ready;
274 }
275
276 ready.Push(processing.PopN(to_ready));
277}
278
279// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
280extern "C" cyclus::Agent* ConstructStorage(cyclus::Context* ctx) {
281 return new Storage(ctx);
282}
283
284} // namespace cycamore
Storage(cyclus::Context *ctx)
cyclus::Agent * ConstructStorage(cyclus::Context *ctx)