/** * @file artis/kernel/AbstractModel.hpp * @author See the AUTHORS file */ /* * Copyright (C) 2012-2017 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 . */ #ifndef __ARTIS_KERNEL_ABSTRACT_ATOMIC_MODEL_HPP #define __ARTIS_KERNEL_ABSTRACT_ATOMIC_MODEL_HPP #include #include #include #include #include #include #include namespace artis { namespace kernel { template < typename T, typename U, typename V > class AbstractAtomicModel : public AbstractModel < U, V >, public States < T, U, V >, public Internals < T, U, V >, public Externals < T, U, V > { typedef AbstractModel < U, V > type; public: AbstractAtomicModel(const type* parent = 0) : type(parent) { #ifdef WITH_TRACE utils::Trace < utils::DoubleTime >::trace() << utils::TraceElement < utils::DoubleTime >( boost::core::demangle(typeid(T).name()).erase(0,6), utils::DoubleTime::null, utils::CONSTRUCT); utils::Trace < utils::DoubleTime >::trace().flush(); #endif } virtual ~AbstractAtomicModel() { #ifdef WITH_TRACE trace_element(utils::DoubleTime::null, utils::CONSTRUCT); #endif } virtual const Node < U >* atomic(unsigned int /* index */) const { return this; } virtual void after(typename U::type t) { #ifdef WITH_TRACE trace_element(t, utils::AFTER_COMPUTE); trace_internals(t, utils::AFTER_COMPUTE); #else (void) t; #endif } virtual void before(typename U::type t) { #ifdef WITH_TRACE trace_element(t, utils::BEFORE_COMPUTE); trace_internals(t, utils::BEFORE_COMPUTE); trace_externals(t, utils::BEFORE_COMPUTE); #else (void) t; #endif } virtual bool check(typename U::type t) const { return Externals < T, U, V >::check(t); } virtual void compute(typename U::type t, bool update) = 0; virtual const Any& get(typename U::type t, unsigned int index) const { if (type::last_time != t) { throw utils::InvalidGet("Variable not computed"); } return Internals < T, U, V >::get(index); } template < typename W > W get(typename U::type t, unsigned int index) const { 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 >()); } virtual std::string get(const ValueType& value_type, typename U::type t, unsigned int index) const { if (type::last_time != t) { throw utils::InvalidGet("Variable not computed"); } Any value = Internals < T, U, V >::get(index); switch (value_type) { case DOUBLE: { std::ostringstream ss; ss << std::setprecision(10) << static_cast < const T* >(this)->*( value.get < T, double >()); return ss.str(); } case INT: return std::to_string( static_cast < const T* >(this)->*(value.get < T, int >())); case BOOL: return std::to_string( static_cast < const T* >(this)->*(value.get < T, bool >())); default: return "NA"; } } virtual void init(typename U::type t, const V& parameters) = 0; virtual bool is_atomic() const { return true; } bool is_computed(typename U::type t, unsigned int /* index */) const { return type::last_time == t; } bool is_stable(typename U::type t) const { return type::last_time == t; } virtual bool is_updated() const { return Externals < T, U, V >::updated; } virtual void restore(const context::State < U >& state) { Externals < T, U, V >::restore(this, state); Internals < T, U, V >::restore(this, state); States < T, U, V >::restore(this, state); type::last_time = state.last_time(); } virtual void save(context::State < U >& state) const { Externals < T, U, V >::save(this, state); Internals < T, U, V >::save(this, state); States < T, U, V >::save(this, state); state.last_time(type::last_time); } virtual void trace_element(typename U::type t, utils::TraceType type = utils::KERNEL, std::string comment = "") const { utils::Trace < utils::DoubleTime >::trace() << utils::TraceElement < utils::DoubleTime >( AbstractAtomicModel < T, U, V >::path(this), t, type) << comment;; utils::Trace < utils::DoubleTime >::trace().flush(); } virtual void trace_internals(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 >( 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(); } } } virtual void trace_externals(typename U::type t, utils::TraceType type = utils::KERNEL) 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 >( 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(); } } } virtual void trace_model(typename U::type t, utils::TraceType type = utils::KERNEL) const { trace_element(t, type); trace_internals(t, type); trace_externals(t, type); } virtual void stable() { Externals < T, U, V >::updated = false; } }; } } #endif