From 157c67e04b37e738d3b6aa339cd0f59bff807ec1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Tue, 12 Jul 2022 15:28:52 +0200
Subject: [PATCH] New helpers to simplify common operations with derivation IDs

---
 src/DataTree.cc     |  6 +++++
 src/DataTree.hh     | 13 ++++++++-
 src/DynamicModel.cc | 66 ++++++++++++++++++++++++---------------------
 src/DynamicModel.hh |  5 ++--
 src/ModelTree.cc    | 10 +++----
 src/ModelTree.hh    | 16 +++++------
 src/StaticModel.cc  | 65 +++++++++++++++++++++++++-------------------
 src/StaticModel.hh  |  6 ++---
 8 files changed, 106 insertions(+), 81 deletions(-)

diff --git a/src/DataTree.cc b/src/DataTree.cc
index f2d17173..56f506ed 100644
--- a/src/DataTree.cc
+++ b/src/DataTree.cc
@@ -827,6 +827,12 @@ DataTree::getSymbIDByDerivID([[maybe_unused]] int deriv_id) const noexcept(false
   throw UnknownDerivIDException();
 }
 
+int
+DataTree::getTypeSpecificIDByDerivID([[maybe_unused]] int deriv_id) const
+{
+  throw UnknownDerivIDException();
+}
+
 void
 DataTree::addAllParamDerivId([[maybe_unused]] set<int> &deriv_id_set)
 {
diff --git a/src/DataTree.hh b/src/DataTree.hh
index d8e9439e..73f8a7e8 100644
--- a/src/DataTree.hh
+++ b/src/DataTree.hh
@@ -300,11 +300,22 @@ public:
     }
   };
 
-  //! Returns the derivation ID, or throws an exception if the derivation ID does not exist
+  // Returns the derivation ID, or throws an exception if the derivation ID does not exist
   virtual int getDerivID(int symb_id, int lag) const noexcept(false);
+  // Get the type corresponding to a derivation ID
   virtual SymbolType getTypeByDerivID(int deriv_id) const noexcept(false);
+  // Get the lag corresponding to a derivation ID
   virtual int getLagByDerivID(int deriv_id) const noexcept(false);
+  // Get the symbol ID corresponding to a derivation ID
   virtual int getSymbIDByDerivID(int deriv_id) const noexcept(false);
+  // Get the type-specific ID corresponding to a derivation ID
+  virtual int getTypeSpecificIDByDerivID(int deriv_id) const;
+  // Get the symbol name corresponding to a derivation ID
+  string
+  getNameByDerivID(int deriv_id) const
+  {
+    return symbol_table.getName(getSymbIDByDerivID(deriv_id));
+  }
 
   //! Returns the column of the Jacobian associated to a derivation ID
   virtual int
diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 9e17b4c0..a2e7c9fa 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -564,8 +564,7 @@ DynamicModel::writeDynamicBytecode(const string &basename) const
     {
       int deriv_id = indices[1];
       int eq = indices[0];
-      int symb = getSymbIDByDerivID(deriv_id);
-      int var = symbol_table.getTypeSpecificID(symb);
+      int var { getTypeSpecificIDByDerivID(deriv_id) };
       int lag = getLagByDerivID(deriv_id);
       if (getTypeByDerivID(deriv_id) == SymbolType::endogenous)
         first_derivatives_reordered_endo[{ lag, var, eq }] = d1;
@@ -652,8 +651,7 @@ DynamicModel::writeDynamicBytecode(const string &basename) const
       if (getTypeByDerivID(deriv_id) == SymbolType::endogenous)
         {
           int eq = indices[0];
-          int symb = getSymbIDByDerivID(deriv_id);
-          int var = symbol_table.getTypeSpecificID(symb);
+          int var { getTypeSpecificIDByDerivID(deriv_id) };
           int lag = getLagByDerivID(deriv_id);
           code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, eq, var, lag};
           if (!my_derivatives[eq].size())
@@ -1830,7 +1828,7 @@ DynamicModel::writeDynamicJacobianNonZeroElts(const string &basename) const
     {
       if (getTypeByDerivID(indices[1]) != SymbolType::endogenous)
         continue;
-      int tsid = symbol_table.getTypeSpecificID(getSymbIDByDerivID(indices[1]));
+      int tsid { getTypeSpecificIDByDerivID(indices[1]) };
       int lag = getLagByDerivID(indices[1]);
       if (lag == -1)
         nzij_pred.emplace_back(tsid, indices[0]);
@@ -2253,7 +2251,7 @@ DynamicModel::writeBlockDriverOutput(ostream &output, const string &basename,
         getTypeByDerivID(deriv_id) == SymbolType::endogenous)
       {
         int eq = indices[0];
-        int var = symbol_table.getTypeSpecificID(getSymbIDByDerivID(deriv_id));
+        int var { getTypeSpecificIDByDerivID(deriv_id) };
         int lag = getLagByDerivID(deriv_id);
         lag_row_incidence[lag].insert({ eq, var });
       }
@@ -3971,7 +3969,7 @@ DynamicModel::computeBlockDynJacobianCols()
       int eq_orig = indices[0];
       int block_eq = eq2block[eq_orig];
       int eq = getBlockInitialEquationID(block_eq, eq_orig);
-      int var = symbol_table.getTypeSpecificID(getSymbIDByDerivID(indices[1]));
+      int var { getTypeSpecificIDByDerivID(indices[1]) };
       int lag = getLagByDerivID(indices[1]);
       switch (getTypeByDerivID(indices[1]))
         {
@@ -4440,6 +4438,12 @@ DynamicModel::getSymbIDByDerivID(int deriv_id) const noexcept(false)
   return inv_deriv_id_table[deriv_id].first;
 }
 
+int
+DynamicModel::getTypeSpecificIDByDerivID(int deriv_id) const
+{
+  return symbol_table.getTypeSpecificID(getSymbIDByDerivID(deriv_id));
+}
+
 int
 DynamicModel::getDerivID(int symb_id, int lag) const noexcept(false)
 {
@@ -5446,7 +5450,7 @@ DynamicModel::writeJsonComputingPassOutput(ostream &output, bool writeDetails) c
 
           if (writeDetails)
             for (size_t j = 1; j < vidx.size(); j++)
-              d_output[i] << R"(, "var)" << (i > 1 ? to_string(j) : "") << R"(": ")" << symbol_table.getName(getSymbIDByDerivID(vidx[j])) << R"(")"
+              d_output[i] << R"(, "var)" << (i > 1 ? to_string(j) : "") << R"(": ")" << getNameByDerivID(vidx[j]) << R"(")"
                           << R"(, "shift)" << (i > 1 ? to_string(j) : "") << R"(": )" << getLagByDerivID(vidx[j]);
 
           d_output[i] << R"(, "val": ")";
@@ -5502,7 +5506,7 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
 
       auto [eq, param] = vectorToTuple<2>(vidx);
 
-      int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
+      int param_col { getTypeSpecificIDByDerivID(param) + 1 };
 
       if (writeDetails)
         rp_output << R"({"eq": )" << eq + 1;
@@ -5512,7 +5516,7 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
       rp_output << R"(, "param_col": )" << param_col + 1;
 
       if (writeDetails)
-        rp_output << R"(, "param": ")" << symbol_table.getName(getSymbIDByDerivID(param)) << R"(")";
+        rp_output << R"(, "param": ")" << getNameByDerivID(param) << R"(")";
 
       rp_output << R"(, "val": ")";
       d->writeJsonOutput(rp_output, temp_term_union, tef_terms);
@@ -5534,7 +5538,7 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
       auto [eq, var, param] = vectorToTuple<3>(vidx);
 
       int var_col = getJacobianCol(var) + 1;
-      int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
+      int param_col { getTypeSpecificIDByDerivID(param) + 1 };
 
       if (writeDetails)
         gp_output << R"({"eq": )" << eq + 1;
@@ -5545,9 +5549,9 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
                 << R"(, "param_col": )" << param_col + 1;
 
       if (writeDetails)
-        gp_output << R"(, "var": ")" << symbol_table.getName(getSymbIDByDerivID(var)) << R"(")"
+        gp_output << R"(, "var": ")" << getNameByDerivID(var) << R"(")"
                   << R"(, "lag": )" << getLagByDerivID(var)
-                  << R"(, "param": ")" << symbol_table.getName(getSymbIDByDerivID(param)) << R"(")";
+                  << R"(, "param": ")" << getNameByDerivID(param) << R"(")";
 
       gp_output << R"(, "val": ")";
       d->writeJsonOutput(gp_output, temp_term_union, tef_terms);
@@ -5568,8 +5572,8 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
 
       auto [eq, param1, param2] = vectorToTuple<3>(vidx);
 
-      int param1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1;
-      int param2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1;
+      int param1_col { getTypeSpecificIDByDerivID(param1) + 1 };
+      int param2_col { getTypeSpecificIDByDerivID(param2) + 1 };
 
       if (writeDetails)
         rpp_output << R"({"eq": )" << eq + 1;
@@ -5579,8 +5583,8 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
                  << R"(, "param2_col": )" << param2_col + 1;
 
       if (writeDetails)
-        rpp_output << R"(, "param1": ")" << symbol_table.getName(getSymbIDByDerivID(param1)) << R"(")"
-                   << R"(, "param2": ")" << symbol_table.getName(getSymbIDByDerivID(param2)) << R"(")";
+        rpp_output << R"(, "param1": ")" << getNameByDerivID(param1) << R"(")"
+                   << R"(, "param2": ")" << getNameByDerivID(param2) << R"(")";
 
       rpp_output << R"(, "val": ")";
       d->writeJsonOutput(rpp_output, temp_term_union, tef_terms);
@@ -5603,8 +5607,8 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
       auto [eq, var, param1, param2] = vectorToTuple<4>(vidx);
 
       int var_col = getJacobianCol(var) + 1;
-      int param1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1;
-      int param2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1;
+      int param1_col { getTypeSpecificIDByDerivID(param1) + 1 };
+      int param2_col { getTypeSpecificIDByDerivID(param2) + 1 };
 
       if (writeDetails)
         gpp_output << R"({"eq": )" << eq + 1;
@@ -5616,10 +5620,10 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
                  << R"(, "param2_col": )" << param2_col + 1;
 
       if (writeDetails)
-        gpp_output << R"(, "var": ")" << symbol_table.getName(getSymbIDByDerivID(var)) << R"(")"
+        gpp_output << R"(, "var": ")" << getNameByDerivID(var) << R"(")"
                    << R"(, "lag": )" << getLagByDerivID(var)
-                   << R"(, "param1": ")" << symbol_table.getName(getSymbIDByDerivID(param1)) << R"(")"
-                   << R"(, "param2": ")" << symbol_table.getName(getSymbIDByDerivID(param2)) << R"(")";
+                   << R"(, "param1": ")" << getNameByDerivID(param1) << R"(")"
+                   << R"(, "param2": ")" << getNameByDerivID(param2) << R"(")";
 
       gpp_output << R"(, "val": ")";
       d->writeJsonOutput(gpp_output, temp_term_union, tef_terms);
@@ -5643,7 +5647,7 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
 
       int var1_col = getJacobianCol(var1) + 1;
       int var2_col = getJacobianCol(var2) + 1;
-      int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
+      int param_col { getTypeSpecificIDByDerivID(param) + 1 };
 
       if (writeDetails)
         hp_output << R"({"eq": )" << eq + 1;
@@ -5655,11 +5659,11 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
                 << R"(, "param_col": )" << param_col + 1;
 
       if (writeDetails)
-        hp_output << R"(, "var1": ")" << symbol_table.getName(getSymbIDByDerivID(var1)) << R"(")"
+        hp_output << R"(, "var1": ")" << getNameByDerivID(var1) << R"(")"
                   << R"(, "lag1": )" << getLagByDerivID(var1)
-                  << R"(, "var2": ")" << symbol_table.getName(getSymbIDByDerivID(var2)) << R"(")"
+                  << R"(, "var2": ")" << getNameByDerivID(var2) << R"(")"
                   << R"(, "lag2": )" << getLagByDerivID(var2)
-                  << R"(, "param": ")" << symbol_table.getName(getSymbIDByDerivID(param)) << R"(")";
+                  << R"(, "param": ")" << getNameByDerivID(param) << R"(")";
 
       hp_output << R"(, "val": ")";
       d->writeJsonOutput(hp_output, temp_term_union, tef_terms);
@@ -5685,7 +5689,7 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
       int var1_col = getJacobianCol(var1) + 1;
       int var2_col = getJacobianCol(var2) + 1;
       int var3_col = getJacobianCol(var3) + 1;
-      int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
+      int param_col { getTypeSpecificIDByDerivID(param) + 1 };
 
       if (writeDetails)
         g3p_output << R"({"eq": )" << eq + 1;
@@ -5698,13 +5702,13 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
                  << R"(, "param_col": )" << param_col + 1;
 
       if (writeDetails)
-        g3p_output << R"(, "var1": ")" << symbol_table.getName(getSymbIDByDerivID(var1)) << R"(")"
+        g3p_output << R"(, "var1": ")" << getNameByDerivID(var1) << R"(")"
                    << R"(, "lag1": )" << getLagByDerivID(var1)
-                   << R"(, "var2": ")" << symbol_table.getName(getSymbIDByDerivID(var2)) << R"(")"
+                   << R"(, "var2": ")" << getNameByDerivID(var2) << R"(")"
                    << R"(, "lag2": )" << getLagByDerivID(var2)
-                   << R"(, "var3": ")" << symbol_table.getName(getSymbIDByDerivID(var3)) << R"(")"
+                   << R"(, "var3": ")" << getNameByDerivID(var3) << R"(")"
                    << R"(, "lag3": )" << getLagByDerivID(var3)
-                   << R"(, "param": ")" << symbol_table.getName(getSymbIDByDerivID(param)) << R"(")";
+                   << R"(, "param": ")" << getNameByDerivID(param) << R"(")";
 
       g3p_output << R"(, "val": ")";
       d->writeJsonOutput(g3p_output, temp_term_union, tef_terms);
diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh
index ce051ec4..94c5d8fc 100644
--- a/src/DynamicModel.hh
+++ b/src/DynamicModel.hh
@@ -180,12 +180,11 @@ private:
   //! Write chain rule derivative bytecode of an equation w.r. to a variable
   void writeBytecodeChainRuleDerivative(BytecodeWriter &code_file, int blk, int eq, int var, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
 
-  //! Get the type corresponding to a derivation ID
   SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override;
-  //! Get the lag corresponding to a derivation ID
   int getLagByDerivID(int deriv_id) const noexcept(false) override;
-  //! Get the symbol ID corresponding to a derivation ID
   int getSymbIDByDerivID(int deriv_id) const noexcept(false) override;
+  int getTypeSpecificIDByDerivID(int deriv_id) const override;
+
   //! Compute the column indices of the dynamic Jacobian
   void computeDynJacobianCols(bool jacobianExo);
   //! Computes derivatives of the Jacobian w.r. to trend vars and tests that they are equal to zero
diff --git a/src/ModelTree.cc b/src/ModelTree.cc
index f96efb26..bef4a6bd 100644
--- a/src/ModelTree.cc
+++ b/src/ModelTree.cc
@@ -330,8 +330,7 @@ ModelTree::evaluateAndReduceJacobian(const eval_context_t &eval_context) const
       if (getTypeByDerivID(deriv_id) == SymbolType::endogenous)
         {
           int eq = indices[0];
-          int symb = getSymbIDByDerivID(deriv_id);
-          int var = symbol_table.getTypeSpecificID(symb);
+          int var { getTypeSpecificIDByDerivID(deriv_id) };
           int lag = getLagByDerivID(deriv_id);
           double val = 0;
           try
@@ -347,7 +346,7 @@ ModelTree::evaluateAndReduceJacobian(const eval_context_t &eval_context) const
               cerr << "ERROR: evaluation of Jacobian failed for equation " << eq+1;
               if (equations_lineno[eq])
                 cerr << " (line " << *equations_lineno[eq] << ")";
-              cerr << " and variable " << symbol_table.getName(symb) << "(" << lag << ") [" << symb << "] !" << endl;
+              cerr << " and variable " << getNameByDerivID(deriv_id) << "(" << lag << ") !" << endl;
               d1->writeOutput(cerr, ExprNodeOutputType::matlabDynamicModel, {}, {});
               cerr << endl;
               exit(EXIT_FAILURE);
@@ -1311,8 +1310,7 @@ ModelTree::writeBytecodeBinFile(const string &filename, int &u_count_int, bool &
       if (getTypeByDerivID(deriv_id) == SymbolType::endogenous)
         {
           int eq = indices[0];
-          int symb = getSymbIDByDerivID(deriv_id);
-          int var = symbol_table.getTypeSpecificID(symb);
+          int var { getTypeSpecificIDByDerivID(deriv_id) };
           int lag = getLagByDerivID(deriv_id);
           SaveCode.write(reinterpret_cast<char *>(&eq), sizeof(eq));
           int varr = var + lag * symbol_table.endo_nbr();
@@ -1851,7 +1849,7 @@ ModelTree::collectFirstOrderDerivativesEndogenous()
     if (getTypeByDerivID(indices[1]) == SymbolType::endogenous)
       {
         int eq = indices[0];
-        int var = symbol_table.getTypeSpecificID(getSymbIDByDerivID(indices[1]));
+        int var { getTypeSpecificIDByDerivID(indices[1]) };
         int lag = getLagByDerivID(indices[1]);
         endo_derivatives[{ eq, var, lag }] = d1;
       }
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index 7061eb6d..e7c92264 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -799,7 +799,7 @@ ModelTree::writeParamsDerivativesFileHelper() const
     {
       auto [eq, param] { vectorToTuple<2>(indices) };
 
-      int param_col { symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1 };
+      int param_col { getTypeSpecificIDByDerivID(param) + 1 };
 
       rp_output << "rp" << LEFT_ARRAY_SUBSCRIPT(output_type) << eq+1 << ", " << param_col
                 << RIGHT_ARRAY_SUBSCRIPT(output_type) << " = ";
@@ -812,7 +812,7 @@ ModelTree::writeParamsDerivativesFileHelper() const
       auto [eq, var, param] { vectorToTuple<3>(indices) };
 
       int var_col { getJacobianCol(var) + 1 };
-      int param_col { symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1 };
+      int param_col { getTypeSpecificIDByDerivID(param) + 1 };
 
       gp_output << "gp" << LEFT_ARRAY_SUBSCRIPT(output_type) << eq+1 << ", " << var_col
                 << ", " << param_col << RIGHT_ARRAY_SUBSCRIPT(output_type) << " = ";
@@ -825,8 +825,8 @@ ModelTree::writeParamsDerivativesFileHelper() const
     {
       auto [eq, param1, param2] { vectorToTuple<3>(indices) };
 
-      int param1_col { symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1 };
-      int param2_col { symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1 };
+      int param1_col { getTypeSpecificIDByDerivID(param1) + 1 };
+      int param2_col { getTypeSpecificIDByDerivID(param2) + 1 };
 
       rpp_output << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1"
                  << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl
@@ -864,8 +864,8 @@ ModelTree::writeParamsDerivativesFileHelper() const
       auto [eq, var, param1, param2] { vectorToTuple<4>(indices) };
 
       int var_col { getJacobianCol(var) + 1 };
-      int param1_col { symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1 };
-      int param2_col { symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1 };
+      int param1_col { getTypeSpecificIDByDerivID(param1) + 1 };
+      int param2_col { getTypeSpecificIDByDerivID(param2) + 1 };
 
       gpp_output << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1"
                  << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl
@@ -908,7 +908,7 @@ ModelTree::writeParamsDerivativesFileHelper() const
 
       int var1_col { getJacobianCol(var1) + 1 };
       int var2_col { getJacobianCol(var2) + 1 };
-      int param_col { symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1 };
+      int param_col { getTypeSpecificIDByDerivID(param) + 1 };
 
       hp_output << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1"
                 << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl
@@ -954,7 +954,7 @@ ModelTree::writeParamsDerivativesFileHelper() const
         int var1_col { getJacobianCol(var1) + 1 };
         int var2_col { getJacobianCol(var2) + 1 };
         int var3_col { getJacobianCol(var3) + 1 };
-        int param_col { symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1 };
+        int param_col { getTypeSpecificIDByDerivID(param) + 1 };
 
         g3p_output << "g3p" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1"
                    << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl
diff --git a/src/StaticModel.cc b/src/StaticModel.cc
index 639108e2..84d9db50 100644
--- a/src/StaticModel.cc
+++ b/src/StaticModel.cc
@@ -311,8 +311,7 @@ StaticModel::writeStaticBytecode(const string &basename) const
       if (getTypeByDerivID(deriv_id) == SymbolType::endogenous)
         {
           int eq = indices[0];
-          int symb = getSymbIDByDerivID(deriv_id);
-          int var = symbol_table.getTypeSpecificID(symb);
+          int var { getTypeSpecificIDByDerivID(deriv_id) };
           code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, eq, var};
           if (!my_derivatives[eq].size())
             my_derivatives[eq].clear();
@@ -358,8 +357,7 @@ StaticModel::writeStaticBytecode(const string &basename) const
       if (getTypeByDerivID(deriv_id) == SymbolType::endogenous)
         {
           int eq = indices[0];
-          int symb = getSymbIDByDerivID(deriv_id);
-          int var = symbol_table.getTypeSpecificID(symb);
+          int var { getTypeSpecificIDByDerivID(deriv_id) };
           code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, eq, var};
           if (!my_derivatives[eq].size())
             my_derivatives[eq].clear();
@@ -1613,7 +1611,7 @@ StaticModel::writeDriverOutput(ostream &output, bool block) const
         getTypeByDerivID(deriv_id) == SymbolType::endogenous)
       {
         int eq = indices[0];
-        int var = symbol_table.getTypeSpecificID(getSymbIDByDerivID(deriv_id));
+        int var { getTypeSpecificIDByDerivID(deriv_id) };
         row_incidence.emplace(eq, var);
       }
   output << "M_.block_structure_stat.incidence.sparse_IM = [" << endl;
@@ -1652,6 +1650,17 @@ StaticModel::getSymbIDByDerivID(int deriv_id) const noexcept(false)
     throw UnknownDerivIDException();
 }
 
+int
+StaticModel::getTypeSpecificIDByDerivID(int deriv_id) const
+{
+  if (deriv_id < symbol_table.endo_nbr())
+    return deriv_id;
+  else if (deriv_id < symbol_table.endo_nbr() + symbol_table.param_nbr())
+    return deriv_id - symbol_table.endo_nbr();
+  else
+    throw UnknownDerivIDException();
+}
+
 int
 StaticModel::getDerivID(int symb_id, [[maybe_unused]] int lag) const noexcept(false)
 {
@@ -1895,7 +1904,7 @@ StaticModel::writeJsonComputingPassOutput(ostream &output, bool writeDetails) co
 
           if (writeDetails)
             for (size_t j = 1; j < vidx.size(); j++)
-              d_output[i] << R"(, "var)" << (i > 1 ? to_string(j) : "") << R"(": ")" << symbol_table.getName(getSymbIDByDerivID(vidx[j])) << R"(")";
+              d_output[i] << R"(, "var)" << (i > 1 ? to_string(j) : "") << R"(": ")" << getNameByDerivID(vidx[j]) << R"(")";
 
           d_output[i] << R"(, "val": ")";
           d->writeJsonOutput(d_output[i], temp_term_union, tef_terms);
@@ -1949,7 +1958,7 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
 
       auto [eq, param] = vectorToTuple<2>(vidx);
 
-      int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
+      int param_col { getTypeSpecificIDByDerivID(param) + 1 };
 
       if (writeDetails)
         jacobian_output << R"({"eq": )" << eq + 1;
@@ -1959,7 +1968,7 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
       if (writeDetails)
         jacobian_output << R"(, "param_col": )" << param_col;
 
-      jacobian_output << R"(, "param": ")" << symbol_table.getName(getSymbIDByDerivID(param)) << R"(")";
+      jacobian_output << R"(, "param": ")" << getNameByDerivID(param) << R"(")";
 
       jacobian_output << R"(, "val": ")";
       d->writeJsonOutput(jacobian_output, temp_term_union, tef_terms);
@@ -1980,8 +1989,8 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
 
       auto [eq, var, param] = vectorToTuple<3>(vidx);
 
-      int var_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(var)) + 1;
-      int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
+      int var_col { getTypeSpecificIDByDerivID(var) + 1 };
+      int param_col { getTypeSpecificIDByDerivID(param) + 1 };
 
       if (writeDetails)
         hessian_output << R"({"eq": )" << eq + 1;
@@ -1989,8 +1998,8 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
         hessian_output << R"({"row": )" << eq + 1;
 
       if (writeDetails)
-        hessian_output << R"(, "var": ")" << symbol_table.getName(getSymbIDByDerivID(var)) << R"(")"
-                       << R"(, "param": ")" << symbol_table.getName(getSymbIDByDerivID(param)) << R"(")";
+        hessian_output << R"(, "var": ")" << getNameByDerivID(var) << R"(")"
+                       << R"(, "param": ")" << getNameByDerivID(param) << R"(")";
 
       hessian_output << R"(, "var_col": )" << var_col
                      << R"(, "param_col": )" << param_col
@@ -2013,8 +2022,8 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
 
       auto [eq, param1, param2] = vectorToTuple<3>(vidx);
 
-      int param1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1;
-      int param2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1;
+      int param1_col { getTypeSpecificIDByDerivID(param1) + 1 };
+      int param2_col { getTypeSpecificIDByDerivID(param2) + 1 };
 
       if (writeDetails)
         hessian1_output << R"({"eq": )" << eq + 1;
@@ -2025,8 +2034,8 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
                       << R"(, "param2_col": )" << param2_col;
 
       if (writeDetails)
-        hessian1_output << R"(, "param1": ")" << symbol_table.getName(getSymbIDByDerivID(param1)) << R"(")"
-                        << R"(, "param2": ")" << symbol_table.getName(getSymbIDByDerivID(param2)) << R"(")";
+        hessian1_output << R"(, "param1": ")" << getNameByDerivID(param1) << R"(")"
+                        << R"(, "param2": ")" << getNameByDerivID(param2) << R"(")";
 
       hessian1_output << R"(, "val": ")";
       d->writeJsonOutput(hessian1_output, temp_term_union, tef_terms);
@@ -2048,9 +2057,9 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
 
       auto [eq, var, param1, param2] = vectorToTuple<4>(vidx);
 
-      int var_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(var)) + 1;
-      int param1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1;
-      int param2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1;
+      int var_col { getTypeSpecificIDByDerivID(var) + 1 };
+      int param1_col { getTypeSpecificIDByDerivID(param1) + 1 };
+      int param2_col { getTypeSpecificIDByDerivID(param2) + 1 };
 
       if (writeDetails)
         third_derivs_output << R"({"eq": )" << eq + 1;
@@ -2061,9 +2070,9 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
                           << R"(, "param2_col": )" << param2_col;
 
       if (writeDetails)
-        third_derivs_output << R"(, "var": ")" << symbol_table.getName(getSymbIDByDerivID(var)) << R"(")"
-                            << R"(, "param1": ")" << symbol_table.getName(getSymbIDByDerivID(param1)) << R"(")"
-                            << R"(, "param2": ")" << symbol_table.getName(getSymbIDByDerivID(param2)) << R"(")";
+        third_derivs_output << R"(, "var": ")" << getNameByDerivID(var) << R"(")"
+                            << R"(, "param1": ")" << getNameByDerivID(param1) << R"(")"
+                            << R"(, "param2": ")" << getNameByDerivID(param2) << R"(")";
 
       third_derivs_output << R"(, "val": ")";
       d->writeJsonOutput(third_derivs_output, temp_term_union, tef_terms);
@@ -2085,9 +2094,9 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
 
       auto [eq, var1, var2, param] = vectorToTuple<4>(vidx);
 
-      int var1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(var1)) + 1;
-      int var2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(var2)) + 1;
-      int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
+      int var1_col { getTypeSpecificIDByDerivID(var1) + 1 };
+      int var2_col { getTypeSpecificIDByDerivID(var2) + 1 };
+      int param_col { getTypeSpecificIDByDerivID(param) + 1 };
 
       if (writeDetails)
         third_derivs1_output << R"({"eq": )" << eq + 1;
@@ -2099,9 +2108,9 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
                            << R"(, "param_col": )" << param_col;
 
       if (writeDetails)
-        third_derivs1_output << R"(, "var1": ")" << symbol_table.getName(getSymbIDByDerivID(var1)) << R"(")"
-                             << R"(, "var2": ")" << symbol_table.getName(getSymbIDByDerivID(var2)) << R"(")"
-                             << R"(, "param1": ")" << symbol_table.getName(getSymbIDByDerivID(param)) << R"(")";
+        third_derivs1_output << R"(, "var1": ")" << getNameByDerivID(var1) << R"(")"
+                             << R"(, "var2": ")" << getNameByDerivID(var2) << R"(")"
+                             << R"(, "param1": ")" << getNameByDerivID(param) << R"(")";
 
       third_derivs1_output << R"(, "val": ")";
       d->writeJsonOutput(third_derivs1_output, temp_term_union, tef_terms);
diff --git a/src/StaticModel.hh b/src/StaticModel.hh
index fa412814..9e6abbb1 100644
--- a/src/StaticModel.hh
+++ b/src/StaticModel.hh
@@ -81,17 +81,15 @@ private:
   //! Write chain rule derivative bytecode of an equation w.r. to a variable
   void writeBytecodeChainRuleDerivative(BytecodeWriter &code_file, int blk, int eq, int var, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
 
-  //! Get the type corresponding to a derivation ID
   SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override;
-  //! Get the lag corresponding to a derivation ID
   int getLagByDerivID(int deriv_id) const noexcept(false) override;
-  //! Get the symbol ID corresponding to a derivation ID
   int getSymbIDByDerivID(int deriv_id) const noexcept(false) override;
+  int getTypeSpecificIDByDerivID(int deriv_id) const override;
 
   int
   getJacobianCol(int deriv_id) const override
   {
-    return symbol_table.getTypeSpecificID(getSymbIDByDerivID(deriv_id));
+    return getTypeSpecificIDByDerivID(deriv_id);
   }
   int
   getJacobianColsNbr() const override
-- 
GitLab