Coordinator.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /**
  2. * @file Coordinator.cpp
  3. * @author The PARADEVS Development Team
  4. * See the AUTHORS or Authors.txt file
  5. */
  6. /*
  7. * PARADEVS - the multimodeling and simulation environment
  8. * This file is a part of the PARADEVS environment
  9. *
  10. * Copyright (C) 2013 ULCO http://www.univ-litoral.fr
  11. *
  12. * This program is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation, either version 3 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. */
  25. #include <common/Trace.hpp>
  26. #include <pdevs/Coordinator.hpp>
  27. #include <pdevs/Simulator.hpp>
  28. #include <algorithm>
  29. #include <cassert>
  30. namespace paradevs { namespace pdevs {
  31. Coordinator::Coordinator(const std::string& name) : common::Coordinator(name)
  32. { }
  33. Coordinator::~Coordinator()
  34. {
  35. for (unsigned int i = 0; i < _child_list.size(); i++)
  36. { delete _child_list[i]; }
  37. }
  38. common::Time Coordinator::start(common::Time t)
  39. {
  40. common::Trace::trace() << common::TraceElement(get_name(), t,
  41. common::I_MESSAGE)
  42. << ": BEFORE => "
  43. << "tl = " << _tl << " ; tn = " << _tn;
  44. common::Trace::trace().flush();
  45. assert(_child_list.size() > 0);
  46. for (auto & child : _child_list) {
  47. _event_table.init(child->start(_tn), child);
  48. }
  49. _tl = t;
  50. _tn = _event_table.get_current_time();
  51. common::Trace::trace() << common::TraceElement(get_name(), t,
  52. common::I_MESSAGE)
  53. << ": AFTER => "
  54. << "tl = " << _tl << " ; tn = " << _tn;
  55. common::Trace::trace().flush();
  56. return _tn;
  57. }
  58. /**************************************************
  59. * when *-message(t)
  60. * calculate IMM (models with tn = t in scheduler
  61. * calculate INF from IMM
  62. * for each e in IMM U INF
  63. * calculate influencer
  64. * ...
  65. * send done to parent
  66. **************************************************/
  67. void Coordinator::output(common::Time t)
  68. {
  69. common::Trace::trace() << common::TraceElement(get_name(), t,
  70. common::OUTPUT)
  71. << ": BEFORE";
  72. common::Trace::trace().flush();
  73. assert(t == _tn);
  74. common::Models IMM = _event_table.get_current_models(t);
  75. for (auto & model : IMM) {
  76. model->output(t);
  77. }
  78. common::Trace::trace() << common::TraceElement(get_name(), t,
  79. common::OUTPUT)
  80. << ": AFTER";
  81. common::Trace::trace().flush();
  82. }
  83. /*******************************************************************
  84. * when x-message(t)
  85. * receivers = { r | r in children, N in Ir, Z(N,r)(x) isn't empty
  86. * for each r in receivers
  87. * send x-message(Z(N,r)(x), t) with input value Z(N,r)(x) to r
  88. * for each r in IMM and not in receivers
  89. * send x-message(empty, t) to r
  90. * sort event list acocrding to tn
  91. * tl = t
  92. * tn = min(tn_d | d in D)
  93. *******************************************************************/
  94. common::Time Coordinator::transition(common::Time t)
  95. {
  96. common::Trace::trace() << common::TraceElement(get_name(), t,
  97. common::S_MESSAGE)
  98. << ": BEFORE => "
  99. << "tl = " << _tl << " ; tn = " << _tn
  100. << " ; scheduler = " << _event_table.to_string();
  101. common::Trace::trace().flush();
  102. assert(t >= _tl and t <= _tn);
  103. common::Models receivers = _event_table.get_current_models(t);
  104. for (common::Models::const_iterator it = _child_list.begin();
  105. it != _child_list.end(); ++it) {
  106. Model* model = dynamic_cast < Model* >(*it);
  107. if (model->event_number() > 0) {
  108. common::Models::const_iterator itm = std::find(receivers.begin(),
  109. receivers.end(),
  110. model);
  111. if (itm == receivers.end()) {
  112. receivers.push_back(model);
  113. }
  114. }
  115. }
  116. common::Trace::trace() << common::TraceElement(get_name(), t,
  117. common::S_MESSAGE)
  118. << ": receivers = " << receivers.to_string();
  119. common::Trace::trace().flush();
  120. for (common::Models::const_iterator it = receivers.begin();
  121. it != receivers.end(); ++it) {
  122. common::Time tn = (*it)->transition(t);
  123. _event_table.put(tn, *it);
  124. }
  125. for (common::Models::const_iterator it = _child_list.begin();
  126. it != _child_list.end(); ++it) {
  127. Model* model = dynamic_cast < Model* >(*it);
  128. if (model->event_number() > 0) {
  129. _event_table.put(t, model);
  130. }
  131. }
  132. _tl = t;
  133. _tn = _event_table.get_current_time();
  134. clear_bag();
  135. common::Trace::trace() << common::TraceElement(get_name(), t,
  136. common::S_MESSAGE)
  137. << ": AFTER => "
  138. << "tl = " << _tl << " ; tn = " << _tn
  139. << " ; scheduler = " << _event_table.to_string();
  140. common::Trace::trace().flush();
  141. return _tn;
  142. }
  143. void Coordinator::post_message(common::Time t,
  144. const common::ExternalEvent& message)
  145. {
  146. common::Trace::trace() << common::TraceElement(get_name(), t,
  147. common::POST_MESSAGE)
  148. << ": BEFORE => " << message.to_string();
  149. common::Trace::trace().flush();
  150. add_event(message);
  151. std::pair < common::Links::iterator, common::Links::iterator > result =
  152. _link_list.equal_range(common::Node(message.get_port_name(), this));
  153. for (common::Links::iterator it_r = result.first;
  154. it_r != result.second; ++it_r) {
  155. Model* model = dynamic_cast < Model* >((*it_r).second.get_model());
  156. model->post_message(t,
  157. common::ExternalEvent(it_r->second.get_port_name(),
  158. model,
  159. message.get_content()));
  160. }
  161. for (common::Models::const_iterator it = _child_list.begin();
  162. it != _child_list.end(); ++it) {
  163. Model* model = dynamic_cast < Model* >(*it);
  164. if (model->event_number() > 0) {
  165. _event_table.put(t, model);
  166. }
  167. }
  168. _tn = _event_table.get_current_time();
  169. common::Trace::trace() << common::TraceElement(get_name(), t,
  170. common::POST_MESSAGE)
  171. << ": AFTER => " << message.to_string();
  172. common::Trace::trace().flush();
  173. }
  174. /*******************************************************************
  175. * when y-message(y_d, t) with output y_d from d
  176. *******************************************************************/
  177. common::Time Coordinator::dispatch_events(common::Bag bag, common::Time t)
  178. {
  179. common::Trace::trace() << common::TraceElement(get_name(), t,
  180. common::Y_MESSAGE)
  181. << ": BEFORE => "
  182. << "tl = " << _tl << " ; tn = " << _tn
  183. << " ; bag = " << bag.to_string();
  184. common::Trace::trace().flush();
  185. for (auto & ymsg : bag) {
  186. std::pair < common::Links::iterator ,
  187. common::Links::iterator > result_model =
  188. _link_list.equal_range(common::Node(ymsg.get_port_name(),
  189. ymsg.get_model()));
  190. for (common::Links::iterator it = result_model.first;
  191. it != result_model.second; ++it) {
  192. // event on output port of coupled model
  193. if (it->second.get_model() == this) {
  194. common::Bag ymessages;
  195. ymessages.push_back(
  196. common::ExternalEvent(it->second.get_port_name(),
  197. it->second.get_model(),
  198. ymsg.get_content()));
  199. dynamic_cast < Coordinator* >(get_parent())->dispatch_events(
  200. ymessages, t);
  201. } else { // event on input port of internal model
  202. Model* model = dynamic_cast < Model* >(
  203. it->second.get_model());
  204. common::ExternalEvent message(it->second.get_port_name(),
  205. model, ymsg.get_content());
  206. model->post_message(t, message);
  207. }
  208. }
  209. }
  210. common::Trace::trace() << common::TraceElement(get_name(), t,
  211. common::Y_MESSAGE)
  212. << ": BEFORE => "
  213. << "tl = " << _tl << " ; tn = " << _tn;
  214. common::Trace::trace().flush();
  215. return _tn;
  216. }
  217. void Coordinator::observation(std::ostream& file) const
  218. {
  219. for (unsigned i = 0; i < _child_list.size(); i++) {
  220. _child_list[i]->observation(file);
  221. }
  222. }
  223. void Coordinator::add_child(Model* child)
  224. {
  225. _child_list.push_back(child);
  226. child->set_parent(this);
  227. }
  228. void Coordinator::add_link(const common::Node& source,
  229. const common::Node& destination)
  230. { _link_list.insert(std::pair < common::Node, common::Node >(source,
  231. destination)); }
  232. } } // namespace paradevs pdevs