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=" << 0
21 << " 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
63 ctx_); // always do a snapshot at the end of every simulation
64}
65
66void Timer::DoBuild() {
67 // build queued agents
68 std::vector<std::pair<std::string, Agent*>> build_list = build_queue_[time_];
69 for (int i = 0; i < build_list.size(); ++i) {
70 Agent* m = ctx_->CreateAgent<Agent>(build_list[i].first);
71 Agent* parent = build_list[i].second;
72 CLOG(LEV_INFO3) << "Building a " << build_list[i].first << " from parent "
73 << build_list[i].second;
74 m->Build(parent);
75 if (parent != NULL) {
76 parent->BuildNotify(m);
77 } else {
78 CLOG(LEV_DEBUG1) << "Hey! Listen! Built an Agent without a Parent.";
79 }
80 }
81}
82
83void Timer::DoTick() {
84 for (TimeListener* agent : py_tickers_) {
85 agent->Tick();
86 }
87
88#pragma omp parallel for
89 for (size_t i = 0; i < cpp_tickers_.size(); ++i) {
90 cpp_tickers_[i]->Tick();
91 }
92}
93
94void Timer::DoResEx(ExchangeManager<Material>* matmgr,
96 matmgr->Execute();
97 genmgr->Execute();
98}
99
100void Timer::DoTock() {
101 for (TimeListener* agent : py_tickers_) {
102 agent->Tock();
103 }
104
105#pragma omp parallel for
106 for (size_t i = 0; i < cpp_tickers_.size(); ++i) {
107 cpp_tickers_[i]->Tock();
108 }
109
110 if (si_.explicit_inventory || si_.explicit_inventory_compact) {
111 std::set<Agent*> ags = ctx_->agent_list_;
112 std::vector<Agent*> agent_vec(ags.begin(), ags.end());
113#pragma omp parallel for
114 for (int i = 0; i < agent_vec.size(); i++) {
115 Agent* a = agent_vec[i];
116 if (a->enter_time() != -1) {
117 RecordInventories(a);
118 }
119 }
120 }
121}
122
123void Timer::DoDecision() {
124 for (std::map<int, TimeListener*>::iterator agent = tickers_.begin();
125 agent != tickers_.end();
126 agent++) {
127 agent->second->Decision();
128 }
129}
130
131void Timer::RecordInventories(Agent* a) {
132 Inventories invs = a->SnapshotInv();
133 Inventories::iterator it2;
134 for (it2 = invs.begin(); it2 != invs.end(); ++it2) {
135 std::string name = it2->first;
136 std::vector<Resource::Ptr> mats = it2->second;
137 if (mats.empty() || ResCast<Material>(mats[0]) == NULL) {
138 continue; // skip non-material inventories
139 }
140
141 Material::Ptr m = ResCast<Material>(mats[0]->Clone());
142 for (int i = 1; i < mats.size(); i++) {
143 m->Absorb(ResCast<Material>(mats[i]->Clone()));
144 }
145 RecordInventory(a, name, m);
146 }
147}
148
149void Timer::RecordInventory(Agent* a, std::string name, Material::Ptr m) {
150 if (si_.explicit_inventory) {
151 CompMap c = m->comp()->mass();
152 compmath::Normalize(&c, m->quantity());
153 CompMap::iterator it;
154 for (it = c.begin(); it != c.end(); ++it) {
155 ctx_->NewDatum("ExplicitInventory")
156 ->AddVal("AgentId", a->id())
157 ->AddVal("Time", time_)
158 ->AddVal("InventoryName", name)
159 ->AddVal("NucId", it->first)
160 ->AddVal("Quantity", it->second)
161 ->AddVal("Units", m->units())
162 ->Record();
163 }
164 }
165
166 if (si_.explicit_inventory_compact) {
167 CompMap c = m->comp()->mass();
168 compmath::Normalize(&c, 1);
169 ctx_->NewDatum("ExplicitInventoryCompact")
170 ->AddVal("AgentId", a->id())
171 ->AddVal("Time", time_)
172 ->AddVal("InventoryName", name)
173 ->AddVal("Quantity", m->quantity())
174 ->AddVal("Units", m->units())
175 ->AddVal("Composition", c)
176 ->Record();
177 }
178}
179
180void Timer::DoDecom() {
181 // decommission queued agents
182 std::vector<Agent*> decom_list = decom_queue_[time_];
183 for (int i = 0; i < decom_list.size(); ++i) {
184 Agent* m = decom_list[i];
185 if (m->parent() != NULL) {
186 m->parent()->DecomNotify(m);
187 }
188 m->Decommission();
189 }
190}
191
193 tickers_[agent->id()] = agent;
194 if (agent->IsShim()) {
195 py_tickers_.push_back(agent);
196 } else {
197 cpp_tickers_.push_back(agent);
198 }
199}
200
202 tickers_.erase(tl->id());
203 if (tl->IsShim()) {
204 py_tickers_.erase(std::remove(py_tickers_.begin(), py_tickers_.end(), tl),
205 py_tickers_.end());
206 } else {
207 cpp_tickers_.erase(
208 std::remove(cpp_tickers_.begin(), cpp_tickers_.end(), tl),
209 cpp_tickers_.end());
210 }
211}
212
213void Timer::SchedBuild(Agent* parent, std::string proto_name, int t) {
214 if (t <= time_) {
215 throw ValueError("Cannot schedule build for t < [current-time]");
216 }
217 build_queue_[t].push_back(std::make_pair(proto_name, parent));
218}
219
220void Timer::SchedDecom(Agent* m, int t) {
221 if (t < time_) {
222 throw ValueError("Cannot schedule decommission for t < [current-time]");
223 }
224
225 // It is possible that a single agent may be scheduled for decommissioning
226 // multiple times. If this happens, we cannot just add it to the queue again
227 // - the duplicate entries will result in a double delete attempt and
228 // segfaults and otherwise bad things. Remove previous decommissionings
229 // before scheduling this new one.
230 std::map<int, std::vector<Agent*>>::iterator it;
231 bool done = false;
232 for (it = decom_queue_.begin(); it != decom_queue_.end(); ++it) {
233 int t = it->first;
234 std::vector<Agent*> ags = it->second;
235 for (int i = 0; i < ags.size(); i++) {
236 if (ags[i] == m) {
237 CLOG(LEV_WARN) << "scheduled over previous decommissioning of "
238 << m->id();
239 decom_queue_[t].erase(decom_queue_[t].begin() + i);
240 done = true;
241 break;
242 }
243 }
244 if (done) {
245 break;
246 }
247 }
248
249 decom_queue_[t].push_back(m);
250}
251
253 return time_;
254}
255
257 tickers_.clear();
258 cpp_tickers_.clear();
259 py_tickers_.clear();
260 build_queue_.clear();
261 decom_queue_.clear();
262 si_ = SimInfo(0);
263}
264
266 if (si.m0 < 1 || si.m0 > 12) {
267 throw ValueError("Invalid month0; must be between 1 and 12 (inclusive).");
268 }
269
270 want_kill_ = false;
271 ctx_ = ctx;
272 time_ = 0;
273 si_ = si;
274
275 if (si.branch_time > -1) {
276 time_ = si.branch_time;
277 }
278}
279
281 return si_.duration;
282}
283
284Timer::Timer() : time_(0), si_(0), want_snapshot_(false), want_kill_(false) {}
285
286} // namespace cyclus
The abstract base class used by all types of agents that live and interact in a simulation.
Definition agent.h:50
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:144
virtual const int id() const
The agent instance's unique ID within a simulation.
Definition agent.h:349
A simulation context provides access to necessary simulation-global functions and state.
Definition context.h:146
T * CreateAgent(std::string proto_name)
Create a new agent by cloning the named prototype.
Definition context.h:190
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:49
int m0
start month for the simulation: Jan = 1, ..., Dec = 12
Definition context.h:95
int duration
length of the simulation in timesteps (months)
Definition context.h:89
int branch_time
timestep at which simulation branching occurs if any
Definition context.h:105
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:78
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:252
void UnregisterTimeListener(TimeListener *tl)
Removes an agent from receiving tick/tock notifications.
Definition timer.cc:201
int dur()
Returns the duration of the simulation this Timer's timing.
Definition timer.cc:280
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:213
void Reset()
resets all data (registered listeners, etc.) to empty or initial state
Definition timer.cc:256
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:192
void Initialize(Context *ctx, SimInfo si)
Sets intial time-related parameters for the simulation.
Definition timer.cc:265
void SchedDecom(Agent *m, int time)
Schedules the given Agent to be decommissioned at the specified timestep t.
Definition timer.cc:220
For values that are too big, too small, etc.
Definition error.h:37
Code providing rudimentary logging capability for the Cyclus core.
#define CLOG(level)
Definition logger.h:40
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:93
@ LEV_INFO3
Information helpful for simulation users and developers alike.
Definition logger.h:64
@ LEV_DEBUG1
debugging information - least verbose
Definition logger.h:70
@ LEV_WARN
Use to report questionable simulation state (use extremely sparingly)
Definition logger.h:58
@ LEV_INFO2
Information helpful for simulation users and developers alike.
Definition logger.h:62
@ LEV_INFO1
Information helpful for simulation users and developers alike.
Definition logger.h:60
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:135
std::map< std::string, std::vector< Resource::Ptr > > Inventories
map<inventory_name, vector<resources_in_inventory> >.
Definition agent.h:39
std::string name(int nuc)
Definition pyne.cc:1239