From 746f88eb6eb321e76b8dac8de4764c0a049c4823 Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Thu, 2 Mar 2017 18:34:18 +0100
Subject: [PATCH] preprocessor: create two different static and dynamic files
 with the option jsonprintderivdetail. #1387

---
 ComputingTasks.cc |   2 +-
 DynamicModel.cc   | 216 +++++++++++++++++++++++++++++++---------------
 DynamicModel.hh   |   4 +-
 DynareMain.cc     |   9 +-
 DynareMain2.cc    |   4 +-
 ModFile.cc        | 138 +++++++++++++++++------------
 ModFile.hh        |   6 +-
 StaticModel.cc    | 189 +++++++++++++++++++++++++++++-----------
 StaticModel.hh    |   4 +-
 9 files changed, 388 insertions(+), 184 deletions(-)

diff --git a/ComputingTasks.cc b/ComputingTasks.cc
index bc9aa02a..7eccf256 100644
--- a/ComputingTasks.cc
+++ b/ComputingTasks.cc
@@ -1866,7 +1866,7 @@ PlannerObjectiveStatement::writeJsonOutput(ostream &output) const
   output << "{\"statementName\": \"planner_objective\""
          << ", ";
   if (computing_pass_called)
-    model_tree->writeJsonComputingPassOutput(output);
+    model_tree->writeJsonComputingPassOutput(output, false);
   else
     model_tree->writeJsonOutput(output);
 
diff --git a/DynamicModel.cc b/DynamicModel.cc
index 213ead14..10db3a8b 100644
--- a/DynamicModel.cc
+++ b/DynamicModel.cc
@@ -5345,7 +5345,7 @@ DynamicModel::writeJsonOutput(ostream &output) const
 }
 
 void
-DynamicModel::writeJsonComputingPassOutput(ostream &output) const
+DynamicModel::writeJsonComputingPassOutput(ostream &output, bool writeDetails) const
 {
   ostringstream model_local_vars_output;  // Used for storing model local vars
   ostringstream model_output;             // Used for storing model temp vars and equations
@@ -5383,13 +5383,17 @@ DynamicModel::writeJsonComputingPassOutput(ostream &output) const
         jacobian_output << ", ";
 
       int eq = it->first.first;
-      string var = symbol_table.getName(getSymbIDByDerivID(it->first.second));
-      int lag = getLagByDerivID(it->first.second);
+      int var = it->first.second;
+      int col =  getDynJacobianCol(var);
       expr_t d1 = it->second;
 
-      jacobian_output << "{\"eq\": " << eq + 1
-                      << ", \"var\": \"" << var << "\""
-                      << ", \"lag\": " << lag
+      if (writeDetails)
+        jacobian_output << "{\"eq\": " << eq + 1
+                        << ", \"var\": \"" << symbol_table.getName(getSymbIDByDerivID(var)) << "\""
+                        << ", \"lag\": " << getLagByDerivID(var);
+      else
+        jacobian_output << "{\"row\": " << eq + 1;
+      jacobian_output << ", \"col\": " << col + 1
                       << ", \"val\": \"";
       d1->writeJsonOutput(jacobian_output, temp_term_union, tef_terms);
       jacobian_output << "\"}" << endl;
@@ -5412,17 +5416,27 @@ DynamicModel::writeJsonComputingPassOutput(ostream &output) const
         hessian_output << ", ";
 
       int eq = it->first.first;
-      string var1 = symbol_table.getName(getSymbIDByDerivID(it->first.second.first));
-      int lag1 = getLagByDerivID(it->first.second.first);
-      string var2 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second));
-      int lag2 = getLagByDerivID(it->first.second.second);
+      int var1 = it->first.second.first;
+      int var2 = it->first.second.second;
       expr_t d2 = it->second;
+      int id1 = getDynJacobianCol(var1);
+      int id2 = getDynJacobianCol(var2);
+      int col_nb = id1 * dynJacobianColsNbr + id2;
+      int col_nb_sym = id2 * dynJacobianColsNbr + id1;
 
-      hessian_output << "{\"eq\": " << eq + 1
-                     << ", \"var1\": \"" << var1 << "\""
-                     << ", \"lag1\": " << lag1
-                     << ", \"var2\": \"" << var2 << "\""
-                     << ", \"lag2\": " << lag2
+      if (writeDetails)
+        hessian_output << "{\"eq\": " << eq + 1
+                       << ", \"var1\": \"" << symbol_table.getName(getSymbIDByDerivID(var1)) << "\""
+                       << ", \"lag1\": " << getLagByDerivID(var1)
+                       << ", \"var2\": \"" << symbol_table.getName(getSymbIDByDerivID(var2)) << "\""
+                       << ", \"lag2\": " << getLagByDerivID(var2);
+      else
+        hessian_output << "{\"row\": " << eq + 1;
+
+      hessian_output << ", \"col\": [" << col_nb + 1;
+      if (id1 != id2)
+        hessian_output << ", " << col_nb_sym + 1;
+      hessian_output << "]"
                      << ", \"val\": \"";
       d2->writeJsonOutput(hessian_output, temp_term_union, tef_terms);
       hessian_output << "\"}" << endl;
@@ -5445,29 +5459,52 @@ DynamicModel::writeJsonComputingPassOutput(ostream &output) const
         third_derivatives_output << ", ";
 
       int eq = it->first.first;
-      string var1 = symbol_table.getName(getSymbIDByDerivID(it->first.second.first));
-      int lag1 = getLagByDerivID(it->first.second.first);
-      string var2 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second.first));
-      int lag2 = getLagByDerivID(it->first.second.second.first);
-      string var3 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second.second));
-      int lag3 = getLagByDerivID(it->first.second.second.second);
+      int var1 = it->first.second.first;
+      int var2 = it->first.second.second.first;
+      int var3 = it->first.second.second.second;
       expr_t d3 = it->second;
 
-      third_derivatives_output << "{\"eq\": " << eq + 1
-                               << ", \"var1\": \"" << var1 << "\""
-                               << ", \"lag1\": " << lag1
-                               << ", \"var2\": \"" << var2 << "\""
-                               << ", \"lag2\": " << lag2
-                               << ", \"var3\": \"" << var3 << "\""
-                               << ", \"lag3\": " << lag3
+      if (writeDetails)
+        third_derivatives_output << "{\"eq\": " << eq + 1
+                                 << ", \"var1\": \"" << symbol_table.getName(getSymbIDByDerivID(var1)) << "\""
+                                 << ", \"lag1\": " << getLagByDerivID(var1)
+                                 << ", \"var2\": \"" << symbol_table.getName(getSymbIDByDerivID(var2)) << "\""
+                                 << ", \"lag2\": " << getLagByDerivID(var2)
+                                 << ", \"var3\": \"" << symbol_table.getName(getSymbIDByDerivID(var3)) << "\""
+                                 << ", \"lag3\": " << getLagByDerivID(var3);
+      else
+        third_derivatives_output << "{\"row\": " << eq + 1;
+
+      int id1 = getDynJacobianCol(var1);
+      int id2 = getDynJacobianCol(var2);
+      int id3 = getDynJacobianCol(var3);
+      set<int> cols;
+      cols.insert(id1 * hessianColsNbr + id2 * dynJacobianColsNbr + id3);
+      cols.insert(id1 * hessianColsNbr + id3 * dynJacobianColsNbr + id2);
+      cols.insert(id2 * hessianColsNbr + id1 * dynJacobianColsNbr + id3);
+      cols.insert(id2 * hessianColsNbr + id3 * dynJacobianColsNbr + id1);
+      cols.insert(id3 * hessianColsNbr + id1 * dynJacobianColsNbr + id2);
+      cols.insert(id3 * hessianColsNbr + id2 * dynJacobianColsNbr + id1);
+
+      third_derivatives_output << ", \"col\": [";
+      for (set<int>::iterator it2 = cols.begin(); it2 != cols.end(); it2++)
+        {
+          if (it2 != cols.begin())
+            third_derivatives_output << ", ";
+          third_derivatives_output << *it2 + 1;
+        }
+      third_derivatives_output << "]"
                                << ", \"val\": \"";
       d3->writeJsonOutput(third_derivatives_output, temp_term_union, tef_terms);
       third_derivatives_output << "\"}" << endl;
     }
   third_derivatives_output << "]}";
 
-  output << "\"dynamic_model_derivatives\": {"
-         << model_local_vars_output.str()
+  if (writeDetails)
+    output << "\"dynamic_model_derivative_details\": {";
+  else
+    output << "\"dynamic_model_derivatives\": {";
+  output << model_local_vars_output.str()
          << ", " << model_output.str()
          << ", " << jacobian_output.str()
          << ", " << hessian_output.str()
@@ -5476,7 +5513,7 @@ DynamicModel::writeJsonComputingPassOutput(ostream &output) const
 }
 
 void
-DynamicModel::writeJsonParamsDerivativesFile(ostream &output) const
+DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails) const
 {
   if (!residuals_params_derivatives.size()
       && !residuals_params_second_derivatives.size()
@@ -5510,11 +5547,17 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output) const
         jacobian_output << ", ";
 
       int eq = it->first.first;
-      string param = symbol_table.getName(getSymbIDByDerivID(it->first.second));
+      int param = it->first.second;
       expr_t d1 = it->second;
 
-      jacobian_output << "{\"eq\": " << eq + 1
-                      << ", \"param\": \"" << param << "\""
+      int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
+
+      if (writeDetails)
+        jacobian_output << "{\"eq\": " << eq + 1
+                        << ", \"param\": \"" << symbol_table.getName(getSymbIDByDerivID(param)) << "\"";
+      else
+        jacobian_output << "{\"row\": " << eq + 1;
+      jacobian_output << ", \"param_col\": " << param_col + 1
                       << ", \"val\": \"";
       d1->writeJsonOutput(jacobian_output, params_derivs_temporary_terms, tef_terms);
       jacobian_output << "\"}" << endl;
@@ -5532,15 +5575,22 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output) const
         hessian_output << ", ";
 
       int eq = it->first.first;
-      string var = symbol_table.getName(getSymbIDByDerivID(it->first.second.first));
-      int lag = getLagByDerivID(it->first.second.first);
-      string param = symbol_table.getName(getSymbIDByDerivID(it->first.second.second));
+      int var = it->first.second.first;
+      int param = it->first.second.second;
       expr_t d2 = it->second;
 
-      hessian_output << "{\"eq\": " << eq + 1
-                     << ", \"var\": \"" << var << "\""
-                     << ", \"lag\": " << lag
-                     << ", \"param\": \"" << param << "\""
+      int var_col = getDynJacobianCol(var) + 1;
+      int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
+
+      if (writeDetails)
+        hessian_output << "{\"eq\": " << eq + 1
+                       << ", \"var\": \"" << symbol_table.getName(getSymbIDByDerivID(var)) << "\""
+                       << ", \"lag\": " << getLagByDerivID(var)
+                       << ", \"param\": \"" << symbol_table.getName(getSymbIDByDerivID(param)) << "\"";
+      else
+        hessian_output << "{\"row\": " << eq + 1;
+      hessian_output << ", \"var_col\": " << var_col + 1
+                     << ", \"param_col\": " << param_col + 1
                      << ", \"val\": \"";
       d2->writeJsonOutput(hessian_output, params_derivs_temporary_terms, tef_terms);
       hessian_output << "\"}" << endl;
@@ -5559,14 +5609,22 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output) const
         hessian1_output << ", ";
 
       int eq = it->first.first;
-      string param1 = symbol_table.getName(getSymbIDByDerivID(it->first.second.first));
-      string param2 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second));
+      int param1 = it->first.second.first;
+      int param2 = it->first.second.second;
       expr_t d2 = it->second;
 
-      hessian1_output << "{\"eq\": " << eq + 1
-                     << ", \"param1\": \"" << param1 << "\""
-                     << ", \"param2\": \"" << param2 << "\""
-                     << ", \"val\": \"";
+      int param1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1;
+      int param2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1;
+
+      if (writeDetails)
+        hessian1_output << "{\"eq\": " << eq + 1
+                        << ", \"param1\": \"" << symbol_table.getName(getSymbIDByDerivID(param1)) << "\""
+                        << ", \"param2\": \"" << symbol_table.getName(getSymbIDByDerivID(param2)) << "\"";
+      else
+        hessian1_output << "{\"row\": " << eq + 1;
+      hessian1_output << ", \"param1_col\": " << param1_col + 1
+                      << ", \"param2_col\": " << param2_col + 1
+                      << ", \"val\": \"";
       d2->writeJsonOutput(hessian1_output, params_derivs_temporary_terms, tef_terms);
       hessian1_output << "\"}" << endl;
     }
@@ -5584,17 +5642,26 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output) const
         third_derivs_output << ", ";
 
       int eq = it->first.first;
-      string var = symbol_table.getName(it->first.second.first);
-      int lag = getLagByDerivID(it->first.second.first);
-      string param1 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second.first));
-      string param2 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second.second));
+      int var = it->first.second.first;
+      int param1 = it->first.second.second.first;
+      int param2 = it->first.second.second.second;
       expr_t d2 = it->second;
 
-      third_derivs_output << "{\"eq\": " << eq + 1
-                          << ", \"var\": \"" << var << "\""
-                          << ", \"lag\": " << lag
-                          << ", \"param1\": \"" << param1 << "\""
-                          << ", \"param2\": \"" << param2 << "\""
+      int var_col = getDynJacobianCol(var) + 1;
+      int param1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1;
+      int param2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1;
+
+      if (writeDetails)
+        third_derivs_output << "{\"eq\": " << eq + 1
+                            << ", \"var\": \"" << symbol_table.getName(var) << "\""
+                            << ", \"lag\": " << getLagByDerivID(var)
+                            << ", \"param1\": \"" << symbol_table.getName(getSymbIDByDerivID(param1)) << "\""
+                            << ", \"param2\": \"" << symbol_table.getName(getSymbIDByDerivID(param2)) << "\"";
+      else
+        third_derivs_output << "{\"row\": " << eq + 1;
+      third_derivs_output << ", \"var_col\": " << var_col + 1
+                          << ", \"param1_col\": " << param1_col + 1
+                          << ", \"param2_col\": " << param2_col + 1
                           << ", \"val\": \"";
       d2->writeJsonOutput(third_derivs_output, params_derivs_temporary_terms, tef_terms);
       third_derivs_output << "\"}" << endl;
@@ -5614,27 +5681,38 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output) const
         third_derivs1_output << ", ";
 
       int eq = it->first.first;
-      string var1 = symbol_table.getName(getSymbIDByDerivID(it->first.second.first));
-      int lag1 = getLagByDerivID(it->first.second.first);
-      string var2 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second.first));
-      int lag2 = getLagByDerivID(it->first.second.second.first);
-      string param = symbol_table.getName(getSymbIDByDerivID(it->first.second.second.second));
+      int var1 = it->first.second.first;
+      int var2 = it->first.second.second.first;
+      int param = it->first.second.second.second;
       expr_t d2 = it->second;
 
-      third_derivs1_output << "{\"eq\": " << eq + 1
-                           << ", \"var1\": \"" << var1 << "\""
-                           << ", \"lag1\": " << lag1
-                           << ", \"var2\": \"" << var2 << "\""
-                           << ", \"lag2\": " << lag2
-                           << ", \"param1\": \"" << param << "\""
+      int var1_col = getDynJacobianCol(var1) + 1;
+      int var2_col = getDynJacobianCol(var2) + 1;
+      int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
+
+      if (writeDetails)
+        third_derivs1_output << "{\"eq\": " << eq + 1
+                             << ", \"var1\": \"" << symbol_table.getName(getSymbIDByDerivID(var1)) << "\""
+                             << ", \"lag1\": " << getLagByDerivID(var1)
+                             << ", \"var2\": \"" << symbol_table.getName(getSymbIDByDerivID(var2)) << "\""
+                             << ", \"lag2\": " << getLagByDerivID(var2)
+                             << ", \"param\": \"" << symbol_table.getName(getSymbIDByDerivID(param)) << "\"";
+      else
+        third_derivs1_output << "{\"row\": " << eq + 1;
+      third_derivs1_output << ", \"var1_col\": " << var1_col + 1
+                           << ", \"var2_col\": " << var2_col + 1
+                           << ", \"param_col\": " << param_col + 1
                            << ", \"val\": \"";
       d2->writeJsonOutput(third_derivs1_output, params_derivs_temporary_terms, tef_terms);
       third_derivs1_output << "\"}" << endl;
     }
   third_derivs1_output << "]}" << endl;
 
-  output << "\"dynamic_model_params_derivatives\": {"
-         << model_local_vars_output.str()
+  if (writeDetails)
+    output << "\"dynamic_model_params_derivative_details\": {";
+  else
+    output << "\"dynamic_model_params_derivatives\": {";
+  output << model_local_vars_output.str()
          << ", " << model_output.str()
          << ", " << jacobian_output.str()
          << ", " << hessian_output.str()
diff --git a/DynamicModel.hh b/DynamicModel.hh
index 87e41e38..b0828a2b 100644
--- a/DynamicModel.hh
+++ b/DynamicModel.hh
@@ -221,10 +221,10 @@ public:
   void writeJsonOutput(ostream &output) const;
 
   //! Write JSON Output representation of dynamic model after computing pass
-  void writeJsonComputingPassOutput(ostream &output) const;
+  void writeJsonComputingPassOutput(ostream &output, bool writeDetails) const;
 
   //! Write JSON prams derivatives file
-  void writeJsonParamsDerivativesFile(ostream &output) const;
+  void writeJsonParamsDerivativesFile(ostream &output, bool writeDetails) const;
 
   //! Return true if the hessian is equal to zero
   inline bool checkHessianZero() const;
diff --git a/DynareMain.cc b/DynareMain.cc
index 3aa0aa3f..03c74ec6 100644
--- a/DynareMain.cc
+++ b/DynareMain.cc
@@ -45,7 +45,7 @@ void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool
 #if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
            , bool cygwin, bool msvc, bool mingw
 #endif
-           , JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson
+           , JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonprintderivdetail
            );
 
 void main1(char *modfile, string &basename, bool debug, bool save_macro, string &save_macro_file,
@@ -62,7 +62,7 @@ usage()
 #if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
        << " [cygwin] [msvc] [mingw]"
 #endif
-       << "[json=parse|check|transform|compute] [jsonstdout] [onlyjson]"
+       << "[json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonprintderivdetail]"
        << endl;
   exit(EXIT_FAILURE);
 }
@@ -118,6 +118,7 @@ main(int argc, char **argv)
   JsonOutputPointType json = nojson;
   JsonFileOutputType json_output_mode = file;
   bool onlyjson = false;
+  bool jsonprintderivdetail = false;
   LanguageOutputType language = matlab;
 
   // Parse options
@@ -300,6 +301,8 @@ main(int argc, char **argv)
         json_output_mode = standardout;
       else if (!strcmp(argv[arg], "onlyjson"))
         onlyjson = true;
+      else if (!strcmp(argv[arg], "jsonprintderivdetail"))
+      jsonprintderivdetail = true;
       else if (strlen(argv[arg]) >= 4 && !strncmp(argv[arg], "json", 4))
         {
 	  if (strlen(argv[arg]) <= 5 || argv[arg][4] != '=')
@@ -367,7 +370,7 @@ main(int argc, char **argv)
 #if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
         , cygwin, msvc, mingw
 #endif
-        , json, json_output_mode, onlyjson
+        , json, json_output_mode, onlyjson, jsonprintderivdetail
         );
 
   return EXIT_SUCCESS;
diff --git a/DynareMain2.cc b/DynareMain2.cc
index 5139cd3d..c3a24936 100644
--- a/DynareMain2.cc
+++ b/DynareMain2.cc
@@ -34,7 +34,7 @@ main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear
 #if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
       , bool cygwin, bool msvc, bool mingw
 #endif
-      , JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson
+      , JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonprintderivdetail
       )
 {
   ParsingDriver p(warnings, nostrict);
@@ -60,7 +60,7 @@ main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear
   // Do computations
   mod_file->computingPass(no_tmp_terms, output_mode, compute_xrefs, params_derivs_order);
   if (json == computingpass)
-    mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
+    mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, jsonprintderivdetail);
 
   // Write outputs
   if (output_mode != none)
diff --git a/ModFile.cc b/ModFile.cc
index 32cb70bf..7ee204ad 100644
--- a/ModFile.cc
+++ b/ModFile.cc
@@ -1248,7 +1248,7 @@ ModFile::writeExternalFilesJulia(const string &basename, FileOutputType output)
 }
 
 void
-ModFile::writeJsonOutput(const string &basename, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson)
+ModFile::writeJsonOutput(const string &basename, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonprintderivdetail)
 {
   if (json == nojson)
     return;
@@ -1262,7 +1262,7 @@ ModFile::writeJsonOutput(const string &basename, JsonOutputPointType json, JsonF
     symbol_table.unfreeze();
 
   if (json == computingpass)
-    writeJsonComputingPassOutput(basename, json_output_mode);
+    writeJsonComputingPassOutput(basename, json_output_mode, jsonprintderivdetail);
 
   switch (json)
     {
@@ -1340,40 +1340,78 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
 }
 
 void
-ModFile::writeJsonComputingPassOutput(const string &basename, JsonFileOutputType json_output_mode) const
+ModFile::writeJsonComputingPassOutput(const string &basename, JsonFileOutputType json_output_mode, bool jsonprintderivdetail) const
 {
-  ostringstream static_output;
+  ostringstream static_output, static_detail_output;
   static_output << "{";
-  static_model.writeJsonComputingPassOutput(static_output);
+  static_model.writeJsonComputingPassOutput(static_output, false);
   static_output << "}" << endl;
 
-  ostringstream dynamic_output;
+  ostringstream dynamic_output, dynamic_detail_output;
   dynamic_output << "{";
-  dynamic_model.writeJsonComputingPassOutput(dynamic_output);
+  dynamic_model.writeJsonComputingPassOutput(dynamic_output, false);
   dynamic_output << "}" << endl;
 
-  ostringstream tmp_out, static_paramsd_output;
+  ostringstream tmp_out, static_paramsd_output, static_paramsd_detail_output;
   tmp_out << "";
   static_paramsd_output << "";
-  static_model.writeJsonParamsDerivativesFile(tmp_out);
+  static_paramsd_detail_output << "";
+  static_model.writeJsonParamsDerivativesFile(tmp_out, false);
   if (!tmp_out.str().empty())
     static_paramsd_output << "{" << tmp_out.str() << "}" << endl;
 
-  ostringstream tmp1_out, dynamic_paramsd_output;
+  ostringstream tmp1_out, dynamic_paramsd_output, dynamic_paramsd_detail_output;
   tmp1_out << "";
   dynamic_paramsd_output << "";
-  dynamic_model.writeJsonParamsDerivativesFile(tmp1_out);
+  dynamic_paramsd_detail_output << "";
+  dynamic_model.writeJsonParamsDerivativesFile(tmp1_out, false);
   if (!tmp1_out.str().empty())
     dynamic_paramsd_output << "{" << tmp1_out.str() << "}" << endl;
 
+  if (jsonprintderivdetail)
+    {
+      static_detail_output << "{";
+      static_model.writeJsonComputingPassOutput(static_detail_output, true);
+      static_detail_output << "}";
+
+      dynamic_detail_output << "{";
+      dynamic_model.writeJsonComputingPassOutput(dynamic_detail_output, true);
+      dynamic_detail_output << "}";
+
+      ostringstream tmpd_out, tmpd1_out;
+      tmpd_out << "";
+      tmpd1_out << "";
+      static_model.writeJsonParamsDerivativesFile(tmpd_out, true);
+      if (!tmpd_out.str().empty())
+        static_paramsd_detail_output << "{" << tmpd_out.str() << "}" << endl;
+
+      dynamic_model.writeJsonParamsDerivativesFile(tmpd1_out, true);
+      if (!tmpd1_out.str().empty())
+        dynamic_paramsd_detail_output << "{" << tmpd1_out.str() << "}" << endl;
+    }
+
   if (json_output_mode == standardout)
     {
-      cout << static_output.str() << endl;
-      cout << dynamic_output.str() << endl;
-      if (!dynamic_paramsd_output.str().empty())
-        cout << dynamic_paramsd_output.str() << endl;
+      cout << static_output.str() << endl
+           << dynamic_output.str() << endl;
+
       if (!static_paramsd_output.str().empty())
         cout << static_paramsd_output.str() << endl;
+
+      if (!dynamic_paramsd_output.str().empty())
+        cout << dynamic_paramsd_output.str() << endl;
+
+      if (jsonprintderivdetail)
+        {
+          cout << static_detail_output.str() << endl
+               << dynamic_detail_output.str() << endl;
+
+          if (!static_paramsd_detail_output.str().empty())
+            cout << static_paramsd_detail_output.str() << endl;
+
+          if (!dynamic_paramsd_detail_output.str().empty())
+            cout << dynamic_paramsd_detail_output.str() << endl;
+        }
     }
   else
     {
@@ -1387,56 +1425,50 @@ ModFile::writeJsonComputingPassOutput(const string &basename, JsonFileOutputType
       fname_static = basename + "_static.json";
       fname_dynamic = basename + "_dynamic.json";
 
-      ofstream jsonOutputFileStatic, jsonOutputFileDynamic;
-      jsonOutputFileStatic.open(fname_static.c_str(), ios::out | ios::binary);
-      if (!jsonOutputFileStatic.is_open())
-        {
-          cerr << "ERROR: Can't open file " << fname_static << " for writing" << endl;
-          exit(EXIT_FAILURE);
-        }
+      writeJsonFileHelper(fname_static, static_output);
+      writeJsonFileHelper(fname_dynamic, dynamic_output);
 
-      jsonOutputFileDynamic.open(fname_dynamic.c_str(), ios::out | ios::binary);
-      if (!jsonOutputFileDynamic.is_open())
+      if (jsonprintderivdetail)
         {
-          cerr << "ERROR: Can't open file " << fname_dynamic << " for writing" << endl;
-          exit(EXIT_FAILURE);
-        }
+          string fname_static_details, fname_dynamic_details;
+          fname_static_details = basename + "_static_details.json";
+          fname_dynamic_details = basename + "_dynamic_details.json";
 
-      jsonOutputFileStatic << static_output.str();
-      jsonOutputFileStatic.close();
-      jsonOutputFileDynamic << dynamic_output.str();
-      jsonOutputFileDynamic.close();
+          writeJsonFileHelper(fname_static_details, static_detail_output);
+          writeJsonFileHelper(fname_dynamic_details, dynamic_detail_output);
+        }
 
       if (!static_paramsd_output.str().empty())
         {
-          string fname_static_params;
+          string fname_static_params, fname_static_params_details;
           fname_static_params = basename + "_static_params_derivs.json";
-          ofstream jsonOutputFileStaticParamsDerivs;
-          jsonOutputFileStaticParamsDerivs.open(fname_static_params.c_str(), ios::out | ios::binary);
-          if (!jsonOutputFileStaticParamsDerivs.is_open())
-            {
-              cerr << "ERROR: Can't open file " << fname_static_params << " for writing" << endl;
-              exit(EXIT_FAILURE);
-            }
-
-          jsonOutputFileStaticParamsDerivs << static_paramsd_output.str();
-          jsonOutputFileStaticParamsDerivs.close();
+          fname_static_params_details = basename + "_static_params_derivs_details.json";
+          writeJsonFileHelper(fname_static_params, static_paramsd_output);
+          writeJsonFileHelper(fname_static_params_details, static_paramsd_detail_output);
         }
 
       if (!dynamic_paramsd_output.str().empty())
         {
-          string fname_dynamic_params;
+          string fname_dynamic_params, fname_dynamic_params_details;
           fname_dynamic_params = basename + "_params_derivs.json";
-          ofstream jsonOutputFileDynamicParamsDerivs;
-          jsonOutputFileDynamicParamsDerivs.open(fname_dynamic_params.c_str(), ios::out | ios::binary);
-          if (!jsonOutputFileDynamicParamsDerivs.is_open())
-            {
-              cerr << "ERROR: Can't open file " << fname_dynamic_params << " for writing" << endl;
-              exit(EXIT_FAILURE);
-            }
-
-          jsonOutputFileDynamicParamsDerivs << dynamic_paramsd_output.str();
-          jsonOutputFileDynamicParamsDerivs.close();
+          fname_dynamic_params_details = basename + "_params_derivs_details.json";
+          writeJsonFileHelper(fname_dynamic_params, dynamic_paramsd_output);
+          writeJsonFileHelper(fname_dynamic_params_details, dynamic_paramsd_detail_output);
         }
     }
 }
+
+void
+ModFile::writeJsonFileHelper(string &fname, ostringstream &output) const
+{
+  ofstream jsonOutput;
+  jsonOutput.open(fname.c_str(), ios::out | ios::binary);
+  if (!jsonOutput.is_open())
+    {
+      cerr << "ERROR: Can't open file " << fname << " for writing" << endl;
+      exit(EXIT_FAILURE);
+    }
+  jsonOutput << output.str();
+  jsonOutput.close();
+
+}
diff --git a/ModFile.hh b/ModFile.hh
index 385e97b6..c04f4de5 100644
--- a/ModFile.hh
+++ b/ModFile.hh
@@ -119,8 +119,8 @@ private:
   WarningConsolidation &warnings;
   //! Functions used in writing of JSON outut. See writeJsonOutput
   void writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType json_output_mode) const;
-  void writeJsonComputingPassOutput(const string &basename, JsonFileOutputType json_output_mode) const;
-
+  void writeJsonComputingPassOutput(const string &basename, JsonFileOutputType json_output_mode, bool jsonprintderivdetail) const;
+  void writeJsonFileHelper(string &fname, ostringstream &output) const;
 public:
   //! Add a statement
   void addStatement(Statement *st);
@@ -174,7 +174,7 @@ public:
   //! Initially created to enable Julia to work with .mod files
   //! Potentially outputs ModFile after the various parts of processing (parsing, checkPass, transformPass, computingPass)
   //! Allows user of other host language platforms (python, fortran, etc) to provide support for dynare .mod files
-  void writeJsonOutput(const string &basename, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson);
+  void writeJsonOutput(const string &basename, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonprintderivdetail = false);
 };
 
 #endif // ! MOD_FILE_HH
diff --git a/StaticModel.cc b/StaticModel.cc
index 35c9f516..65d4d632 100644
--- a/StaticModel.cc
+++ b/StaticModel.cc
@@ -2422,7 +2422,7 @@ StaticModel::writeJsonOutput(ostream &output) const
 }
 
 void
-StaticModel::writeJsonComputingPassOutput(ostream &output) const
+StaticModel::writeJsonComputingPassOutput(ostream &output, bool writeDetails) const
 {
   ostringstream model_local_vars_output;   // Used for storing model local vars
   ostringstream model_output;              // Used for storing model
@@ -2463,11 +2463,17 @@ StaticModel::writeJsonComputingPassOutput(ostream &output) const
         jacobian_output << ", ";
 
       int eq = it->first.first;
-      string var = symbol_table.getName(getSymbIDByDerivID(it->first.second));
+      int var = it->first.second;
+      int symb_id = getSymbIDByDerivID(var);
+      int col = symbol_table.getTypeSpecificID(symb_id);
       expr_t d1 = it->second;
 
-      jacobian_output << "{\"eq\": " << eq + 1
-                      << ", \"var\": \"" << var << "\""
+      if (writeDetails)
+        jacobian_output << "{\"eq\": " << eq + 1
+                        << ", \"var\": \"" << symbol_table.getName(symb_id) << "\"";
+      else
+        jacobian_output << "{\"row\": " << eq + 1;
+      jacobian_output << ", \"col\": " << col + 1
                       << ", \"val\": \"";
       d1->writeJsonOutput(jacobian_output, temp_term_union, tef_terms);
       jacobian_output << "\"}" << endl;
@@ -2491,13 +2497,27 @@ StaticModel::writeJsonComputingPassOutput(ostream &output) const
         hessian_output << ", ";
 
       int eq = it->first.first;
-      string var1 = symbol_table.getName(getSymbIDByDerivID(it->first.second.first));
-      string var2 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second));
+      int symb_id1 = getSymbIDByDerivID(it->first.second.first);
+      int symb_id2 = getSymbIDByDerivID(it->first.second.second);
       expr_t d2 = it->second;
 
-      hessian_output << "{\"eq\": " << eq + 1
-                     << ", \"var1\": \"" << var1 << "\""
-                     << ", \"var2\": \"" << var2 << "\""
+      int tsid1 = symbol_table.getTypeSpecificID(symb_id1);
+      int tsid2 = symbol_table.getTypeSpecificID(symb_id2);
+
+      int col = tsid1*symbol_table.endo_nbr()+tsid2;
+      int col_sym = tsid2*symbol_table.endo_nbr()+tsid1;
+
+      if (writeDetails)
+        hessian_output << "{\"eq\": " << eq + 1
+                       << ", \"var1\": \"" << symbol_table.getName(symb_id1) << "\""
+                       << ", \"var2\": \"" << symbol_table.getName(symb_id2) << "\"";
+      else
+        hessian_output << "{\"row\": " << eq + 1;
+
+      hessian_output << ", \"col\": [" << col + 1;
+      if (symb_id1 != symb_id2)
+        hessian_output << ", " <<  col_sym + 1;
+      hessian_output << "]"
                      << ", \"val\": \"";
       d2->writeJsonOutput(hessian_output, temp_term_union, tef_terms);
       hessian_output << "\"}" << endl;
@@ -2520,23 +2540,49 @@ StaticModel::writeJsonComputingPassOutput(ostream &output) const
         third_derivatives_output << ", ";
 
       int eq = it->first.first;
-      string var1 = symbol_table.getName(getSymbIDByDerivID(it->first.second.first));
-      string var2 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second.first));
-      string var3 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second.second));
+      int var1 = it->first.second.first;
+      int var2 = it->first.second.second.first;
+      int var3 = it->first.second.second.second;
       expr_t d3 = it->second;
 
-      third_derivatives_output << "{\"eq\": " << eq + 1
-                               << ", \"var1\": \"" << var1 << "\""
-                               << ", \"var2\": \"" << var2 << "\""
-                               << ", \"var3\": \"" << var3 << "\""
+      if (writeDetails)
+        third_derivatives_output << "{\"eq\": " << eq + 1
+                                 << ", \"var1\": \"" << symbol_table.getName(getSymbIDByDerivID(var1)) << "\""
+                                 << ", \"var2\": \"" << symbol_table.getName(getSymbIDByDerivID(var2)) << "\""
+                                 << ", \"var3\": \"" << symbol_table.getName(getSymbIDByDerivID(var3)) << "\"";
+      else
+        third_derivatives_output << "{\"row\": " << eq + 1;
+
+      int id1 = getSymbIDByDerivID(var1);
+      int id2 = getSymbIDByDerivID(var2);
+      int id3 = getSymbIDByDerivID(var3);
+      set<int> cols;
+      cols.insert(id1 * hessianColsNbr + id2 * JacobianColsNbr + id3);
+      cols.insert(id1 * hessianColsNbr + id3 * JacobianColsNbr + id2);
+      cols.insert(id2 * hessianColsNbr + id1 * JacobianColsNbr + id3);
+      cols.insert(id2 * hessianColsNbr + id3 * JacobianColsNbr + id1);
+      cols.insert(id3 * hessianColsNbr + id1 * JacobianColsNbr + id2);
+      cols.insert(id3 * hessianColsNbr + id2 * JacobianColsNbr + id1);
+
+      third_derivatives_output << ", \"col\": [";
+      for (set<int>::iterator it2 = cols.begin(); it2 != cols.end(); it2++)
+        {
+          if (it2 != cols.begin())
+            third_derivatives_output << ", ";
+          third_derivatives_output << *it2 + 1;
+        }
+      third_derivatives_output << "]"
                                << ", \"val\": \"";
       d3->writeJsonOutput(third_derivatives_output, temp_term_union, tef_terms);
       third_derivatives_output << "\"}" << endl;
     }
   third_derivatives_output << "]}";
 
-  output << "\"static_model_derivatives\": {"
-         << model_local_vars_output.str()
+  if (writeDetails)
+    output << "\"static_model_derivative_details\": {";
+  else
+    output << "\"static_model_derivatives\": {";
+  output  << model_local_vars_output.str()
          << ", " << model_output.str()
          << ", " << jacobian_output.str()
          << ", " << hessian_output.str()
@@ -2545,7 +2591,7 @@ StaticModel::writeJsonComputingPassOutput(ostream &output) const
 }
 
 void
-StaticModel::writeJsonParamsDerivativesFile(ostream &output) const
+StaticModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails) const
 {
   if (!residuals_params_derivatives.size()
       && !residuals_params_second_derivatives.size()
@@ -2579,11 +2625,17 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output) const
         jacobian_output << ", ";
 
       int eq = it->first.first;
-      string param = symbol_table.getName(getSymbIDByDerivID(it->first.second));
+      int param = it->first.second;
       expr_t d1 = it->second;
 
-      jacobian_output << "{\"eq\": " << eq + 1
-                      << ", \"param\": \"" << param << "\""
+      int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
+
+      if (writeDetails)
+        jacobian_output << "{\"eq\": " << eq + 1
+                        << ", \"param\": \"" << symbol_table.getName(getSymbIDByDerivID(param)) << "\"";
+      else
+        jacobian_output << "{\"row\": " << eq + 1;
+      jacobian_output << ", \"param_col\": " << param_col
                       << ", \"val\": \"";
       d1->writeJsonOutput(jacobian_output, params_derivs_temporary_terms, tef_terms);
       jacobian_output << "\"}" << endl;
@@ -2601,13 +2653,21 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output) const
         hessian_output << ", ";
 
       int eq = it->first.first;
-      string var = symbol_table.getName(getSymbIDByDerivID(it->first.second.first));
-      string param = symbol_table.getName(getSymbIDByDerivID(it->first.second.second));
+      int var = it->first.second.first;
+      int param = it->first.second.second;
       expr_t d2 = it->second;
 
-      hessian_output << "{\"eq\": " << eq + 1
-                     << ", \"var\": \"" << var << "\""
-                     << ", \"param\": \"" << param << "\""
+      int var_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(var)) + 1;
+      int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1;
+
+      if (writeDetails)
+        hessian_output << "{\"eq\": " << eq + 1
+                       << ", \"var\": \"" << symbol_table.getName(getSymbIDByDerivID(var)) << "\""
+                       << ", \"param\": \"" << symbol_table.getName(getSymbIDByDerivID(param)) << "\"";
+      else
+        hessian_output << "{\"row\": " << eq + 1;
+      hessian_output << ", \"var_col\": " << var_col
+                     << ", \"param_col\": " << param_col
                      << ", \"val\": \"";
       d2->writeJsonOutput(hessian_output, params_derivs_temporary_terms, tef_terms);
       hessian_output << "\"}" << endl;
@@ -2626,14 +2686,22 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output) const
         hessian1_output << ", ";
 
       int eq = it->first.first;
-      string param1 = symbol_table.getName(getSymbIDByDerivID(it->first.second.first));
-      string param2 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second));
+      int param1 = it->first.second.first;
+      int param2 = it->first.second.second;
       expr_t d2 = it->second;
 
-      hessian1_output << "{\"eq\": " << eq + 1
-                     << ", \"param1\": \"" << param1 << "\""
-                     << ", \"param2\": \"" << param2 << "\""
-                     << ", \"val\": \"";
+      int param1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1;
+      int param2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1;
+
+      if (writeDetails)
+        hessian1_output << "{\"eq\": " << eq + 1
+                        << ", \"param1\": \"" << symbol_table.getName(getSymbIDByDerivID(param1)) << "\""
+                        << ", \"param2\": \"" << symbol_table.getName(getSymbIDByDerivID(param2)) << "\"";
+      else
+        hessian1_output << "{\"row\": " << eq + 1;
+      hessian1_output << ", \"param1_col\": " << param1_col
+                      << ", \"param2_col\": " << param2_col
+                      << ", \"val\": \"";
       d2->writeJsonOutput(hessian1_output, params_derivs_temporary_terms, tef_terms);
       hessian1_output << "\"}" << endl;
     }
@@ -2651,15 +2719,25 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output) const
         third_derivs_output << ", ";
 
       int eq = it->first.first;
-      string var = symbol_table.getName(it->first.second.first);
-      string param1 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second.first));
-      string param2 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second.second));
+      int var = it->first.second.first;
+      int param1 = it->first.second.second.first;
+      int param2 = it->first.second.second.second;
       expr_t d2 = it->second;
 
-      third_derivs_output << "{\"eq\": " << eq + 1
-                          << ", \"var\": \"" << var << "\""
-                          << ", \"param1\": \"" << param1 << "\""
-                          << ", \"param2\": \"" << param2 << "\""
+      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;
+
+      if (writeDetails)
+        third_derivs_output << "{\"eq\": " << eq + 1
+                            << ", \"var\": \"" << symbol_table.getName(var) << "\""
+                            << ", \"param1\": \"" << symbol_table.getName(getSymbIDByDerivID(param1)) << "\""
+                            << ", \"param2\": \"" << symbol_table.getName(getSymbIDByDerivID(param2)) << "\"";
+      else
+        third_derivs_output << "{\"row\": " << eq + 1;
+      third_derivs_output << ", \"var_col\": " << var_col
+                          << ", \"param1_col\": " << param1_col
+                          << ", \"param2_col\": " << param2_col
                           << ", \"val\": \"";
       d2->writeJsonOutput(third_derivs_output, params_derivs_temporary_terms, tef_terms);
       third_derivs_output << "\"}" << endl;
@@ -2679,23 +2757,36 @@ StaticModel::writeJsonParamsDerivativesFile(ostream &output) const
         third_derivs1_output << ", ";
 
       int eq = it->first.first;
-      string var1 = symbol_table.getName(getSymbIDByDerivID(it->first.second.first));
-      string var2 = symbol_table.getName(getSymbIDByDerivID(it->first.second.second.first));
-      string param = symbol_table.getName(getSymbIDByDerivID(it->first.second.second.second));
+      int var1 = it->first.second.first;
+      int var2 = it->first.second.second.first;
+      int param = it->first.second.second.second;
       expr_t d2 = it->second;
 
-      third_derivs1_output << "{\"eq\": " << eq + 1
-                           << ", \"var1\": \"" << var1 << "\""
-                           << ", \"var2\": \"" << var2 << "\""
-                           << ", \"param1\": \"" << param << "\""
+      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;
+
+      if (writeDetails)
+        third_derivs1_output << "{\"eq\": " << eq + 1
+                             << ", \"var1\": \"" << symbol_table.getName(getSymbIDByDerivID(var1)) << "\""
+                             << ", \"var2\": \"" << symbol_table.getName(getSymbIDByDerivID(var2)) << "\""
+                             << ", \"param1\": \"" << symbol_table.getName(getSymbIDByDerivID(param)) << "\"";
+      else
+        third_derivs1_output << "{\"row\": " << eq + 1;
+      third_derivs1_output << ", \"var1_col\": " << var1_col
+                           << ", \"var2_col\": " << var2_col
+                           << ", \"param_col\": " << param_col
                            << ", \"val\": \"";
       d2->writeJsonOutput(third_derivs1_output, params_derivs_temporary_terms, tef_terms);
       third_derivs1_output << "\"}" << endl;
     }
   third_derivs1_output << "]}" << endl;
 
-  output << "\"static_model_params_derivatives\": {"
-         << model_local_vars_output.str()
+  if (writeDetails)
+    output << "\"static_model_params_derivative_details\": {";
+  else
+    output << "\"static_model_params_derivatives\": {";
+  output << model_local_vars_output.str()
          << ", " << model_output.str()
          << ", " << jacobian_output.str()
          << ", " << hessian_output.str()
diff --git a/StaticModel.hh b/StaticModel.hh
index d770896e..f1a7d36a 100644
--- a/StaticModel.hh
+++ b/StaticModel.hh
@@ -174,10 +174,10 @@ public:
   void writeJsonOutput(ostream &output) const;
 
   //! Write JSON representation of static model
-  void writeJsonComputingPassOutput(ostream &output) const;
+  void writeJsonComputingPassOutput(ostream &output, bool writeDetails) const;
 
   //! Writes file containing static parameters derivatives
-  void writeJsonParamsDerivativesFile(ostream &output) const;
+  void writeJsonParamsDerivativesFile(ostream &output, bool writeDetails) const;
 
   //! Writes file containing static parameters derivatives
   void writeParamsDerivativesFile(const string &basename, bool julia) const;
-- 
GitLab