Browse Source

Remove warnings and begin builder mecanism.

Eric Ramat 7 years ago
parent
commit
5060800da9

+ 4 - 0
src/artis/kernel/AbstractAtomicModel.hpp

@@ -63,6 +63,8 @@ public:
             << " - AFTER - "
             << AbstractAtomicModel < T, U, V >::path(this);
         utils::Trace < utils::DoubleTime >::trace().flush();
+#else
+        (void) t;
 #endif
 
     }
@@ -77,6 +79,8 @@ public:
             << " - BEFORE - "
             << AbstractAtomicModel < T, U, V >::path(this);
         utils::Trace < utils::DoubleTime >::trace().flush();
+#else
+        (void) t;
 #endif
 
     }

+ 14 - 10
src/artis/kernel/AbstractCoupledModel.hpp

@@ -73,6 +73,8 @@ public:
             << " - AFTER - "
             << AbstractCoupledModel < T, U, V, W >::path(this);
         utils::Trace < utils::DoubleTime >::trace().flush();
+#else
+        (void) t;
 #endif
 
     }
@@ -99,6 +101,8 @@ public:
             << " - BEFORE - "
             << AbstractCoupledModel < T, U, V, W >::path(this);
         utils::Trace < utils::DoubleTime >::trace().flush();
+#else
+        (void) t;
 #endif
 
     }
@@ -307,6 +311,16 @@ public:
     virtual void stable()
     { Externals < T, U >::updated = false; }
 
+    void submodel(unsigned int index, type* model)
+    {
+        if (model) {
+            submodels[index] = model;
+            model->set_parent(this);
+        } else {
+            submodels[index] = 0;
+        }
+    }
+
 protected:
     void change_internal(unsigned int index, double T::* var)
     {
@@ -349,16 +363,6 @@ protected:
         }
     }
 
-    void submodel(unsigned int index, type* model)
-    {
-        if (model) {
-            submodels[index] = model;
-            model->set_parent(this);
-        } else {
-            submodels[index] = 0;
-        }
-    }
-
     void S(std::initializer_list < std::pair <  unsigned int,
            type* > > models)
     {

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

@@ -35,44 +35,45 @@
 
 namespace artis { namespace kernel {
 
-template < typename U, typename V >
-class AbstractModel : public Node < U >
+template < typename Time, typename Parameters >
+class AbstractModel : public Node < Time >
 {
-    typedef AbstractModel < U, V > type;
+    typedef AbstractModel < Time, Parameters > type;
 
 public:
-    AbstractModel(const AbstractModel < U, V >* parent = 0) :
+    AbstractModel(const AbstractModel < Time, Parameters >* parent = 0) :
         parent(parent), last_time(-1)
     { }
 
     virtual ~AbstractModel()
     { }
 
-    virtual void after(typename U::type t) = 0;
+    virtual void after(typename Time::type t) = 0;
 
-    virtual const Node < U >* atomic(unsigned int index) const = 0;
+    virtual const Node < Time >* atomic(unsigned int index) const = 0;
 
-    virtual void before(typename U::type t) = 0;
+    virtual void before(typename Time::type t) = 0;
 
-    virtual bool check(typename U::type /* t */) const
+    virtual bool check(typename Time::type /* t */) const
     { return true; }
 
-    virtual void compute(typename U::type t, bool update) = 0;
+    virtual void compute(typename Time::type t, bool update) = 0;
 
-    virtual void init(typename U::type t, const V& parameters) = 0;
+    virtual void init(typename Time::type t, const Parameters& parameters) = 0;
 
     virtual bool is_atomic() const = 0;
 
-    virtual bool is_computed(typename U::type t) const
+    virtual bool is_computed(typename Time::type t) const
     { return last_time == t; }
 
-    virtual bool is_stable(typename U::type t) const = 0;
+    virtual bool is_stable(typename Time::type t) const = 0;
 
-    virtual bool is_computed(typename U::type t, unsigned int index) const = 0;
+    virtual bool is_computed(typename Time::type t,
+                             unsigned int index) const = 0;
 
     virtual bool is_updated() const = 0;
 
-    virtual void operator()(typename U::type t)
+    virtual void operator()(typename Time::type t)
     {
         before(t);
         if (check(t) and (last_time != t or
@@ -84,7 +85,8 @@ public:
         after(t);
     }
 
-    virtual std::string path(const AbstractModel < U, V >* child) const
+    virtual std::string path(
+        const AbstractModel < Time, Parameters >* child) const
     {
         int index = -1;
         std::string p = type::parent ? type::parent->path_index(child, index) :
@@ -100,8 +102,8 @@ public:
         }
     }
 
-    virtual std::string path_index(const AbstractModel < U, V >* child,
-                                   int& index) const
+    virtual std::string path_index(
+        const AbstractModel < Time, Parameters >* child, int& index) const
     {
         (void) child;
         int i = -1;
@@ -119,18 +121,18 @@ public:
         }
     }
 
-    virtual void restore(const State < U >& state) = 0;
+    virtual void restore(const State < Time >& state) = 0;
 
-    virtual void save(State < U >& state) const = 0;
+    virtual void save(State < Time >& state) const = 0;
 
-    void set_parent(const AbstractModel < U, V >* p)
+    void set_parent(const AbstractModel < Time, Parameters >* p)
     { parent = p; }
 
     virtual void stable() = 0;
 
 protected:
-    const AbstractModel < U, V >* parent;
-    typename U::type              last_time;
+    const AbstractModel < Time, Parameters >* parent;
+    typename Time::type                       last_time;
 };
 
 } }

+ 115 - 6
src/artis/kernel/Builder.hpp

@@ -27,12 +27,13 @@
 #include <boost/property_tree/json_parser.hpp>
 
 #include <artis/kernel/AbstractCoupledModel.hpp>
+#include <artis/kernel/ModelFactory.hpp>
 
 #include <sstream>
 
 namespace artis { namespace kernel {
 
-template < typename T, typename U, typename V, typename W >
+template < typename F, typename T, typename U, typename V, typename W >
 class Builder
 {
 public:
@@ -41,19 +42,127 @@ public:
         std::stringstream ss;
 
         ss << json;
-        boost::property_tree::read_json(ss, pt);
+        boost::property_tree::read_json(ss, tree);
     }
 
     virtual ~Builder()
     { }
 
-    artis::kernel::AbstractCoupledModel < T, U, V, W >* build()
+    T* build()
+    { return dynamic_cast < T* >(build_model(tree)); }
+
+private:
+    AbstractModel < U, V >* build_model(boost::property_tree::ptree const& pt)
     {
-        return 0;
+        using boost::property_tree::ptree;
+
+        AbstractModel < U, V >* model = nullptr;
+        std::string name;
+        ptree::const_iterator it_type = pt.end();
+        ptree::const_iterator it_name = pt.end();
+        ptree::const_iterator it_states = pt.end();
+        ptree::const_iterator it_internals = pt.end();
+        ptree::const_iterator it_externals = pt.end();
+        ptree::const_iterator it_submodels = pt.end();
+
+        for (ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) {
+            if (it->first == "type") {
+                it_type = it;
+            } else if (it->first == "name") {
+                it_name = it;
+            } else if (it->first == "states") {
+                it_states = it;
+            } else if (it->first == "internals") {
+                it_internals = it;
+            } else if (it->first == "externals") {
+                it_externals = it;
+            } else if (it->first == "submodels") {
+                it_submodels = it;
+            }
+        }
+
+        // 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 >();
+        }
+        // submodels
+        if (it_submodels != pt.end()) {
+            for (ptree::const_iterator itm = it_submodels->second.begin();
+                 itm != it_submodels->second.end(); ++itm) {
+                build_model(itm->second);
+            }
+        }
+        // states
+        if (it_states != pt.end()) {
+            build_states(it_states->second, model);
+        }
+        // internals
+        if (it_internals != pt.end()) {
+            build_internals(it_internals->second, model);
+        }
+        // externals
+        if (it_externals != pt.end()) {
+            build_externals(it_externals->second, model);
+        }
+        return model;
     }
 
-private:
-    boost::property_tree::ptree pt;
+    void build_internals(boost::property_tree::ptree const& pt,
+                         AbstractModel < U, V >* model)
+    {
+        using boost::property_tree::ptree;
+
+        for (ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) {
+            build_variable(it->second, model);
+        }
+    }
+
+    void build_externals(boost::property_tree::ptree const& pt,
+                         AbstractModel < U, V >* model)
+    {
+        using boost::property_tree::ptree;
+
+        for (ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) {
+            build_variable(it->second, model);
+        }
+    }
+
+    void build_states(boost::property_tree::ptree const& pt,
+                      AbstractModel < U, V >* model)
+    {
+        using boost::property_tree::ptree;
+
+        for (ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) {
+            build_variable(it->second, model);
+        }
+    }
+
+    void build_variable(boost::property_tree::ptree const& pt,
+                        AbstractModel < U, V >* /* model */)
+    {
+        using boost::property_tree::ptree;
+
+        std::string name;
+        std::string type;
+
+        for (ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) {
+            if (it->first == "name") {
+                name = it->second.get_value < std::string >();
+            } else if (it->first == "type") {
+                type = it->second.get_value < std::string >();
+            }
+        }
+
+        std::cout << name << ": " << type << std::endl;
+
+    }
+
+    boost::property_tree::ptree tree;
 };
 
 } }

+ 145 - 0
src/artis/kernel/ModelFactory.hpp

@@ -0,0 +1,145 @@
+/**
+ * @file artis/kernel/ModelFactory.hpp
+ * @author See the AUTHORS file
+ */
+
+/*
+ * Copyright (C) 2012-2016 ULCO http://www.univ-littoral.fr
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARTIS_KERNEL_MODEL_FACTORY_HPP
+#define __ARTIS_KERNEL_MODEL_FACTORY_HPP
+
+#include <algorithm>
+#include <memory>
+#include <mutex>
+#include <typeinfo>
+
+#include <boost/core/demangle.hpp>
+
+namespace artis { namespace kernel {
+
+template < typename M >
+class ObjectCreator
+{
+public:
+    ObjectCreator()
+    { }
+    virtual ~ObjectCreator()
+    { }
+
+    virtual std::string get() const = 0;
+
+    virtual M* operator()() const = 0;
+};
+
+template < typename M, typename I, typename O >
+class ModelFactory
+{
+    typedef ModelFactory < M, I, O > type;
+
+public:
+    virtual ~ModelFactory()
+    { }
+
+    bool add(const I& id, O* creator)
+    {
+        std::lock_guard < std::mutex > lock(_mutex);
+        return creators.insert(typename Creators::value_type(
+                                   creator->get(),
+                                   std::make_pair(id, creator))).second;
+    }
+
+    M* create(const std::string& id)
+    {
+        std::lock_guard < std::mutex > lock(_mutex);
+        typename Creators::const_iterator it = creators.find(id);
+
+        if (it != creators.end()) {
+            return (*it->second.second)();
+        } else {
+            return nullptr;
+        }
+    }
+
+    static ModelFactory& factory()
+    {
+        std::call_once(_flag, [] ()
+                       { _instance.reset(new ModelFactory()); });
+        return *_instance;
+    }
+
+    int make_id()
+    {
+        std::lock_guard < std::mutex > lock(_mutex);
+        return ++id;
+    }
+
+    bool remove(const I& id)
+    {
+/*        std::lock_guard < std::mutex > lock(_mutex);
+        typename Creators::const_iterator it = creators.find(id);
+
+        if (it != creators.end()) {
+            creators.erase(it);
+            return true;
+        } else {
+            return false;
+            } */
+        return false;
+    }
+
+private:
+    ModelFactory()
+    { id = -1; }
+
+    typedef std::pair < I, O* > Creator;
+    typedef std::map < std::string, Creator > Creators;
+
+    static std::shared_ptr < type > _instance;
+    static std::once_flag           _flag;
+    std::mutex                      _mutex;
+
+    Creators creators;
+    int      id;
+};
+
+} }
+
+template < typename M, typename I, typename O >
+std::shared_ptr < artis::kernel::ModelFactory < M, I, O > >
+artis::kernel::ModelFactory < M, I, O >::_instance;
+
+template < typename M, typename I, typename O >
+std::once_flag artis::kernel::ModelFactory < M, I, O >::_flag;
+
+#define DECLARE_MODEL(mdl, type, fct)                                   \
+    class creator_##mdl : public artis::kernel::ObjectCreator < type > { \
+    public:                                                             \
+    creator_##mdl()                                                     \
+        {                                                               \
+            bool r = fct::factory().add(fct::factory().make_id(),       \
+                                        this);                          \
+        }                                                               \
+    std::string get() const                                             \
+        { return boost::core::demangle(typeid(mdl).name()); }           \
+    type* operator()() const                                            \
+        { return new mdl(); }                                           \
+    static creator_##mdl an_##mdl;                                      \
+    };                                                                  \
+    creator_##mdl an_##mdl;
+
+#endif

+ 248 - 0
src/artis/utils/Singleton.hpp

@@ -0,0 +1,248 @@
+/**
+ * @file utils/Trace.hpp
+ * @author See the AUTHORS file
+ */
+
+/*
+ * Copyright (C) 2012-2016 ULCO http://www.univ-littoral.fr
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_TRACE
+#define UTILS_TRACE
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <mutex>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <artis/utils/DateTime.hpp>
+
+namespace artis { namespace utils {
+
+enum TraceType { NONE = 0, CHECK, COMPUTE, INIT, KERNEL, PUT };
+
+template < class Time >
+class TraceElement
+{
+public:
+    TraceElement() : _time(Time::null), _type(NONE)
+    { }
+
+    TraceElement(const std::string& model_name, typename Time::type time,
+                 TraceType type) :
+        _model_name(model_name), _time(time), _type(type)
+    { }
+
+    virtual ~TraceElement()
+    { }
+
+    const std::string& get_comment() const
+    { return _comment; }
+
+    const std::string& get_model_name() const
+    { return _model_name; }
+
+    typename Time::type get_time() const
+    { return _time; }
+
+    TraceType get_type() const
+    { return _type; }
+
+    void set_comment(const std::string& comment)
+    { _comment = comment; }
+
+private:
+    std::string         _model_name;
+    typename Time::type _time;
+    TraceType           _type;
+    std::string         _comment;
+};
+
+template < class Time >
+class TraceElements : public std::vector < TraceElement < Time > >
+{
+public:
+    TraceElements()
+    { }
+    virtual ~TraceElements()
+    { }
+
+    TraceElements filter_model_name(
+        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; });
+        return result;
+    }
+
+    TraceElements filter_time(typename Time::type time) const
+    {
+        TraceElements result;
+
+        std::copy_if(TraceElements < Time >::begin(),
+                     TraceElements < Time >::end(), std::back_inserter(result),
+                     [time](TraceElement < Time > const & x)
+                     { return x.get_time() == time; });
+        return result;
+    }
+
+    TraceElements filter_type(TraceType type) const
+    {
+        TraceElements result;
+
+        std::copy_if(TraceElements < Time >::begin(),
+                     TraceElements < Time >::end(), std::back_inserter(result),
+                     [type](TraceElement < Time > const & x)
+                     { return x.get_type() == type; });
+        return result;
+    }
+
+    std::string to_string() const
+    {
+        std::ostringstream ss;
+
+        for (typename TraceElements < Time >::const_iterator it =
+                 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;
+        }
+        return ss.str();
+    }
+};
+
+template < class Time >
+class Trace
+{
+public:
+    virtual ~Trace()
+    { }
+
+    static Trace& trace()
+    {
+        std::call_once(_flag, [] ()
+                       { _instance.reset(new Trace()); }
+            );
+        return *_instance;
+    }
+
+    void clear()
+    { _trace.clear(); }
+
+    const TraceElements < Time >& elements() const
+    { return _trace; }
+
+    void flush()
+    {
+        if (_sstream) {
+            _element.set_comment(_sstream->str());
+            delete _sstream;
+            _sstream = 0;
+        }
+        _trace.push_back(_element);
+    }
+
+    std::mutex& mutex()
+    { return _mutex; }
+
+    void set_element(const TraceElement < Time >& element)
+    { _element = element; }
+
+    std::ostringstream& sstream()
+    {
+        if (_sstream == 0) {
+            _sstream = new std::ostringstream();
+        }
+        return *_sstream;
+    }
+
+private:
+    Trace()
+    { _sstream = 0; }
+
+    static std::shared_ptr < Trace < Time > > _instance;
+    static std::once_flag                     _flag;
+
+    TraceElements < Time > _trace;
+    TraceElement < Time >  _element;
+    std::ostringstream*    _sstream;
+    std::mutex             _mutex;
+};
+
+} }
+
+template < class Time >
+artis::utils::Trace < Time >& operator<<(
+    artis::utils::Trace < Time >& trace,
+    const artis::utils::TraceElement < Time >& e)
+{
+    std::lock_guard < std::mutex > lock(trace.mutex());
+
+    trace.set_element(e);
+    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());
+
+    trace.sstream() << str;
+    return trace;
+}
+
+template < class Time >
+artis::utils::Trace < Time >& operator<<(
+    artis::utils::Trace < Time >& trace,
+    typename Time::type t)
+{
+    std::lock_guard < std::mutex > lock(trace.mutex());
+
+    trace.sstream() << t;
+    return trace;
+}
+
+template < class Time >
+std::shared_ptr < artis::utils::Trace < Time > >
+artis::utils::Trace < Time >::_instance;
+
+template < class Time >
+std::once_flag artis::utils::Trace < Time >::_flag;
+
+#endif

+ 1 - 1
src/artis/utils/Trace.hpp

@@ -240,7 +240,7 @@ artis::utils::Trace < Time >& operator<<(
 
 template < class Time >
 std::shared_ptr < artis::utils::Trace < Time > >
-artis::utils::Trace < Time >::_instance = nullptr;
+artis::utils::Trace < Time >::_instance;
 
 template < class Time >
 std::once_flag artis::utils::Trace < Time >::_flag;

+ 226 - 42
src/test/test.cpp

@@ -20,18 +20,21 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#define CATCH_CONFIG_MAIN
-#include <test/catch.hpp>
+//#define CATCH_CONFIG_MAIN
+//#include <test/catch.hpp>
 
 #include <artis/kernel/AbstractAtomicModel.hpp>
 #include <artis/kernel/AbstractCoupledModel.hpp>
-#include <artis/kernel/Builder.hpp>
+//#include <artis/kernel/Builder.hpp>
+#include <artis/kernel/ModelFactory.hpp>
 #include <artis/kernel/Simulator.hpp>
 #include <artis/observer/Output.hpp>
 
 #include <artis/utils/DateTime.hpp>
 #include <artis/utils/Trace.hpp>
 
+#include <memory>
+
 struct GlobalParameters
 { };
 
@@ -42,9 +45,19 @@ using namespace artis::kernel;
 using namespace artis::utils;
 
 using Model = AbstractModel < DoubleTime, ModelParameters >;
+using Creator = ObjectCreator < Model >;
+using Factory = ModelFactory < Model, int, Creator >;
+
+using Trace = Trace < DoubleTime >;
+using TraceElement = TraceElement < DoubleTime >;
+
 template < typename T >
 using AtomicModel = AbstractAtomicModel < T, DoubleTime, ModelParameters >;
 
+template < typename T >
+using CoupledModel = AbstractCoupledModel < T, DoubleTime, ModelParameters,
+                                            GlobalParameters >;
+
 class AModel : public AtomicModel < AModel >
 {
 public:
@@ -62,11 +75,15 @@ public:
     virtual ~AModel()
     { }
 
-    void compute(double /* t */, bool /* update */)
+    void compute(double t, bool /* update */)
     {
         ++_ix;
         _bx = not _bx;
         ++_dx;
+
+        ::Trace::trace() << ::TraceElement("A", t, COMPUTE);
+        ::Trace::trace().flush();
+
     }
 
     void init(double /* t */, const ModelParameters& /* parameters */)
@@ -82,6 +99,8 @@ private:
     double _dx;
 };
 
+DECLARE_MODEL(AModel, ::Model, ::Factory);
+
 class BModel : public AtomicModel < BModel >
 {
 public:
@@ -109,7 +128,7 @@ public:
     virtual ~BModel()
     { }
 
-    void compute(double /* t */, bool update)
+    void compute(double t, bool update)
     {
         if (update)
             std::cout << "UPDATE" << std::endl;
@@ -118,6 +137,10 @@ public:
         _by = not _bx;
         _dy = _dx + 1;
         ++_n;
+
+        ::Trace::trace() << ::TraceElement("B", t, COMPUTE);
+        ::Trace::trace().flush();
+
     }
 
     void init(double /* t */, const ModelParameters& /* parameters */)
@@ -143,20 +166,18 @@ private:
     int _n;
 };
 
-class RootModel :
-    public artis::kernel::AbstractCoupledModel < RootModel,
-                                                 artis::utils::DoubleTime,
-                                                 ModelParameters,
-                                                 GlobalParameters >
+DECLARE_MODEL(BModel, ::Model, ::Factory);
+
+class RootModel : public CoupledModel < RootModel >
 {
 public:
     enum submodels { A, B };
     enum states { N };
 
-    RootModel()
+    RootModel() : _a(new AModel), _b(new BModel)
     {
         // submodels
-        S({ { A, &_a }, { B, &_b } });
+        S({ { A, _a.get() }, { B, _b.get() } });
 
         // states
         S < int >({ { N, &RootModel::_n } });
@@ -167,41 +188,47 @@ public:
 
     void compute(double t, bool /* update */)
     {
-        _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));
-        _b.put < bool >(t, BModel::BX, _a.get < bool >(t, AModel::BX));
-        _b(t);
+        (*_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));
+        _b->put < bool >(t, BModel::BX, _a->get < bool >(t, AModel::BX));
+        (*_b)(t);
 
         ++_n;
+
+        ::Trace::trace() << ::TraceElement("ROOT", t, COMPUTE);
+        ::Trace::trace().flush();
+
     }
 
     void init(double t, const ModelParameters& parameters)
     {
-        _a.init(t, parameters);
-        _b.init(t, parameters);
+        _a->init(t, parameters);
+        _b->init(t, parameters);
         _n = 0;
     }
 
 private:
     // submodels
-    AModel _a;
-    BModel _b;
+    std::unique_ptr < AModel > _a;
+    std::unique_ptr < BModel > _b;
 
     // states
     int _n;
 };
 
+DECLARE_MODEL(RootModel, ::Model, ::Factory);
+
 typedef artis::kernel::Simulator < RootModel,
                                    artis::utils::DoubleTime,
                                    ModelParameters,
                                    GlobalParameters > ASimulator;
 
-typedef artis::kernel::Builder < RootModel,
-                                 artis::utils::DoubleTime,
-                                 ModelParameters,
-                                 GlobalParameters > ABuilder;
+// typedef artis::kernel::Builder < ::Factory,
+//                                  RootModel,
+//                                  artis::utils::DoubleTime,
+//                                  ModelParameters,
+//                                  GlobalParameters > ABuilder;
 
 class AView : public artis::observer::View < artis::utils::DoubleTime,
                                              ModelParameters >
@@ -224,26 +251,183 @@ public:
 typedef artis::observer::Output < artis::utils::DoubleTime,
                                   ModelParameters > AnOutput;
 
-TEST_CASE("Simulator_tests", "simple")
+struct NullModel : CoupledModel < NullModel >
+{ };
+
+template < typename T >
+struct TType
 {
-    GlobalParameters globalParameters;
-    ModelParameters modelParameters;
-    ABuilder builder("{ \"type\": \"RootModel\", "                      \
-                     "\"submodels\": [ "                                \
-                     "{ \"type\": \"AModel\", \"internals\": [] }, "    \
-                     "{ \"type\": \"BModel\", \"internals\": [] } "     \
-                     "] }");
-    ASimulator simulator(new RootModel, globalParameters);
+    typedef T type;
 
-    simulator.attachView("Root", new AView);
+    T* operator()()
+    { return new T(); }
+};
 
-    artis::utils::Trace < artis::utils::DoubleTime >::trace().clear();
+template < typename P, typename T, typename N /*, typename ST */ > // I, In, Ex, S >
+struct TCoupledModel
+{
+    typename T::type* operator()(P* parent)
+    {
+        //T::type* m = T()();
+        N n;
+        // ST st;
 
-    simulator.init(0, modelParameters);
-    simulator.run(artis::utils::DateTime::toJulianDayNumber(2016, 1, 1),
-                  artis::utils::DateTime::toJulianDayNumber(2016, 1, 10));
+        n(parent);
+        //st(m);
+        return T()();
+    }
+};
+
+// template < T, N, I, ST, In, Ex >
+// class AtomicModel
+// {
+// };
+
+template < typename P >
+struct TNull
+{
+    P* operator()()
+    { return nullptr; }
+};
+
+template < typename T, typename X >
+struct TVariable
+{
+    X T::* variable;
+};
+
+template < typename P, typename N = TNull < P > >
+struct TName
+{
+    void operator()(P* parent)
+    {
+        if (parent) {
+            N n;
+
+            parent->submodel(0, n());
+        }
+    }
+};
+
+// template < typename M, typename N, typename I, typename T >
+// struct TState
+// {
+//     void operator()(M* m)
+//     {
+//         N n;
+
+//     }
+// };
+
+template < typename T, typename M >
+struct TBuilder
+{
+    T* operator()()
+    {
+        M m;
 
-    AnOutput output(simulator.observer());
+        return m(nullptr);
+    }
+};
 
-    output();
+// constexpr int AModel::* p = AModel::_ix;
+
+// typedef TBuilder <
+//     RootModel,
+//     TCoupledModel <
+//         NullModel,
+//         TType < RootModel >,
+//         TName < NullModel >/*,
+//         TState <
+//             RootModel,
+//             TName < AModel::_ix >,
+//             TID < AModel::IX >,
+//             TType < int >
+//             > */
+//         >
+//     > ABuilder;
+
+// typedef Builder <
+//     CoupledModel <
+//         Type < RootModel >,
+//         Name < >,
+//         ID < >,
+//         States < >,
+//         Internals < >,
+//         Externals < >,
+//         Submodels <
+//             AtomicModel <
+//                 Type < AModel >,
+//                 Name < RootModel::_a >,
+//                 ID < A >,
+//                 States < >,
+//                 Internals <
+//                     Variable < Name < AModel::_ix >, ID < IX >, Type < int > >,
+//                     Variable < Name < AModel::_bx >, ID < BX >, Type < bool > >,
+//                     Variable < Name < AModel::_dx >, ID < DX >, Type < double > >
+//                     >,
+//                 Externals < >,
+//                 >,
+//             AtomicModel <
+//                 Type < BModel >,
+//                 Name < RootModel::_b >,
+//                 ID < B >,
+//                 States < >,
+//                 Internals < >,
+//                 Externals < >,
+//                 >
+//             >
+//         >
+//     > ABuilder;
+
+//TEST_CASE("Simulator_tests", "simple")
+int main()
+{
+    GlobalParameters globalParameters;
+    ModelParameters modelParameters;
+    // ABuilder builder;
+
+    // ABuilder builder("{ \"type\": \"RootModel\", "                   \
+    //                  "\"name\": \"root\", "                          \
+    //                  "\"states\": [ "                                \
+    //                  "{ \"name\":\"_i\", \"type\":\"int\"} "         \
+    //                  "],"                                            \
+    //                  "\"submodels\": [ "                             \
+    //                  "{ \"type\": \"AModel\", "                      \
+    //                  "\"name\": \"_a\", "                            \
+    //                  "\"internals\": ["                              \
+    //                  "{ \"name\":\"_ix\", \"type\":\"int\"}, "       \
+    //                  "{ \"name\":\"_bx\", \"type\":\"bool\"}, "      \
+    //                  "{ \"name\":\"_dx\", \"type\":\"double\"} "     \
+    //                  "] }, "                                         \
+    //                  "{ \"type\": \"BModel\", "                      \
+    //                  "\"name\": \"_b\", "                            \
+    //                  "\"internals\": ["                              \
+    //                  "{ \"name\":\"_iy\", \"type\":\"int\"}, "       \
+    //                  "{ \"name\":\"_by\", \"type\":\"bool\"}, "      \
+    //                  "{ \"name\":\"_dy\", \"type\":\"double\"} "     \
+    //                  "], "                                           \
+    //                  "\"externals\": ["                              \
+    //                  "{ \"name\":\"_ix\", \"type\":\"int\"}, "       \
+    //                  "{ \"name\":\"_bx\", \"type\":\"bool\"}, "      \
+    //                  "{ \"name\":\"_dx\", \"type\":\"double\"} "     \
+    //                  "], "                                           \
+    //                  "\"states\": [ "                                \
+    //                  "{ \"name\":\"_n\", \"type\":\"int\"} "         \
+    //                  "] }"                                           \
+    //                  "] }");
+    // ASimulator simulator(builder(), globalParameters);
+
+    // simulator.attachView("Root", new AView);
+
+    // ::Trace::trace().clear();
+
+    // simulator.init(0, modelParameters);
+    // simulator.run(artis::utils::DateTime::toJulianDayNumber(2016, 1, 1),
+    //               artis::utils::DateTime::toJulianDayNumber(2016, 1, 10));
+
+    // AnOutput output(simulator.observer());
+
+    // output();
+    return 0;
 }