diff --git a/src/ExprNode.cc b/src/ExprNode.cc
index 3432f2cc3545fe50d74a2b8e15e4ebd5e91cd187..fc6686a80eee73fe1f4f3a3b4136b73e836f1087 100644
--- a/src/ExprNode.cc
+++ b/src/ExprNode.cc
@@ -7901,11 +7901,179 @@ SecondDerivExternalFunctionNode::sameTefTermPredicate() const
     };
 }
 
+SubModelNode::SubModelNode(DataTree &datatree_arg,
+                           int idx_arg,
+                           string model_name_arg) :
+  ExprNode{datatree_arg, idx_arg},
+  model_name{move(model_name_arg)}
+{
+}
+
+expr_t
+SubModelNode::toStatic(DataTree &static_datatree) const
+{
+  cerr << "SubModelNode::toStatic not implemented." << endl;
+  exit(EXIT_FAILURE);
+}
+
+void
+SubModelNode::prepareForDerivation()
+{
+  cerr << "SubModelNode::prepareForDerivation not implemented." << endl;
+  exit(EXIT_FAILURE);
+}
+
+expr_t
+SubModelNode::computeDerivative(int deriv_id)
+{
+  cerr << "SubModelNode::computeDerivative not implemented." << endl;
+  exit(EXIT_FAILURE);
+}
+
+expr_t
+SubModelNode::getChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode *> &recursive_variables)
+{
+  cerr << "SubModelNode::getChainRuleDerivative not implemented." << endl;
+  exit(EXIT_FAILURE);
+}
+
+bool
+SubModelNode::containsExternalFunction() const
+{
+  return false;
+}
+
+double
+SubModelNode::eval(const eval_context_t &eval_context) const noexcept(false)
+{
+  throw EvalException();
+}
+
+void
+SubModelNode::computeXrefs(EquationInfo &ei) const
+{
+}
+
+void
+SubModelNode::collectVARLHSVariable(set<expr_t> &result) const
+{
+  cerr << "ERROR: you can only have variables or unary ops on LHS of VAR" << endl;
+  exit(EXIT_FAILURE);
+}
+
+void
+SubModelNode::collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const
+{
+}
+
+void
+SubModelNode::compile(ostream &CompileCode, unsigned int &instruction_number,
+                            bool lhs_rhs, const temporary_terms_t &temporary_terms,
+                            const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
+                            const deriv_node_temp_terms_t &tef_terms) const
+{
+  cerr << "SubModelNode::compile not implemented." << endl;
+  exit(EXIT_FAILURE);
+}
+
+void
+SubModelNode::computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const
+{
+}
+
+BinaryOpNode *
+SubModelNode::normalizeEquationHelper(const set<expr_t> &contain_var, expr_t rhs) const
+{
+  throw NormalizationFailed();
+}
+
+expr_t
+SubModelNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const
+{
+  return const_cast<SubModelNode *>(this);
+}
+
+expr_t
+SubModelNode::substituteAdl() const
+{
+  return const_cast<SubModelNode *>(this);
+}
+
+expr_t
+SubModelNode::substituteModelLocalVariables() const
+{
+  return const_cast<SubModelNode *>(this);
+}
+
+void
+SubModelNode::findDiffNodes(lag_equivalence_table_t &nodes) const
+{
+}
+
+void
+SubModelNode::findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const
+{
+}
+
+int
+SubModelNode::findTargetVariable(int lhs_symb_id) const
+{
+  return -1;
+}
+
+expr_t
+SubModelNode::substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table,
+                                   vector<BinaryOpNode *> &neweqs) const
+{
+  return const_cast<SubModelNode *>(this);
+}
+
+expr_t
+SubModelNode::substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
+{
+  return const_cast<SubModelNode *>(this);
+}
+
+bool
+SubModelNode::isNumConstNodeEqualTo(double value) const
+{
+  return false;
+}
+
+bool
+SubModelNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
+{
+  return false;
+}
+
+bool
+SubModelNode::isInStaticForm() const
+{
+  return false;
+}
+
+bool
+SubModelNode::isParamTimesEndogExpr() const
+{
+  return false;
+}
+
+expr_t
+SubModelNode::substituteStaticAuxiliaryVariable() const
+{
+  return const_cast<SubModelNode *>(this);
+}
+
+expr_t
+SubModelNode::replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const
+{
+  return const_cast<SubModelNode *>(this);
+}
+
 VarExpectationNode::VarExpectationNode(DataTree &datatree_arg,
                                        int idx_arg,
                                        string model_name_arg) :
-  ExprNode{datatree_arg, idx_arg},
-  model_name{move(model_name_arg)}
+  SubModelNode{datatree_arg, idx_arg, move(model_name_arg)}
 {
 }
 
@@ -7927,13 +8095,6 @@ VarExpectationNode::computeBlockTemporaryTerms(int blk, int eq, vector<vector<te
   exit(EXIT_FAILURE);
 }
 
-expr_t
-VarExpectationNode::toStatic(DataTree &static_datatree) const
-{
-  cerr << "VarExpectationNode::toStatic not implemented." << endl;
-  exit(EXIT_FAILURE);
-}
-
 expr_t
 VarExpectationNode::clone(DataTree &datatree) const
 {
@@ -8034,39 +8195,6 @@ VarExpectationNode::decreaseLeadsLags(int n) const
   exit(EXIT_FAILURE);
 }
 
-void
-VarExpectationNode::prepareForDerivation()
-{
-  cerr << "VarExpectationNode::prepareForDerivation not implemented." << endl;
-  exit(EXIT_FAILURE);
-}
-
-expr_t
-VarExpectationNode::computeDerivative(int deriv_id)
-{
-  cerr << "VarExpectationNode::computeDerivative not implemented." << endl;
-  exit(EXIT_FAILURE);
-}
-
-expr_t
-VarExpectationNode::getChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode *> &recursive_variables)
-{
-  cerr << "VarExpectationNode::getChainRuleDerivative not implemented." << endl;
-  exit(EXIT_FAILURE);
-}
-
-bool
-VarExpectationNode::containsExternalFunction() const
-{
-  return false;
-}
-
-double
-VarExpectationNode::eval(const eval_context_t &eval_context) const noexcept(false)
-{
-  throw EvalException();
-}
-
 int
 VarExpectationNode::countDiffs() const
 {
@@ -8074,43 +8202,6 @@ VarExpectationNode::countDiffs() const
   exit(EXIT_FAILURE);
 }
 
-void
-VarExpectationNode::computeXrefs(EquationInfo &ei) const
-{
-}
-
-void
-VarExpectationNode::collectVARLHSVariable(set<expr_t> &result) const
-{
-  cerr << "ERROR: you can only have variables or unary ops on LHS of VAR" << endl;
-  exit(EXIT_FAILURE);
-}
-
-void
-VarExpectationNode::collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const
-{
-}
-
-void
-VarExpectationNode::compile(ostream &CompileCode, unsigned int &instruction_number,
-                            bool lhs_rhs, const temporary_terms_t &temporary_terms,
-                            const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
-                            const deriv_node_temp_terms_t &tef_terms) const
-{
-  cerr << "VarExpectationNode::compile not implemented." << endl;
-  exit(EXIT_FAILURE);
-}
-
-void
-VarExpectationNode::computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const
-{
-}
-
-BinaryOpNode *
-VarExpectationNode::normalizeEquationHelper(const set<expr_t> &contain_var, expr_t rhs) const
-{
-  throw NormalizationFailed();
-}
 
 expr_t
 VarExpectationNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const
@@ -8140,24 +8231,6 @@ VarExpectationNode::substituteExoLag(subst_table_t &subst_table, vector<BinaryOp
   exit(EXIT_FAILURE);
 }
 
-expr_t
-VarExpectationNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const
-{
-  return const_cast<VarExpectationNode *>(this);
-}
-
-expr_t
-VarExpectationNode::substituteAdl() const
-{
-  return const_cast<VarExpectationNode *>(this);
-}
-
-expr_t
-VarExpectationNode::substituteModelLocalVariables() const
-{
-  return const_cast<VarExpectationNode *>(this);
-}
-
 expr_t
 VarExpectationNode::substituteVarExpectation(const map<string, expr_t> &subst_table) const
 {
@@ -8170,35 +8243,6 @@ VarExpectationNode::substituteVarExpectation(const map<string, expr_t> &subst_ta
   return it->second;
 }
 
-void
-VarExpectationNode::findDiffNodes(lag_equivalence_table_t &nodes) const
-{
-}
-
-void
-VarExpectationNode::findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const
-{
-}
-
-int
-VarExpectationNode::findTargetVariable(int lhs_symb_id) const
-{
-  return -1;
-}
-
-expr_t
-VarExpectationNode::substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table,
-                                   vector<BinaryOpNode *> &neweqs) const
-{
-  return const_cast<VarExpectationNode *>(this);
-}
-
-expr_t
-VarExpectationNode::substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
-{
-  return const_cast<VarExpectationNode *>(this);
-}
-
 expr_t
 VarExpectationNode::substitutePacExpectation(const string &name, expr_t subexpr)
 {
@@ -8218,12 +8262,6 @@ VarExpectationNode::containsPacExpectation(const string &pac_model_name) const
   return false;
 }
 
-bool
-VarExpectationNode::isNumConstNodeEqualTo(double value) const
-{
-  return false;
-}
-
 expr_t
 VarExpectationNode::decreaseLeadsLagsPredeterminedVariables() const
 {
@@ -8231,12 +8269,6 @@ VarExpectationNode::decreaseLeadsLagsPredeterminedVariables() const
   exit(EXIT_FAILURE);
 }
 
-bool
-VarExpectationNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
-{
-  return false;
-}
-
 expr_t
 VarExpectationNode::replaceTrendVar() const
 {
@@ -8258,30 +8290,6 @@ VarExpectationNode::removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map
   exit(EXIT_FAILURE);
 }
 
-bool
-VarExpectationNode::isInStaticForm() const
-{
-  return false;
-}
-
-bool
-VarExpectationNode::isParamTimesEndogExpr() const
-{
-  return false;
-}
-
-expr_t
-VarExpectationNode::substituteStaticAuxiliaryVariable() const
-{
-  return const_cast<VarExpectationNode *>(this);
-}
-
-expr_t
-VarExpectationNode::replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const
-{
-  return const_cast<VarExpectationNode *>(this);
-}
-
 void
 VarExpectationNode::writeJsonAST(ostream &output) const
 {
@@ -8303,8 +8311,7 @@ VarExpectationNode::writeJsonOutput(ostream &output,
 PacExpectationNode::PacExpectationNode(DataTree &datatree_arg,
                                        int idx_arg,
                                        string model_name_arg) :
-  ExprNode{datatree_arg, idx_arg},
-  model_name{move(model_name_arg)}
+  SubModelNode{datatree_arg, idx_arg, move(model_name_arg)}
 {
 }
 
@@ -8324,13 +8331,6 @@ PacExpectationNode::computeBlockTemporaryTerms(int blk, int eq, vector<vector<te
   blocks_temporary_terms[blk][eq].insert(const_cast<PacExpectationNode *>(this));
 }
 
-expr_t
-PacExpectationNode::toStatic(DataTree &static_datatree) const
-{
-  cerr << "PacExpectationNode::toStatic not implemented." << endl;
-  exit(EXIT_FAILURE);
-}
-
 expr_t
 PacExpectationNode::clone(DataTree &datatree) const
 {
@@ -8412,83 +8412,12 @@ PacExpectationNode::decreaseLeadsLags(int n) const
   return const_cast<PacExpectationNode *>(this);
 }
 
-void
-PacExpectationNode::prepareForDerivation()
-{
-  cerr << "PacExpectationNode::prepareForDerivation: shouldn't arrive here." << endl;
-  exit(EXIT_FAILURE);
-}
-
-expr_t
-PacExpectationNode::computeDerivative(int deriv_id)
-{
-  cerr << "PacExpectationNode::computeDerivative: shouldn't arrive here." << endl;
-  exit(EXIT_FAILURE);
-}
-
-expr_t
-PacExpectationNode::getChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode *> &recursive_variables)
-{
-  cerr << "PacExpectationNode::getChainRuleDerivative: shouldn't arrive here." << endl;
-  exit(EXIT_FAILURE);
-}
-
-bool
-PacExpectationNode::containsExternalFunction() const
-{
-  return false;
-}
-
-double
-PacExpectationNode::eval(const eval_context_t &eval_context) const noexcept(false)
-{
-  throw EvalException();
-}
-
-void
-PacExpectationNode::computeXrefs(EquationInfo &ei) const
-{
-}
-
-void
-PacExpectationNode::collectVARLHSVariable(set<expr_t> &result) const
-{
-  cerr << "ERROR: you can only have variables or unary ops on LHS of VAR" << endl;
-  exit(EXIT_FAILURE);
-}
-
-void
-PacExpectationNode::collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const
-{
-}
-
-void
-PacExpectationNode::compile(ostream &CompileCode, unsigned int &instruction_number,
-                            bool lhs_rhs, const temporary_terms_t &temporary_terms,
-                            const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
-                            const deriv_node_temp_terms_t &tef_terms) const
-{
-  cerr << "PacExpectationNode::compile not implemented." << endl;
-  exit(EXIT_FAILURE);
-}
-
 int
 PacExpectationNode::countDiffs() const
 {
   return 0;
 }
 
-void
-PacExpectationNode::computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const
-{
-}
-
-BinaryOpNode *
-PacExpectationNode::normalizeEquationHelper(const set<expr_t> &contain_var, expr_t rhs) const
-{
-  throw NormalizationFailed();
-}
-
 expr_t
 PacExpectationNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const
 {
@@ -8513,59 +8442,12 @@ PacExpectationNode::substituteExoLag(subst_table_t &subst_table, vector<BinaryOp
   return const_cast<PacExpectationNode *>(this);
 }
 
-expr_t
-PacExpectationNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const
-{
-  return const_cast<PacExpectationNode *>(this);
-}
-
-expr_t
-PacExpectationNode::substituteAdl() const
-{
-  return const_cast<PacExpectationNode *>(this);
-}
-
-expr_t
-PacExpectationNode::substituteModelLocalVariables() const
-{
-  return const_cast<PacExpectationNode *>(this);
-}
-
 expr_t
 PacExpectationNode::substituteVarExpectation(const map<string, expr_t> &subst_table) const
 {
   return const_cast<PacExpectationNode *>(this);
 }
 
-void
-PacExpectationNode::findDiffNodes(lag_equivalence_table_t &nodes) const
-{
-}
-
-void
-PacExpectationNode::findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const
-{
-}
-
-int
-PacExpectationNode::findTargetVariable(int lhs_symb_id) const
-{
-  return -1;
-}
-
-expr_t
-PacExpectationNode::substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table,
-                                   vector<BinaryOpNode *> &neweqs) const
-{
-  return const_cast<PacExpectationNode *>(this);
-}
-
-expr_t
-PacExpectationNode::substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
-{
-  return const_cast<PacExpectationNode *>(this);
-}
-
 expr_t
 PacExpectationNode::differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
@@ -8581,24 +8463,12 @@ PacExpectationNode::containsPacExpectation(const string &pac_model_name) const
     return pac_model_name == model_name;
 }
 
-bool
-PacExpectationNode::isNumConstNodeEqualTo(double value) const
-{
-  return false;
-}
-
 expr_t
 PacExpectationNode::decreaseLeadsLagsPredeterminedVariables() const
 {
   return const_cast<PacExpectationNode *>(this);
 }
 
-bool
-PacExpectationNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
-{
-  return false;
-}
-
 expr_t
 PacExpectationNode::replaceTrendVar() const
 {
@@ -8617,24 +8487,6 @@ PacExpectationNode::removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map
   return const_cast<PacExpectationNode *>(this);
 }
 
-bool
-PacExpectationNode::isInStaticForm() const
-{
-  return false;
-}
-
-expr_t
-PacExpectationNode::substituteStaticAuxiliaryVariable() const
-{
-  return const_cast<PacExpectationNode *>(this);
-}
-
-expr_t
-PacExpectationNode::replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const
-{
-  return const_cast<PacExpectationNode *>(this);
-}
-
 void
 PacExpectationNode::writeJsonAST(ostream &output) const
 {
@@ -8653,12 +8505,6 @@ PacExpectationNode::writeJsonOutput(ostream &output,
          << ")";
 }
 
-bool
-PacExpectationNode::isParamTimesEndogExpr() const
-{
-  return false;
-}
-
 expr_t
 PacExpectationNode::substitutePacExpectation(const string &name, expr_t subexpr)
 {
diff --git a/src/ExprNode.hh b/src/ExprNode.hh
index 612bd9ebbbda369706b0296b072403e072a6aa5d..cab7516c3245fd179f80626a154d6fb2204b1ade 100644
--- a/src/ExprNode.hh
+++ b/src/ExprNode.hh
@@ -1422,10 +1422,49 @@ public:
   expr_t clone(DataTree &datatree) const override;
 };
 
-class VarExpectationNode : public ExprNode
+/* Common superclass for nodes that have the following two characteristics:
+   – they take a submodel name as an argument
+   – they will be substituted out in the middle of the transform pass
+*/
+class SubModelNode : public ExprNode
 {
 public:
   const string model_name;
+  SubModelNode(DataTree &datatree_arg, int idx_arg, string model_name_arg);
+  expr_t toStatic(DataTree &static_datatree) const override;
+  void prepareForDerivation() override;
+  expr_t computeDerivative(int deriv_id) override;
+  expr_t getChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode *> &recursive_variables) override;
+  bool containsExternalFunction() const override;
+  double eval(const eval_context_t &eval_context) const noexcept(false) override;
+  void computeXrefs(EquationInfo &ei) const override;
+  expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
+  expr_t substituteAdl() const override;
+  expr_t substituteModelLocalVariables() const override;
+  void findDiffNodes(lag_equivalence_table_t &nodes) const override;
+  void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const override;
+  int findTargetVariable(int lhs_symb_id) const override;
+  expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
+  expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
+  void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const override;
+  BinaryOpNode *normalizeEquationHelper(const set<expr_t> &contain_var, expr_t rhs) const override;
+  void compile(ostream &CompileCode, unsigned int &instruction_number,
+               bool lhs_rhs, const temporary_terms_t &temporary_terms,
+               const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
+               const deriv_node_temp_terms_t &tef_terms) const override;
+  void collectVARLHSVariable(set<expr_t> &result) const override;
+  void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
+  bool isNumConstNodeEqualTo(double value) const override;
+  bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
+  bool isInStaticForm() const override;
+  expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
+  bool isParamTimesEndogExpr() const override;
+  expr_t substituteStaticAuxiliaryVariable() const override;
+};
+
+class VarExpectationNode : public SubModelNode
+{
+public:
   VarExpectationNode(DataTree &datatree_arg, int idx_arg, string model_name_arg);
   void computeTemporaryTerms(const pair<int, int> &derivOrder,
                              map<pair<int, int>, temporary_terms_t> &temp_terms_map,
@@ -1434,7 +1473,6 @@ public:
   void computeBlockTemporaryTerms(int blk, int eq, vector<vector<temporary_terms_t>> &blocks_temporary_terms,
                                   map<expr_t, tuple<int, int, int>> &reference_count) const override;
   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
-  expr_t toStatic(DataTree &static_datatree) const override;
   expr_t clone(DataTree &datatree) const override;
   int maxEndoLead() const override;
   int maxExoLead() const override;
@@ -1446,55 +1484,25 @@ public:
   int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
   expr_t undiff() const override;
   expr_t decreaseLeadsLags(int n) const override;
-  void prepareForDerivation() override;
-  expr_t computeDerivative(int deriv_id) override;
-  expr_t getChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode *> &recursive_variables) override;
-  bool containsExternalFunction() const override;
-  double eval(const eval_context_t &eval_context) const noexcept(false) override;
-  void computeXrefs(EquationInfo &ei) const override;
   expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
   expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
   expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
   expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
-  expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
-  expr_t substituteAdl() const override;
-  expr_t substituteModelLocalVariables() const override;
   expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
-  void findDiffNodes(lag_equivalence_table_t &nodes) const override;
-  void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const override;
-  int findTargetVariable(int lhs_symb_id) const override;
-  expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
-  expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
   expr_t substitutePacExpectation(const string &name, expr_t subexpr) override;
-  void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const override;
-  BinaryOpNode *normalizeEquationHelper(const set<expr_t> &contain_var, expr_t rhs) const override;
-  void compile(ostream &CompileCode, unsigned int &instruction_number,
-               bool lhs_rhs, const temporary_terms_t &temporary_terms,
-               const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
-               const deriv_node_temp_terms_t &tef_terms) const override;
-  void collectVARLHSVariable(set<expr_t> &result) const override;
-  void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
   int countDiffs() const override;
-  bool isNumConstNodeEqualTo(double value) const override;
   expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
   expr_t decreaseLeadsLagsPredeterminedVariables() const override;
-  bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
   expr_t replaceTrendVar() const override;
   expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
   expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
-  bool isInStaticForm() const override;
-  expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
   bool containsPacExpectation(const string &pac_model_name = "") const override;
-  bool isParamTimesEndogExpr() const override;
-  expr_t substituteStaticAuxiliaryVariable() const override;
   void writeJsonAST(ostream &output) const override;
   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
 };
 
-class PacExpectationNode : public ExprNode
+class PacExpectationNode : public SubModelNode
 {
-public:
-  const string model_name;
 public:
   PacExpectationNode(DataTree &datatree_arg, int idx_arg, string model_name);
   void computeTemporaryTerms(const pair<int, int> &derivOrder,
@@ -1504,7 +1512,6 @@ public:
   void computeBlockTemporaryTerms(int blk, int eq, vector<vector<temporary_terms_t>> &blocks_temporary_terms,
                                   map<expr_t, tuple<int, int, int>> &reference_count) const override;
   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
-  expr_t toStatic(DataTree &static_datatree) const override;
   expr_t clone(DataTree &datatree) const override;
   int maxEndoLead() const override;
   int maxExoLead() const override;
@@ -1516,47 +1523,19 @@ public:
   int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
   expr_t undiff() const override;
   expr_t decreaseLeadsLags(int n) const override;
-  void prepareForDerivation() override;
-  expr_t computeDerivative(int deriv_id) override;
-  expr_t getChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode *> &recursive_variables) override;
-  bool containsExternalFunction() const override;
-  double eval(const eval_context_t &eval_context) const noexcept(false) override;
-  void computeXrefs(EquationInfo &ei) const override;
   expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
   expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
   expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
   expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
-  expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
-  expr_t substituteAdl() const override;
-  expr_t substituteModelLocalVariables() const override;
   expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
-  void findDiffNodes(lag_equivalence_table_t &nodes) const override;
-  void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const override;
-  int findTargetVariable(int lhs_symb_id) const override;
-  expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
-  expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
   expr_t substitutePacExpectation(const string &name, expr_t subexpr) override;
-  void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const override;
-  BinaryOpNode *normalizeEquationHelper(const set<expr_t> &contain_var, expr_t rhs) const override;
-  void compile(ostream &CompileCode, unsigned int &instruction_number,
-               bool lhs_rhs, const temporary_terms_t &temporary_terms,
-               const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
-               const deriv_node_temp_terms_t &tef_terms) const override;
-  void collectVARLHSVariable(set<expr_t> &result) const override;
-  void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
   int countDiffs() const override;
-  bool isNumConstNodeEqualTo(double value) const override;
   expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
   expr_t decreaseLeadsLagsPredeterminedVariables() const override;
-  bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
   expr_t replaceTrendVar() const override;
   expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
   expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
-  bool isInStaticForm() const override;
-  expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
   bool containsPacExpectation(const string &pac_model_name = "") const override;
-  bool isParamTimesEndogExpr() const override;
-  expr_t substituteStaticAuxiliaryVariable() const override;
   void writeJsonAST(ostream &output) const override;
   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
 };