diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 85037d4dcce09c630db097418a98f47e8582b8f5..1807762fcc02f0513a827e4f9552d67522052d3a 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -953,7 +953,7 @@ DynamicModel::writeDynamicCFile(const string &basename) const
       exit(EXIT_FAILURE);
     }
   output << "/*" << endl
-         << " * " << filename << " : Computes dynamic model for Dynare" << endl
+         << " * " << filename << " : Computes " << modelClassName() << " for Dynare" << endl
          << " *" << endl
          << " * Warning : this file is generated automatically by Dynare" << endl
          << " *           from model file (.mod)" << endl
@@ -3261,7 +3261,7 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
      getJacobianColsNbr() is not yet set.*/
   if (log2(getJacobianColsNbr())*derivsOrder >= numeric_limits<int>::digits)
     {
-      cerr << "ERROR: The dynamic derivatives matrix is too large. Please decrease the approximation order." << endl;
+      cerr << "ERROR: The derivatives matrix of the " << modelClassName() << " is too large. Please decrease the approximation order." << endl;
       exit(EXIT_FAILURE);
     }
 
@@ -3275,7 +3275,7 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
     }
 
   // Launch computations
-  cout << "Computing dynamic model derivatives (order " << derivsOrder << ")." << endl;
+  cout << "Computing " << modelClassName() << " derivatives (order " << derivsOrder << ")." << endl;
 
   computeDerivatives(derivsOrder, vars);
 
@@ -3285,7 +3285,7 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
 
   if (paramsDerivsOrder > 0)
     {
-      cout << "Computing dynamic model derivatives w.r.t. parameters (order " << paramsDerivsOrder << ")." << endl;
+      cout << "Computing " << modelClassName() << " derivatives w.r.t. parameters (order " << paramsDerivsOrder << ")." << endl;
       computeParamsDerivatives(paramsDerivsOrder);
     }
 
@@ -3307,12 +3307,12 @@ bool
 DynamicModel::computingPassBlock(const eval_context_t &eval_context, bool no_tmp_terms)
 {
   auto contemporaneous_jacobian = evaluateAndReduceJacobian(eval_context);
-  if (!computeNonSingularNormalization(contemporaneous_jacobian, true))
+  if (!computeNonSingularNormalization(contemporaneous_jacobian))
     return false;
   auto [prologue, epilogue] = computePrologueAndEpilogue();
   auto first_order_endo_derivatives = collectFirstOrderDerivativesEndogenous();
   equationTypeDetermination(first_order_endo_derivatives, mfs);
-  cout << "Finding the optimal block decomposition of the dynamic model..." << endl;
+  cout << "Finding the optimal block decomposition of the " << modelClassName() << "..." << endl;
   computeBlockDecomposition(prologue, epilogue);
   reduceBlockDecomposition();
   printBlockDecomposition();
@@ -3663,7 +3663,7 @@ DynamicModel::writeSetAuxiliaryVariables(const string &basename, bool julia) con
     output << "ds = ";
   output << func_name + "(ds, params)" << endl
          << comment << endl
-         << comment << " Status : Computes Auxiliary variables of the dynamic model and returns a dseries" << endl
+         << comment << " Status : Computes Auxiliary variables of the " << modelClassName() << " and returns a dseries" << endl
          << comment << endl
          << comment << " Warning : this file is generated automatically by Dynare" << endl
          << comment << "           from model file (.mod)" << endl << endl;
diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh
index 37051525e6b6b90bcd2854b076476a8b7070ddc8..458de8d1e3036aeb208f95ed8ad79ecbad43de32 100644
--- a/src/DynamicModel.hh
+++ b/src/DynamicModel.hh
@@ -303,6 +303,13 @@ private:
      (failure can happen in normalization). */
   virtual bool computingPassBlock(const eval_context_t &eval_context, bool no_tmp_terms);
 
+protected:
+  string
+  modelClassName() const override
+  {
+    return "dynamic model";
+  }
+
 public:
   DynamicModel(SymbolTable &symbol_table_arg,
                NumericalConstants &num_constants_arg,
diff --git a/src/ModFile.hh b/src/ModFile.hh
index 90d73f8990d1fd81705437efb041820d50d2fcb4..02bc8027f6af05480eb07d92b05bb766f32a44ed 100644
--- a/src/ModFile.hh
+++ b/src/ModFile.hh
@@ -68,7 +68,7 @@ public:
   //! A copy of Dynamic model, for testing trends declared by user
   DynamicModel trend_dynamic_model;
   //! A copy of the original model, used to test model linearity under ramsey problem
-  DynamicModel orig_ramsey_dynamic_model;
+  OrigRamseyDynamicModel orig_ramsey_dynamic_model;
   //! Epilogue model, as declared in the "epilogue" block
   Epilogue epilogue;
   //! Static model, as derived from the "model" block when leads and lags have been removed
diff --git a/src/ModelEquationBlock.cc b/src/ModelEquationBlock.cc
index fe0d649146333b3842a4c4d7ef06b82ada493b87..58db1c8a1aacdc205eae895f47c016a8b44529ab 100644
--- a/src/ModelEquationBlock.cc
+++ b/src/ModelEquationBlock.cc
@@ -38,6 +38,23 @@ PlannerObjective::computingPassBlock([[maybe_unused]] const eval_context_t &eval
   return false;
 }
 
+OrigRamseyDynamicModel::OrigRamseyDynamicModel(SymbolTable &symbol_table_arg,
+                                               NumericalConstants &num_constants_arg,
+                                               ExternalFunctionsTable &external_functions_table_arg,
+                                               TrendComponentModelTable &trend_component_model_table_arg,
+                                               VarModelTable &var_model_table_arg) :
+  DynamicModel {symbol_table_arg, num_constants_arg, external_functions_table_arg,
+                trend_component_model_table_arg, var_model_table_arg}
+{
+}
+
+OrigRamseyDynamicModel &
+OrigRamseyDynamicModel::operator=(const DynamicModel &m)
+{
+  DynamicModel::operator=(m);
+  return *this;
+}
+
 SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg,
                                    NumericalConstants &num_constants_arg,
                                    ExternalFunctionsTable &external_functions_table_arg,
diff --git a/src/ModelEquationBlock.hh b/src/ModelEquationBlock.hh
index eb255e03ef61e6e53152fcb2fb9babb5e4cea6db..a34fb6dcfcf887dab547747823c225de00f210ec 100644
--- a/src/ModelEquationBlock.hh
+++ b/src/ModelEquationBlock.hh
@@ -32,10 +32,35 @@ public:
   PlannerObjective(SymbolTable &symbol_table_arg,
                    NumericalConstants &num_constants_arg,
                    ExternalFunctionsTable &external_functions_table_arg);
+protected:
+  string
+  modelClassName() const override
+  {
+    return "planner objective";
+  }
+
 private:
   bool computingPassBlock(const eval_context_t &eval_context, bool no_tmp_terms) override;
 };
 
+class OrigRamseyDynamicModel : public DynamicModel
+{
+public:
+  OrigRamseyDynamicModel(SymbolTable &symbol_table_arg,
+                         NumericalConstants &num_constants_arg,
+                         ExternalFunctionsTable &external_functions_table_arg,
+                         TrendComponentModelTable &trend_component_model_table_arg,
+                         VarModelTable &var_model_table_arg);
+  OrigRamseyDynamicModel &operator=(const DynamicModel &m);
+
+protected:
+  string
+  modelClassName() const override
+  {
+    return "original Ramsey model";
+  }
+};
+
 class SteadyStateModel : public DataTree
 {
 private:
@@ -104,6 +129,14 @@ public:
 
   //! Write Output
   void writeOutput(ostream &output) const;
+
+protected:
+  string
+  modelClassName() const override
+  {
+    return "epilogue";
+  }
+
 private:
   //! Helper for public writeEpilogueFile
   void writeStaticEpilogueFile(const string &basename) const;
diff --git a/src/ModelTree.cc b/src/ModelTree.cc
index 8da7b1ad8a2ebd67ca8e79e9b3dc299aadc2acf8..1ad98dd65a8ae9e97bfe9fff4894529c7a111620 100644
--- a/src/ModelTree.cc
+++ b/src/ModelTree.cc
@@ -202,7 +202,7 @@ ModelTree::operator=(const ModelTree &m)
 }
 
 bool
-ModelTree::computeNormalization(const jacob_map_t &contemporaneous_jacobian, bool dynamic, bool verbose)
+ModelTree::computeNormalization(const jacob_map_t &contemporaneous_jacobian, bool verbose)
 {
   const int n = equations.size();
 
@@ -242,7 +242,7 @@ ModelTree::computeNormalization(const jacob_map_t &contemporaneous_jacobian, boo
       it != mate_map.begin() + n)
     {
       if (verbose)
-        cerr << "Could not normalize the " << (dynamic ? "dynamic" : "static") << " model. Variable "
+        cerr << "Could not normalize the " << modelClassName() << " . Variable "
              << symbol_table.getName(symbol_table.getID(SymbolType::endogenous, it - mate_map.begin()))
              << " is not in the maximum cardinality matching." << endl;
       check = false;
@@ -251,7 +251,7 @@ ModelTree::computeNormalization(const jacob_map_t &contemporaneous_jacobian, boo
 }
 
 bool
-ModelTree::computeNonSingularNormalization(const jacob_map_t &contemporaneous_jacobian, bool dynamic)
+ModelTree::computeNonSingularNormalization(const jacob_map_t &contemporaneous_jacobian)
 {
   int n = equations.size();
 
@@ -259,11 +259,11 @@ ModelTree::computeNonSingularNormalization(const jacob_map_t &contemporaneous_ja
      not have as many equations as variables. */
   if (n != symbol_table.endo_nbr())
     {
-      cout << "The " << (dynamic ? "dynamic" : "static") << " model cannot be normalized, since it does not have as many equations as variables." << endl;
+      cout << "The " << modelClassName() << " cannot be normalized, since it does not have as many equations as variables." << endl;
       return false;
     }
 
-  cout << "Normalizing the " << (dynamic ? "dynamic" : "static") << " model..." << endl;
+  cout << "Normalizing the " << modelClassName() << "..." << endl;
 
   // Compute the maximum value of each row of the contemporaneous Jacobian matrix
   vector max_val(n, 0.0);
@@ -293,14 +293,14 @@ ModelTree::computeNonSingularNormalization(const jacob_map_t &contemporaneous_ja
           suppressed++;
 
       if (suppressed != last_suppressed)
-        found_normalization = computeNormalization(normalized_contemporaneous_jacobian_above_cutoff, dynamic, false);
+        found_normalization = computeNormalization(normalized_contemporaneous_jacobian_above_cutoff, false);
       last_suppressed = suppressed;
       if (!found_normalization)
         {
           current_cutoff /= 2;
           // In this last case try to normalize with the complete jacobian
           if (current_cutoff <= cutoff_lower_limit)
-            found_normalization = computeNormalization(normalized_contemporaneous_jacobian, dynamic, false);
+            found_normalization = computeNormalization(normalized_contemporaneous_jacobian, false);
         }
     }
 
@@ -311,7 +311,7 @@ ModelTree::computeNonSingularNormalization(const jacob_map_t &contemporaneous_ja
          normalization even with a potential singularity.
          TODO: Explain why symbolic_jacobian is not contemporaneous. */
       auto symbolic_jacobian = computeSymbolicJacobian();
-      found_normalization = computeNormalization(symbolic_jacobian, dynamic, true);
+      found_normalization = computeNormalization(symbolic_jacobian, true);
     }
 
   /* NB: If normalization failed, an explanatory message has been printed by the last call
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index ecb49614c135e0dcb464a81039c0e50759b443b7..fdeb5ecaf6fc3ffc79f01d2146a13d4dfefbfc47 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -344,7 +344,7 @@ protected:
     \param contemporaneous_jacobian Jacobian used as an incidence matrix: all elements declared in the map (even if they are zero), are used as vertices of the incidence matrix
     \return True if a complete normalization has been achieved
   */
-  bool computeNormalization(const jacob_map_t &contemporaneous_jacobian, bool dynamic, bool verbose);
+  bool computeNormalization(const jacob_map_t &contemporaneous_jacobian, bool verbose);
 
   //! Try to compute the matching between endogenous and variable using a decreasing cutoff
   /*!
@@ -354,7 +354,7 @@ protected:
     The resulting normalization is stored in endo2eq.
     Returns a boolean indicating success.
   */
-  bool computeNonSingularNormalization(const jacob_map_t &contemporaneous_jacobian, bool dynamic);
+  bool computeNonSingularNormalization(const jacob_map_t &contemporaneous_jacobian);
   //! Evaluate the jacobian (w.r.t. endogenous) and suppress all the elements below the cutoff
   /*! Returns the contemporaneous_jacobian.
       Elements below the cutoff are discarded. External functions are evaluated to 1. */
@@ -453,6 +453,9 @@ protected:
      “var” is the block-specific endogenous variable index. */
   virtual int getBlockJacobianEndoCol(int blk, int var, int lag) const = 0;
 
+  // Returns a human-readable string describing the model class (e.g. “dynamic model”…)
+  virtual string modelClassName() const = 0;
+
 private:
   //! Internal helper for the copy constructor and assignment operator
   /*! Copies all the structures that contain ExprNode*, by the converting the
diff --git a/src/StaticModel.cc b/src/StaticModel.cc
index 8636bd76407a9f908c53d98ddd44c6c84b205a85..13a023f51c77bd2dc3f68779403de8b286a6388e 100644
--- a/src/StaticModel.cc
+++ b/src/StaticModel.cc
@@ -344,7 +344,7 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co
      with DynamicModel::computingPass(). */
   if (log2(symbol_table.endo_nbr())*derivsOrder >= numeric_limits<int>::digits)
     {
-      cerr << "ERROR: The static derivatives matrix is too large. Please decrease the approximation order." << endl;
+      cerr << "ERROR: The derivatives matrix of the " << modelClassName() << " is too large. Please decrease the approximation order." << endl;
       exit(EXIT_FAILURE);
     }
 
@@ -357,13 +357,13 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co
     }
 
   // Launch computations
-  cout << "Computing static model derivatives (order " << derivsOrder << ")." << endl;
+  cout << "Computing " << modelClassName() << " derivatives (order " << derivsOrder << ")." << endl;
 
   computeDerivatives(derivsOrder, vars);
 
   if (paramsDerivsOrder > 0)
     {
-      cout << "Computing static model derivatives w.r.t. parameters (order " << paramsDerivsOrder << ")." << endl;
+      cout << "Computing " << modelClassName() << " derivatives w.r.t. parameters (order " << paramsDerivsOrder << ")." << endl;
       computeParamsDerivatives(paramsDerivsOrder);
     }
 
@@ -385,12 +385,12 @@ bool
 StaticModel::computingPassBlock(const eval_context_t &eval_context, bool no_tmp_terms)
 {
   auto contemporaneous_jacobian = evaluateAndReduceJacobian(eval_context);
-  if (!computeNonSingularNormalization(contemporaneous_jacobian, false))
+  if (!computeNonSingularNormalization(contemporaneous_jacobian))
     return false;
   auto [prologue, epilogue] = computePrologueAndEpilogue();
   auto first_order_endo_derivatives = collectFirstOrderDerivativesEndogenous();
   equationTypeDetermination(first_order_endo_derivatives, mfs);
-  cout << "Finding the optimal block decomposition of the static model..." << endl;
+  cout << "Finding the optimal block decomposition of the " << modelClassName() << "..." << endl;
   computeBlockDecomposition(prologue, epilogue);
   reduceBlockDecomposition();
   printBlockDecomposition();
@@ -637,7 +637,7 @@ StaticModel::writeStaticCFile(const string &basename) const
     }
 
   output << "/*" << endl
-         << " * " << filename << " : Computes static model for Dynare" << endl
+         << " * " << filename << " : Computes " << modelClassName() << " for Dynare" << endl
          << " *" << endl
          << " * Warning : this file is generated automatically by Dynare" << endl
          << " *           from model file (.mod)" << endl << endl
@@ -1325,7 +1325,7 @@ StaticModel::writeSetAuxiliaryVariables(const string &basename, bool julia) cons
     output << "y = ";
   output << func_name << "(y, x, params)" << endl
          << comment << endl
-         << comment << " Status : Computes static model for Dynare" << endl
+         << comment << " Status : Computes Auxiliary variables of the " << modelClassName() << endl
          << comment << endl
          << comment << " Warning : this file is generated automatically by Dynare" << endl
          << comment << "           from model file (.mod)" << endl << endl;
diff --git a/src/StaticModel.hh b/src/StaticModel.hh
index da65283905cc5a4069e114d64bbf491744138a5f..127252b1e91b7225cf3abcf3b4355765b735ca54 100644
--- a/src/StaticModel.hh
+++ b/src/StaticModel.hh
@@ -116,6 +116,13 @@ private:
      (failure can happen in normalization). */
   virtual bool computingPassBlock(const eval_context_t &eval_context, bool no_tmp_terms);
 
+protected:
+  string
+  modelClassName() const override
+  {
+    return "static model";
+  }
+
 public:
   StaticModel(SymbolTable &symbol_table_arg,
               NumericalConstants &num_constants,