From bcdfb43fd3a1ef66b2aca405f66250c7bda234fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= Date: Wed, 10 Oct 2018 17:08:54 +0200 Subject: [PATCH] Replate DynamicModel::toStatic() by a converting constructor in StaticModel It is therefore now possible to write: static_model = static_cast(dynamic_model); --- src/DynamicModel.cc | 49 ---------------------------------------- src/DynamicModel.hh | 9 +++----- src/ModFile.cc | 2 +- src/StaticModel.cc | 54 +++++++++++++++++++++++++++++++++++++++++++++ src/StaticModel.hh | 12 +++++++++- 5 files changed, 69 insertions(+), 57 deletions(-) diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc index 13a46849..7c0cbf8f 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -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> 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 { diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh index cad78c57..9e1b553a 100644 --- a/src/DynamicModel.hh +++ b/src/DynamicModel.hh @@ -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 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 diff --git a/src/ModFile.cc b/src/ModFile.cc index dc6a4841..1a36ca68 100644 --- a/src/ModFile.cc +++ b/src/ModFile.cc @@ -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(dynamic_model); if (linear_decomposition) { non_linear_equations_dynamic_model = dynamic_model; diff --git a/src/StaticModel.cc b/src/StaticModel.cc index 83fb7635..3a4a2f69 100644 --- a/src/StaticModel.cc +++ b/src/StaticModel.cc @@ -28,6 +28,7 @@ #include #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(m.equations.size()); i++) + { + // Detect if equation is marked [dynamic] + bool is_dynamic_only = false; + vector> 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 { diff --git a/src/StaticModel.hh b/src/StaticModel.hh index 300d3dad..b7d6aba3 100644 --- a/src/StaticModel.hh +++ b/src/StaticModel.hh @@ -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;