Browse Source

New run method (with step duration)

Eric Ramat 1 year ago
parent
commit
97f16c76a9

+ 45 - 21
src/artis-star/common/RootCoordinator.hpp

@@ -46,28 +46,28 @@ public :
                   const typename Coordinator::graph_parameters_type &graph_parameters)
     :
     _root(root_name, parameters, graph_parameters), _observer(&_root),
-    _t_max(context.end()), _tn(context.begin()) {}
+    _t_max(context.end()), _tn(context.begin()), _started(false) {}
 
   RootCoordinator(const common::context::Context<Time> &context,
                   const std::string &root_name,
                   const typename Coordinator::parameters_type &parameters)
     :
     _root(root_name, parameters, NoParameters()), _observer(&_root),
-    _t_max(context.end()), _tn(context.begin()) {}
+    _t_max(context.end()), _tn(context.begin()), _started(false) {}
 
   RootCoordinator(const common::context::Context<Time> &context,
                   const std::string &root_name)
     :
     _root(root_name, NoParameters(), NoParameters()), _observer(&_root),
-    _t_max(context.end()), _tn(context.begin()) {}
+    _t_max(context.end()), _tn(context.begin()), _started(false) {}
 
   virtual ~RootCoordinator() {}
 
-  void attachView(const std::string &name, observer::View <Time> *view) {
+  void attachView(const std::string &name, observer::View<Time> *view) {
     _observer.attachView(name, view);
   }
 
-  const observer::Observer <Time> &observer() const { return _observer; }
+  const observer::Observer<Time> &observer() const { return _observer; }
 
   void run(const common::context::Context<Time> &context) {
 //             DSDE synchroniser
@@ -81,26 +81,20 @@ public :
 //                  endWhile
 //               end
 
-    _observer.init();
-    if (context.valid()) {
-      _root.restore(context.state());
-      _tn = _root.get_tn();
-    } else {
-      _tn = _root.start(_tn);
-    }
-    if (_tn > context.begin()) {
-      _observer.observe(context.begin(), _tn, false);
-    }
+    start(context);
     while (_tn <= _t_max) {
-      typename Time::type next_tn;
+      transition();
+    }
+  }
 
-      _root.output(_tn);
-      next_tn = _root.transition(_tn);
+  void run(const typename Time::type &duration) {
+    typename Time::type t_max = _tn + duration;
 
-      assert(next_tn >= _tn);
+    assert(_started);
 
-      _observer.observe(_tn, _t_max < next_tn ? _t_max : next_tn, _t_max < next_tn);
-      _tn = next_tn;
+    _observer.clear();
+    while (_tn < t_max and _tn <= _t_max) {
+      transition();
     }
   }
 
@@ -109,6 +103,23 @@ public :
     context.saved();
   }
 
+  void start(const context::Context<Time> &context) {
+
+    assert(not _started);
+
+    _observer.init();
+    if (context.valid()) {
+      _root.restore(context.state());
+      _tn = _root.get_tn();
+    } else {
+      _tn = _root.start(_tn);
+    }
+    if (_tn > context.begin()) {
+      _observer.observe(context.begin(), _tn, false);
+    }
+    _started = true;
+  }
+
   void switch_to_timed_observer(double step) { _observer.switch_to_timed_observer(step); }
 
   std::string to_string() const {
@@ -119,10 +130,23 @@ public :
   }
 
 private :
+  void transition() {
+    typename Time::type next_tn;
+
+    _root.output(_tn);
+    next_tn = _root.transition(_tn);
+
+    assert(next_tn >= _tn);
+
+    _observer.observe(_tn, _t_max < next_tn ? _t_max : next_tn, _t_max < next_tn);
+    _tn = next_tn;
+  }
+
   Coordinator _root;
   observer::Observer<Time> _observer;
   typename Time::type _t_max;
   typename Time::type _tn;
+  bool _started;
 };
 
 } // namespace artis common

+ 6 - 0
src/artis-star/common/observer/Observer.hpp

@@ -53,6 +53,12 @@ public:
     view->attachModel(_model);
   }
 
+  void clear() {
+    for (typename Views::iterator it = _views.begin(); it != _views.end(); ++it) {
+      it->second->clear();
+    }
+  }
+
   Views *cloneViews() const {
     auto view = new Views();
 

+ 12 - 8
src/artis-star/common/observer/View.hpp

@@ -56,7 +56,15 @@ public:
 
   virtual ~View() {}
 
-  void attachModel(const artis::common::Model<Time> *m) { _model = m; }
+  void attachModel(const artis::common::Model<Time> *model) { _model = model; }
+
+  void clear() {
+    for (auto &a: _values) {
+      for (auto &b: a.second) {
+        b.second.clear();
+      }
+    }
+  }
 
   View *clone() const {
     View *v = new View();
@@ -111,10 +119,8 @@ public:
           result.push_back(std::make_pair(value.first, data));
         }
         return result;
-
-      } else {
-        assert(false);
       }
+      assert(false);
     } else {
       throw std::range_error("selector name not found");
     }
@@ -127,9 +133,8 @@ public:
       assert(it->second.size() == 1);
 
       return it->second.begin()->second;
-    } else {
-      throw std::range_error("selector name not found");
     }
+    throw std::range_error("selector name not found");
   }
 
   template<typename W>
@@ -149,9 +154,8 @@ public:
         result.push_back(std::make_pair(value.first, data));
       }
       return result;
-    } else {
-      throw std::range_error("selector name not found");
     }
+    throw std::range_error("selector name not found");
   }
 
   void observe(double time, const common::Model<common::DoubleTime> *model,

+ 103 - 9
tests/common_observe.cpp

@@ -24,13 +24,17 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "artis-star/common/context/Context.hpp"
-#include "artis-star/common/observer/Observer.hpp"
-#include "artis-star/common/observer/View.hpp"
-#include "artis-star/kernel/pdevs/Dynamics.hpp"
-#include "artis-star/kernel/pdevs/Simulator.hpp"
+#include <artis-star/common/RootCoordinator.hpp>
+#include <artis-star/common/context/Context.hpp>
+#include <artis-star/common/observer/Observer.hpp>
+#include <artis-star/common/observer/View.hpp>
 #include <artis-star/common/time/DoubleTime.hpp>
 
+#include <artis-star/kernel/pdevs/Coordinator.hpp>
+#include <artis-star/kernel/pdevs/Dynamics.hpp>
+#include <artis-star/kernel/pdevs/GraphManager.hpp>
+#include <artis-star/kernel/pdevs/Simulator.hpp>
+
 #define BOOST_TEST_MODULE Common_Observe_Tests
 
 #include <boost/test/unit_test.hpp>
@@ -39,6 +43,29 @@
  * Tests
  *************************************************/
 
+template<typename M>
+class OnlyOneGraphManager :
+  public artis::pdevs::GraphManager<artis::common::DoubleTime> {
+public:
+  enum sub_models {
+    OneM
+  };
+
+  OnlyOneGraphManager(artis::common::Coordinator<artis::common::DoubleTime> *coordinator,
+                      const artis::common::NoParameters &parameters,
+                      const artis::common::NoParameters &graph_parameters)
+    :
+    artis::pdevs::GraphManager<artis::common::DoubleTime>(coordinator, parameters, graph_parameters),
+    model("a", parameters) {
+    this->add_child(OneM, &model);
+  }
+
+  ~OnlyOneGraphManager() override = default;
+
+private:
+  artis::pdevs::Simulator<artis::common::DoubleTime, M> model;
+};
+
 class MyDynamics : public artis::pdevs::Dynamics<artis::common::DoubleTime, MyDynamics> {
 public:
   struct vars {
@@ -49,24 +76,40 @@ public:
 
   MyDynamics(const std::string &name,
              const artis::pdevs::Context<artis::common::DoubleTime, MyDynamics, artis::common::NoParameters> &context)
-    : artis::pdevs::Dynamics<artis::common::DoubleTime, MyDynamics, artis::common::NoParameters>(name, context) {
+    : artis::pdevs::Dynamics<artis::common::DoubleTime, MyDynamics, artis::common::NoParameters>(name, context),
+      _counter(1) {
     observables({{vars::VALUE, "value"}});
   }
 
+  void dint(const artis::common::DoubleTime::type & /* t */) override {
+    if (_counter < 100) { ++_counter; } else { _counter = 1; }
+  }
+
+  void start(const artis::common::DoubleTime::type & /* t */) override {
+    _counter = 1;
+  }
+
+  artis::common::DoubleTime::type ta(const artis::common::DoubleTime::type & /* t */) const override {
+    return 1;
+  }
+
   artis::common::event::Value observe(const artis::common::DoubleTime::type & /* t */,
                                       unsigned int index) const override {
     if (index == vars::VALUE) {
-      return (int) 1;
+      return (unsigned int) _counter;
     }
     return {};
   }
+
+private:
+  unsigned int _counter;
 };
 
 BOOST_AUTO_TEST_CASE(Common_Observe_TestCase_1)
 {
   artis::pdevs::Simulator<artis::common::DoubleTime, MyDynamics> model("A", {});
   artis::common::observer::View<artis::common::DoubleTime> view;
-  artis::common::event::Value ref{1};
+  artis::common::event::Value ref{(unsigned int) 1};
 
   view.attachModel(&model);
   view.selector("value", {MyDynamics::vars::VALUE});
@@ -80,7 +123,7 @@ BOOST_AUTO_TEST_CASE(Common_Observe_TestCase_2)
   artis::pdevs::Simulator<artis::common::DoubleTime, MyDynamics> model("A", {});
   auto view = new artis::common::observer::View<artis::common::DoubleTime>();
   artis::common::observer::Observer<artis::common::DoubleTime> observer(&model);
-  artis::common::event::Value ref{1};
+  artis::common::event::Value ref{(unsigned int) 1};
 
   view->selector("value", {MyDynamics::vars::VALUE});
   observer.attachView("global", view);
@@ -89,4 +132,55 @@ BOOST_AUTO_TEST_CASE(Common_Observe_TestCase_2)
 
   BOOST_REQUIRE_EQUAL(observer.views().at("global")->get("value").back().second, ref);
   BOOST_REQUIRE_EQUAL(observer.view("global").get("value").back().second, ref);
+}
+
+BOOST_AUTO_TEST_CASE(Common_Observe_TestCase_3)
+{
+  artis::pdevs::Simulator<artis::common::DoubleTime, MyDynamics> model("A", {});
+  auto view = new artis::common::observer::View<artis::common::DoubleTime>();
+  artis::common::observer::Observer<artis::common::DoubleTime> observer(&model);
+  artis::common::event::Value ref{(unsigned int) 1};
+
+  view->selector("value", {OnlyOneGraphManager<MyDynamics>::OneM, MyDynamics::vars::VALUE});
+
+  artis::common::context::Context<artis::common::DoubleTime> context(0, 200);
+  artis::common::RootCoordinator<artis::common::DoubleTime, artis::pdevs::Coordinator<
+    artis::common::DoubleTime, OnlyOneGraphManager<MyDynamics>,
+    artis::common::NoParameters, artis::common::NoParameters>> rc(context, "root", artis::common::NoParameters(),
+                                                                  artis::common::NoParameters());
+
+  rc.attachView("global", view);
+  rc.run(context);
+
+  BOOST_REQUIRE_EQUAL(rc.observer().view("global").get("value").back().second, ref);
+}
+
+BOOST_AUTO_TEST_CASE(Common_Observe_TestCase_4)
+{
+  artis::pdevs::Simulator<artis::common::DoubleTime, MyDynamics> model("A", {});
+  auto view = new artis::common::observer::View<artis::common::DoubleTime>();
+  artis::common::observer::Observer<artis::common::DoubleTime> observer(&model);
+  artis::common::event::Value ref1{(unsigned int) 11};
+  artis::common::event::Value ref2{(unsigned int) 21};
+
+  view->selector("value", {OnlyOneGraphManager<MyDynamics>::OneM, MyDynamics::vars::VALUE});
+
+  artis::common::context::Context<artis::common::DoubleTime> context(0, 200);
+  artis::common::RootCoordinator<artis::common::DoubleTime, artis::pdevs::Coordinator<
+    artis::common::DoubleTime, OnlyOneGraphManager<MyDynamics>,
+    artis::common::NoParameters, artis::common::NoParameters>> rc(context, "root", artis::common::NoParameters(),
+                                                                  artis::common::NoParameters());
+
+  rc.attachView("global", view);
+  rc.switch_to_timed_observer(0.1);
+  rc.start(context);
+  rc.run(10);
+
+  BOOST_REQUIRE_EQUAL(rc.observer().view("global").get("value").back().second, ref1);
+  BOOST_REQUIRE_EQUAL(rc.observer().view("global").get("value").size(), 100);
+
+  rc.run(10);
+
+  BOOST_REQUIRE_EQUAL(rc.observer().view("global").get("value").back().second, ref2);
+  BOOST_REQUIRE_EQUAL(rc.observer().view("global").get("value").size(), 100);
 }