diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index b406b20b24886a5c61235189466db5039f3f06b5..2213fbdd4f91320c6712338632f9e8318cb7db0b 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -3050,6 +3050,15 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de
       output << "};" << endl;
     }
 
+  // Write mapping for variables and equations they are present in
+  for (const auto & variable : variableMapping)
+    {
+      output << modstruct << "mapping." << symbol_table.getName(variable.first) << ".eqidx = [";
+      for (auto equation : variable.second)
+        output << equation + 1 << " ";
+      output << "];" << endl;
+    }
+
   /* Say if static and dynamic models differ (because of [static] and [dynamic]
      equation tags) */
   output << modstruct << "static_and_dynamic_models_differ = "
@@ -5483,6 +5492,52 @@ DynamicModel::ParamUsedWithLeadLag() const
   return ParamUsedWithLeadLagInternal();
 }
 
+void
+DynamicModel::createVariableMapping(int orig_eq_nbr)
+{
+  for (int ii = 0; ii < orig_eq_nbr; ii++)
+    {
+      set<int> eqvars;
+      equations[ii]->collectVariables(SymbolType::endogenous, eqvars);
+      equations[ii]->collectVariables(SymbolType::exogenous, eqvars);
+      for (auto eqvar : eqvars)
+        {
+          while (symbol_table.isAuxiliaryVariable(eqvar))
+            eqvar = symbol_table.getOrigSymbIdForAuxVar(eqvar);
+          variableMapping[eqvar].emplace(ii);
+        }
+    }
+}
+
+void
+DynamicModel::expandEqTags()
+{
+  set<int> existing_tags;
+  for (const auto & eqn : equation_tags)
+    if (eqn.second.first == "name")
+      existing_tags.insert(eqn.first);
+
+  for (int eq = 0; eq < static_cast<int>(equations.size()); eq++)
+    if (existing_tags.find(eq) == existing_tags.end())
+      if (auto lhs_expr = dynamic_cast<VariableNode *>(equations[eq]->arg1); lhs_expr && equation_tags_xref.find(pair("name", symbol_table.getName(lhs_expr->symb_id))) == equation_tags_xref.end())
+        {
+          equation_tags.push_back(pair(eq, pair("name", symbol_table.getName(lhs_expr->symb_id))));
+          equation_tags_xref.emplace(pair("name", symbol_table.getName(lhs_expr->symb_id)), eq);
+        }
+      else if (equation_tags_xref.find(pair("name",to_string(eq+1))) == equation_tags_xref.end())
+        {
+          equation_tags.push_back(pair(eq, pair("name", to_string(eq+1))));
+          equation_tags_xref.emplace(pair("name", to_string(eq+1)), eq);
+        }
+      else
+        {
+          cerr << "Error creating default equation tag: cannot assign default tag to equation number " << eq+1 << " because it is already in use" << endl;
+          exit(EXIT_FAILURE);
+        }
+
+  sort(equation_tags.begin(), equation_tags.end());
+}
+
 set<int>
 DynamicModel::findUnusedEndogenous()
 {
@@ -6642,6 +6697,8 @@ DynamicModel::writeJsonOutput(ostream &output) const
   writeJsonXrefs(output);
   output << ", ";
   writeJsonAST(output);
+  output << ", ";
+  writeJsonVariableMapping(output);
 }
 
 void
@@ -6682,6 +6739,26 @@ DynamicModel::writeJsonAST(ostream &output) const
   output << "]";
 }
 
+void
+DynamicModel::writeJsonVariableMapping(ostream &output) const
+{
+  output << R"("variable_mapping":[)" << endl;
+  int ii = 0;
+  int end_idx_map = static_cast<int>(variableMapping.size()-1);
+  for (const auto & variable : variableMapping)
+    {
+      output << R"({"name": ")" << symbol_table.getName(variable.first) << R"(", "equations":[)";
+      int it = 0;
+      int end_idx_eq = static_cast<int>(variable.second.size())-1;
+      for (const auto & equation : variable.second)
+        for (const auto & equation_tag : equation_tags)
+          if (equation_tag.first == equation && equation_tag.second.first == "name")
+            output << R"(")" << equation_tag.second.second << (it++ == end_idx_eq ? R"("])":R"(", )");
+      output << (ii++ == end_idx_map ? R"(})":R"(},)") << endl;
+    }
+  output << "]";
+}
+
 void
 DynamicModel::writeJsonXrefsHelper(ostream &output, const map<pair<int, int>, set<int>> &xrefs) const
 {
diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh
index b8bc149537ba75e3a54dd87ec9a8d9ae4a41a104..67ca4019efa0c140e6ada23539da1856b6a902bb 100644
--- a/src/DynamicModel.hh
+++ b/src/DynamicModel.hh
@@ -97,6 +97,9 @@ private:
 
   vector<temporary_terms_inuse_t> v_temporary_terms_inuse;
 
+  //! Creates mapping for variables and equations they are present in
+  map<int, set<int>> variableMapping;
+
   //! Store the derivatives or the chainrule derivatives:map<tuple<equation, variable, lead_lag>, expr_t>
   using first_chain_rule_derivatives_t = map<tuple<int, int, int>, expr_t>;
   first_chain_rule_derivatives_t first_chain_rule_derivatives;
@@ -289,6 +292,9 @@ public:
   //! Write JSON AST
   void writeJsonAST(ostream &output) const;
 
+  //! Write JSON variable mapping
+  void writeJsonVariableMapping(ostream &output) const;
+
   //! Write JSON Output
   void writeJsonOutput(ostream &output) const;
 
@@ -369,6 +375,12 @@ public:
   /*! It assumes that the nonlinear model given in argument has just been allocated */
   void toNonlinearPart(DynamicModel &non_linear_equations_dynamic_model) const;
 
+  //! Creates mapping for variables and equations they are present in
+  void createVariableMapping(int orig_eq_nbr);
+
+  //! Expands equation tags with default equation names (available "name" tag or LHS variable or equation ID)
+  void expandEqTags();
+
   //! Find endogenous variables not used in model
   set<int> findUnusedEndogenous();
   //! Find exogenous variables not used in model
diff --git a/src/ModFile.cc b/src/ModFile.cc
index eb283507a8d167ca032227614e7500bb0fc8a70e..bb55a0c03a81c10f41bde806eca37234d77a52c9 100644
--- a/src/ModFile.cc
+++ b/src/ModFile.cc
@@ -394,6 +394,7 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
   dynamic_model.substituteAdl();
   dynamic_model.setLeadsLagsOrig();
   original_model = dynamic_model;
+  dynamic_model.expandEqTags();
 
   // Check that all declared endogenous are used in equations
   set<int> unusedEndogs = dynamic_model.findUnusedEndogenous();
@@ -602,6 +603,7 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
     }
   // And finally perform the substitutions
   dynamic_model.substituteVarExpectation(var_expectation_subst_table);
+  dynamic_model.createVariableMapping(original_model.equation_number());
 
   if (mod_file_struct.stoch_simul_present
       || mod_file_struct.estimation_present