diff --git a/preprocessor/DynamicModel.cc b/preprocessor/DynamicModel.cc
index 0481ec73ab54a18f70f0f6d298ceffcb7a0651cb..6a1a5546c7c3ef900667f9a04a89a221cdccfc44 100644
--- a/preprocessor/DynamicModel.cc
+++ b/preprocessor/DynamicModel.cc
@@ -2112,26 +2112,27 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri
 void
 DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia) const
 {
-  ostringstream model_output;    // Used for storing model
-  ostringstream model_eq_output; // Used for storing model equations
-  ostringstream jacobian_output; // Used for storing jacobian equations
-  ostringstream hessian_output;  // Used for storing Hessian equations
+  ostringstream model_local_vars_output;  // Used for storing model local vars
+  ostringstream model_output;             // Used for storing model temp vars and equations
+  ostringstream jacobian_output;          // Used for storing jacobian equations
+  ostringstream hessian_output;           // Used for storing Hessian equations
   ostringstream third_derivatives_output;
 
   ExprNodeOutputType output_type = (use_dll ? oCDynamicModel :
                                     julia ? oJuliaDynamicModel : oMatlabDynamicModel);
 
   deriv_node_temp_terms_t tef_terms;
-  writeModelLocalVariables(model_output, output_type, tef_terms);
+  writeModelLocalVariables(model_local_vars_output, output_type, tef_terms);
 
-  writeTemporaryTerms(temporary_terms, model_output, output_type, tef_terms);
+  writeTemporaryTerms(temporary_terms_res, model_output, output_type, tef_terms);
 
-  writeModelEquations(model_eq_output, output_type);
+  writeModelEquations(model_output, output_type);
 
   int nrows = equations.size();
   int hessianColsNbr = dynJacobianColsNbr * dynJacobianColsNbr;
 
   // Writing Jacobian
+  writeTemporaryTerms(temporary_terms_g1, jacobian_output, output_type, tef_terms);
   for (first_derivatives_t::const_iterator it = first_derivatives.begin();
        it != first_derivatives.end(); it++)
     {
@@ -2141,11 +2142,13 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia
 
       jacobianHelper(jacobian_output, eq, getDynJacobianCol(var), output_type);
       jacobian_output << "=";
-      d1->writeOutput(jacobian_output, output_type, temporary_terms, tef_terms);
+      d1->writeOutput(jacobian_output, output_type, temporary_terms_g1, tef_terms);
       jacobian_output << ";" << endl;
     }
 
   // Writing Hessian
+  if (second_derivatives.size() > 0)
+    writeTemporaryTerms(temporary_terms_g2, hessian_output, output_type, tef_terms);
   int k = 0; // Keep the line of a 2nd derivative in v2
   for (second_derivatives_t::const_iterator it = second_derivatives.begin();
        it != second_derivatives.end(); it++)
@@ -2166,7 +2169,7 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia
         {
           for_sym << "g2[" << eq + 1 << "," << col_nb + 1 << "]";
           hessian_output << "  @inbounds " << for_sym.str() << " = ";
-          d2->writeOutput(hessian_output, output_type, temporary_terms, tef_terms);
+          d2->writeOutput(hessian_output, output_type, temporary_terms_g2, tef_terms);
           hessian_output << endl;
         }
       else
@@ -2208,6 +2211,8 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia
     }
 
   // Writing third derivatives
+  if (third_derivatives.size() > 0)
+    writeTemporaryTerms(temporary_terms_g3, third_derivatives_output, output_type, tef_terms);
   k = 0; // Keep the line of a 3rd derivative in v3
   for (third_derivatives_t::const_iterator it = third_derivatives.begin();
        it != third_derivatives.end(); it++)
@@ -2230,7 +2235,7 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia
         {
           for_sym << "g3[" << eq + 1 << "," << ref_col + 1 << "]";
           third_derivatives_output << "  @inbounds " << for_sym.str() << " = ";
-          d3->writeOutput(third_derivatives_output, output_type, temporary_terms, tef_terms);
+          d3->writeOutput(third_derivatives_output, output_type, temporary_terms_g3, tef_terms);
           third_derivatives_output << endl;
         }
       else
@@ -2287,8 +2292,8 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia
                     << "%" << endl
                     << endl
                     << "residual = zeros(" << nrows << ", 1);" << endl
+                    << model_local_vars_output.str()
                     << model_output.str()
-                    << model_eq_output.str()
         // Writing initialization instruction for matrix g1
                     << "if nargout >= 2," << endl
                     << "  g1 = zeros(" << nrows << ", " << dynJacobianColsNbr << ");" << endl
@@ -2337,8 +2342,8 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia
                     << "  double lhs, rhs;" << endl
                     << endl
                     << "  /* Residual equations */" << endl
+                    << model_local_vars_output.str()
                     << model_output.str()
-                    << model_eq_output.str()
                     << "  /* Jacobian  */" << endl
                     << "  if (g1 == NULL)" << endl
                     << "    return;" << endl
@@ -2396,8 +2401,8 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia
                     << "  #" << endl
                     << "  # Model equations" << endl
                     << "  #" << endl
+                    << model_local_vars_output.str()
                     << model_output.str()
-                    << model_eq_output.str()
                     << "end" << endl << endl
                     << "function dynamic!(y::Vector{Float64}, x::Matrix{Float64}, "
                     << "params::Vector{Float64}," << endl
@@ -2413,7 +2418,7 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia
                     << "  @assert size(g1) == (" << nrows << ", " << dynJacobianColsNbr << ")" << endl
                     << "  fill!(g1, 0.0)" << endl
                     << "  dynamic!(y, x, params, steady_state, it_, residual)" << endl
-                    << model_output.str()
+                    << model_local_vars_output.str()
                     << "  #" << endl
                     << "  # Jacobian matrix" << endl
                     << "  #" << endl
@@ -2433,7 +2438,7 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia
                     << "  @assert size(g2) == (" << nrows << ", " << hessianColsNbr << ")" << endl
                     << "  dynamic!(y, x, params, steady_state, it_, residual, g1)" << endl;
       if (second_derivatives.size())
-        DynamicOutput << model_output.str()
+        DynamicOutput << model_local_vars_output.str()
                       << "  #" << endl
                       << "  # Hessian matrix" << endl
                       << "  #" << endl
@@ -2456,7 +2461,7 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia
                     << "  @assert size(g3) == (" << nrows << ", " << ncols << ")" << endl
                     << "  dynamic!(y, x, params, steady_state, it_, residual, g1, g2)" << endl;
       if (third_derivatives.size())
-        DynamicOutput << model_output.str()
+        DynamicOutput << model_local_vars_output.str()
                       << "  #" << endl
                       << "  # Third order derivatives" << endl
                       << "  #" << endl
diff --git a/preprocessor/ExprNode.cc b/preprocessor/ExprNode.cc
index 7b52a0bdaf6b06591d160939e2b3ac6969279614..8145115ae572ea56db5489dd5185ad90771dd8a9 100644
--- a/preprocessor/ExprNode.cc
+++ b/preprocessor/ExprNode.cc
@@ -128,6 +128,14 @@ ExprNode::computeTemporaryTerms(map<expr_t, int> &reference_count,
   // Nothing to do for a terminal node
 }
 
+void
+ExprNode::computeSplitTemporaryTerms(map<expr_t, int> &reference_count,
+                                     temporary_terms_t &temporary_terms,
+                                     bool is_matlab) const
+{
+  // Nothing to do for a terminal node
+}
+
 pair<int, expr_t >
 ExprNode::normalizeEquation(int var_endo, vector<pair<int, pair<expr_t, expr_t> > > &List_of_Op_RHS) const
 {
@@ -1748,6 +1756,19 @@ UnaryOpNode::collectTemporary_terms(const temporary_terms_t &temporary_terms, te
     arg->collectTemporary_terms(temporary_terms, temporary_terms_inuse, Curr_Block);
 }
 
+void
+UnaryOpNode::computeSplitTemporaryTerms(map<expr_t, int> &reference_count,
+                                        temporary_terms_t &temporary_terms,
+                                        bool is_matlab) const
+{
+  expr_t this2 = const_cast<UnaryOpNode *>(this);
+
+  arg->computeSplitTemporaryTerms(reference_count, temporary_terms, is_matlab);
+
+  if (reference_count[this2] * cost(temporary_terms, is_matlab) > MIN_COST(is_matlab))
+    temporary_terms.insert(this2);
+}
+
 bool
 UnaryOpNode::containsExternalFunction() const
 {
@@ -2815,6 +2836,21 @@ BinaryOpNode::computeTemporaryTerms(map<expr_t, int> &reference_count,
     }
 }
 
+void
+BinaryOpNode::computeSplitTemporaryTerms(map<expr_t, int> &reference_count,
+                                         temporary_terms_t &temporary_terms,
+                                         bool is_matlab) const
+{
+  expr_t this2 = const_cast<BinaryOpNode *>(this);
+
+  arg1->computeSplitTemporaryTerms(reference_count, temporary_terms, is_matlab);
+  arg2->computeSplitTemporaryTerms(reference_count, temporary_terms, is_matlab);
+
+  if (reference_count[this2] * cost(temporary_terms, is_matlab) > MIN_COST(is_matlab)
+      && op_code != oEqual)
+    temporary_terms.insert(this2);
+}
+
 double
 BinaryOpNode::eval_opcode(double v1, BinaryOpcode op_code, double v2, int derivOrder) throw (EvalException, EvalExternalFunctionException)
 {
@@ -3947,6 +3983,21 @@ TrinaryOpNode::computeTemporaryTerms(map<expr_t, int> &reference_count,
     }
 }
 
+void
+TrinaryOpNode::computeSplitTemporaryTerms(map<expr_t, int> &reference_count,
+                                          temporary_terms_t &temporary_terms,
+                                          bool is_matlab) const
+{
+  expr_t this2 = const_cast<TrinaryOpNode *>(this);
+
+  arg1->computeSplitTemporaryTerms(reference_count, temporary_terms, is_matlab);
+  arg2->computeSplitTemporaryTerms(reference_count, temporary_terms, is_matlab);
+  arg3->computeSplitTemporaryTerms(reference_count, temporary_terms, is_matlab);
+
+  if (reference_count[this2] * cost(temporary_terms, is_matlab) > MIN_COST(is_matlab))
+    temporary_terms.insert(this2);
+}
+
 double
 TrinaryOpNode::eval_opcode(double v1, TrinaryOpcode op_code, double v2, double v3) throw (EvalException, EvalExternalFunctionException)
 {
@@ -4738,6 +4789,14 @@ ExternalFunctionNode::computeTemporaryTerms(map<expr_t, int> &reference_count,
   v_temporary_terms[Curr_block][equation].insert(this2);
 }
 
+void
+ExternalFunctionNode::computeSplitTemporaryTerms(map<expr_t, int> &reference_count,
+                                                 temporary_terms_t &temporary_terms,
+                                                 bool is_matlab) const
+{
+  temporary_terms.insert(const_cast<ExternalFunctionNode *>(this));
+}
+
 void
 ExternalFunctionNode::compile(ostream &CompileCode, unsigned int &instruction_number,
                               bool lhs_rhs, const temporary_terms_t &temporary_terms,
@@ -4993,6 +5052,14 @@ FirstDerivExternalFunctionNode::computeTemporaryTerms(map<expr_t, int> &referenc
   v_temporary_terms[Curr_block][equation].insert(this2);
 }
 
+void
+FirstDerivExternalFunctionNode::computeSplitTemporaryTerms(map<expr_t, int> &reference_count,
+                                                           temporary_terms_t &temporary_terms,
+                                                           bool is_matlab) const
+{
+  temporary_terms.insert(const_cast<FirstDerivExternalFunctionNode *>(this));
+}
+
 expr_t
 FirstDerivExternalFunctionNode::composeDerivatives(const vector<expr_t> &dargs)
 {
@@ -5301,6 +5368,14 @@ SecondDerivExternalFunctionNode::computeTemporaryTerms(map<expr_t, int> &referen
   v_temporary_terms[Curr_block][equation].insert(this2);
 }
 
+void
+SecondDerivExternalFunctionNode::computeSplitTemporaryTerms(map<expr_t, int> &reference_count,
+                                                            temporary_terms_t &temporary_terms,
+                                                            bool is_matlab) const
+{
+  temporary_terms.insert(const_cast<SecondDerivExternalFunctionNode *>(this));
+}
+
 expr_t
 SecondDerivExternalFunctionNode::composeDerivatives(const vector<expr_t> &dargs)
 
diff --git a/preprocessor/ExprNode.hh b/preprocessor/ExprNode.hh
index a8f48e306dce6b72e91e99d711f448e848360529..6584cb87eaa53f30594e7c87c99b881c2fd062f0 100644
--- a/preprocessor/ExprNode.hh
+++ b/preprocessor/ExprNode.hh
@@ -188,6 +188,10 @@ public:
   /*! A node will be marked as a temporary term if it is referenced at least two times (i.e. has at least two parents), and has a computing cost (multiplied by reference count) greater to datatree.min_cost */
   virtual void computeTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
 
+  //! Splits temporary terms into those used for each of residuals, jacobian, hessian, 3rd derivs
+  //! based on the reference counts computed by computeTemporaryTerms
+    virtual void computeSplitTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
+
   //! Writes output of node, using a Txxx notation for nodes in temporary_terms, and specifiying the set of already written external functions
   /*!
     \param[in] output the output stream
@@ -566,6 +570,7 @@ public:
   UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg);
   virtual void prepareForDerivation();
   virtual void computeTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
+  virtual void computeSplitTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual bool containsExternalFunction() const;
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
@@ -645,6 +650,7 @@ public:
   virtual void prepareForDerivation();
   virtual int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const;
   virtual void computeTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
+  virtual void computeSplitTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual bool containsExternalFunction() const;
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
@@ -740,6 +746,7 @@ public:
   virtual void prepareForDerivation();
   virtual int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const;
   virtual void computeTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
+  virtual void computeSplitTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual bool containsExternalFunction() const;
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
@@ -812,6 +819,7 @@ public:
                                const vector<expr_t> &arguments_arg);
   virtual void prepareForDerivation();
   virtual void computeTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const = 0;
+  virtual void computeSplitTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const = 0;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const = 0;
   virtual bool containsExternalFunction() const;
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
@@ -872,6 +880,7 @@ public:
   ExternalFunctionNode(DataTree &datatree_arg, int symb_id_arg,
                        const vector<expr_t> &arguments_arg);
   virtual void computeTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
+  virtual void computeSplitTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
                                            const temporary_terms_t &temporary_terms,
@@ -909,6 +918,7 @@ public:
                                      int Curr_block,
                                      vector< vector<temporary_terms_t> > &v_temporary_terms,
                                      int equation) const;
+  virtual void computeSplitTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual void compile(ostream &CompileCode, unsigned int &instruction_number,
                        bool lhs_rhs, const temporary_terms_t &temporary_terms,
@@ -945,6 +955,7 @@ public:
                                      int Curr_block,
                                      vector< vector<temporary_terms_t> > &v_temporary_terms,
                                      int equation) const;
+  virtual void computeSplitTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
   virtual void compile(ostream &CompileCode, unsigned int &instruction_number,
                        bool lhs_rhs, const temporary_terms_t &temporary_terms,
diff --git a/preprocessor/ModelTree.cc b/preprocessor/ModelTree.cc
index 10fb02f7a0c1aa0b000df38015f734703047ccdc..e6b2dab68d7df05f5954ff7322fc8208c703808b 100644
--- a/preprocessor/ModelTree.cc
+++ b/preprocessor/ModelTree.cc
@@ -1110,6 +1110,27 @@ ModelTree::computeTemporaryTerms(bool is_matlab)
   for (third_derivatives_t::iterator it = third_derivatives.begin();
        it != third_derivatives.end(); it++)
     it->second->computeTemporaryTerms(reference_count, temporary_terms, is_matlab);
+
+  // Now split up temporary terms
+  temporary_terms_res.clear();
+  for (vector<BinaryOpNode *>::iterator it = equations.begin();
+       it != equations.end(); it++)
+    (*it)->computeSplitTemporaryTerms(reference_count, temporary_terms_res, is_matlab);
+
+  temporary_terms_g1 = temporary_terms_res;
+  for (first_derivatives_t::iterator it = first_derivatives.begin();
+       it != first_derivatives.end(); it++)
+    it->second->computeSplitTemporaryTerms(reference_count, temporary_terms_g1, is_matlab);
+
+  temporary_terms_g2 = temporary_terms_g1;
+  for (second_derivatives_t::iterator it = second_derivatives.begin();
+       it != second_derivatives.end(); it++)
+    it->second->computeSplitTemporaryTerms(reference_count, temporary_terms_g2, is_matlab);
+
+  temporary_terms_g3 = temporary_terms_g2;
+  for (third_derivatives_t::iterator it = third_derivatives.begin();
+       it != third_derivatives.end(); it++)
+    it->second->computeSplitTemporaryTerms(reference_count, temporary_terms_g3, is_matlab);
 }
 
 void
@@ -1118,7 +1139,6 @@ ModelTree::writeTemporaryTerms(const temporary_terms_t &tt, ostream &output,
 {
   // Local var used to keep track of temp nodes already written
   temporary_terms_t tt2;
-
   for (temporary_terms_t::const_iterator it = tt.begin();
        it != tt.end(); it++)
     {
@@ -1213,6 +1233,12 @@ ModelTree::writeModelLocalVariables(ostream &output, ExprNodeOutputType output_t
 void
 ModelTree::writeModelEquations(ostream &output, ExprNodeOutputType output_type) const
 {
+  temporary_terms_t temp_terms;
+  if (IS_JULIA(output_type))
+    temp_terms = temporary_terms_res;
+  else
+    temp_terms = temporary_terms;
+
   for (int eq = 0; eq < (int) equations.size(); eq++)
     {
       BinaryOpNode *eq_node = equations[eq];
@@ -1234,13 +1260,13 @@ ModelTree::writeModelEquations(ostream &output, ExprNodeOutputType output_type)
           if (IS_JULIA(output_type))
             output << "  @inbounds ";
           output << "lhs =";
-          lhs->writeOutput(output, output_type, temporary_terms);
+          lhs->writeOutput(output, output_type, temp_terms);
           output << ";" << endl;
 
           if (IS_JULIA(output_type))
             output << "  @inbounds ";
           output << "rhs =";
-          rhs->writeOutput(output, output_type, temporary_terms);
+          rhs->writeOutput(output, output_type, temp_terms);
           output << ";" << endl;
 
           if (IS_JULIA(output_type))
@@ -1258,7 +1284,7 @@ ModelTree::writeModelEquations(ostream &output, ExprNodeOutputType output_type)
                  << eq + ARRAY_SUBSCRIPT_OFFSET(output_type)
                  << RIGHT_ARRAY_SUBSCRIPT(output_type)
                  << " = ";
-          lhs->writeOutput(output, output_type, temporary_terms);
+          lhs->writeOutput(output, output_type, temp_terms);
           output << ";" << endl;
         }
     }
diff --git a/preprocessor/ModelTree.hh b/preprocessor/ModelTree.hh
index ea799585c2b2f0b1cddca7fd678a333e3feccdd5..09132552bfab9de787a2b232440efc3a9d265d16 100644
--- a/preprocessor/ModelTree.hh
+++ b/preprocessor/ModelTree.hh
@@ -130,6 +130,10 @@ protected:
 
   //! Temporary terms for the static/dynamic file (those which will be noted Txxxx)
   temporary_terms_t temporary_terms;
+  temporary_terms_t temporary_terms_res;
+  temporary_terms_t temporary_terms_g1;
+  temporary_terms_t temporary_terms_g2;
+  temporary_terms_t temporary_terms_g3;
 
   //! Temporary terms for the file containing parameters derivatives
   temporary_terms_t params_derivs_temporary_terms;