Replate DynamicModel::toStatic() by a converting constructor in StaticModel

It is therefore now possible to write:

  static_model = static_cast<StaticModel>(dynamic_model);
issue#70
Sébastien Villemot 2018-10-10 17:08:54 +02:00
parent 0e7d831e6f
commit bcdfb43fd3
5 changed files with 69 additions and 57 deletions

View File

@ -5119,55 +5119,6 @@ DynamicModel::toNonlinearPart(DynamicModel &non_linear_equations_dynamic_model)
non_linear_equations_dynamic_model.AddLocalVariable(it->first, it->second);
}
void
DynamicModel::toStatic(StaticModel &static_model) const
{
/* Ensure that we are using the same symbol table, because at many places we manipulate
symbol IDs rather than strings */
assert(&symbol_table == &static_model.symbol_table);
// Convert model local variables (need to be done first)
for (int it : local_variables_vector)
static_model.AddLocalVariable(it, local_variables_table.find(it)->second->toStatic(static_model));
// Convert equations
int static_only_index = 0;
for (int i = 0; i < (int) equations.size(); i++)
{
// Detect if equation is marked [dynamic]
bool is_dynamic_only = false;
vector<pair<string, string>> eq_tags;
for (const auto & equation_tag : equation_tags)
if (equation_tag.first == i)
{
eq_tags.push_back(equation_tag.second);
if (equation_tag.second.first == "dynamic")
is_dynamic_only = true;
}
try
{
// If yes, replace it by an equation marked [static]
if (is_dynamic_only)
{
static_model.addEquation(static_only_equations[static_only_index]->toStatic(static_model), static_only_equations_lineno[static_only_index], static_only_equations_equation_tags[static_only_index]);
static_only_index++;
}
else
static_model.addEquation(equations[i]->toStatic(static_model), equations_lineno[i], eq_tags);
}
catch (DataTree::DivisionByZeroException)
{
cerr << "...division by zero error encountred when converting equation " << i << " to static" << endl;
exit(EXIT_FAILURE);
}
}
// Convert auxiliary equations
for (auto aux_equation : aux_equations)
static_model.addAuxEquation(aux_equation->toStatic(static_model));
}
bool
DynamicModel::ParamUsedWithLeadLag() const
{

View File

@ -39,7 +39,7 @@ private:
constexpr static double zero_band{1e-8};
//! Stores equations declared as [static]
/*! They will be used in toStatic() to replace equations marked as [dynamic] */
/*! They will be used in the conversion to StaticModel to replace equations marked as [dynamic] */
vector<BinaryOpNode *> static_only_equations;
//! Stores line numbers of equations declared as [static]
@ -363,11 +363,6 @@ public:
//! Writes file containing parameters derivatives
void writeParamsDerivativesFile(const string &basename, bool julia) const;
//! Converts to static model (only the equations)
/*! It assumes that the static model given in argument has just been allocated */
void toStatic(StaticModel &static_model) const;
//! Converts to nonlinear model (only the equations)
/*! It assumes that the nonlinear model given in argument has just been allocated */
void toNonlinearPart(DynamicModel &non_linear_equations_dynamic_model) const;
@ -473,6 +468,8 @@ public:
//! Fills eval context with values of model local variables and auxiliary variables
void fillEvalContext(eval_context_t &eval_context) const;
auto getStaticOnlyEquationsInfo() const { return make_tuple(static_only_equations, static_only_equations_lineno, static_only_equations_equation_tags); };
//! Return the number of blocks
unsigned int
getNbBlocks() const override

View File

@ -693,7 +693,7 @@ ModFile::computingPass(bool no_tmp_terms, FileOutputType output, int params_deri
trend_dynamic_model.runTrendTest(global_eval_context);
// Compute static model and its derivatives
dynamic_model.toStatic(static_model);
static_model = static_cast<StaticModel>(dynamic_model);
if (linear_decomposition)
{
non_linear_equations_dynamic_model = dynamic_model;

View File

@ -28,6 +28,7 @@
#include <boost/filesystem.hpp>
#include "StaticModel.hh"
#include "DynamicModel.hh"
void
StaticModel::copyHelper(const StaticModel &m)
@ -163,6 +164,59 @@ StaticModel::operator=(const StaticModel &m)
return *this;
}
StaticModel::StaticModel(const DynamicModel &m) :
ModelTree {m.symbol_table, m.num_constants, m.external_functions_table}
{
// Convert model local variables (need to be done first)
for (int it : m.local_variables_vector)
AddLocalVariable(it, m.local_variables_table.find(it)->second->toStatic(*this));
// Convert equations
int static_only_index = 0;
for (int i = 0; i < static_cast<int>(m.equations.size()); i++)
{
// Detect if equation is marked [dynamic]
bool is_dynamic_only = false;
vector<pair<string, string>> eq_tags;
for (const auto & equation_tag : equation_tags)
if (equation_tag.first == i)
{
eq_tags.push_back(equation_tag.second);
if (equation_tag.second.first == "dynamic")
is_dynamic_only = true;
}
try
{
// If yes, replace it by an equation marked [static]
if (is_dynamic_only)
{
auto tuple = m.getStaticOnlyEquationsInfo();
auto static_only_equations = get<0>(tuple);
auto static_only_equations_lineno = get<1>(tuple);
auto static_only_equations_equation_tags = get<2>(tuple);
// With C++17, rather use structured bindings, as:
//auto [ static_only_equations, static_only_equations_lineno, static_only_equations_equation_tags ] = m.getStaticOnlyEquationsInfo();
addEquation(static_only_equations[static_only_index]->toStatic(*this), static_only_equations_lineno[static_only_index], static_only_equations_equation_tags[static_only_index]);
static_only_index++;
}
else
addEquation(m.equations[i]->toStatic(*this), m.equations_lineno[i], eq_tags);
}
catch (DataTree::DivisionByZeroException)
{
cerr << "...division by zero error encountred when converting equation " << i << " to static" << endl;
exit(EXIT_FAILURE);
}
}
// Convert auxiliary equations
for (auto aux_eq : m.aux_equations)
addAuxEquation(aux_eq->toStatic(*this));
}
void
StaticModel::compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, map_idx_t &map_idx, temporary_terms_t temporary_terms) const
{

View File

@ -26,6 +26,8 @@ using namespace std;
#include "ModelTree.hh"
class DynamicModel;
//! Stores a static model, as derived from the "model" block when leads and lags have been removed
class StaticModel : public ModelTree
{
@ -172,7 +174,15 @@ public:
StaticModel(const StaticModel &m);
StaticModel(StaticModel &&) = delete;
StaticModel & operator=(const StaticModel &m);
StaticModel & operator=(StaticModel &&) = delete;
/* The move assignment operator is not explicitly deleted, otherwise the
static_cast from DynamicModel does not work. However it looks like this
operator will not be used in the end. See
https://en.cppreference.com/w/cpp/language/copy_initialization
With C++17, it should be possible to explicitly delete it */
//StaticModel & operator=(StaticModel &&) = delete;
//! Creates the static version of a dynamic model
explicit StaticModel(const DynamicModel &m);
//! Writes information on block decomposition when relevant
void writeOutput(ostream &output, bool block) const;