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