From afe0e475b1a8d9ddb0ff687fa87ef081ad2418c5 Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Tue, 14 Aug 2018 14:23:21 +0200
Subject: [PATCH] trend_component_model statement

---
 src/ComputingTasks.cc   |  28 ++--
 src/ComputingTasks.hh   |  11 +-
 src/DataTree.cc         |   4 +-
 src/DataTree.hh         |   8 +-
 src/DynamicModel.cc     | 349 +++++++++++++++++++++-------------------
 src/DynamicModel.hh     |  28 +---
 src/DynareBison.yy      |  28 +++-
 src/DynareFlex.ll       |   3 +
 src/Makefile.am         |   4 +-
 src/ModFile.cc          | 134 ++++++++-------
 src/ModFile.hh          |   4 +
 src/ModelTree.cc        |   6 +-
 src/ModelTree.hh        |   5 +-
 src/ParsingDriver.cc    |  48 ++++--
 src/ParsingDriver.hh    |   6 +-
 src/StaticModel.cc      |   6 +-
 src/StaticModel.hh      |   5 +-
 src/SteadyStateModel.cc |  10 +-
 src/SteadyStateModel.hh |   6 +-
 src/SubModel.cc         | 288 +++++++++++++++++++++++++++++++++
 src/SubModel.hh         |  96 +++++++++++
 21 files changed, 767 insertions(+), 310 deletions(-)
 create mode 100644 src/SubModel.cc
 create mode 100644 src/SubModel.hh

diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc
index 6a66fba3..992f38a7 100644
--- a/src/ComputingTasks.cc
+++ b/src/ComputingTasks.cc
@@ -258,16 +258,14 @@ PriorPosteriorFunctionStatement::writeJsonOutput(ostream &output) const
 }
 
 PacModelStatement::PacModelStatement(string name_arg,
-                                     string var_name_arg,
+                                     string aux_model_name_arg,
                                      string discount_arg,
                                      string growth_arg,
-                                     map<string, int> undiff_arg,
                                      const SymbolTable &symbol_table_arg) :
   name{move(name_arg)},
-  var_name{move(var_name_arg)},
+  aux_model_name{move(aux_model_name_arg)},
   discount{move(discount_arg)},
   growth{move(growth_arg)},
-  undiff{move(undiff_arg)},
   symbol_table{symbol_table_arg}
 {
 }
@@ -289,7 +287,7 @@ PacModelStatement::fillUndiffedLHS(vector<int> &lhs_arg)
 void
 PacModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
 {
-  output << "M_.pac." << name << ".var_model_name = '" << var_name << "';" << endl
+  output << "M_.pac." << name << ".auxiliary_model_name = '" << aux_model_name << "';" << endl
          << "M_.pac." << name << ".discount_index = " << symbol_table.getTypeSpecificID(discount) + 1 << ";" << endl;
 
   if (!growth.empty())
@@ -320,7 +318,8 @@ PacModelStatement::writeOutput(ostream &output, const string &basename, bool min
         output << " ";
       output << *it + 1;
     }
-  output << "];" << endl
+  output << "];" << endl;
+  /*
          << "M_.pac." << name << ".undiff_eqtags = {";
   for (auto it = undiff.begin(); it != undiff.end(); it++)
     {
@@ -337,6 +336,7 @@ PacModelStatement::writeOutput(ostream &output, const string &basename, bool min
       output << it->second;
     }
   output << "];" << endl;
+  */
 }
 
 void
@@ -344,7 +344,7 @@ PacModelStatement::writeJsonOutput(ostream &output) const
 {
   output << "{\"statementName\": \"pac_model\","
          << "\"model_name\": \"" << name << "\","
-         << "\"var_model_name\": \"" << var_name << "\","
+         << "\"auxiliary_model_name\": \"" << aux_model_name << "\","
          << "\"discount_index\": " << symbol_table.getTypeSpecificID(discount) + 1;
 
   if (!growth.empty())
@@ -371,13 +371,13 @@ PacModelStatement::writeJsonOutput(ostream &output) const
   output << "}";
 }
 
-void
-PacModelStatement::getPacModelInfoForPacExpectation(tuple<string, string, string, int, map<string, int>> &pac_model_info) const
+tuple<string, string, int>
+PacModelStatement::getPacModelInfoForPacExpectation() const
 {
   int growth_symb_id = -1;
   if (!growth.empty())
     growth_symb_id = symbol_table.getID(growth);
-  pac_model_info = { name, var_name, discount, growth_symb_id, undiff };
+  return { name, aux_model_name, growth_symb_id };
 }
 
 VarModelStatement::VarModelStatement(SymbolList symbol_list_arg,
@@ -2207,8 +2207,12 @@ ModelComparisonStatement::writeJsonOutput(ostream &output) const
   output << "}";
 }
 
-PlannerObjectiveStatement::PlannerObjectiveStatement(SymbolTable &symbol_table, NumericalConstants &num_constants, ExternalFunctionsTable &external_functions_table) :
-  model_tree{symbol_table, num_constants, external_functions_table}
+PlannerObjectiveStatement::PlannerObjectiveStatement(SymbolTable &symbol_table,
+                                                     NumericalConstants &num_constants,
+                                                     ExternalFunctionsTable &external_functions_table,
+                                                     TrendComponentModelTable &trend_component_model_table_arg) :
+  model_tree{symbol_table, num_constants,
+             external_functions_table, trend_component_model_table_arg}
 {
 }
 
diff --git a/src/ComputingTasks.hh b/src/ComputingTasks.hh
index f6e7a094..cdfe4499 100644
--- a/src/ComputingTasks.hh
+++ b/src/ComputingTasks.hh
@@ -123,24 +123,22 @@ class PacModelStatement : public Statement
 {
 private:
   const string name;
-  const string var_name;
+  const string aux_model_name;
   const string discount;
   const string growth;
-  const map<string, int> undiff;
   const SymbolTable &symbol_table;
   vector<int> lhs;
 public:
   PacModelStatement(string name_arg,
-                    string var_name_arg,
+                    string aux_model_name_arg,
                     string discount_arg,
                     string growth_arg,
-                    map<string, int> undiff_arg,
                     const SymbolTable &symbol_table_arg);
   void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
   void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
   void writeJsonOutput(ostream &output) const override;
   void fillUndiffedLHS(vector<int> &lhs);
-  void getPacModelInfoForPacExpectation(tuple<string, string, string, int, map<string, int>> &pac_model_info) const;
+  tuple<string, string, int> getPacModelInfoForPacExpectation() const;
 };
 
 class VarModelStatement : public Statement
@@ -542,7 +540,8 @@ private:
 public:
   PlannerObjectiveStatement(SymbolTable &symbol_table,
                             NumericalConstants &num_constants,
-                            ExternalFunctionsTable &external_functions_table);
+                            ExternalFunctionsTable &external_functions_table,
+                            TrendComponentModelTable &trend_component_model_table_arg);
   /*! \todo check there are only endogenous variables at the current period in the objective
     (no exogenous, no lead/lag) */
   void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
diff --git a/src/DataTree.cc b/src/DataTree.cc
index 36f7c08b..b824ccab 100644
--- a/src/DataTree.cc
+++ b/src/DataTree.cc
@@ -28,10 +28,12 @@
 
 DataTree::DataTree(SymbolTable &symbol_table_arg,
                    NumericalConstants &num_constants_arg,
-                   ExternalFunctionsTable &external_functions_table_arg) :
+                   ExternalFunctionsTable &external_functions_table_arg,
+                   TrendComponentModelTable &trend_component_model_table_arg) :
   symbol_table(symbol_table_arg),
   num_constants(num_constants_arg),
   external_functions_table(external_functions_table_arg),
+  trend_component_model_table(trend_component_model_table_arg),
   node_counter(0)
 {
   Zero = AddNonNegativeConstant("0");
diff --git a/src/DataTree.hh b/src/DataTree.hh
index 45c90723..7e0635de 100644
--- a/src/DataTree.hh
+++ b/src/DataTree.hh
@@ -34,6 +34,7 @@ using namespace std;
 #include "NumericalConstants.hh"
 #include "ExternalFunctionsTable.hh"
 #include "ExprNode.hh"
+#include "SubModel.hh"
 
 class DataTree
 {
@@ -56,6 +57,8 @@ protected:
   NumericalConstants &num_constants;
   //! A reference to the external functions table
   ExternalFunctionsTable &external_functions_table;
+  //! A reference to the trend component model table
+  TrendComponentModelTable &trend_component_model_table;
 
   //! num_constant_id -> NumConstNode
   using num_const_node_map_t = map<int, NumConstNode *>;
@@ -130,7 +133,10 @@ private:
   inline expr_t AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3);
 
 public:
-  DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg);
+  DataTree(SymbolTable &symbol_table_arg,
+           NumericalConstants &num_constants_arg,
+           ExternalFunctionsTable &external_functions_table_arg,
+           TrendComponentModelTable &trend_component_model_table_arg);
   virtual
   ~DataTree();
 
diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 5d89412a..157def47 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -33,8 +33,10 @@
 
 DynamicModel::DynamicModel(SymbolTable &symbol_table_arg,
                            NumericalConstants &num_constants_arg,
-                           ExternalFunctionsTable &external_functions_table_arg) :
-  ModelTree(symbol_table_arg, num_constants_arg, external_functions_table_arg),
+                           ExternalFunctionsTable &external_functions_table_arg,
+                           TrendComponentModelTable &trend_component_model_table_arg) :
+  ModelTree(symbol_table_arg, num_constants_arg,
+            external_functions_table_arg, trend_component_model_table_arg),
   max_lag(0), max_lead(0),
   max_endo_lag(0), max_endo_lead(0),
   max_exo_lag(0), max_exo_lead(0),
@@ -3453,153 +3455,192 @@ DynamicModel::runTrendTest(const eval_context_t &eval_context)
 }
 
 void
-DynamicModel::getVarModelVariablesFromEqTags(vector<string> &var_model_eqtags,
-                                             vector<int> &eqnumber,
-                                             vector<int> &lhs,
-                                             vector<expr_t> &lhs_expr_t,
-                                             vector<set<pair<int, int>>> &rhs,
-                                             vector<bool> &nonstationary) const
+DynamicModel::fillTrendComponentModelTable() const
 {
-  for (vector<string>::const_iterator itvareqs = var_model_eqtags.begin();
-       itvareqs != var_model_eqtags.end(); itvareqs++)
+  map<string, vector<int>> eqnums, trend_eqnums, lhsr;
+  map<string, vector<expr_t>> lhs_expr_tr;
+  map<string, vector<bool>> nonstationaryr;
+  map<string, vector<set<pair<int, int>>>> rhsr;
+  map<string, vector<string>> eqtags = trend_component_model_table.getEqTags();
+  map<string, vector<string>> trend_eqtags = trend_component_model_table.getTrendEqTags();
+  for (const auto &it : trend_eqtags)
     {
-      int eqn = -1;
-      set<pair<int, int>> lhs_set, lhs_tmp_set, rhs_set;
-      string eqtag (*itvareqs);
-      for (const auto & equation_tag : equation_tags)
-        if (equation_tag.second.first == "name"
-            && equation_tag.second.second == eqtag)
-          {
-            eqn = equation_tag.first;
-            break;
-          }
-
-      if (eqn == -1)
+      vector<int> trend_eqnumber;
+      for (const auto &eqtag : it.second)
         {
-          cerr << "ERROR: equation tag '" << eqtag << "' not found" << endl;
-          exit(EXIT_FAILURE);
-        }
+          int eqn = -1;
+          for (const auto &equation_tag : equation_tags)
+            if (equation_tag.second.first == "name"
+                && equation_tag.second.second == eqtag)
+              {
+                eqn = equation_tag.first;
+                break;
+              }
 
-      bool nonstationary_bool = false;
-      for (const auto & equation_tag : equation_tags)
-        if (equation_tag.first == eqn)
-          if (equation_tag.second.first == "data_type"
-              && equation_tag.second.second == "nonstationary")
+          if (eqn == -1)
             {
-              nonstationary_bool = true;
-              break;
+              cerr << "ERROR: trend equation tag '" << eqtag << "' not found" << endl;
+              exit(EXIT_FAILURE);
             }
-      nonstationary.push_back(nonstationary_bool);
-
-      equations[eqn]->get_arg1()->collectDynamicVariables(SymbolType::endogenous, lhs_set);
-      equations[eqn]->get_arg1()->collectDynamicVariables(SymbolType::exogenous, lhs_tmp_set);
-      equations[eqn]->get_arg1()->collectDynamicVariables(SymbolType::parameter, lhs_tmp_set);
-
-      if (lhs_set.size() != 1 || !lhs_tmp_set.empty())
-        {
-          cerr << "ERROR: in Equation " << eqtag
-               << ". A VAR may only have one endogenous variable on the LHS. " << endl;
-          exit(EXIT_FAILURE);
-        }
-
-      auto it = lhs_set.begin();
-      if (it->second != 0)
-        {
-          cerr << "ERROR: in Equation " << eqtag
-               << ". The variable on the LHS of a VAR may not appear with a lead or a lag. "
-               << endl;
-          exit(EXIT_FAILURE);
+          trend_eqnumber.push_back(eqn);
         }
-
-      eqnumber.push_back(eqn);
-      lhs.push_back(it->first);
-      lhs_set.clear();
-      set<expr_t> lhs_expr_t_set;
-      equations[eqn]->get_arg1()->collectVARLHSVariable(lhs_expr_t_set);
-      lhs_expr_t.push_back(*(lhs_expr_t_set.begin()));
-
-      equations[eqn]->get_arg2()->collectDynamicVariables(SymbolType::endogenous, rhs_set);
-      for (it = rhs_set.begin(); it != rhs_set.end(); it++)
-        if (it->second > 0)
-          {
-            cerr << "ERROR: in Equation " << eqtag
-                 << ". A VAR may not have leaded or contemporaneous variables on the RHS. " << endl;
-            exit(EXIT_FAILURE);
-          }
-      rhs.push_back(rhs_set);
+      trend_eqnums[it.first] = trend_eqnumber;
     }
-}
 
-void
-DynamicModel::checkVarMinLag(vector<int> &eqnumber) const
-{
-  int eqn = 1;
-  for (vector<int>::const_iterator it = eqnumber.begin();
-       it != eqnumber.end(); it++, eqn++)
+  for (const auto &it : eqtags)
     {
-      int min_lag = -1;
-      min_lag = equations[*it]->get_arg2()->VarMinLag();
-      if (min_lag <= 0)
+      vector<int> eqnumber, lhs;
+      vector<expr_t> lhs_expr_t;
+      vector<set<pair<int, int>>> rhs;
+      vector<bool> nonstationary;
+
+      for (const auto &eqtag : it.second)
         {
-          cerr << "ERROR in VAR Equation #" << eqn << ". "
-               << "Leaded exogenous variables and leaded or contemporaneous endogenous variables not allowed in VAR";
-          exit(EXIT_FAILURE);
-        }
-    }
-}
+          int eqn = -1;
+          set<pair<int, int>> lhs_set, lhs_tmp_set, rhs_set;
+          for (const auto &equation_tag : equation_tags)
+            if (equation_tag.second.first == "name"
+                && equation_tag.second.second == eqtag)
+              {
+                eqn = equation_tag.first;
+                break;
+              }
 
-int
-DynamicModel::getVarMaxLag(StaticModel &static_model, vector<int> &eqnumber) const
-{
-  set<expr_t> lhs;
-  for (vector<int>::const_iterator it = eqnumber.begin();
-       it != eqnumber.end(); it++)
-    equations[*it]->get_arg1()->collectVARLHSVariable(lhs);
+          if (eqn == -1)
+            {
+              cerr << "ERROR: equation tag '" << eqtag << "' not found" << endl;
+              exit(EXIT_FAILURE);
+            }
 
-  if (eqnumber.size() != lhs.size())
-    {
-      cerr << "The LHS variables of the VAR are not unique" << endl;
-      exit(EXIT_FAILURE);
-    }
+          bool nonstationary_bool = false;
+          for (const auto &equation_tag : equation_tags)
+            if (equation_tag.first == eqn)
+              if (equation_tag.second.first == "data_type"
+                  && equation_tag.second.second == "nonstationary")
+                {
+                  nonstationary_bool = true;
+                  break;
+                }
+          nonstationary.push_back(nonstationary_bool);
+
+          equations[eqn]->get_arg1()->collectDynamicVariables(SymbolType::endogenous, lhs_set);
+          equations[eqn]->get_arg1()->collectDynamicVariables(SymbolType::exogenous, lhs_tmp_set);
+          equations[eqn]->get_arg1()->collectDynamicVariables(SymbolType::parameter, lhs_tmp_set);
+
+          if (lhs_set.size() != 1 || !lhs_tmp_set.empty())
+            {
+              cerr << "ERROR: in Equation " << eqtag
+                   << ". A VAR may only have one endogenous variable on the LHS. " << endl;
+              exit(EXIT_FAILURE);
+            }
 
-  set<expr_t> lhs_static;
-  for(auto lh : lhs)
-    lhs_static.insert(lh->toStatic(static_model));
+          auto it = lhs_set.begin();
+          if (it->second != 0)
+            {
+              cerr << "ERROR: in Equation " << eqtag
+                   << ". The variable on the LHS of a VAR may not appear with a lead or a lag. "
+                   << endl;
+              exit(EXIT_FAILURE);
+            }
 
-  int max_lag = 0;
-  for (vector<int>::const_iterator it = eqnumber.begin();
-       it != eqnumber.end(); it++)
-    max_lag = max(max_lag,
-                  equations[*it]->get_arg2()->VarMaxLag(static_model, lhs_static));
+          eqnumber.push_back(eqn);
+          lhs.push_back(it->first);
+          lhs_set.clear();
+          set<expr_t> lhs_expr_t_set;
+          equations[eqn]->get_arg1()->collectVARLHSVariable(lhs_expr_t_set);
+          lhs_expr_t.push_back(*(lhs_expr_t_set.begin()));
 
-  return max_lag;
+          equations[eqn]->get_arg2()->collectDynamicVariables(SymbolType::endogenous, rhs_set);
+          for (it = rhs_set.begin(); it != rhs_set.end(); it++)
+            if (it->second > 0)
+              {
+                cerr << "ERROR: in Equation " << eqtag
+                     << ". A VAR may not have leaded or contemporaneous variables on the RHS. " << endl;
+                exit(EXIT_FAILURE);
+              }
+          rhs.push_back(rhs_set);
+        }
+      eqnums[it.first] = eqnumber;
+      lhsr[it.first] = lhs;
+      lhs_expr_tr[it.first] = lhs_expr_t;
+      rhsr[it.first] = rhs;
+      nonstationaryr[it.first] = nonstationary;
+    }
+  trend_component_model_table.setEqNums(eqnums);
+  trend_component_model_table.setTrendEqNums(trend_eqnums);
+  trend_component_model_table.setLhs(lhsr);
+  trend_component_model_table.setRhs(rhsr);
+  trend_component_model_table.setLhsExprT(lhs_expr_tr);
+  trend_component_model_table.setNonstationary(nonstationaryr);
 }
 
 void
-DynamicModel::getVarLhsDiffAndInfo(vector<int> &eqnumber, vector<bool> &diff,
-                                   vector<int> &orig_diff_var) const
+DynamicModel::fillTrendComponentModelTableFromOrigModel(StaticModel &static_model) const
 {
-  for (vector<int>::const_iterator it = eqnumber.begin();
-       it != eqnumber.end(); it++)
+  map<string, vector<int>> lags, orig_diff_var;
+  map<string, vector<bool>> diff;
+  for (const auto &it : trend_component_model_table.getEqNums())
     {
-      equations[*it]->get_arg1()->countDiffs() > 0 ? diff.push_back(true) : diff.push_back(false);
-      if (diff.back())
+      set<expr_t> lhs;
+      vector<int> orig_diff_var_vec;
+      vector<bool> diff_vec;
+      for (auto eqn : it.second)
         {
-          set<pair<int, int>> diff_set;
-          equations[*it]->get_arg1()->collectDynamicVariables(SymbolType::endogenous, diff_set);
-
-          if (diff_set.size() != 1)
+          // ensure no leads in equations
+          if (equations[eqn]->get_arg2()->VarMinLag() <= 0)
             {
-              cerr << "ERROR: problem getting variable for LHS diff operator in equation " << *it << endl;
+              cerr << "ERROR in VAR Equation (#" << eqn << "). "
+                   << "Leaded exogenous variables "
+                   << "and leaded or contemporaneous endogenous variables not allowed in VAR"
+                   << endl;
               exit(EXIT_FAILURE);
             }
-          orig_diff_var.push_back(diff_set.begin()->first);
+
+          // save lhs variables
+          equations[eqn]->get_arg1()->collectVARLHSVariable(lhs);
+
+          equations[eqn]->get_arg1()->countDiffs() > 0 ?
+            diff_vec.push_back(true) : diff_vec.push_back(false);
+          if (diff_vec.back())
+            {
+              set<pair<int, int>> diff_set;
+              equations[eqn]->get_arg1()->collectDynamicVariables(SymbolType::endogenous, diff_set);
+
+              if (diff_set.size() != 1)
+                {
+                  cerr << "ERROR: problem getting variable for LHS diff operator in equation "
+                       << eqn << endl;
+                  exit(EXIT_FAILURE);
+                }
+              orig_diff_var_vec.push_back(diff_set.begin()->first);
+            }
+          else
+            orig_diff_var_vec.push_back(-1);
+
         }
-      else
-        orig_diff_var.push_back(-1);
+
+      if (it.second.size() != lhs.size())
+        {
+          cerr << "ERROR: The LHS variables of the VAR are not unique" << endl;
+          exit(EXIT_FAILURE);
+        }
+
+      set<expr_t> lhs_static;
+      for(const auto &lh : lhs)
+        lhs_static.insert(lh->toStatic(static_model));
+
+      vector<int> max_lag;
+      for (auto eqn : it.second)
+        max_lag.push_back(equations[eqn]->get_arg2()->VarMaxLag(static_model, lhs_static));
+      lags[it.first] = max_lag;
+      diff[it.first] = diff_vec;
+      orig_diff_var[it.first] = orig_diff_var_vec;
     }
+  trend_component_model_table.setDiff(diff);
+  trend_component_model_table.setMaxLags(lags);
+  trend_component_model_table.setOrigDiffVar(orig_diff_var);
 }
-
+/*
 void
 DynamicModel::addEquationsForVar(map<string, pair<SymbolList, int>> &var_model_info)
 {
@@ -3651,34 +3692,20 @@ DynamicModel::addEquationsForVar(map<string, pair<SymbolList, int>> &var_model_i
   if (count > 0)
     cout << "Accounting for var_model lags not in model block: added " << count << " auxiliary variables and equations." << endl;
 }
-
-void
-DynamicModel::getUndiffLHSForPac(vector<int> &lhs, vector<expr_t> &lhs_expr_t, vector<bool> &diff, vector<int> &orig_diff_var,
-                                 vector<int> &eqnumber, map<string, int> &undiff, ExprNode::subst_table_t &diff_subst_table)
+*/
+vector<int>
+DynamicModel::getUndiffLHSForPac(const string &aux_model_name,
+                                 ExprNode::subst_table_t &diff_subst_table)
 {
-  if (undiff.empty())
-    return;
-
-  for (map<string, int>::const_iterator it = undiff.begin();
-       it != undiff.end(); it++)
+  vector<expr_t> lhs_expr_t = trend_component_model_table.getLhsExprT(aux_model_name);
+  vector<int> lhs = trend_component_model_table.getLhs(aux_model_name);
+  vector<bool> diff = trend_component_model_table.getDiff(aux_model_name);
+  vector<int> orig_diff_var = trend_component_model_table.getOrigDiffVar(aux_model_name);
+  vector<int> eqnumber = trend_component_model_table.getEqNums(aux_model_name);
+  vector<int> nontrend_eqnums = trend_component_model_table.getNonTrendEqNums(aux_model_name);
+
+  for (auto eqn : nontrend_eqnums)
     {
-      int eqn = -1;
-      string eqtag (it->first);
-      for (vector<pair<int, pair<string, string>>>::const_iterator iteqtag =
-             equation_tags.begin(); iteqtag != equation_tags.end(); iteqtag++)
-        if (iteqtag->second.first == "name"
-            && iteqtag->second.second == eqtag)
-          {
-            eqn = iteqtag->first;
-            break;
-          }
-
-      if (eqn == -1)
-        {
-          cerr << "ERROR: undiff equation tag '" << eqtag << "' not found" << endl;
-          exit(EXIT_FAILURE);
-        }
-
       int i = 0;
       for (vector<int>::const_iterator it1 = eqnumber.begin();
            it1 != eqnumber.end(); it1++, i++)
@@ -3693,9 +3720,9 @@ DynamicModel::getUndiffLHSForPac(vector<int> &lhs, vector<expr_t> &lhs_expr_t, v
 
       if (diff.at(i) != true)
         {
-          cerr << "ERROR: the variable on the LHS of equation #" << eqn << " (VAR equation #" << i
-               << " with equation tag '" << eqtag
-               << "') does not have the diff operator applied to it yet you are trying to undiff it." << endl;
+          cerr << "ERROR: the variable on the LHS of equation #" << eqn
+               << " does not have the diff operator applied to it yet you are trying to undiff it."
+               << endl;
           exit(EXIT_FAILURE);
         }
 
@@ -3716,20 +3743,10 @@ DynamicModel::getUndiffLHSForPac(vector<int> &lhs, vector<expr_t> &lhs_expr_t, v
           exit(EXIT_FAILURE);
         }
 
-      for (int j = it->second; j > 0; j--)
-        if (printerr)
-          {
-            cerr << "You are undiffing the LHS of equation #" << eqn << " "
-                 << it->second << " times but it has only been diffed " << j << " time(s)" << endl;
-            exit(EXIT_FAILURE);
-          }
-        else
-          {
-            node = node->undiff();
-            it1 = diff_subst_table.find(node);
-            if (it1 == diff_subst_table.end())
-              printerr = true;
-          }
+      node = node->undiff();
+      it1 = diff_subst_table.find(node);
+      if (it1 == diff_subst_table.end())
+        printerr = true;
 
       if (printerr)
         { // we have undiffed something like diff(x), hence x is not in diff_subst_table
@@ -3742,6 +3759,7 @@ DynamicModel::getUndiffLHSForPac(vector<int> &lhs, vector<expr_t> &lhs_expr_t, v
           lhs.at(i) = const_cast<VariableNode *>(it1->second)->get_symb_id();
         }
     }
+  return lhs;
 }
 
 void
@@ -3807,7 +3825,8 @@ DynamicModel::fillPacExpectationVarInfo(string &pac_model_name,
                                         int growth_symb_id)
 {
   for (size_t i = 0; i < equations.size(); i++)
-    equations[i]->fillPacExpectationVarInfo(pac_model_name, lhs, max_lag, pac_max_lag, nonstationary, growth_symb_id, i);
+    equations[i]->fillPacExpectationVarInfo(pac_model_name, lhs, max_lag,
+                                            pac_max_lag, nonstationary, growth_symb_id, i);
 }
 
 void
diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh
index 51b87ff5..90814436 100644
--- a/src/DynamicModel.hh
+++ b/src/DynamicModel.hh
@@ -250,7 +250,7 @@ private:
   void findPacExpectationEquationNumbers(vector<int> &eqnumber) const;
 
 public:
-  DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg);
+  DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg, TrendComponentModelTable &trend_component_model_table_arg);
   //! Adds a variable node
   /*! This implementation allows for non-zero lag */
   VariableNode *AddVariable(int symb_id, int lag = 0) override;
@@ -300,26 +300,12 @@ public:
   //! Set the equations that have non-zero second derivatives
   void setNonZeroHessianEquations(map<int, string> &eqs);
 
-  //! Get equation info associated with equation tags from var_model
-  void getVarModelVariablesFromEqTags(vector<string> &var_model_eqtags,
-                                      vector<int> &eqnumber,
-                                      vector<int> &lhs,
-                                      vector<expr_t> &lhs_expr_t,
-                                      vector<set<pair<int, int>>> &rhs,
-                                      vector<bool> &nonstationary) const;
-
-  //! Returns the max lag of the VAR
-  void checkVarMinLag(vector<int> &eqnumber) const;
-
-  //! Returns the max lag of the VAR
-  int getVarMaxLag(StaticModel &static_model, vector<int> &eqnumber) const;
-
-  // Get equtaino information on diff operator and max lag info
-  void getVarLhsDiffAndInfo(vector<int> &eqnumber, vector<bool> &diff,
-                            vector<int> &orig_diff_var) const;
+  //! Fill the Trend Component Model Table
+  void fillTrendComponentModelTable() const;
+  void fillTrendComponentModelTableFromOrigModel(StaticModel &static_model) const;
 
   //! Add aux equations (and aux variables) for variables declared in var_model at max order if they don't already exist
-  void addEquationsForVar(map<string, pair<SymbolList, int>> &var_model_info);
+  //  void addEquationsForVar(map<string, pair<SymbolList, int>> &var_model_info);
   //! Get Pac equation parameter info
   void walkPacParameters();
   //! Add var_model info to pac_expectation nodes
@@ -439,8 +425,8 @@ public:
   int getPacMaxLag(const string &pac_model_name) const;
 
   //! Table to undiff LHS variables for pac vector z
-  void getUndiffLHSForPac(vector<int> &lhs, vector<expr_t> &lhs_expr_t, vector<bool> &diff, vector<int> &orig_diff_var,
-                          vector<int> &eqnumber, map<string, int> &undiff, ExprNode::subst_table_t &diff_subst_table);
+  vector<int> getUndiffLHSForPac(const string &aux_model_name,
+                                 ExprNode::subst_table_t &diff_subst_table);
 
   //! Transforms the model by replacing trend variables with a 1
   void removeTrendVariableFromEquations();
diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index 87bf4f67..ba29f096 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -111,7 +111,7 @@ class ParsingDriver;
 %token PRINT PRIOR_MC PRIOR_TRUNC PRIOR_MODE PRIOR_MEAN POSTERIOR_MODE POSTERIOR_MEAN POSTERIOR_MEDIAN MLE_MODE PRUNING
 %token <string> QUOTED_STRING
 %token QZ_CRITERIUM QZ_ZERO_THRESHOLD DSGE_VAR DSGE_VARLAG DSGE_PRIOR_WEIGHT TRUNCATE PIPE_E PIPE_X PIPE_P
-%token RELATIVE_IRF REPLIC SIMUL_REPLIC RPLOT SAVE_PARAMS_AND_STEADY_STATE PARAMETER_UNCERTAINTY
+%token RELATIVE_IRF REPLIC SIMUL_REPLIC RPLOT SAVE_PARAMS_AND_STEADY_STATE PARAMETER_UNCERTAINTY TRENDS
 %token SHOCKS SHOCK_DECOMPOSITION SHOCK_GROUPS USE_SHOCK_GROUPS SIGMA_E SIMUL SIMUL_ALGO SIMUL_SEED ENDOGENOUS_TERMINAL_PERIOD
 %token SMOOTHER SMOOTHER2HISTVAL SQUARE_ROOT_SOLVER STACK_SOLVE_ALGO STEADY_STATE_MODEL SOLVE_ALGO SOLVER_PERIODS ROBUST_LIN_SOLVE
 %token STDERR STEADY STOCH_SIMUL SYLVESTER SYLVESTER_FIXED_POINT_TOL REGIMES REGIME REALTIME_SHOCK_DECOMPOSITION
@@ -120,14 +120,14 @@ class ParsingDriver;
 %token UNIFORM_PDF UNIT_ROOT_VARS USE_DLL USEAUTOCORR GSA_SAMPLE_FILE USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED
 %token VALUES VAR VAREXO VAREXO_DET VARIABLE VAROBS VAREXOBS PREDETERMINED_VARIABLES VAR_EXPECTATION VAR_EXPECTATION_MODEL PLOT_SHOCK_DECOMPOSITION MODEL_LOCAL_VARIABLE
 %token WRITE_LATEX_DYNAMIC_MODEL WRITE_LATEX_STATIC_MODEL WRITE_LATEX_ORIGINAL_MODEL CROSSEQUATIONS COVARIANCE WRITE_LATEX_STEADY_STATE_MODEL
-%token XLS_SHEET XLS_RANGE LMMCP OCCBIN BANDPASS_FILTER COLORMAP VAR_MODEL PAC_MODEL QOQ YOY AOA UNDIFF PAC_EXPECTATION
+%token XLS_SHEET XLS_RANGE LMMCP OCCBIN BANDPASS_FILTER COLORMAP VAR_MODEL PAC_MODEL QOQ YOY AOA UNDIFF PAC_EXPECTATION TREND_COMPONENT_MODEL
 %left EQUAL_EQUAL EXCLAMATION_EQUAL
 %left LESS GREATER LESS_EQUAL GREATER_EQUAL
 %left PLUS MINUS
 %left TIMES DIVIDE
 %precedence UMINUS UPLUS
 %nonassoc POWER
-%token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN ERF DIFF ADL
+%token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN ERF DIFF ADL AUXILIARY_MODEL_NAME
 %token SQRT NORMCDF NORMPDF STEADY_STATE EXPECTATION VAR_ESTIMATION
 /* GSA analysis */
 %token DYNARE_SENSITIVITY MORRIS STAB REDFORM PPRIOR PRIOR_RANGE PPOST ILPTAU MORRIS_NLIV
@@ -223,6 +223,7 @@ statement : parameters
           | data
           | var_model
           | pac_model
+          | trend_component_model
           | restrictions
           | prior
           | prior_eq
@@ -374,6 +375,18 @@ var_model_options : o_var_name
                   | o_var_eq_tags
                   ;
 
+trend_component_model : TREND_COMPONENT_MODEL '('  trend_component_model_options_list ')' ';' { driver.trend_component_model(); }
+                      ;
+
+trend_component_model_options_list : trend_component_model_options_list COMMA trend_component_model_options
+                                   | trend_component_model_options
+                                   ;
+
+trend_component_model_options : o_trend_component_model_name
+                              | o_trend_component_model_trends
+                              | o_trend_component_model_eq_tags
+                              ;
+
 pac_model : PAC_MODEL '(' pac_model_options_list ')' ';' { driver.pac_model(); } ;
 
 pac_model_options_list : pac_model_options_list COMMA pac_model_options
@@ -381,11 +394,9 @@ pac_model_options_list : pac_model_options_list COMMA pac_model_options
                        ;
 
 pac_model_options : o_pac_name
-                  | o_pac_var_name
+                  | o_pac_aux_model_name
                   | o_pac_discount
                   | o_pac_growth
-                  | UNDIFF '(' QUOTED_STRING COMMA INT_NUMBER ')'
-                    { driver.pac_model_undiff($3, $5); }
                   ;
 
 var_expectation_model : VAR_EXPECTATION_MODEL '(' var_expectation_model_options_list ')' ';'
@@ -3084,7 +3095,7 @@ o_qz_criterium : QZ_CRITERIUM EQUAL non_negative_number { driver.option_num("qz_
 o_qz_zero_threshold : QZ_ZERO_THRESHOLD EQUAL non_negative_number { driver.option_num("qz_zero_threshold", $3); };
 o_file : FILE EQUAL filename { driver.option_str("file", $3); };
 o_pac_name : MODEL_NAME EQUAL symbol { driver.option_str("pac.model_name", $3); };
-o_pac_var_name : VAR_MODEL_NAME EQUAL symbol { driver.option_str("pac.var_model_name", $3); };
+o_pac_aux_model_name : AUXILIARY_MODEL_NAME EQUAL symbol { driver.option_str("pac.aux_model_name", $3); };
 o_pac_discount : DISCOUNT EQUAL symbol { driver.option_str("pac.discount", $3); };
 o_pac_growth : GROWTH EQUAL symbol { driver.option_str("pac.growth", $3); };
 o_var_name : MODEL_NAME EQUAL symbol { driver.option_str("var.model_name", $3); };
@@ -3101,6 +3112,9 @@ o_nobs : NOBS EQUAL vec_int
        | NOBS EQUAL vec_int_number
          { driver.option_vec_int("nobs", $3); }
        ;
+o_trend_component_model_name : MODEL_NAME EQUAL symbol { driver.option_str("trend_component.name", $3); };
+o_trend_component_model_trends : TRENDS EQUAL vec_str { driver.option_vec_str("trend_component.trends", $3); }
+o_trend_component_model_eq_tags : EQTAGS EQUAL vec_str { driver.option_vec_str("trend_component.eqtags", $3); }
 o_conditional_variance_decomposition : CONDITIONAL_VARIANCE_DECOMPOSITION EQUAL vec_int
                                        { driver.option_vec_int("conditional_variance_decomposition", $3); }
                                      | CONDITIONAL_VARIANCE_DECOMPOSITION EQUAL vec_int_number
diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll
index 6d41a906..8f0ac71a 100644
--- a/src/DynareFlex.ll
+++ b/src/DynareFlex.ll
@@ -141,6 +141,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
 <INITIAL>simul {BEGIN DYNARE_STATEMENT; return token::SIMUL;}
 <INITIAL>stoch_simul {BEGIN DYNARE_STATEMENT; return token::STOCH_SIMUL;}
 <INITIAL>var_model {BEGIN DYNARE_STATEMENT; return token::VAR_MODEL;}
+<INITIAL>trend_component_model {BEGIN DYNARE_STATEMENT; return token::TREND_COMPONENT_MODEL;}
 <INITIAL>var_expectation_model {BEGIN DYNARE_STATEMENT; return token::VAR_EXPECTATION_MODEL;}
 <INITIAL>pac_model {BEGIN DYNARE_STATEMENT; return token::PAC_MODEL;}
 <INITIAL>dsample {BEGIN DYNARE_STATEMENT; return token::DSAMPLE;}
@@ -348,6 +349,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
 <DYNARE_STATEMENT>periods	{return token::PERIODS;}
 <DYNARE_STATEMENT,DYNARE_BLOCK>model_name	{return token::MODEL_NAME;}
 <DYNARE_STATEMENT>var_model_name    {return token::VAR_MODEL_NAME;}
+<DYNARE_STATEMENT>auxiliary_model_name    {return token::AUXILIARY_MODEL_NAME;}
 <DYNARE_STATEMENT>endogenous_terminal_period 	{return token::ENDOGENOUS_TERMINAL_PERIOD;}
 <DYNARE_STATEMENT>sub_draws	{return token::SUB_DRAWS;}
 <DYNARE_STATEMENT>minimal_solving_periods {return token::MINIMAL_SOLVING_PERIODS;}
@@ -487,6 +489,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
 }
 <DYNARE_STATEMENT>write_equation_tags {return token::WRITE_EQUATION_TAGS;}
 <DYNARE_STATEMENT>eqtags {return token::EQTAGS;}
+<DYNARE_STATEMENT>trends {return token::TRENDS;}
 <DYNARE_STATEMENT>indxap {return token::INDXAP;}
 <DYNARE_STATEMENT>apband {return token::APBAND;}
 <DYNARE_STATEMENT>indximf {return token::INDXIMF;}
diff --git a/src/Makefile.am b/src/Makefile.am
index 35da494f..4fea4104 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -52,7 +52,9 @@ dynare_m_SOURCES = \
 	SteadyStateModel.cc \
 	WarningConsolidation.hh \
 	WarningConsolidation.cc \
-	ExtendedPreprocessorTypes.hh
+	ExtendedPreprocessorTypes.hh \
+	SubModel.cc \
+	SubModel.hh
 
 
 ACLOCAL_AMFLAGS = -I m4
diff --git a/src/ModFile.cc b/src/ModFile.cc
index 815a7d99..6f377258 100644
--- a/src/ModFile.cc
+++ b/src/ModFile.cc
@@ -30,15 +30,25 @@
 #include "ComputingTasks.hh"
 
 ModFile::ModFile(WarningConsolidation &warnings_arg)
-  : expressions_tree(symbol_table, num_constants, external_functions_table),
-    original_model(symbol_table, num_constants, external_functions_table),
-    dynamic_model(symbol_table, num_constants, external_functions_table),
-    trend_dynamic_model(symbol_table, num_constants, external_functions_table),
-    ramsey_FOC_equations_dynamic_model(symbol_table, num_constants, external_functions_table),
-    orig_ramsey_dynamic_model(symbol_table, num_constants, external_functions_table),
-    static_model(symbol_table, num_constants, external_functions_table),
-    steady_state_model(symbol_table, num_constants, external_functions_table, static_model),
-    diff_static_model(symbol_table, num_constants, external_functions_table),
+  : trend_component_model_table(symbol_table),
+    expressions_tree(symbol_table, num_constants,
+                     external_functions_table, trend_component_model_table),
+    original_model(symbol_table, num_constants,
+                   external_functions_table, trend_component_model_table),
+    dynamic_model(symbol_table, num_constants,
+                  external_functions_table, trend_component_model_table),
+    trend_dynamic_model(symbol_table, num_constants,
+                        external_functions_table, trend_component_model_table),
+    ramsey_FOC_equations_dynamic_model(symbol_table, num_constants,
+                                       external_functions_table, trend_component_model_table),
+    orig_ramsey_dynamic_model(symbol_table, num_constants,
+                              external_functions_table, trend_component_model_table),
+    static_model(symbol_table, num_constants,
+                 external_functions_table, trend_component_model_table),
+    steady_state_model(symbol_table, num_constants,
+                       external_functions_table, trend_component_model_table, static_model),
+    diff_static_model(symbol_table, num_constants,
+                      external_functions_table, trend_component_model_table),
     linear(false), block(false), byte_code(false), use_dll(false), no_static(false),
     differentiate_forward_vars(false), nonstationary_variables(false),
     param_used_with_lead_lag(false), warnings(warnings_arg)
@@ -368,16 +378,10 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
   set<string> eqtags;
   map<string, vector<string>> var_model_eq_tags;
   map<string, pair<SymbolList, int>> var_model_info_var_expectation;
-  for (auto & statement : statements)
-    {
-      auto *vms = dynamic_cast<VarModelStatement *>(statement);
-      if (vms != nullptr)
-        {
-          vms->getVarModelInfo(var_model_name, var_model_info_var_expectation, var_model_eq_tags);
-          for (auto & eqtag : var_model_eq_tags[var_model_name])
-            eqtags.insert(eqtag);
-        }
-    }
+
+  for (auto const &it : trend_component_model_table.getEqTags())
+    for (auto &it1 : it.second)
+      eqtags.insert(it1);
 
   if (transform_unary_ops)
     dynamic_model.substituteUnaryOps(diff_static_model);
@@ -389,64 +393,46 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
   ExprNode::subst_table_t diff_subst_table;
   dynamic_model.substituteDiff(diff_static_model, diff_subst_table);
 
+  // Fill Trend Component Model Table
+  dynamic_model.fillTrendComponentModelTable();
+  original_model.fillTrendComponentModelTableFromOrigModel(diff_static_model);
+
   // Var Model
-  map<string, tuple<vector<int>, vector<expr_t>, vector<bool>, vector<int>, int, vector<bool>, vector<int>>>
-    var_model_info_pac_expectation;
   for (auto & statement : statements)
     {
-      int max_lag;
-      string var_model_name;
-      vector<string> eqtags;
-      vector<expr_t> lhs_expr_t;
-      vector<bool> nonstationary, diff;
-      vector<int> lhs, eqnumber, orig_diff_var;
-      auto *vms = dynamic_cast<VarModelStatement *>(statement);
-      if (vms != nullptr)
-        {
-          vector<set<pair<int, int>>> rhs;
-          vms->getVarModelInfo(var_model_name, var_model_info_var_expectation, var_model_eq_tags);
-          eqtags = var_model_eq_tags[var_model_name];
-          dynamic_model.getVarModelVariablesFromEqTags(eqtags,
-                                                       eqnumber, lhs, lhs_expr_t, rhs, nonstationary);
-          original_model.checkVarMinLag(eqnumber);
-          max_lag = original_model.getVarMaxLag(diff_static_model, eqnumber);
-          original_model.getVarLhsDiffAndInfo(eqnumber, diff, orig_diff_var);
-          vms->fillVarModelInfoFromEquations(eqnumber, lhs, rhs, nonstationary,
-                                             diff, orig_diff_var, max_lag);
-          var_model_info_pac_expectation[var_model_name] =
-            { lhs, lhs_expr_t, diff, orig_diff_var, max_lag, nonstationary, eqnumber };
-        }
       auto *pms = dynamic_cast<PacModelStatement *>(statement);
       if (pms != nullptr)
          {
-           int growth_symb_id;
-           string pac_model_name;
-           map<string, int> undiff;
-           tuple<string, string, string, int, map<string, int>> pac_model_info_pac_expectation;
-           pms->getPacModelInfoForPacExpectation(pac_model_info_pac_expectation);
-           tie ( pac_model_name, var_model_name, ignore, growth_symb_id, undiff ) = pac_model_info_pac_expectation;
-           eqtags = var_model_eq_tags[var_model_name];
-           if (!eqtags.empty())
+           vector<int> lhs;
+           vector<bool> nonstationary;
+           int growth_symb_id, max_lag;
+           string aux_model_name, pac_model_name;
+           tie ( pac_model_name, aux_model_name, growth_symb_id ) =
+             pms->getPacModelInfoForPacExpectation();
+           if (trend_component_model_table.isExistingTrendComponentModelName(aux_model_name))
+             {
+               max_lag = trend_component_model_table.getMaxLag(aux_model_name) + 1;
+               lhs = dynamic_model.getUndiffLHSForPac(aux_model_name, diff_subst_table);
+               nonstationary = trend_component_model_table.getNonstationary(aux_model_name);
+             }
+           else
              {
-               tie ( lhs, lhs_expr_t, diff, orig_diff_var, max_lag, nonstationary, eqnumber ) =
-                 var_model_info_pac_expectation[var_model_name];
-               if (!undiff.empty())
-                 {
-                   dynamic_model.getUndiffLHSForPac(lhs, lhs_expr_t, diff, orig_diff_var, eqnumber, undiff, diff_subst_table);
-                   max_lag++;
-                 }
-               pms->fillUndiffedLHS(lhs);
-               dynamic_model.walkPacParameters();
-               int pac_max_lag = original_model.getPacMaxLag(pac_model_name);
-               dynamic_model.fillPacExpectationVarInfo(pac_model_name, lhs, max_lag, pac_max_lag, nonstationary, growth_symb_id);
-               dynamic_model.substitutePacExpectation();
+               // get var_model lhs and max_lag; for now stop with error
+               cerr << "ERROR: var_models not yet supported for use with pac_model" << endl;
+               exit(EXIT_FAILURE);
              }
+           pms->fillUndiffedLHS(lhs);
+           dynamic_model.walkPacParameters();
+           int pac_max_lag = original_model.getPacMaxLag(pac_model_name);
+           dynamic_model.fillPacExpectationVarInfo(pac_model_name, lhs, max_lag,
+                                                   pac_max_lag, nonstationary, growth_symb_id);
+           dynamic_model.substitutePacExpectation();
          }
      }
-
+  /*
   if (!var_model_info_var_expectation.empty())
     dynamic_model.addEquationsForVar(var_model_info_var_expectation);
-
+  */
   if (symbol_table.predeterminedNbr() > 0)
     dynamic_model.transformPredeterminedVariables();
 
@@ -542,9 +528,11 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
       vector<set<pair<int, int>>> rhs;
       vector<bool> nonstationary;
       vector<string> eqtags{var_model_eq_tags[var_model_name]};
+      /*
       dynamic_model.getVarModelVariablesFromEqTags(eqtags,
                                                    eqnumber, lhs, lhs_expr_t, rhs, nonstationary);
-      int max_lag{original_model.getVarMaxLag(diff_static_model, eqnumber)};
+      */
+      int max_lag = trend_component_model_table.getMaxLag(var_model_name);
 
       /* Create auxiliary parameters and the expression to be substituted to
          the var_expectations statement */
@@ -596,13 +584,15 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
      probably add a VarModelTable class (similar to SymbolTable) for storing all
      this information about VAR models, instead of putting it inside the
      Statement(s) classes */
+  dynamic_model.fillTrendComponentModelTable();
+  /*
   for (auto & statement : statements)
     {
       auto *vms = dynamic_cast<VarModelStatement *>(statement);
       if (vms != nullptr)
         {
           string var_model_name;
-          vms->getVarModelInfo(var_model_name, var_model_info_var_expectation, var_model_eq_tags);
+          //vms->getVarModelInfo(var_model_name, var_model_info_var_expectation, var_model_eq_tags);
           vector<expr_t> lhs_expr_t;
           vector<int> lhs, eqnumber, orig_diff_var;
           vector<set<pair<int, int>>> rhs;
@@ -610,13 +600,15 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
           vector<string> eqtags = var_model_eq_tags[var_model_name];
           dynamic_model.getVarModelVariablesFromEqTags(eqtags,
                                                        eqnumber, lhs, lhs_expr_t, rhs, nonstationary);
-          int max_lag = original_model.getVarMaxLag(diff_static_model, eqnumber);
-          original_model.getVarLhsDiffAndInfo(eqnumber, diff, orig_diff_var);
+
+          int max_lag = trend_component_model_table.getMaxLag(var_model_name);
+      //          int max_lag = original_model.getVarMaxLag(diff_static_model, eqnumber);
+          //original_model.getVarLhsDiffAndInfo(eqnumber, diff, orig_diff_var);
           vms->fillVarModelInfoFromEquations(eqnumber, lhs, rhs, nonstationary,
                                              diff, orig_diff_var, max_lag);
         }
     }
-
+*/
   if (differentiate_forward_vars)
     dynamic_model.differentiateForwardVars(differentiate_forward_vars_subset);
 
@@ -911,6 +903,8 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
 
   symbol_table.writeOutput(mOutputFile);
 
+  trend_component_model_table.writeOutput(mOutputFile);
+
   // Initialize M_.Sigma_e, M_.Correlation_matrix, M_.H, and M_.Correlation_matrix_ME
   mOutputFile << "M_.Sigma_e = zeros(" << symbol_table.exo_nbr() << ", "
               << symbol_table.exo_nbr() << ");" << endl
diff --git a/src/ModFile.hh b/src/ModFile.hh
index 1ecac964..2e33b74e 100644
--- a/src/ModFile.hh
+++ b/src/ModFile.hh
@@ -38,6 +38,7 @@ using namespace std;
 #include "ConfigFile.hh"
 #include "WarningConsolidation.hh"
 #include "ExtendedPreprocessorTypes.hh"
+#include "SubModel.hh"
 
 //! The abstract representation of a "mod" file
 class ModFile
@@ -51,6 +52,8 @@ public:
   ExternalFunctionsTable external_functions_table;
   //! Numerical constants table
   NumericalConstants num_constants;
+  //! Trend Component Model Table used for storing info about trend component models
+  TrendComponentModelTable trend_component_model_table;
   //! Expressions outside model block
   DataTree expressions_tree;
   //! Original model, as declared in the "model" block, that won't be modified by the preprocessor
@@ -69,6 +72,7 @@ public:
   SteadyStateModel steady_state_model;
   //! Static model used for mapping arguments of diff operator
   StaticModel diff_static_model;
+
   //! Option linear
   bool linear;
 
diff --git a/src/ModelTree.cc b/src/ModelTree.cc
index 31343942..401ad86b 100644
--- a/src/ModelTree.cc
+++ b/src/ModelTree.cc
@@ -1003,8 +1003,10 @@ ModelTree::BlockLinear(const blocks_derivatives_t &blocks_derivatives, const vec
 
 ModelTree::ModelTree(SymbolTable &symbol_table_arg,
                      NumericalConstants &num_constants_arg,
-                     ExternalFunctionsTable &external_functions_table_arg) :
-  DataTree(symbol_table_arg, num_constants_arg, external_functions_table_arg),
+                     ExternalFunctionsTable &external_functions_table_arg,
+                     TrendComponentModelTable &trend_component_model_table_arg) :
+  DataTree(symbol_table_arg, num_constants_arg,
+           external_functions_table_arg, trend_component_model_table_arg),
   cutoff(1e-15),
   mfs(0)
 
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index bee2defd..84772d5b 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -321,7 +321,10 @@ protected:
   //! Initialize equation_reordered & variable_reordered
   void initializeVariablesAndEquations();
 public:
-  ModelTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg);
+  ModelTree(SymbolTable &symbol_table_arg,
+            NumericalConstants &num_constants_arg,
+            ExternalFunctionsTable &external_functions_table_arg,
+            TrendComponentModelTable &trend_component_model_table_arg);
   //! Absolute value under which a number is considered to be zero
   double cutoff;
   //! Compute the minimum feedback set
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index dc97c67c..5265aa82 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -348,7 +348,8 @@ ParsingDriver::declare_or_change_type(SymbolType new_type, const string &name)
       // change in equations in ModelTree
       auto dm = make_unique<DynamicModel>(mod_file->symbol_table,
                                           mod_file->num_constants,
-                                          mod_file->external_functions_table);
+                                          mod_file->external_functions_table,
+                                          mod_file->trend_component_model_table);
       mod_file->dynamic_model.updateAfterVariableChange(*dm);
 
       // remove error messages
@@ -1418,6 +1419,30 @@ ParsingDriver::stoch_simul()
   options_list.clear();
 }
 
+void
+ParsingDriver::trend_component_model()
+{
+ OptionsList::string_options_t::const_iterator it =
+   options_list.string_options.find("trend_component.name");
+  if (it == options_list.string_options.end())
+    error("You must pass the model_name option to the trend_component_model statement.");
+  auto name = it->second;
+
+  OptionsList::vec_str_options_t::const_iterator it1 =
+    options_list.vector_str_options.find("trend_component.eqtags");
+  if (it1 == options_list.vector_str_options.end())
+    error("You must pass the eqtags option to the trend_component_model statement.");
+  auto eqtags = it1->second;
+
+  it1 = options_list.vector_str_options.find("trend_component.trends");
+  if (it1 == options_list.vector_str_options.end())
+    error("You must pass the trends option to the trend_component_model statement.");
+  auto trends = it1->second;
+
+  mod_file->trend_component_model_table.addTrendComponentModel(name, eqtags, trends);
+  options_list.clear();
+}
+
 void
 ParsingDriver::var_model()
 {
@@ -2045,7 +2070,10 @@ ParsingDriver::run_model_comparison()
 void
 ParsingDriver::begin_planner_objective()
 {
-  planner_objective_statement = new PlannerObjectiveStatement(mod_file->symbol_table, mod_file->num_constants, mod_file->external_functions_table);
+  planner_objective_statement = new PlannerObjectiveStatement(mod_file->symbol_table,
+                                                              mod_file->num_constants,
+                                                              mod_file->external_functions_table,
+                                                              mod_file->trend_component_model_table);
 
   set_current_data_tree(&planner_objective_statement->getPlannerObjective());
 }
@@ -2527,10 +2555,10 @@ ParsingDriver::pac_model()
     error("You must pass the model_name option to the pac_model statement.");
   auto name = it->second;
 
-  it = options_list.string_options.find("pac.var_model_name");
+  it = options_list.string_options.find("pac.aux_model_name");
   if (it == options_list.string_options.end())
-    error("You must pass the var_model_name option to the pac_model statement.");
-  auto var_name = it->second;
+    error("You must pass the auxiliary_model_name option to the pac_model statement.");
+  auto aux_model_name = it->second;
 
   it = options_list.string_options.find("pac.discount");
   if (it == options_list.string_options.end())
@@ -2542,17 +2570,11 @@ ParsingDriver::pac_model()
   if (it != options_list.string_options.end())
     growth = it->second;
 
-  mod_file->addStatement(new PacModelStatement(name, var_name, discount, growth, pac_undiff, mod_file->symbol_table));
+  mod_file->addStatement(new PacModelStatement(name, aux_model_name, discount, growth,
+                                               mod_file->symbol_table));
 
   symbol_list.clear();
   options_list.clear();
-  pac_undiff.clear();
-}
-
-void
-ParsingDriver::pac_model_undiff(string eqtag, const string &order)
-{
-  pac_undiff[move(eqtag)] = stoi(order);
 }
 
 expr_t
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index e055199f..b53af1ab 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -242,8 +242,6 @@ private:
   SymbolList graph_formats;
   //! Temporary storage for equation tags
   vector<pair<string, string>> eq_tags;
-  //! Temporary storage for pac statement undiff option
-  map<string, int> pac_undiff;
 
   //! Map Var name to variables
   map<string, vector<string>> var_map;
@@ -463,6 +461,8 @@ public:
   void rplot();
   //! Writes a stock_simul command
   void stoch_simul();
+  //! Writes a trend component command
+  void trend_component_model();
   //! Writes a var (vector autoregression) command
   void var_model();
   //! Writes a simul command
@@ -697,8 +697,6 @@ public:
   expr_t add_pac_expectation(const string &var_model_name);
   //! Creates pac_model statement
   void pac_model();
-  //! Add undiff option for pac_model statement
-  void pac_model_undiff(string eqtag, const string &order);
   //! Writes token "diff(arg1)" to model tree
   expr_t add_diff(expr_t arg1);
   //! Writes token "adl(arg1, lag)" to model tree
diff --git a/src/StaticModel.cc b/src/StaticModel.cc
index 60ed9fc1..f9834c2f 100644
--- a/src/StaticModel.cc
+++ b/src/StaticModel.cc
@@ -31,8 +31,10 @@
 
 StaticModel::StaticModel(SymbolTable &symbol_table_arg,
                          NumericalConstants &num_constants_arg,
-                         ExternalFunctionsTable &external_functions_table_arg) :
-  ModelTree(symbol_table_arg, num_constants_arg, external_functions_table_arg),
+                         ExternalFunctionsTable &external_functions_table_arg,
+                         TrendComponentModelTable &trend_component_model_table_arg) :
+  ModelTree(symbol_table_arg, num_constants_arg,
+            external_functions_table_arg, trend_component_model_table_arg),
   global_temporary_terms(true)
 {
 }
diff --git a/src/StaticModel.hh b/src/StaticModel.hh
index 4fad5171..5374739d 100644
--- a/src/StaticModel.hh
+++ b/src/StaticModel.hh
@@ -160,7 +160,10 @@ protected:
   void writeStaticModel(ostream &DynamicOutput, bool use_dll, bool julia) const;
   void writeStaticModel(const string &dynamic_basename, bool use_dll, bool julia) const;
 public:
-  StaticModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants, ExternalFunctionsTable &external_functions_table_arg);
+  StaticModel(SymbolTable &symbol_table_arg,
+              NumericalConstants &num_constants,
+              ExternalFunctionsTable &external_functions_table_arg,
+              TrendComponentModelTable &trend_component_model_table_arg);
 
   //! Writes information on block decomposition when relevant
   void writeOutput(ostream &output, bool block) const;
diff --git a/src/SteadyStateModel.cc b/src/SteadyStateModel.cc
index d3bee83b..282d8e1b 100644
--- a/src/SteadyStateModel.cc
+++ b/src/SteadyStateModel.cc
@@ -22,8 +22,14 @@
 
 #include "SteadyStateModel.hh"
 
-SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg, const StaticModel &static_model_arg) :
-  DataTree(symbol_table_arg, num_constants_arg, external_functions_table_arg), static_model(static_model_arg)
+SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg,
+                                   NumericalConstants &num_constants_arg,
+                                   ExternalFunctionsTable &external_functions_table_arg,
+                                   TrendComponentModelTable &trend_component_model_table_arg,
+                                   const StaticModel &static_model_arg) :
+  DataTree(symbol_table_arg, num_constants_arg,
+           external_functions_table_arg, trend_component_model_table_arg),
+  static_model(static_model_arg)
 {
 }
 
diff --git a/src/SteadyStateModel.hh b/src/SteadyStateModel.hh
index 04166dd8..d3b4e2db 100644
--- a/src/SteadyStateModel.hh
+++ b/src/SteadyStateModel.hh
@@ -35,7 +35,11 @@ private:
   const StaticModel &static_model;
 
 public:
-  SteadyStateModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg, const StaticModel &static_model_arg);
+  SteadyStateModel(SymbolTable &symbol_table_arg,
+                   NumericalConstants &num_constants_arg,
+                   ExternalFunctionsTable &external_functions_table_arg,
+                   TrendComponentModelTable &trend_component_model_table_arg,
+                   const StaticModel &static_model_arg);
   //! Add an expression of the form "var = expr;"
   void addDefinition(int symb_id, expr_t expr);
   //! Add an expression of the form "[ var1, var2, ... ] = expr;"
diff --git a/src/SubModel.cc b/src/SubModel.cc
new file mode 100644
index 00000000..2d69b4de
--- /dev/null
+++ b/src/SubModel.cc
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2018 Dynare Team
+ *
+ * This file is part of Dynare.
+ *
+ * Dynare 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.
+ *
+ * Dynare 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 Dynare.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <algorithm>
+
+#include "SubModel.hh"
+
+TrendComponentModelTable::TrendComponentModelTable(SymbolTable &symbol_table_arg) :
+  symbol_table(symbol_table_arg)
+{
+}
+
+void
+TrendComponentModelTable::addTrendComponentModel(string name_arg,
+                                                 vector<string> eqtags_arg,
+                                                 vector<string> trend_eqtags_arg)
+{
+  if (isExistingTrendComponentModelName(name_arg))
+    {
+      cerr << "Error: a trend component model already exists with the name " << name_arg << endl;
+      exit(EXIT_FAILURE);
+    }
+  eqtags[name_arg] = move(eqtags_arg);
+  trend_eqtags[name_arg] = move(trend_eqtags_arg);
+  names.insert(move(name_arg));
+}
+
+void
+TrendComponentModelTable::setEqNums(map<string, vector<int>> eqnums_arg)
+{
+  eqnums = move(eqnums_arg);
+  setUndiffEqnums();
+}
+
+void
+TrendComponentModelTable::setTrendEqNums(map<string, vector<int>> trend_eqnums_arg)
+{
+  trend_eqnums = move(trend_eqnums_arg);
+  setUndiffEqnums();
+}
+
+void
+TrendComponentModelTable::setUndiffEqnums()
+{
+  if (!nontrend_eqnums.empty() || eqnums.empty() || trend_eqnums.empty())
+    return;
+
+  for (const auto &it : eqnums)
+    {
+      vector<int> nontrend_vec;
+      for (auto eq : it.second)
+        if (find(trend_eqnums[it.first].begin(), trend_eqnums[it.first].end(), eq)
+            == trend_eqnums[it.first].end())
+          nontrend_vec.push_back(eq);
+      nontrend_eqnums[it.first] = nontrend_vec;
+    }
+}
+
+void
+TrendComponentModelTable::setNonstationary(map<string, vector<bool>> nonstationary_arg)
+{
+  nonstationary = move(nonstationary_arg);
+}
+
+void
+TrendComponentModelTable::setLhs(map<string, vector<int>> lhs_arg)
+{
+  lhs = move(lhs_arg);
+}
+
+void
+TrendComponentModelTable::setRhs(map<string, vector<set<pair<int, int>>>> rhs_arg)
+{
+  rhs = move(rhs_arg);
+}
+
+void
+TrendComponentModelTable::setLhsExprT(map<string, vector<expr_t>> lhs_expr_t_arg)
+{
+  lhs_expr_t = move(lhs_expr_t_arg);
+}
+
+void
+TrendComponentModelTable::setMaxLags(map<string, vector<int>> max_lags_arg)
+{
+  max_lags = move(max_lags_arg);
+}
+
+void
+TrendComponentModelTable::setDiff(map<string, vector<bool>> diff_arg)
+{
+  diff = move(diff_arg);
+}
+
+void
+TrendComponentModelTable::setOrigDiffVar(map<string, vector<int>> orig_diff_var_arg)
+{
+  orig_diff_var = move(orig_diff_var_arg);
+}
+
+map<string, vector<string>>
+TrendComponentModelTable::getEqTags() const
+{
+  return eqtags;
+}
+
+vector<string>
+TrendComponentModelTable::getEqTags(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return eqtags.find(name_arg)->second;
+}
+
+void
+TrendComponentModelTable::checkModelName(const string &name_arg) const
+{
+  if (!isExistingTrendComponentModelName(name_arg))
+    {
+      cerr << name_arg
+           << " is not a recognized equation tag of a trend component model equation" << endl;
+      exit(EXIT_FAILURE);
+    }
+}
+
+vector<bool>
+TrendComponentModelTable::getNonstationary(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return nonstationary.find(name_arg)->second;
+}
+
+vector<int>
+TrendComponentModelTable::getLhs(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return lhs.find(name_arg)->second;
+}
+
+vector<expr_t>
+TrendComponentModelTable::getLhsExprT(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return lhs_expr_t.find(name_arg)->second;
+}
+
+map<string, vector<string>>
+TrendComponentModelTable::getTrendEqTags() const
+{
+  return trend_eqtags;
+}
+
+map<string, vector<int>>
+TrendComponentModelTable::getEqNums() const
+{
+  return eqnums;
+}
+
+vector<int>
+TrendComponentModelTable::getNonTrendEqNums(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return nontrend_eqnums.find(name_arg)->second;
+}
+
+vector<int>
+TrendComponentModelTable::getEqNums(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return eqnums.find(name_arg)->second;
+}
+
+vector<int>
+TrendComponentModelTable::getMaxLags(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return max_lags.find(name_arg)->second;
+}
+
+int
+TrendComponentModelTable::getMaxLag(const string &name_arg) const
+{
+  int max_lag_int = 0;
+  for (auto it : getMaxLags(name_arg))
+    max_lag_int = max(max_lag_int, it);
+  return max_lag_int;
+}
+
+vector<bool>
+TrendComponentModelTable::getDiff(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return diff.find(name_arg)->second;
+}
+
+vector<int>
+TrendComponentModelTable::getOrigDiffVar(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return orig_diff_var.find(name_arg)->second;
+}
+
+void
+TrendComponentModelTable::writeOutput(ostream &output) const
+{
+  for (const auto &name : names)
+    {
+      output << "M_.trend_component." << name << ".model_name = '" << name << "'" << endl
+             << "M_.trend_component." << name << ".eqtags = {";
+      for (const auto &it : eqtags.at(name))
+        output << "'" << it << "'; ";
+      output << "};" << endl
+             << "M_.trend_component." << name << ".eqn = [";
+      for (auto it : eqnums.at(name))
+        output << it + 1 << " ";
+      output << "];" << endl
+             << "M_.trend_component." << name << ".trend_eqn = [";
+      for (auto it : trend_eqnums.at(name))
+        output << it + 1 << " ";
+      output << "];" << endl
+             << "M_.trend_component." << name << ".trends = [";
+      for (auto it : eqnums.at(name))
+        if (find(trend_eqnums.at(name).begin(), trend_eqnums.at(name).end(), it)
+            == trend_eqnums.at(name).end())
+          output << "false ";
+        else
+          output << "true ";
+      output << "];" << endl
+             << "M_.trend_component." << name << ".lhs = [";
+      for (auto it : lhs.at(name))
+        output << symbol_table.getTypeSpecificID(it) + 1 << " ";
+      output << "];" << endl
+             << "M_.trend_component." << name << ".max_lag = [";
+      for (auto it : max_lags.at(name))
+        output << it << " ";
+      output << "];" << endl
+             << "M_.trend_component." << name << ".diff = [";
+      for (const auto &it : diff.at(name))
+        output << (it ? "true" : "false") << " ";
+      output << "];" << endl
+             << "M_.trend_component." << name << ".orig_diff_var = [";
+      for (auto it : orig_diff_var.at(name))
+        output << (it >= 0 ? symbol_table.getTypeSpecificID(it) + 1 : -1) << " ";
+      output << "];" << endl;
+
+      int i = 1;
+      for (const auto &it : rhs.at(name))
+        {
+          output << "M_.trend_component." << name << ".rhs.vars_at_eq{" << i << "}.var = [";
+          for (const auto &it1 : it)
+            output << symbol_table.getTypeSpecificID(it1.first) + 1 << " ";
+          output << "];" << endl
+                 << "M_.trend_component." << name << ".rhs.vars_at_eq{" << i << "}.lag = [";
+          for (const auto &it1 : it)
+            output << it1.second << " ";
+          output << "];" << endl;
+
+          i++;
+        }
+    }
+}
+
+void
+TrendComponentModelTable::writeJsonOutput(ostream &output) const
+{
+  for (const auto &name : names)
+    {
+      if (name != *(names.begin()))
+        output << ", ";
+      output << "{\"statementName\": \"trend_component_model\","
+             << "\"model_name\": \"" << name << "\"}";
+    }
+}
diff --git a/src/SubModel.hh b/src/SubModel.hh
new file mode 100644
index 00000000..e7fa2759
--- /dev/null
+++ b/src/SubModel.hh
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 Dynare Team
+ *
+ * This file is part of Dynare.
+ *
+ * Dynare 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.
+ *
+ * Dynare 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 Dynare.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SUBMODEL_HH
+#define _SUBMODEL_HH
+
+#include <set>
+#include <map>
+#include <vector>
+#include <iostream>
+
+#include "ExprNode.hh"
+#include "SymbolTable.hh"
+
+using namespace std;
+
+//! A table with all Trend Component Models in the .mod file
+/*!
+  The unique name of the trend component model is the identifier
+*/
+class TrendComponentModelTable
+{
+private:
+  SymbolTable &symbol_table;
+  set<string> names;
+  map<string, vector<string>> eqtags, trend_eqtags;
+  map<string, vector<int>> eqnums, trend_eqnums, nontrend_eqnums, max_lags, lhs, orig_diff_var;
+  map<string, vector<set<pair<int, int>>>> rhs;
+  map<string, vector<bool>> diff, nonstationary;
+  map<string, vector<expr_t>> lhs_expr_t;
+public:
+  TrendComponentModelTable(SymbolTable &symbol_table_arg);
+
+  //! Add a trend component model
+  void addTrendComponentModel(string name, vector<string> eqtags, vector<string> trend_eqtags);
+
+  inline bool isExistingTrendComponentModelName(const string &name_arg) const;
+
+  map<string, vector<string>> getEqTags() const;
+  vector<string> getEqTags(const string &name_arg) const;
+  map<string, vector<string>> getTrendEqTags() const;
+  map<string, vector<int>> getEqNums() const;
+  vector<int> getEqNums(const string &name_arg) const;
+  vector<int> getMaxLags(const string &name_arg) const;
+  int getMaxLag(const string &name_arg) const;
+  vector<int> getLhs(const string &name_arg) const;
+  vector<expr_t> getLhsExprT(const string &name_arg) const;
+  vector<bool> getDiff(const string &name_arg) const;
+  vector<int> getOrigDiffVar(const string &name_arg) const;
+  vector<int> getNonTrendEqNums(const string &name_arg) const;
+  vector<bool> getNonstationary(const string &name_arg) const;
+
+  void setEqNums(map<string, vector<int>> eqnums_arg);
+  void setTrendEqNums(map<string, vector<int>> trend_eqnums_arg);
+  void setLhs(map<string, vector<int>> lhs_arg);
+  void setRhs(map<string, vector<set<pair<int, int>>>> rhs_arg);
+  void setLhsExprT(map<string, vector<expr_t>> lhs_expr_t_arg);
+  void setMaxLags(map<string, vector<int>> max_lags_arg);
+  void setDiff(map<string, vector<bool>> diff_arg);
+  void setOrigDiffVar(map<string, vector<int>> orig_diff_var_arg);
+  void setNonstationary(map<string, vector<bool>> nonstationary_arg);
+
+  //! Write output of this class
+  void writeOutput(ostream &output) const;
+
+  //! Write JSON Output
+  void writeJsonOutput(ostream &output) const;
+
+private:
+  void checkModelName(const string &name_arg) const;
+  void setUndiffEqnums();
+};
+
+inline bool
+TrendComponentModelTable::isExistingTrendComponentModelName(const string &name_arg) const
+{
+  return names.find(name_arg) == names.end() ? false : true;
+}
+
+#endif
-- 
GitLab