/**
* @file artis/kernel/AbstractCoupledModel.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 .
*/
#ifndef __ARTIS_KERNEL_ABSTRACT_COUPLED_MODEL_HPP
#define __ARTIS_KERNEL_ABSTRACT_COUPLED_MODEL_HPP
#include
#include
#include
#include
#include
namespace artis { namespace kernel {
template < typename T, typename U, typename V, typename W >
class AbstractCoupledModel : public AbstractModel < U, V >,
public States < T, U >,
public Internals < T, U >,
public Externals < T, U >
{
typedef AbstractModel < U, V > type;
typedef std::map < int, type* > Submodels;
typedef std::map < int,
std::vector < type* > > Setsubmodels;
typedef std::map < int, std::pair < type*,
int > > SubModelInternals;
struct Var
{
unsigned int index;
type* model;
int sub_index;
};
public:
AbstractCoupledModel()
{ }
virtual ~AbstractCoupledModel()
{ }
virtual void build(const W& /* parameters */)
{ }
virtual void build(const W& /* parameters */,
const std::string& /* json */)
{ }
virtual bool check(typename U::type t) const
{ return Externals < T, U >::check(t); }
virtual void compute(typename U::type t, bool update) = 0;
virtual double get(typename U::type t, unsigned int index) const
{
typename AbstractCoupledModel::SubModelInternals::const_iterator it =
submodel_internals.find(index);
if (it == submodel_internals.end()) {
return static_cast < const T* >(this)->*(
Internals < T, U >::get(index));
} else {
return it->second.first->get(t, it->second.second);
}
}
virtual int getI(typename U::type t, unsigned int index) const
{
typename AbstractCoupledModel::SubModelInternals::const_iterator it =
submodel_internals.find(index);
if (it == submodel_internals.end()) {
return static_cast < const T* >(this)->*(
Internals < T, U >::getI(index));
} else {
return it->second.first->getI(t, it->second.second);
}
}
virtual bool getB(typename U::type t, unsigned int index) const
{
typename AbstractCoupledModel::SubModelInternals::const_iterator it =
submodel_internals.find(index);
if (it == submodel_internals.end()) {
return static_cast < const T* >(this)->*(
Internals < T, U >::getB(index));
} else {
return it->second.first->getB(t, it->second.second);
}
}
virtual void init(typename U::type t, const V& parameters) = 0;
bool is_computed(typename U::type t, unsigned int index) const
{
typename AbstractCoupledModel::SubModelInternals::const_iterator it =
submodel_internals.find(index);
if (it == submodel_internals.end()) {
return false;
} else {
return it->second.first->is_computed(t, it->second.second);
}
}
bool is_stable(typename U::type t) const
{
typename AbstractCoupledModel::SubModelInternals::const_iterator it =
submodel_internals.begin();
bool stable = true;
while (it != submodel_internals.end() and stable) {
stable = it->second.first->is_stable(t);
++it;
}
return stable;
}
virtual bool is_updated() const
{ return Externals < T, U >::updated; }
virtual const Node < U >* get_submodel(unsigned int index) const
{
typename AbstractCoupledModel::Submodels::const_iterator it =
submodels.find(index);
if (it != submodels.end()) {
return it->second;
} else {
return 0;
}
}
virtual const Node < U >* get_submodel(unsigned int index,
unsigned int rank) const
{
typename AbstractCoupledModel::Setsubmodels::const_iterator it =
setsubmodels.find(index);
if (it != setsubmodels.end() and it->second.size() > rank) {
return it->second.at(rank);
} else {
return 0;
}
}
virtual void restore(const State < U >& state)
{
typename AbstractCoupledModel::Submodels::const_iterator it =
submodels.begin();
while (it != submodels.end()) {
it->second->restore(state.get_substate(it->first));
++it;
}
States < T, U >::restore(state);
Internals < T, U >::restore(state);
}
virtual void save(State < U >& state) const
{
typename AbstractCoupledModel::Submodels::const_iterator it =
submodels.begin();
while (it != submodels.end()) {
State < U > substate;
it->second->save(substate);
state.add_substate(it->first, substate);
++it;
}
States < T, U >::save(state);
Internals < T, U >::save(state);
}
virtual void stable()
{ Externals < T, U >::updated = false; }
protected:
void change_internal(unsigned int index, double T::* var)
{
submodel_internals.erase(index);
Internals < T, U >::internal(index, var);
}
void change_internal(unsigned int index, int T::* var)
{
submodel_internals.erase(index);
Internals < T, U >::internalI(index, var);
}
void change_internal(unsigned int index, bool T::* var)
{
submodel_internals.erase(index);
Internals < T, U >::internalB(index, var);
}
void internal(unsigned int index, double T::* var)
{ Internals < T, U >::internal(index, var); }
void I(std::initializer_list < std::pair < unsigned int,
bool T::* > > internals)
{ Internals < T, U >::I(internals); }
void I(std::initializer_list < std::pair < unsigned int,
int T::* > > internals)
{ Internals < T, U >::I(internals); }
void I(std::initializer_list < std::pair < unsigned int,
double T::* > > internals)
{ Internals < T, U >::I(internals); }
void internal(unsigned int index, type* model, int sub_index)
{
submodel_internals[index] =
std::pair < type*, int >(model, sub_index);
}
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);
}
}
void submodel(unsigned int index, type* model)
{ submodels[index] = model; }
void S(std::initializer_list < std::pair < unsigned int,
type* > > models)
{
for (typename std::initializer_list < std::pair < unsigned int,
type* > >::iterator it =
models.begin(); it != models.end(); ++it) {
submodels[it->first] = it->second;
}
}
void setsubmodel(unsigned int index, type* model)
{
if (setsubmodels.find(index) == setsubmodels.end()) {
setsubmodels[index] = std::vector < type* >();
}
setsubmodels[index].push_back(model);
}
private:
SubModelInternals submodel_internals;
Submodels submodels;
Setsubmodels setsubmodels;
};
template < typename T, typename U, typename V, typename W >
struct IN_t
{
IN_t(AbstractCoupledModel < T, U, V, W >* model,
unsigned int index) : model(model), index(index)
{ }
AbstractCoupledModel < T, U, V, W >* model;
unsigned int index;
};
template < typename T, typename U, typename V, typename W >
struct OUT_SC_t
{
OUT_SC_t(double t, AbstractCoupledModel < T, U, V, W >* model,
unsigned int index) : t(t), model(model), index(index)
{ }
double t;
AbstractCoupledModel < T, U, V, W >* model;
unsigned int index;
};
template < typename T >
struct OUT_A_t
{
OUT_A_t(double t, T value) : t(t), value(value)
{ }
double t;
T value;
};
template < typename T, typename U, typename V, typename W >
IN_t < T, U, V, W > IN(AbstractCoupledModel < T, U, V, W >* model,
unsigned int index)
{ return IN_t < T, U, V, W >(model, index); }
template < typename T, typename U, typename V, typename W >
OUT_SC_t < T, U, V, W > OUT(double t,
AbstractCoupledModel < T, U, V, W >* model,
unsigned int index)
{ return OUT_SC_t < T, U, V, W >(t, model, index); }
template < typename T >
OUT_A_t < T > OUT(double t, T value)
{ return OUT_A_t < T >(t, value); }
template < typename T1, typename U1, typename V1, typename W1,
typename T2, typename U2, typename V2, typename W2 >
void operator>>(OUT_SC_t < T2, U2, V2, W2 > out, IN_t < T1, U1, V1, W1 > in)
{
if (out.model->is_computed(out.t, out.index)) {
in.model->put(out.t, in.index, out.model->get(out.t, out.index));
}
}
template < typename T, typename U, typename V, typename W, typename Z >
void operator>>(OUT_A_t < Z > out, IN_t < T, U, V, W > in)
{ in.model->put(out.t, in.index, out.value); }
} }
#endif