CYCLUS
Loading...
Searching...
No Matches
timer.cc
Go to the documentation of this file.
1#include "platform.h"
2// Implements the Timer class
3#include "timer.h"
4
5#include <iostream>
6#include <string>
7#if CYCLUS_IS_PARALLEL
8#include <omp.h>
9#endif // CYCLUS_IS_PARALLEL
10
11#include "agent.h"
12#include "error.h"
13#include "logger.h"
14#include "pyhooks.h"
15#include "sim_init.h"
16
17namespace cyclus {
18
20 CLOG(LEV_INFO1) << "Simulation set to run from start="
21 << 0 << " to end=" << si_.duration;
22 CLOG(LEV_INFO1) << "Beginning simulation";
23
24 ExchangeManager<Material> matl_manager(ctx_);
25 ExchangeManager<Product> genrsrc_manager(ctx_);
26 while (time_ < si_.duration) {
27 CLOG(LEV_INFO1) << "Current time: " << time_;
28
29 if (want_snapshot_) {
30 want_snapshot_ = false;
32 }
33
34 // run through phases
35 DoBuild();
36 CLOG(LEV_INFO2) << "Beginning Tick for time: " << time_;
37 DoTick();
38 CLOG(LEV_INFO2) << "Beginning DRE for time: " << time_;
39 DoResEx(&matl_manager, &genrsrc_manager);
40 CLOG(LEV_INFO2) << "Beginning Tock for time: " << time_;
41 DoTock();
42 CLOG(LEV_INFO2) << "Beginning Decision for time: " << time_;
43 DoDecision();
44 DoDecom();
45
46#ifdef CYCLUS_WITH_PYTHON
47 EventLoop();
48#endif
49
50 time_++;
51
52 if (want_kill_) {
53 break;
54 }
55 }
56
57 ctx_->NewDatum("Finish")
58 ->AddVal("EarlyTerm", want_kill_)
59 ->AddVal("EndTime", time_-1)
60 ->Record();
61
62 SimInit::Snapshot(ctx_); // always do a snapshot at the end of every simulation
63}
64
65void Timer::DoBuild() {
66 // build queued agents
67 std::vector<std::pair<std::string, Agent*> > build_list = build_queue_[time_];
68 for (int i = 0; i < build_list.size(); ++i) {
69 Agent* m = ctx_->CreateAgent<Agent>(build_list[i].first);
70 Agent* parent = build_list[i].second;
71 CLOG(LEV_INFO3) << "Building a " << build_list[i].first
72 << " from parent " << build_list[i].second;
73 m->Build(parent);
74 if (parent != NULL) {
75 parent->BuildNotify(m);
76 } else {
77 CLOG(LEV_DEBUG1) << "Hey! Listen! Built an Agent without a Parent.";
78 }
79 }
80}
81
82
83void Timer::DoTick() {
84
85 for (TimeListener* agent : py_tickers_) {
86 agent->Tick();
87 }
88
89 #pragma omp parallel for
90 for (size_t i = 0; i < cpp_tickers_.size(); ++i) {
91 cpp_tickers_[i]->Tick();
92 }
93}
94
95void Timer::DoResEx(ExchangeManager<Material>* matmgr,
96 ExchangeManager<Product>* genmgr) {
97 matmgr->Execute();
98 genmgr->Execute();
99}
100
101void Timer::DoTock() {
102 for (TimeListener* agent : py_tickers_) {
103 agent->Tock();
104 }
105
106 #pragma omp parallel for
107 for (size_t i = 0; i < cpp_tickers_.size(); ++i) {
108 cpp_tickers_[i]->Tock();
109 }
110
112 std::set<Agent*> ags = ctx_->agent_list_;
113 std::vector<Agent*> agent_vec(ags.begin(), ags.end());
114 #pragma omp parallel for
115 for (int i = 0; i < agent_vec.size(); i++) {
116 Agent* a = agent_vec[i];
117 if (a->enter_time() != -1) {
118 RecordInventories(a);
119 }
120 }
121 }
122}
123
124void Timer::DoDecision() {
125 for (std::map<int, TimeListener*>::iterator agent = tickers_.begin();
126 agent != tickers_.end();
127 agent++) {
128 agent->second->Decision();
129 }
130}
131
132void Timer::RecordInventories(Agent* a) {
133 Inventories invs = a->SnapshotInv();
134 Inventories::iterator it2;
135 for (it2 = invs.begin(); it2 != invs.end(); ++it2) {
136 std::string name = it2->first;
137 std::vector<Resource::Ptr> mats = it2->second;
138 if (mats.empty() || ResCast<Material>(mats[0]) == NULL) {
139 continue; // skip non-material inventories
140 }
141
142 Material::Ptr m = ResCast<Material>(mats[0]->Clone());
143 for (int i = 1; i < mats.size(); i++) {
144 m->Absorb(ResCast<Material>(mats[i]->Clone()));
145 }
146 RecordInventory(a, name, m);
147 }
148}
149
150void Timer::RecordInventory(Agent* a, std::string name, Material::Ptr m) {
151 if (si_.explicit_inventory) {
152 CompMap c = m->comp()->mass();
153 compmath::Normalize(&c, m->quantity());
154 CompMap::iterator it;
155 for (it = c.begin(); it != c.end(); ++it) {
156 ctx_->NewDatum("ExplicitInventory")
157 ->AddVal("AgentId", a->id())
158 ->AddVal("Time", time_)
159 ->AddVal("InventoryName", name)
160 ->AddVal("NucId", it->first)
161 ->AddVal("Quantity", it->second)
162 ->AddVal("Units", m->units())
163 ->Record();
164 }
165 }
166
168 CompMap c = m->comp()->mass();
169 compmath::Normalize(&c, 1);
170 ctx_->NewDatum("ExplicitInventoryCompact")
171 ->AddVal("AgentId", a->id())
172 ->AddVal("Time", time_)
173 ->AddVal("InventoryName", name)
174 ->AddVal("Quantity", m->quantity())
175 ->AddVal("Units", m->units())
176 ->AddVal("Composition", c)
177 ->Record();
178 }
179}
180
181void Timer::DoDecom() {
182 // decommission queued agents
183 std::vector<Agent*> decom_list = decom_queue_[time_];
184 for (int i = 0; i < decom_list.size(); ++i) {
185 Agent* m = decom_list[i];
186 if (m->parent() != NULL) {
187 m->parent()->DecomNotify(m);
188 }
189 m->Decommission();
190 }
191}
192
194 tickers_[agent->id()] = agent;
195 if (agent->IsShim()) {
196 py_tickers_.push_back(agent);
197 } else {
198 cpp_tickers_.push_back(agent);
199 }
200}
201
203 tickers_.erase(tl->id());
204 if (tl->IsShim()) {
205 py_tickers_.erase(
206 std::remove(py_tickers_.begin(), py_tickers_.end(), tl),
207 py_tickers_.end()
208 );
209 } else {
210 cpp_tickers_.erase(
211 std::remove(cpp_tickers_.begin(), cpp_tickers_.end(), tl),
212 cpp_tickers_.end()
213 );
214 }
215}
216
217void Timer::SchedBuild(Agent* parent, std::string proto_name, int t) {
218 if (t <= time_) {
219 throw ValueError("Cannot schedule build for t < [current-time]");
220 }
221 build_queue_[t].push_back(std::make_pair(proto_name, parent));
222}
223
224void Timer::SchedDecom(Agent* m, int t) {
225 if (t < time_) {
226 throw ValueError("Cannot schedule decommission for t < [current-time]");
227 }
228
229 // It is possible that a single agent may be scheduled for decommissioning
230 // multiple times. If this happens, we cannot just add it to the queue again
231 // - the duplicate entries will result in a double delete attempt and
232 // segfaults and otherwise bad things. Remove previous decommissionings
233 // before scheduling this new one.
234 std::map<int, std::vector<Agent*> >::iterator it;
235 bool done = false;
236 for (it = decom_queue_.begin(); it != decom_queue_.end(); ++it) {
237 int t = it->first;
238 std::vector<Agent*> ags = it->second;
239 for (int i = 0; i < ags.size(); i++) {
240 if (ags[i] == m) {
241 CLOG(LEV_WARN) << "scheduled over previous decommissioning of " << m->id();
242 decom_queue_[t].erase(decom_queue_[t].begin()+i);
243 done = true;
244 break;
245 }
246 }
247 if (done) {
248 break;
249 }
250 }
251
252 decom_queue_[t].push_back(m);
253}
254
256 return time_;
257}
258
260 tickers_.clear();
261 cpp_tickers_.clear();
262 py_tickers_.clear();
263 build_queue_.clear();
264 decom_queue_.clear();
265 si_ = SimInfo(0);
266}
267
269 if (si.m0 < 1 || si.m0 > 12) {
270 throw ValueError("Invalid month0; must be between 1 and 12 (inclusive).");
271 }
272
273 want_kill_ = false;
274 ctx_ = ctx;
275 time_ = 0;
276 si_ = si;
277
278 if (si.branch_time > -1) {
279 time_ = si.branch_time;
280 }
281}
282
284 return si_.duration;
285}
286
287Timer::Timer() : time_(0), si_(0), want_snapshot_(false), want_kill_(false) {}
288
289} // namespace cyclus
The abstract base class used by all types of agents that live and interact in a simulation.
Definition agent.h:49
virtual void Build(Agent *parent)
Called when the agent enters the smiulation as an active participant and is only ever called once.
Definition agent.cc:153
virtual const int id() const
The agent instance's unique ID within a simulation.
Definition agent.h:352
A simulation context provides access to necessary simulation-global functions and state.
Definition context.h:145
T * CreateAgent(std::string proto_name)
Create a new agent by cloning the named prototype.
Definition context.h:195
Datum * NewDatum(std::string title)
See Recorder::NewDatum documentation.
Definition context.cc:361
Datum * AddVal(const char *field, boost::spirit::hold_any val, std::vector< int > *shape=NULL)
Add an arbitrary field-value pair to the datum.
Definition datum.cc:22
void Record()
Record this datum to its Recorder.
Definition datum.cc:35
The ExchangeManager is designed to house all of the internals involved in executing a resource exchan...
virtual const int id() const =0
boost::shared_ptr< Material > Ptr
Definition material.h:75
Container for a static simulation-global parameters that both describe the simulation and affect its ...
Definition context.h:45
int m0
start month for the simulation: Jan = 1, ..., Dec = 12
Definition context.h:94
bool explicit_inventory_compact
True if per-agent inventories should be explicitly queried/recorded every time step in a table (i....
Definition context.h:122
int duration
length of the simulation in timesteps (months)
Definition context.h:88
int branch_time
timestep at which simulation branching occurs if any
Definition context.h:104
bool explicit_inventory
True if per-agent inventories should be explicitly queried/recorded every time step in a table (i....
Definition context.h:117
static void Snapshot(Context *ctx)
Records a snapshot of the current state of the simulation being managed by ctx into the simulation's ...
Definition sim_init.cc:76
The TimeListener class is an inheritable class for any Agent that requires knowlege of ticks and tock...
virtual bool IsShim()
int time()
Returns the current time, in months since the simulation started.
Definition timer.cc:255
void UnregisterTimeListener(TimeListener *tl)
Removes an agent from receiving tick/tock notifications.
Definition timer.cc:202
int dur()
Returns the duration of the simulation this Timer's timing.
Definition timer.cc:283
void SchedBuild(Agent *parent, std::string proto_name, int t)
Schedules the named prototype to be built for the specified parent at timestep t.
Definition timer.cc:217
void Reset()
resets all data (registered listeners, etc.) to empty or initial state
Definition timer.cc:259
void RunSim()
Runs the simulation.
Definition timer.cc:19
void RegisterTimeListener(TimeListener *agent)
Registers an agent to receive tick/tock notifications every timestep.
Definition timer.cc:193
void Initialize(Context *ctx, SimInfo si)
Sets intial time-related parameters for the simulation.
Definition timer.cc:268
void SchedDecom(Agent *m, int time)
Schedules the given Agent to be decommissioned at the specified timestep t.
Definition timer.cc:224
For values that are too big, too small, etc.
Definition error.h:41
Code providing rudimentary logging capability for the Cyclus core.
#define CLOG(level)
Definition logger.h:39
void Normalize(CompMap *v, double val)
The sum of quantities of all nuclides of v is normalized to val.
Definition comp_math.cc:63
taken directly from OsiSolverInterface.cpp on 2/17/14 from https://projects.coin-or....
Definition agent.cc:14
void EventLoop(void)
Definition pyhooks.cc:75
@ LEV_INFO3
Information helpful for simulation users and developers alike.
Definition logger.h:55
@ LEV_DEBUG1
debugging information - least verbose
Definition logger.h:58
@ LEV_WARN
Use to report questionable simulation state (use extremely sparingly)
Definition logger.h:52
@ LEV_INFO2
Information helpful for simulation users and developers alike.
Definition logger.h:54
@ LEV_INFO1
Information helpful for simulation users and developers alike - least verbose.
Definition logger.h:53
std::map< Nuc, double > CompMap
a raw definition of nuclides and corresponding (dimensionless quantities).
Definition composition.h:17
std::vector< typename T::Ptr > ResCast(std::vector< Resource::Ptr > rs)
Casts a vector of Resources into a vector of a specific resource type T.
Definition resource.h:124
std::map< std::string, std::vector< Resource::Ptr > > Inventories
map<inventory_name, vector<resources_in_inventory> >.
Definition agent.h:38
std::string name(int nuc)
Definition pyne.cc:2940