Преглед на файлове

Merge remote-tracking branch 'origin/extended_trace_eric'

Eric Ramat преди 7 години
родител
ревизия
52ad001a34

+ 7 - 6
src/artis/builder/Builder.hpp

@@ -58,6 +58,7 @@ private:
         using boost::property_tree::ptree;
 
         kernel::AbstractModel < U, V >* model = nullptr;
+        kernel::AbstractModels < U, V > submodels;
         std::string name;
         ptree::const_iterator it_type = pt.end();
         ptree::const_iterator it_name = pt.end();
@@ -82,11 +83,6 @@ private:
             }
         }
 
-        // type
-        if (it_type != pt.end()) {
-            model = F::factory().create(
-                it_type->second.get_value < std::string >());
-        }
         // name
         if (it_name != pt.end()) {
             name = it_type->second.get_value < std::string >();
@@ -95,7 +91,7 @@ private:
         if (it_submodels != pt.end()) {
             for (ptree::const_iterator itm = it_submodels->second.begin();
                  itm != it_submodels->second.end(); ++itm) {
-                build_model(itm->second);
+                submodels.push_back(build_model(itm->second));
             }
         }
         // states
@@ -110,6 +106,11 @@ private:
         if (it_externals != pt.end()) {
             build_externals(it_externals->second, model);
         }
+        // type
+        if (it_type != pt.end()) {
+            model = F::factory().create(
+                    it_type->second.get_value < std::string >(), submodels);
+        }
         return model;
     }
 

+ 21 - 18
src/artis/builder/ModelFactory.hpp

@@ -30,9 +30,11 @@
 
 #include <boost/core/demangle.hpp>
 
+#include <artis/kernel/AbstractModel.hpp>
+
 namespace artis { namespace builder {
 
-template < typename M >
+template < typename M, typename U, typename V >
 class ObjectCreator
 {
 public:
@@ -43,13 +45,14 @@ public:
 
     virtual std::string get() const = 0;
 
-    virtual M* operator()() const = 0;
+    virtual M* operator()(artis::kernel::AbstractModels < U,
+                          V > submodels) const = 0;
 };
 
-template < typename M, typename I, typename O >
+template < typename M, typename I, typename O, typename U, typename V >
 class ModelFactory
 {
-    typedef ModelFactory < M, I, O > type;
+    typedef ModelFactory < M, I, O, U, V > type;
 
 public:
     virtual ~ModelFactory()
@@ -63,13 +66,14 @@ public:
                                    std::make_pair(id, creator))).second;
     }
 
-    M* create(const std::string& id)
+    M* create(const std::string& id, artis::kernel::AbstractModels < U,
+              V > submodels)
     {
         std::lock_guard < std::mutex > lock(_mutex);
         typename Creators::const_iterator it = creators.find(id);
 
         if (it != creators.end()) {
-            return (*it->second.second)();
+            return (*it->second.second)(submodels);
         } else {
             return nullptr;
         }
@@ -90,7 +94,7 @@ public:
 
     bool remove(const I& id)
     {
-/*        std::lock_guard < std::mutex > lock(_mutex);
+        std::lock_guard < std::mutex > lock(_mutex);
         typename Creators::const_iterator it = creators.find(id);
 
         if (it != creators.end()) {
@@ -98,8 +102,7 @@ public:
             return true;
         } else {
             return false;
-            } */
-        return false;
+        }
     }
 
 private:
@@ -119,15 +122,15 @@ private:
 
 } }
 
-template < typename M, typename I, typename O >
-std::shared_ptr < artis::builder::ModelFactory < M, I, O > >
-artis::builder::ModelFactory < M, I, O >::_instance;
+template < typename M, typename I, typename O, typename U, typename V >
+std::shared_ptr < artis::builder::ModelFactory < M, I, O, U, V > >
+artis::builder::ModelFactory < M, I, O, U, V >::_instance;
 
-template < typename M, typename I, typename O >
-std::once_flag artis::builder::ModelFactory < M, I, O >::_flag;
+template < typename M, typename I, typename O, typename U, typename V >
+std::once_flag artis::builder::ModelFactory < M, I, O, U, V >::_flag;
 
-#define DECLARE_MODEL(mdl, type, fct)                                   \
-    class creator_##mdl : public artis::builder::ObjectCreator < type > { \
+#define DECLARE_MODEL(mdl, type, fct, U, V )                            \
+    class creator_##mdl : public artis::builder::ObjectCreator < type, U, V > { \
     public:                                                             \
     creator_##mdl()                                                     \
         {                                                               \
@@ -135,8 +138,8 @@ std::once_flag artis::builder::ModelFactory < M, I, O >::_flag;
         }                                                               \
     std::string get() const                                             \
         { return boost::core::demangle(typeid(mdl).name()); }           \
-    type* operator()() const                                            \
-        { return new mdl(); }                                           \
+    type* operator()(artis::kernel::AbstractModels < U, V > submodels) const \
+        { return new mdl(submodels); }                                  \
     static creator_##mdl an_##mdl;                                      \
     };                                                                  \
     creator_##mdl an_##mdl;

+ 110 - 36
src/artis/kernel/AbstractAtomicModel.hpp

@@ -43,12 +43,34 @@ class AbstractAtomicModel : public AbstractModel < U, V >,
 {
     typedef AbstractModel < U, V > type;
 
+    using Externals < T, U, V >::restore;
+    using Internals < T, U, V >::restore;
+    using States < T, U, V >::restore;
+    using Externals < T, U, V >::save;
+    using Internals < T, U, V >::save;
+    using States < T, U, V >::save;
+
 public:
     AbstractAtomicModel(const type* parent = 0) : type(parent)
-    { }
+    {
+#ifdef WITH_TRACE
+        utils::Trace < utils::DoubleTime >::trace()
+            << utils::TraceElement < utils::DoubleTime >(
+                   true,
+                   boost::core::demangle(typeid(T).name()),
+                   utils::DoubleTime::null,
+                   utils::CONSTRUCT);
+        utils::Trace < utils::DoubleTime >::trace().flush();
+#endif
+    }
 
     virtual ~AbstractAtomicModel()
-    { }
+    {
+#ifdef WITH_TRACE
+        trace_element(true, utils::DoubleTime::null,
+                      utils::DESTRUCT);
+#endif
+    }
 
     virtual const Node < U >* atomic(unsigned int /* index */) const
     { return this; }
@@ -57,23 +79,8 @@ public:
     {
 
 #ifdef WITH_TRACE
-        utils::Trace < utils::DoubleTime >::trace()
-            << utils::TraceElement < utils::DoubleTime >("KERNEL", t,
-                                                         utils::KERNEL)
-            << "AFTER - "
-            << AbstractAtomicModel < T, U, V >::path(this);
-        utils::Trace < utils::DoubleTime >::trace().flush();
-        for (size_t i = 0; i < Internals < T, U, V >::size(); ++i) {
-            if (not Internals < T, U, V >::get(i).is_null()) {
-                utils::Trace < utils::DoubleTime >::trace()
-                    << utils::TraceElement < utils::DoubleTime >("KERNEL", t,
-                                                                 utils::KERNEL)
-                    << Internals < T, U, V >::name(i) << " = "
-                    << Internals < T, U, V >::get(i).to_string(
-                        dynamic_cast < const T* >(this));
-                utils::Trace < utils::DoubleTime >::trace().flush();
-            }
-        }
+        trace_element(true, t, utils::AFTER_COMPUTE);
+        trace_internals(true, t, utils::AFTER_COMPUTE);
 #else
         (void) t;
 #endif
@@ -84,23 +91,9 @@ public:
     {
 
 #ifdef WITH_TRACE
-        utils::Trace < utils::DoubleTime >::trace()
-            << utils::TraceElement < utils::DoubleTime >("KERNEL", t,
-                                                         utils::KERNEL)
-            << "BEFORE - "
-            << AbstractAtomicModel < T, U, V >::path(this);
-        utils::Trace < utils::DoubleTime >::trace().flush();
-        for (size_t i = 0; i < Internals < T, U, V >::size(); ++i) {
-            if (not Internals < T, U, V >::get(i).is_null()) {
-                utils::Trace < utils::DoubleTime >::trace()
-                    << utils::TraceElement < utils::DoubleTime >("KERNEL", t,
-                                                                 utils::KERNEL)
-                    << Internals < T, U, V >::name(i) << " = "
-                    << Internals < T, U, V >::get(i).to_string(
-                        dynamic_cast < const T* >(this));
-                utils::Trace < utils::DoubleTime >::trace().flush();
-            }
-        }
+        trace_element(true, t, utils::BEFORE_COMPUTE);
+        trace_internals(true, t, utils::BEFORE_COMPUTE);
+        trace_externals(true, t, utils::BEFORE_COMPUTE);
 #else
         (void) t;
 #endif
@@ -126,6 +119,7 @@ public:
         if (type::last_time != t) {
             throw utils::InvalidGet("Variable not computed");
         }
+
         Any value = Internals < T, U, V >::get(index);
 
         return static_cast < const T* >(this)->*(value.get < T, W >());
@@ -137,6 +131,7 @@ public:
         if (type::last_time != t) {
             throw utils::InvalidGet("Variable not computed");
         }
+
         Any value = Internals < T, U, V >::get(index);
 
         switch (value_type) {
@@ -191,6 +186,85 @@ public:
 
     virtual void stable()
     { Externals < T, U, V >::updated = false; }
+
+    virtual void trace_element(typename U::type t,
+            utils::TraceType type = utils::NONE,
+            std::string comment = "") const
+    { trace_element(false, t, type, comment); }
+
+    virtual void trace_internals(typename U::type t,
+            utils::TraceType type) const
+    { trace_internals(false, t, type); }
+
+    virtual void trace_externals(typename U::type t,
+            utils::TraceType type = utils::NONE) const
+    { trace_externals(false, t, type); }
+
+    virtual void trace_model(typename U::type t,
+            utils::TraceType type = utils::NONE) const
+    { trace_model(false, t, type); }
+
+private:
+    void trace_element(bool from_kernel, typename U::type t,
+                       utils::TraceType type = utils::NONE,
+                       std::string comment = "") const
+    {
+        utils::Trace < utils::DoubleTime >::trace()
+            << utils::TraceElement < utils::DoubleTime >(
+                from_kernel,
+                AbstractAtomicModel < T, U, V >::path(this),
+                t, type)
+            << comment;
+        utils::Trace < utils::DoubleTime >::trace().flush();
+    }
+
+    void trace_internals(bool from_kernel, typename U::type t,
+                         utils::TraceType type) const
+    {
+        for (size_t i = 0; i < Internals < T, U, V >::size(); ++i) {
+            if (not Internals < T, U, V >::get(i).is_null()) {
+                utils::Trace < utils::DoubleTime >::trace()
+                    << utils::TraceElement < utils::DoubleTime >(
+                        from_kernel,
+                        AbstractAtomicModel < T, U, V >::path(this),
+                        t, type)
+                    << utils::KernelInfo(
+                        Internals < T, U, V >::name(i), true,
+                        Internals < T, U, V >::get(i).to_string(
+                            dynamic_cast < const T* >(this))
+                        );
+                utils::Trace < utils::DoubleTime >::trace().flush();
+            }
+        }
+    }
+
+    void trace_externals(bool from_kernel, typename U::type t,
+                         utils::TraceType type = utils::NONE) const
+    {
+        for (size_t i = 0; i < Externals < T, U, V >::size(); ++i) {
+            if (not Externals < T, U, V >::get(i).is_null()) {
+                utils::Trace < utils::DoubleTime >::trace()
+                    << utils::TraceElement < utils::DoubleTime >(
+                        from_kernel,
+                        AbstractAtomicModel < T, U, V >::path(this),
+                        t, type)
+                    << utils::KernelInfo(
+                        Externals < T, U, V >::name(i), false,
+                        Externals < T, U, V >::get(i).to_string(
+                            dynamic_cast < const T* >(this))
+                        );
+                utils::Trace < utils::DoubleTime >::trace().flush();
+            }
+        }
+    }
+
+    void trace_model(bool from_kernel, typename U::type t,
+                     utils::TraceType type = utils::NONE) const
+    {
+        trace_element(from_kernel, t, type);
+        trace_internals(from_kernel, t, type);
+        trace_externals(from_kernel, t, type);
+    }
 };
 
 } }

+ 187 - 59
src/artis/kernel/AbstractCoupledModel.hpp

@@ -36,6 +36,9 @@
 
 namespace artis { namespace kernel {
 
+template < typename T, typename U, typename V, typename W >
+class Simulator;
+
 template < typename T, typename U, typename V, typename W >
 class AbstractCoupledModel : public AbstractModel < U, V >,
                              public States < T, U, V >,
@@ -49,45 +52,60 @@ class AbstractCoupledModel : public AbstractModel < U, V >,
     typedef std::map < int, std::pair < type*,
                                         int > > SubModelInternals;
 
+    using Externals < T, U, V >::restore;
+    using Internals < T, U, V >::restore;
+    using States < T, U, V >::restore;
+    using Externals < T, U, V >::save;
+    using Internals < T, U, V >::save;
+    using States < T, U, V >::save;
+
+#ifdef WITH_TRACE
+    friend class Simulator < T, U, V, W >;
+#endif
+
 public:
     struct Var
     {
         unsigned int index;
         type* model;
         int sub_index;
+        std::string var_name;
+        std::string sub_var_name;
 
-        Var (unsigned int index, type* model, int sub_index) :
-            index(index), model(model), sub_index(sub_index)
+        Var (unsigned int index, std::string var_name,
+             type* model, int sub_index, std::string sub_var_name) :
+            index(index), model(model), sub_index(sub_index),
+            var_name(var_name), sub_var_name(sub_var_name)
         { }
     };
 
     AbstractCoupledModel(const type* parent = 0) : type(parent)
-    { }
+    {
+#ifdef WITH_TRACE
+        utils::Trace < utils::DoubleTime >::trace()
+            << utils::TraceElement < utils::DoubleTime >(
+                true,
+                boost::core::demangle(typeid(T).name()),
+                utils::DoubleTime::null,
+                utils::CONSTRUCT);
+        utils::Trace < utils::DoubleTime >::trace().flush();
+#endif
+    }
 
     virtual ~AbstractCoupledModel()
-    { }
+    {
+#ifdef WITH_TRACE
+        trace_element(true, utils::DoubleTime::null,
+                      utils::DESTRUCT);
+#endif
+    }
 
     virtual void after(typename U::type t)
     {
 
 #ifdef WITH_TRACE
-        utils::Trace < utils::DoubleTime >::trace()
-            << utils::TraceElement < utils::DoubleTime >("KERNEL", t,
-                                                         utils::KERNEL)
-            << "AFTER - "
-            << AbstractCoupledModel < T, U, V, W >::path(this);
-        utils::Trace < utils::DoubleTime >::trace().flush();
-        for (size_t i = 0; i < Internals < T, U, V >::size(); ++i) {
-            if (not Internals < T, U, V >::get(i).is_null()) {
-                utils::Trace < utils::DoubleTime >::trace()
-                    << utils::TraceElement < utils::DoubleTime >("KERNEL", t,
-                                                                 utils::KERNEL)
-                    << Internals < T, U, V >::name(i) << " = "
-                    << Internals < T, U, V >::get(i).to_string(
-                        dynamic_cast < const T* >(this));
-                utils::Trace < utils::DoubleTime >::trace().flush();
-            }
-        }
+        trace_element(true, t, utils::AFTER_COMPUTE);
+        trace_internals(true, t, utils::AFTER_COMPUTE);
 #else
         (void) t;
 #endif
@@ -110,23 +128,9 @@ public:
     {
 
 #ifdef WITH_TRACE
-        utils::Trace < utils::DoubleTime >::trace()
-            << utils::TraceElement < utils::DoubleTime >("KERNEL", t,
-                                                         utils::KERNEL)
-            << "BEFORE - "
-            << AbstractCoupledModel < T, U, V, W >::path(this);
-        utils::Trace < utils::DoubleTime >::trace().flush();
-        for (size_t i = 0; i < Internals < T, U, V >::size(); ++i) {
-            if (not Internals < T, U, V >::get(i).is_null()) {
-                utils::Trace < utils::DoubleTime >::trace()
-                    << utils::TraceElement < utils::DoubleTime >("KERNEL", t,
-                                                                 utils::KERNEL)
-                    << Internals < T, U, V >::name(i) << " = "
-                    << Internals < T, U, V >::get(i).to_string(
-                        dynamic_cast < const T* >(this));
-                utils::Trace < utils::DoubleTime >::trace().flush();
-            }
-        }
+        trace_element(true, t, utils::BEFORE_COMPUTE);
+        trace_internals(true, t, utils::BEFORE_COMPUTE);
+        trace_externals(true, t, utils::BEFORE_COMPUTE);
 #else
         (void) t;
 #endif
@@ -348,37 +352,136 @@ public:
         }
     }
 
+    virtual void trace_element(typename U::type t,
+                               utils::TraceType type = utils::NONE,
+                               std::string comment = "") const
+    { trace_element(false, t, type, comment); }
+
+    virtual void trace_internals(typename U::type t,
+                                 utils::TraceType type) const
+    { trace_internals(false, t, type); }
+
+    virtual void trace_externals(typename U::type t,
+                                 utils::TraceType type = utils::NONE) const
+    { trace_externals(false, t, type); }
+
+    virtual void trace_model(typename U::type t,
+                             utils::TraceType type = utils::NONE) const
+    { trace_model(false, t, type); }
+
+private:
+    void trace_element(bool from_kernel, typename U::type t,
+                       utils::TraceType type = utils::NONE,
+                       std::string comment = "") const
+    {
+        utils::Trace < utils::DoubleTime >::trace()
+            << utils::TraceElement < utils::DoubleTime >(
+                from_kernel,
+                AbstractCoupledModel < T, U, V, W >::path(this),
+                t, type)
+            << comment;
+        utils::Trace < utils::DoubleTime >::trace().flush();
+    }
+
+    void trace_internals(bool from_kernel, typename U::type t,
+                         utils::TraceType type) const
+    {
+        for (size_t i = 0; i < Internals < T, U, V >::size(); ++i) {
+            if (not Internals < T, U, V >::get(i).is_null()) {
+                utils::Trace < utils::DoubleTime >::trace()
+                    << utils::TraceElement < utils::DoubleTime >(
+                        from_kernel,
+                        AbstractCoupledModel < T, U, V, W >::path(this),
+                        t, type)
+                    << utils::KernelInfo(
+                        Internals < T, U, V >::name(i), true,
+                        Internals < T, U, V >::get(i).to_string(
+                            dynamic_cast < const T* >(this))
+                        );
+                utils::Trace < utils::DoubleTime >::trace().flush();
+            }
+        }
+    }
+
+    void trace_externals(bool from_kernel, typename U::type t,
+                         utils::TraceType type = utils::NONE) const
+    {
+        for (size_t i = 0; i < Externals < T, U, V >::size(); ++i) {
+            if (not Externals < T, U, V >::get(i).is_null()) {
+                utils::Trace < utils::DoubleTime >::trace()
+                    << utils::TraceElement < utils::DoubleTime >(
+                        from_kernel,
+                        AbstractCoupledModel < T, U, V, W >::path(this),
+                        t, type)
+                    << utils::KernelInfo(
+                        Externals < T, U, V >::name(i), false,
+                        Externals < T, U, V >::get(i).to_string(
+                            dynamic_cast < const T* >(this))
+                        );
+                utils::Trace < utils::DoubleTime >::trace().flush();
+            }
+        }
+    }
+
+    void trace_model(bool from_kernel, typename U::type t,
+                     utils::TraceType type = utils::NONE) const
+    {
+        trace_element(from_kernel, t, type);
+        trace_internals(from_kernel, t, type);
+        trace_externals(from_kernel, t, type);
+
+        // typename AbstractCoupledModel::Submodels::const_iterator it =
+        //     submodels.begin();
+
+        // while (it != submodels.end()) {
+        //     it->second->trace_model(from_kernel, t, type);
+        //     ++it;
+        // }
+    }
+
 protected:
-     void change_internal(unsigned int index, double T::* var)
-     {
-         submodel_internals.erase(index);
-         Internals < T, U, V >::internal(index, var);
-     }
-
-     void change_internal(unsigned int index, int T::* var)
-     {
-         submodel_internals.erase(index);
-         Internals < T, U, V >::internalI(index, var);
-     }
-
-     void change_internal(unsigned int index, bool T::* var)
-     {
-         submodel_internals.erase(index);
-         Internals < T, U, V >::internalB(index, var);
-     }
-
-    void link_internal_(unsigned int index, type* model, int sub_index)
+    void link_internal_(unsigned int index, std::string var_name,
+                        type* model, int sub_index, std::string sub_var_name)
     {
         submodel_internals[index] =
             std::pair < type*, int >(model, sub_index);
+#ifdef WITH_TRACE
+        utils::Trace < utils::DoubleTime >::trace()
+            << utils::TraceElement < utils::DoubleTime >(
+                true,
+                AbstractCoupledModel < T, U, V, W >::path(this),
+                utils::DoubleTime::null,
+                utils::INTERNAL_LINK)
+            << utils::KernelInfo(
+                var_name,
+                AbstractCoupledModel < T, U, V, W >::path(model),
+                sub_var_name);
+        utils::Trace < utils::DoubleTime >::trace().flush();
+
+#endif
     }
 
     void I_(std::initializer_list < Var > internals)
     {
         for (typename std::initializer_list < Var >::iterator it =
                  internals.begin(); it != internals.end(); ++it) {
+
             submodel_internals[it->index] =
                 std::pair < type*, int >(it->model, it->sub_index);
+
+#ifdef WITH_TRACE
+            utils::Trace < utils::DoubleTime >::trace()
+                << utils::TraceElement < utils::DoubleTime >(
+                    true,
+                    AbstractCoupledModel < T, U, V, W >::path(this),
+                    utils::DoubleTime::null,
+                    utils::INTERNAL_LINK)
+                << utils::KernelInfo(
+                    it->var_name,
+                    AbstractCoupledModel < T, U, V, W >::path(it->model),
+                    it->sub_var_name);
+            utils::Trace < utils::DoubleTime >::trace().flush();
+#endif
         }
     }
 
@@ -390,6 +493,19 @@ protected:
                  models.begin(); it != models.end(); ++it) {
             submodels[it->first] = it->second;
             it->second->set_parent(this);
+
+#ifdef WITH_TRACE
+            utils::Trace < utils::DoubleTime >::trace()
+                << utils::TraceElement < utils::DoubleTime >(
+                    true,
+                    AbstractCoupledModel < T, U, V, W >::path(this),
+                    utils::DoubleTime::null,
+                    utils::SUBMODEL_ADD)
+                << utils::KernelInfo(
+                    AbstractCoupledModel < T, U, V, W >::path(it->second));
+            utils::Trace < utils::DoubleTime >::trace().flush();
+#endif
+
         }
     }
 
@@ -400,6 +516,18 @@ protected:
         }
         setsubmodels[index].push_back(model);
         model->set_parent(this);
+
+#ifdef WITH_TRACE
+        utils::Trace < utils::DoubleTime >::trace()
+            << utils::TraceElement < utils::DoubleTime >(
+                true,
+                AbstractCoupledModel < T, U, V, W >::path(this),
+                utils::DoubleTime::null,
+                utils::SUBMODEL_ADD)
+            << utils::KernelInfo(
+                AbstractCoupledModel < T, U, V, W >::path(model));
+        utils::Trace < utils::DoubleTime >::trace().flush();
+#endif
     }
 
 private:
@@ -408,9 +536,9 @@ private:
     Setsubmodels setsubmodels;
 };
 
-#define InternalS(index, var, sub_index) link_internal_(index, var, sub_index)
 
-#define ITEM_S(index, var, sub_index) Var(index, var, sub_index)
+#define InternalS(index, var, sub_index) link_internal_(index, std::string(ESCAPEQUOTE(index)), var, sub_index, std::string(ESCAPEQUOTE(index)))
+#define ITEM_S(index, var, sub_index) Var(index, std::string(ESCAPEQUOTE(index)), var, sub_index, std::string(ESCAPEQUOTE(index)))
 #define UNWRAP_ITEM_S(...) ITEM_S __VA_ARGS__
 #define LIST_S_16(L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12, L13, L14, L15, L16) { UNWRAP_ITEM_S(L1), UNWRAP_ITEM_S(L2), UNWRAP_ITEM_S(L3), UNWRAP_ITEM_S(L4), UNWRAP_ITEM_S(L5), UNWRAP_ITEM_S(L6), UNWRAP_ITEM_S(L7), UNWRAP_ITEM_S(L8), UNWRAP_ITEM_S(L9), UNWRAP_ITEM_S(L10), UNWRAP_ITEM_S(L11), UNWRAP_ITEM_S(L12), UNWRAP_ITEM_S(L13), UNWRAP_ITEM_S(L14), UNWRAP_ITEM_S(L15), UNWRAP_ITEM_S(L16) }
 #define LIST_S_15(L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12, L13, L14, L15) { UNWRAP_ITEM_S(L1), UNWRAP_ITEM_S(L2), UNWRAP_ITEM_S(L3), UNWRAP_ITEM_S(L4), UNWRAP_ITEM_S(L5), UNWRAP_ITEM_S(L6), UNWRAP_ITEM_S(L7), UNWRAP_ITEM_S(L8), UNWRAP_ITEM_S(L9), UNWRAP_ITEM_S(L10), UNWRAP_ITEM_S(L11), UNWRAP_ITEM_S(L12), UNWRAP_ITEM_S(L13), UNWRAP_ITEM_S(L14), UNWRAP_ITEM_S(L15) }

+ 24 - 2
src/artis/kernel/AbstractModel.hpp

@@ -23,9 +23,11 @@
 #ifndef __ARTIS_KERNEL_ABSTRACT_MODEL_HPP
 #define __ARTIS_KERNEL_ABSTRACT_MODEL_HPP
 
+
 #include <artis/kernel/Node.hpp>
 #include <artis/context/State.hpp>
 #include <artis/utils/DoubleTime.hpp>
+#include <artis/utils/Trace.hpp>
 
 #include <boost/core/demangle.hpp>
 
@@ -79,6 +81,14 @@ public:
         before(t);
         if (check(t) and (last_time != t or
                           (last_time == t and is_updated()))) {
+#ifdef WITH_TRACE
+            utils::Trace < utils::DoubleTime >::trace()
+                << utils::TraceElement < utils::DoubleTime >(
+                    true,
+                    AbstractModel < Time, Parameters >::path(this),
+                    t, utils::COMPUTE);
+            utils::Trace < utils::DoubleTime >::trace().flush();
+#endif
             compute(t, last_time == t);
             last_time = t;
             stable();
@@ -96,10 +106,10 @@ public:
         if (index >= 0) {
             return p +
                 "/[" + std::to_string(index) + "]" +
-                boost::core::demangle(typeid(*child).name());
+                boost::core::demangle(typeid(*child).name()); // .erase(0,6);
         } else {
             return (p.empty() ? "" : p + "/") +
-                boost::core::demangle(typeid(*child).name());
+                boost::core::demangle(typeid(*child).name()); // .erase(0,6);
         }
     }
 
@@ -126,6 +136,15 @@ public:
 
     virtual void save(context::State < Time >& state) const = 0;
 
+    virtual void trace_element(typename Time::type t, utils::TraceType type,
+                               std::string comment = "") const = 0;
+    virtual void trace_internals(typename Time::type t,
+                                 utils::TraceType type) const = 0;
+    virtual void trace_externals(typename Time::type t,
+                                 utils::TraceType type) const = 0;
+    virtual void trace_model(typename Time::type t,
+                             utils::TraceType type) const = 0;
+
     void set_parent(const AbstractModel < Time, Parameters >* p)
     { parent = p; }
 
@@ -136,6 +155,9 @@ protected:
     typename Time::type                       last_time;
 };
 
+template < typename Time, typename Parameters >
+using AbstractModels = std::vector < AbstractModel < Time, Parameters >* >;
+
 } }
 
 #endif

+ 39 - 0
src/artis/kernel/Externals.hpp

@@ -54,6 +54,12 @@ public:
     virtual ~Externals()
     { }
 
+    const Any& get(unsigned int index) const
+    { return externals.at(index).second; }
+
+    const std::string& name(unsigned int index) const
+    { return external_names.at(index); }
+
     bool check(typename U::type t) const
     {
         bool OK = true;
@@ -79,6 +85,17 @@ public:
             }
             externals[it->index] = std::make_pair(-1, it->var);
             external_names[it->index] = it->name;
+
+#ifdef WITH_TRACE
+            utils::Trace < utils::DoubleTime >::trace()
+                    << utils::TraceElement < utils::DoubleTime >(
+                           true,
+                           dynamic_cast<T*>(this)->path(dynamic_cast<T*>(this)),
+                           utils::DoubleTime::null,
+                           utils::EXTERNAL_DECL)
+                    << utils::KernelInfo(it->name, false);
+            utils::Trace < utils::DoubleTime >::trace().flush();
+#endif
         }
     }
 
@@ -91,6 +108,17 @@ public:
         }
         externals[index] = std::make_pair(-1, var);
         external_names[index] = name;
+
+#ifdef WITH_TRACE
+        utils::Trace < utils::DoubleTime >::trace()
+                << utils::TraceElement < utils::DoubleTime >(
+                       true,
+                       dynamic_cast<T*>(this)->path(dynamic_cast<T*>(this)),
+                       utils::DoubleTime::null,
+                       utils::EXTERNAL_DECL)
+                << utils::KernelInfo(name, false);
+        utils::Trace < utils::DoubleTime >::trace().flush();
+#endif
     }
 
     bool is_ready(typename U::type t, unsigned int index) const
@@ -113,6 +141,17 @@ public:
                 updated = true;
             }
         }
+
+#ifdef WITH_TRACE
+        utils::Trace < utils::DoubleTime >::trace()
+                << utils::TraceElement < utils::DoubleTime >(
+                       true,
+                       dynamic_cast<T*>(this)->path(dynamic_cast<T*>(this)),
+                       t, utils::PUT)
+                << utils::KernelInfo(external_names[index], true,
+                                     get(index).to_string(dynamic_cast < const T* >(this)));
+        utils::Trace < utils::DoubleTime >::trace().flush();
+#endif
     }
 
     virtual void restore(AbstractModel < U, V >* model,

+ 27 - 4
src/artis/kernel/Internals.hpp

@@ -60,14 +60,26 @@ public:
     void I_(std::initializer_list < element < W > > list)
     {
         for (typename std::initializer_list <element < W > >::iterator it =
-                 list.begin(); it != list.end(); ++it) {
+             list.begin(); it != list.end(); ++it) {
             if (internals.size() <= it->index) {
                 internals.resize(it->index + 1);
                 internal_names.resize(it->index + 1, std::string());
             }
             internals[it->index] = it->var;
             internal_names[it->index] = it->name;
+
+#ifdef WITH_TRACE
+            utils::Trace < utils::DoubleTime >::trace()
+                    << utils::TraceElement < utils::DoubleTime >(
+                           true,
+                           dynamic_cast<T*>(this)->path(dynamic_cast<T*>(this)),
+                           utils::DoubleTime::null,
+                           utils::INTERNAL_DECL)
+                    << utils::KernelInfo(it->name, true);
+            utils::Trace < utils::DoubleTime >::trace().flush();
+#endif
         }
+
     }
 
     template < typename W >
@@ -79,6 +91,17 @@ public:
         }
         internals[index] = Any(var);
         internal_names[index] = name;
+
+#ifdef WITH_TRACE
+        utils::Trace < utils::DoubleTime >::trace()
+                << utils::TraceElement < utils::DoubleTime >(
+                       true,
+                       dynamic_cast<T*>(this)->path(dynamic_cast<T*>(this)),
+                       utils::DoubleTime::null,
+                       utils::INTERNAL_DECL)
+                << utils::KernelInfo(name, true);
+        utils::Trace < utils::DoubleTime >::trace().flush();
+#endif
     }
 
     const std::string& name(unsigned int index) const
@@ -105,7 +128,7 @@ public:
         unsigned int index = 0;
 
         for (typename std::vector < Any >::const_iterator it =
-                 internals.begin(); it != internals.end(); ++it) {
+             internals.begin(); it != internals.end(); ++it) {
             if (not it->is_null()) {
                 state.add_internal(index,
                                    it->save < T >(
@@ -119,12 +142,12 @@ public:
     { return internals.size(); }
 
 private:
-    std::vector < Any > internals;
     std::vector < std::string > internal_names;
+    std::vector < Any > internals;
 };
 
 #define Internal(index, var)                                    \
-        internal_(index, std::string(ESCAPEQUOTE(index)), var)
+    internal_(index, std::string(ESCAPEQUOTE(index)), var)
 
 #define Internals(W,L) I_< W >(UNWRAP2 L)
 

+ 7 - 0
src/artis/kernel/Simulator.hpp

@@ -50,10 +50,17 @@ public:
     void attachView(const std::string& name, observer::View < U, V >* view)
     { _observer.attachView(name, view); }
 
+
     void init(double time, const V& parameters)
     {
         _model->init(time, parameters);
         _observer.init();
+
+#ifdef WITH_TRACE
+        _model->trace_model(true,
+                            utils::DoubleTime::null,
+                            utils::INIT);
+#endif
     }
 
     const observer::Observer < U, V >& observer() const

+ 22 - 21
src/artis/utils/DateTime.cpp

@@ -86,12 +86,7 @@ struct intern_date
     long mminutes;
     long mseconds;
 
-    enum STR_FORMAT
-    {
-	extended, //"%Y-%m-%d %H:%M:%S"
-	ymd,      //"%Y-%m-%d"
-	hms       //"%H:%M:%S"
-    };
+
 
     intern_date() noexcept
 	: myear(1400)
@@ -133,11 +128,11 @@ struct intern_date
 	mseconds = std::floor(f);
     }
 
-    std::string toString(STR_FORMAT fmt) noexcept
+    std::string toString(DateFormat fmt) noexcept
     {
 	std::stringstream ss;
 
-	if (fmt != hms) {
+    if (fmt != DATE_FORMAT_HMS) {
 	    ss << myear << "-";
 	    if (mmonth < 10) {
 		ss << "0";
@@ -148,10 +143,10 @@ struct intern_date
 	    }
 	    ss << mday ;
 	}
-	if (fmt == extended) {
+    if (fmt == DATE_FORMAT_EXTENDED) {
 	    ss << " ";
 	}
-	if (fmt != ymd) {
+    if (fmt != DATE_FORMAT_YMD) {
 	    if (mhours < 10) {
 		ss << "0";
 	    }
@@ -173,11 +168,11 @@ struct intern_date
     //format : not extended = "%Y-%m-%d"
     //         extended     = "%Y-%m-%d %H:%M:%S"
     //return true if no error
-    bool fromString(const std::string& date, STR_FORMAT toparse) noexcept
+    bool fromString(const std::string& date, DateFormat toparse) noexcept
     {
 	bool error = false;
 
-	if (toparse == extended) {
+    if (toparse == DATE_FORMAT_EXTENDED) {
 	    //parse "%Y-%m-%d %H:%M:%S"
 	    try {
 		std::regex regex("([^\\s]+)\\s([^\\s]+)");
@@ -189,8 +184,8 @@ struct intern_date
 		    std::smatch match = *next;
 
 		    if (match.size() == 3) {
-			fromString(match[1].str(), ymd);
-			fromString(match[2].str(), hms);
+            fromString(match[1].str(), DATE_FORMAT_YMD);
+            fromString(match[2].str(), DATE_FORMAT_HMS);
 		    } else {
 			error = true;
 		    }
@@ -212,19 +207,19 @@ struct intern_date
 		    std::smatch match = *next;
 		    nbmatches++;
 		    if (nbmatches == 1) {
-			if (toparse == ymd) {
+            if (toparse == DATE_FORMAT_YMD) {
 			    myear = std::stol(match.str());
 			} else {
 			    mhours = std::stol(match.str());
 			}
 		    } else if (nbmatches == 3) {
-			if (toparse == ymd) {
+            if (toparse == DATE_FORMAT_YMD) {
 			    mmonth = std::stol(match.str());
 			} else {
 			    mminutes = std::stol(match.str());
 			}
 		    } else if (nbmatches == 5) {
-			if (toparse == ymd) {
+            if (toparse == DATE_FORMAT_YMD) {
 			    mday = std::stol(match.str());
 			} else {
 			    mseconds = std::stol(match.str());
@@ -596,7 +591,7 @@ std::string DateTime::toJulianDayNumber(unsigned long date)
 {
     intern_date d;
     d.fromJulianDay(static_cast<double>(date));
-    return d.toString(intern_date::ymd);
+    return d.toString(DATE_FORMAT_YMD);
 }
 
 
@@ -604,7 +599,7 @@ std::string DateTime::toJulianDayNumber(unsigned long date)
 long DateTime::toJulianDayNumber(const std::string& date)
 {
     intern_date d;
-    d.fromString(date, intern_date::ymd);
+    d.fromString(date, DATE_FORMAT_YMD);
     return d.julianDayNumber();
 }
 
@@ -613,7 +608,13 @@ std::string DateTime::toJulianDay(double date)
 {
     intern_date d;
     d.fromJulianDay(date);
-    return d.toString(intern_date::extended);
+    return d.toString(DATE_FORMAT_EXTENDED);
+}
+
+std::string DateTime::toJulianDayFmt(double date, DateFormat format){
+    intern_date d;
+    d.fromJulianDay(date);
+    return d.toString(format);
 }
 
 
@@ -622,7 +623,7 @@ double DateTime::toJulianDay(const std::string& date)
 {
 
     intern_date d;
-    d.fromString(date, intern_date::extended);
+    d.fromString(date, DATE_FORMAT_EXTENDED);
     return d.julianDay();
 }
 

+ 18 - 0
src/artis/utils/DateTime.hpp

@@ -46,6 +46,13 @@ enum DateTimeUnitOptions
     DATE_TIME_UNIT_YEAR
 };
 
+enum DateFormat
+{
+    DATE_FORMAT_EXTENDED, //"%Y-%m-%d %H:%M:%S"
+    DATE_FORMAT_YMD,      //"%Y-%m-%d"
+    DATE_FORMAT_HMS       //"%H:%M:%S"
+};
+
 class DateTime
 {
 public:
@@ -263,6 +270,17 @@ public:
      */
     static double toJulianDay(const std::string& date);
 
+    /**
+     * @brief Convert a julian date into a string in a given format.
+     * @code
+     * artis::utils::DateTime::toJulianDay(2454115.05486, DATE_FORMAT_YMD)) = "2001-10-9";
+     * @endcode
+     * @param date The date to convert.
+     * @param format The string format from enum artis::utils::DateFormat.
+     * @return A string representation of the julian day.
+     */
+    static std::string toJulianDayFmt(double date, artis::utils::DateFormat format);
+
                                   /* * * * */
 
     /**

+ 280 - 38
src/artis/utils/Trace.hpp

@@ -30,24 +30,206 @@
 #include <sstream>
 #include <string>
 #include <vector>
+#include <map>
 
 #include <artis/utils/DateTime.hpp>
+#include <artis/kernel/Any.hpp>
+
+#if WIN32
+#include <iso646.h>
+#endif
+
+//fwd decl for friend classes in TraceElement
+namespace artis { namespace kernel {
+template < typename T, typename U, typename V, typename W >
+class AbstractCoupledModel;
+template < typename T, typename U, typename V >
+class AbstractAtomicModel;
+template < typename Time, typename Parameters >
+class AbstractModel;
+template < typename T, typename U, typename V >
+class Internals;
+template < typename T, typename U, typename V >
+class Externals;
+}}
 
 namespace artis { namespace utils {
 
-enum TraceType { NONE = 0, CHECK, COMPUTE, INIT, KERNEL, PUT };
+enum TraceType { NONE = 0, CHECK = 1, CONSTRUCT, SUBMODEL_ADD, INTERNAL_DECL,
+                 EXTERNAL_DECL, INTERNAL_LINK, INIT, START, BEFORE_COMPUTE,
+                 COMPUTE, PUT, AFTER_COMPUTE, DESTRUCT, KERNEL};
+static const std::vector <std::string> TraceTypesStr = {
+    "none", "check", "construct", "submodel_add", "internal_decl",
+    "external_decl", "internal_link", "init", "start", "before_compute",
+    "compute", "put", "after_compute", "destruct", "kernel"};
+
+class KernelInfo
+{
+public:
+    static std::map < std::string, int > elt_dictionary;
+    static std::vector < std::string > elt_names;
+    static unsigned int term(const std::string& v) {
+        if(elt_dictionary.find(v) == elt_dictionary.end()) {
+            elt_dictionary[v] = elt_names.size();
+            elt_names.push_back(v);
+        }
+        return elt_dictionary[v];
+    }
+    static const std::string & term(unsigned int i) {return elt_names[i];}
+
+
+    KernelInfo() :
+        _internal_var(false), _empty(true)
+    {
+        set_var("");
+        set_value("");
+        set_tgt_model("");
+        set_tgt_internal_var("");
+    }
+
+    KernelInfo(const std::string& var, bool internal_var,
+               const std::string& value) :
+         _internal_var(internal_var), _empty(false)
+    {
+        set_var(var);
+        set_value(value);
+        set_tgt_model("");
+        set_tgt_internal_var("");
+    }
+
+    KernelInfo(const std::string& var, const std::string& tgt_model,
+               const std::string& tgt_internal_var) :
+        _internal_var(true), _empty(false)
+    {
+        set_var(var);
+        set_value("");
+        set_tgt_model(tgt_model);
+        set_tgt_internal_var(tgt_internal_var);
+    }
+
+    KernelInfo(const std::string& var, bool internal_var) :
+        _internal_var(internal_var), _empty(false)
+    {
+        set_var(var);
+        set_value("");
+        set_tgt_model("");
+        set_tgt_internal_var("");
+    }
+
+    KernelInfo(const std::string& tgt_model) :
+        _internal_var(false), _empty(false)
+    {
+        set_var("");
+        set_value("");
+        set_tgt_model(tgt_model);
+        set_tgt_internal_var("");
+    }
+
+    void set_var(const std::string& v)
+    { _var = KernelInfo::term(v); }
+
+    void set_value(const std::string& v)
+    { _value = KernelInfo::term(v); }
+
+    void set_tgt_model(const std::string& v)
+    { _tgt_model = KernelInfo::term(v); }
+
+    void set_tgt_internal_var(const std::string& v)
+    { _tgt_internal_var = KernelInfo::term(v); }
+
+
+    const std::string& var() const
+    { return KernelInfo::term(_var); }
+
+    const std::string& value() const
+    { return KernelInfo::term(_value); }
+
+    const std::string& tgt_model() const
+    { return KernelInfo::term(_tgt_model); }
+
+    const std::string& tgt_internal_var() const
+    { return KernelInfo::term(_tgt_internal_var); }
+
+    unsigned int var_idx() const
+    { return _var; }
+
+    unsigned int tgt_internal_var_idx() const
+    { return _tgt_internal_var; }
+
+    unsigned int tgt_model_idx() const
+    { return _tgt_model; }
+
+    bool is_internal_var() const
+    { return _internal_var; }
+
+    bool empty() const
+    { return _empty; }
+
+    std::string to_string() const
+    {
+        std::ostringstream ss;
+        if( not KernelInfo::term(_var).empty() ){
+            ss << ":";
+            if (not _internal_var)
+                ss << "*";
+            ss << KernelInfo::term(_var);
+        }
+        if( not KernelInfo::term(_value).empty()) {
+            ss << "=" << KernelInfo::term(_value);
+        }
+        if(not KernelInfo::term(_tgt_model).empty()) {
+            ss << " -> " << KernelInfo::term(_tgt_model);
+            if(not KernelInfo::term(_tgt_internal_var).empty()) {
+                ss << ":" << KernelInfo::term(_tgt_internal_var);
+            }
+        }
+        return ss.str();
+    }
+
+private:
+    unsigned int _var;
+    unsigned int _value;
+    unsigned int _tgt_model;
+    unsigned int _tgt_internal_var;
+    bool        _internal_var;
+    bool        _empty;
+};
 
 template < class Time >
 class TraceElement
 {
+    template < typename T, typename U, typename V, typename W >
+    friend class artis::kernel::AbstractCoupledModel;
+    template < typename T, typename U, typename V >
+    friend class artis::kernel::AbstractAtomicModel;
+    template < typename T, typename P >
+    friend class artis::kernel::AbstractModel;
+    template < typename T, typename U, typename V >
+    friend class artis::kernel::Internals;
+    template < typename T, typename U, typename V >
+    friend class artis::kernel::Externals;
+
+private:
+    TraceElement(bool from_kernel, const std::string& model_name,
+                 typename Time::type time, TraceType type) :
+        _time(time), _type(type),
+        _from_kernel(from_kernel)
+    {
+        _model_name = KernelInfo::term(model_name);
+    }
+
 public:
-    TraceElement() : _time(Time::null), _type(NONE)
+    TraceElement() : _time(Time::null), _type(NONE),
+        _from_kernel(false)
     { }
 
     TraceElement(const std::string& model_name, typename Time::type time,
                  TraceType type) :
-        _model_name(model_name), _time(time), _type(type)
-    { }
+        _time(time), _type(type),
+        _from_kernel(false)
+    {
+        _model_name = KernelInfo::term(model_name);
+    }
 
     virtual ~TraceElement()
     { }
@@ -56,6 +238,9 @@ public:
     { return _comment; }
 
     const std::string& get_model_name() const
+    { return KernelInfo::term(_model_name); }
+
+    unsigned int get_model_name_idx() const
     { return _model_name; }
 
     typename Time::type get_time() const
@@ -64,14 +249,48 @@ public:
     TraceType get_type() const
     { return _type; }
 
+    const KernelInfo& get_kernel_info() const
+    { return _kernel_info; }
+
     void set_comment(const std::string& comment)
     { _comment = comment; }
 
+    bool from_kernel() const
+    { return _from_kernel; }
+
+    void set_kernel_info(const KernelInfo& info)
+    { _kernel_info = info; }
+
+    std::string to_string(artis::utils::DateFormat date_format =
+            artis::utils::DATE_FORMAT_EXTENDED) const
+    {
+        std::ostringstream ss;
+        ss << (from_kernel() ? "KERNEL" : "TRACE ");
+        if (get_time() != Time::null) {
+            ss << "(" << utils::DateTime::toJulianDayFmt(get_time(),
+                                                         date_format)
+               << ")";
+        }
+        ss << ": ";
+        ss << "<" + TraceTypesStr[get_type()] + ">";
+        ss << " " << get_model_name();
+        if (not get_kernel_info().empty()) {
+            ss << get_kernel_info().to_string();
+        }
+        if (not get_comment().empty()) {
+            ss << " => " << get_comment();
+        }
+        return ss.str();
+
+    }
+
 private:
-    std::string         _model_name;
+    unsigned int        _model_name;
     typename Time::type _time;
     TraceType           _type;
     std::string         _comment;
+    KernelInfo          _kernel_info;
+    bool                _from_kernel;
 };
 
 template < class Time >
@@ -80,18 +299,26 @@ class TraceElements : public std::vector < TraceElement < Time > >
 public:
     TraceElements()
     { }
+
     virtual ~TraceElements()
     { }
 
     TraceElements filter_model_name(
-        const std::string& model_name) const
+            const std::string& model_name) const
     {
         TraceElements < Time > result;
 
-        std::copy_if(TraceElements < Time >::begin(),
-                     TraceElements < Time >::end(), std::back_inserter(result),
-                     [model_name](TraceElement < Time > const & x)
-                     { return x.get_model_name() == model_name; });
+        std::copy_if(
+                    TraceElements < Time >::begin(),
+                    TraceElements < Time >::end(), std::back_inserter(result),
+                    [model_name](TraceElement < Time > const & x) {
+            if (not x.get_kernel_info().empty()) {
+                if (x.get_kernel_info().tgt_model() == model_name) {
+                    return true;
+                }
+            }
+            return x.get_model_name() == model_name;
+        });
         return result;
     }
 
@@ -102,7 +329,7 @@ public:
         std::copy_if(TraceElements < Time >::begin(),
                      TraceElements < Time >::end(), std::back_inserter(result),
                      [time](TraceElement < Time > const & x)
-                     { return x.get_time() == time; });
+        { return x.get_time() == time; });
         return result;
     }
 
@@ -113,33 +340,34 @@ public:
         std::copy_if(TraceElements < Time >::begin(),
                      TraceElements < Time >::end(), std::back_inserter(result),
                      [type](TraceElement < Time > const & x)
-                     { return x.get_type() == type; });
+        { return x.get_type() == type; });
         return result;
     }
 
-    std::string to_string() const
+    TraceElements filter_variable(const std::string& var_name) const
+    {
+        TraceElements result;
+
+        std::copy_if(TraceElements < Time >::begin(),
+                     TraceElements < Time >::end(), std::back_inserter(result),
+                     [var_name](TraceElement < Time > const & x)
+        {   if(x.get_kernel_info().empty())
+                return false;
+            return ((x.get_kernel_info().var() == var_name)
+                    or (x.get_kernel_info().tgt_internal_var() == var_name));
+        });
+        return result;
+    }
+
+    std::string to_string(artis::utils::DateFormat date_format =
+            artis::utils::DATE_FORMAT_EXTENDED) const
     {
         std::ostringstream ss;
 
         for (typename TraceElements < Time >::const_iterator it =
-                 TraceElements < Time >::begin();
+             TraceElements < Time >::begin();
              it != TraceElements < Time >::end(); ++it) {
-            ss << "TRACE: " << it->get_model_name() << " at "
-               << utils::DateTime::toJulianDay(it->get_time()) << " <";
-            switch (it->get_type())
-            {
-            case NONE: ss << "none"; break;
-            case CHECK: ss << "check"; break;
-            case COMPUTE:  ss << "compute"; break;
-            case INIT: ss << "init"; break;
-            case KERNEL: ss << "kernel"; break;
-            case PUT: ss << "put"; break;
-            };
-            ss << ">";
-            if (not it->get_comment().empty()) {
-                ss << " => " << it->get_comment();
-            }
-            ss << std::endl;
+            ss << it->to_string(date_format) << std::endl;
         }
         return ss.str();
     }
@@ -155,8 +383,8 @@ public:
     static Trace& trace()
     {
         std::call_once(_flag, [] ()
-                       { _instance.reset(new Trace()); }
-            );
+        { _instance.reset(new Trace()); }
+        );
         return *_instance;
     }
 
@@ -182,6 +410,9 @@ public:
     void set_element(const TraceElement < Time >& element)
     { _element = element; }
 
+    void set_kernel_info(const KernelInfo& info)
+    { _element.set_kernel_info(info); }
+
     std::ostringstream& sstream()
     {
         if (_sstream == 0) {
@@ -207,8 +438,8 @@ private:
 
 template < class Time >
 artis::utils::Trace < Time >& operator<<(
-    artis::utils::Trace < Time >& trace,
-    const artis::utils::TraceElement < Time >& e)
+        artis::utils::Trace < Time >& trace,
+        const artis::utils::TraceElement < Time >& e)
 {
     std::lock_guard < std::mutex > lock(trace.mutex());
 
@@ -218,8 +449,19 @@ artis::utils::Trace < Time >& operator<<(
 
 template < class Time >
 artis::utils::Trace < Time >& operator<<(
-    artis::utils::Trace < Time >& trace,
-    const std::string& str)
+        artis::utils::Trace < Time >& trace,
+        const artis::utils::KernelInfo& info)
+{
+    std::lock_guard < std::mutex > lock(trace.mutex());
+
+    trace.set_kernel_info(info);
+    return trace;
+}
+
+template < class Time >
+artis::utils::Trace < Time >& operator<<(
+        artis::utils::Trace < Time >& trace,
+        const std::string& str)
 {
     std::lock_guard < std::mutex > lock(trace.mutex());
 
@@ -229,8 +471,8 @@ artis::utils::Trace < Time >& operator<<(
 
 template < class Time >
 artis::utils::Trace < Time >& operator<<(
-    artis::utils::Trace < Time >& trace,
-    typename Time::type t)
+        artis::utils::Trace < Time >& trace,
+        typename Time::type t)
 {
     std::lock_guard < std::mutex > lock(trace.mutex());
 

+ 7 - 0
src/artis/utils/trace.cpp

@@ -0,0 +1,7 @@
+#include "Trace.hpp"
+
+std::map < std::string, int > artis::utils::KernelInfo::elt_dictionary;
+std::vector < std::string > artis::utils::KernelInfo::elt_names;
+
+
+

+ 49 - 14
src/test/models.hpp

@@ -38,6 +38,8 @@ struct ModelParameters
 
 using Model = artis::kernel::AbstractModel < artis::utils::DoubleTime,
                                              ModelParameters >;
+using Models = artis::kernel::AbstractModels < artis::utils::DoubleTime,
+        ModelParameters >;
 
 using Trace = artis::utils::Trace < artis::utils::DoubleTime >;
 using TraceElement = artis::utils::TraceElement < artis::utils::DoubleTime >;
@@ -57,7 +59,7 @@ public:
 
     enum internals { DX, BX, IX };
 
-    AModel()
+    AModel(Models = Models())
     {
         Internal(IX, &AModel::_ix);
         Internal(BX, &AModel::_bx);
@@ -69,11 +71,16 @@ public:
 
     void compute(double t, bool /* update */)
     {
+        ::Trace::trace() << ::TraceElement("A", t, artis::utils::COMPUTE)
+                         << "Start";
+        ::Trace::trace().flush();
+
         ++_ix;
         _bx = not _bx;
         ++_dx;
 
-        ::Trace::trace() << ::TraceElement("A", t, artis::utils::COMPUTE);
+        ::Trace::trace() << ::TraceElement("A", t, artis::utils::COMPUTE)
+                         << "Stop";
         ::Trace::trace().flush();
 
     }
@@ -95,10 +102,10 @@ class BModel : public AtomicModel < BModel >
 {
 public:
     enum externals { IX, BX, DX };
-    enum internals { IY, BY, DY, IZ };
+    enum internals { IY, IZ, BY, DY };
     enum states { N };
 
-    BModel()
+    BModel(Models = Models())
     {
         // external(IX, &BModel::_ix);
         Externals(int, (( IX, &BModel::_ix )));
@@ -120,12 +127,17 @@ public:
 
     void compute(double t, bool /* update */)
     {
+        ::Trace::trace() << ::TraceElement("B", t, artis::utils::COMPUTE)
+                         << "Start";
+        ::Trace::trace().flush();
+
         _iy = _ix + 1;
         _by = not _bx;
         _dy = _dx + 1;
         ++_n;
 
-        ::Trace::trace() << ::TraceElement("B", t, artis::utils::COMPUTE);
+        ::Trace::trace() << ::TraceElement("B", t, artis::utils::COMPUTE)
+                         << "Stop";
         ::Trace::trace().flush();
 
     }
@@ -162,15 +174,32 @@ public:
     enum internals { IY, BY, DY, IZ, DX };
     enum states { N };
 
+    RootModel(Models submodels) :
+            _a(dynamic_cast < AModel* >(submodels[0])),
+            _b(dynamic_cast < BModel* >(submodels[1]))
+    {
+        // submodels
+        Submodels(((A, _a), (B, _b)));
+
+        // internals
+        Internal(DX, &RootModel::_dx);
+        InternalsS(((IY, _b, BModel::IY), (IZ, _b, BModel::IZ)));
+        InternalS(BY, _b, BModel::BY);
+
+        // states
+        States(int, ((N, &RootModel::_n)));
+        // State(N, &RootModel::_n);
+    }
+
     RootModel() : _a(new AModel), _b(new BModel)
     {
         // submodels
-        Submodels(((A, _a.get()), (B, _b.get())));
+        Submodels(((A, _a), (B, _b)));
 
         // internals
         Internal(DX, &RootModel::_dx);
-        InternalsS(((IY, _b.get(), BModel::IY), (IZ, _b.get(), BModel::IZ)));
-        InternalS(BY, _b.get(), BModel::BY);
+        InternalsS(((IY, _b, BModel::IY), (IZ, _b, BModel::IZ)));
+        InternalS(BY, _b, BModel::BY);
 
         // states
         States(int, ((N, &RootModel::_n)));
@@ -178,10 +207,17 @@ public:
     }
 
     virtual ~RootModel()
-    { }
+    {
+        delete _a;
+        delete _b;
+    }
 
     void compute(double t, bool /* update */)
     {
+        ::Trace::trace() << ::TraceElement(this->path(this), t,
+                                           artis::utils::COMPUTE)
+                         << "Start";
+        ::Trace::trace().flush();
         (*_a)(t);
         _b->put < double >(t, BModel::DX, _a->get < double >(t, AModel::DX));
         _b->put < int >(t, BModel::IX, _a->get < int >(t, AModel::IX));
@@ -190,9 +226,7 @@ public:
 
         ++_n;
 
-        ::Trace::trace() << ::TraceElement("ROOT", t, artis::utils::COMPUTE);
-        ::Trace::trace().flush();
-
+        this->trace_element(t, artis::utils::COMPUTE, "Stop");
     }
 
     void init(double t, const ModelParameters& parameters)
@@ -200,12 +234,13 @@ public:
         _a->init(t, parameters);
         _b->init(t, parameters);
         _n = 0;
+        _dx = 0;
     }
 
 private:
     // submodels
-    std::unique_ptr < AModel > _a;
-    std::unique_ptr < BModel > _b;
+    AModel* _a;
+    BModel* _b;
 
     //internals
     double _dx;

+ 14 - 12
src/test/test-context.cpp

@@ -49,17 +49,14 @@ int main()
     AContext context(artis::utils::DateTime::toJulianDayNumber("2016-1-1"),
                      artis::utils::DateTime::toJulianDayNumber("2016-1-5"));
 
+    ::Trace::trace().clear();
+
     {
         ASimulator simulator(new RootModel, globalParameters);
 
-        ::Trace::trace().clear();
-
         simulator.init(artis::utils::DateTime::toJulianDayNumber("2016-1-1"),
                        modelParameters);
         simulator.run(context);
-
-        std::cout << ::Trace::trace().elements().to_string() << std::endl;
-
         simulator.save(context);
 
         std::ofstream os("state");
@@ -68,42 +65,47 @@ int main()
         oa << context;
     }
 
+    std::cout << ::Trace::trace().elements().filter_variable("BX").to_string(
+        artis::utils::DATE_FORMAT_YMD) << std::endl;
+
     std::cout << "==== PAUSE ====" << std::endl;
 
+    ::Trace::trace().clear();
+
     {
         AContext new_context(context);
         ASimulator simulator(new RootModel, globalParameters);
 
-        ::Trace::trace().clear();
         new_context.begin(
             artis::utils::DateTime::toJulianDayNumber("2016-1-6"));
         new_context.end(
             artis::utils::DateTime::toJulianDayNumber("2016-1-10"));
         simulator.run(new_context);
-
-        std::cout << ::Trace::trace().elements().to_string() << std::endl;
     }
 
+    std::cout << ::Trace::trace().elements().filter_type(
+        artis::utils::COMPUTE).to_string() << std::endl;
+
     std::cout << "==== PAUSE ====" << std::endl;
 
+    ::Trace::trace().clear();
+
     {
         AContext new_context;
         ASimulator simulator(new RootModel, globalParameters);
-
         std::ifstream is("state");
         boost::archive::binary_iarchive ia(is);
 
         ia >> new_context;
 
-        ::Trace::trace().clear();
         new_context.begin(
             artis::utils::DateTime::toJulianDayNumber("2016-1-6"));
         new_context.end(
             artis::utils::DateTime::toJulianDayNumber("2016-1-10"));
         simulator.run(new_context);
-
-        std::cout << ::Trace::trace().elements().to_string() << std::endl;
     }
 
+    std::cout << ::Trace::trace().elements().to_string() << std::endl;
+
     return 0;
 }

+ 11 - 6
src/test/test.cpp

@@ -35,12 +35,17 @@
 using namespace artis::kernel;
 using namespace artis::builder;
 
-using Creator = ObjectCreator < Model >;
-using Factory = ModelFactory < Model, int, Creator >;
-
-DECLARE_MODEL(AModel, ::Model, ::Factory);
-DECLARE_MODEL(BModel, ::Model, ::Factory);
-DECLARE_MODEL(RootModel, ::Model, ::Factory);
+using Creator = ObjectCreator < Model, artis::utils::DoubleTime,
+                                ModelParameters >;
+using Factory = ModelFactory < Model, int, Creator, artis::utils::DoubleTime,
+                               ModelParameters >;
+
+DECLARE_MODEL(AModel, ::Model, ::Factory, artis::utils::DoubleTime,
+              ModelParameters);
+DECLARE_MODEL(BModel, ::Model, ::Factory, artis::utils::DoubleTime,
+              ModelParameters);
+DECLARE_MODEL(RootModel, ::Model, ::Factory, artis::utils::DoubleTime,
+              ModelParameters);
 
 typedef artis::kernel::Simulator < RootModel,
                                    artis::utils::DoubleTime,