SteadyStateModel.cc 7.73 KB
Newer Older
1
/*
Houtan Bastani's avatar
Houtan Bastani committed
2
 * Copyright (C) 2010-2016 Dynare Team
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * This file is part of Dynare.
 *
 * Dynare is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Dynare is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <cassert>
#include <algorithm>

#include "SteadyStateModel.hh"

25 26
SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg, const StaticModel &static_model_arg) :
  DataTree(symbol_table_arg, num_constants_arg, external_functions_table_arg), static_model(static_model_arg)
27 28 29 30
{
}

void
31
SteadyStateModel::addDefinition(int symb_id, expr_t expr)
32
{
33 34
  AddVariable(symb_id); // Create the variable node to be used in write method

35
  assert(symbol_table.getType(symb_id) == eEndogenous
36 37
         || symbol_table.getType(symb_id) == eModFileLocalVariable
         || symbol_table.getType(symb_id) == eParameter);
38 39

  // Add the variable
40 41
  vector<int> v;
  v.push_back(symb_id);
42
  def_table.push_back(make_pair(v, expr));
43 44 45 46 47 48 49 50 51 52 53 54
}

void
SteadyStateModel::addMultipleDefinitions(const vector<int> &symb_ids, expr_t expr)
{
  for (size_t i = 0; i < symb_ids.size(); i++)
    {
      AddVariable(symb_ids[i]); // Create the variable nodes to be used in write method
      assert(symbol_table.getType(symb_ids[i]) == eEndogenous
             || symbol_table.getType(symb_ids[i]) == eModFileLocalVariable
             || symbol_table.getType(symb_ids[i]) == eParameter);
    }
55
  def_table.push_back(make_pair(symb_ids, expr));
56 57 58
}

void
59
SteadyStateModel::checkPass(bool ramsey_model, WarningConsolidation &warnings) const
60
{
61
  if (def_table.size() == 0)
62 63
    return;

64 65
  vector<int> so_far_defined;

66
  for (size_t i = 0; i < def_table.size(); i++)
67
    {
68
      const vector<int> &symb_ids = def_table[i].first;
69 70 71 72 73

      // Check that symbols are not already defined
      for (size_t j = 0; j < symb_ids.size(); j++)
        if (find(so_far_defined.begin(), so_far_defined.end(), symb_ids[j])
            != so_far_defined.end())
74 75
          warnings << "WARNING: in the 'steady_state_model' block, variable '" << symbol_table.getName(symb_ids[j]) << "' is declared twice" << endl;
      
76
      // Check that expression has no undefined symbol
77
      if (!ramsey_model)
78
        {
79
          set<int> used_symbols;
80
          const expr_t &expr = def_table[i].second;
81 82
          expr->collectVariables(eEndogenous, used_symbols);
          expr->collectVariables(eModFileLocalVariable, used_symbols);
83
          for (set<int>::const_iterator it = used_symbols.begin();
84
               it != used_symbols.end(); ++it)
85
            if (find(so_far_defined.begin(), so_far_defined.end(), *it)
86
                == so_far_defined.end())
87
              {
88
                cerr << "ERROR: in the 'steady_state_model' block, variable '" << symbol_table.getName(*it)
89
                     << "' is undefined in the declaration of variable '" << symbol_table.getName(symb_ids[0]) << "'" << endl;
90 91 92
                exit(EXIT_FAILURE);
              }
        }
93 94

      copy(symb_ids.begin(), symb_ids.end(), back_inserter(so_far_defined));
95
    }
96 97 98 99 100 101 102 103 104

  set<int> orig_endogs = symbol_table.getOrigEndogenous();
  for (set<int>::const_iterator it = orig_endogs.begin();
       it != orig_endogs.end(); ++it)
    {
      if (find(so_far_defined.begin(), so_far_defined.end(), *it)
          == so_far_defined.end())
        warnings << "WARNING: in the 'steady_state_model' block, variable '" << symbol_table.getName(*it) << "' is not assigned a value" << endl;
    }
105 106 107
}

void
Houtan Bastani's avatar
Houtan Bastani committed
108
SteadyStateModel::writeSteadyStateFile(const string &basename, bool ramsey_model, bool julia) const
109
{
110
  if (def_table.size() == 0)
111 112
    return;

Houtan Bastani's avatar
Houtan Bastani committed
113
  string filename = julia ? basename + "SteadyState2.jl" : basename + "_steadystate2.m";
114 115 116 117 118 119 120 121
  ofstream output;
  output.open(filename.c_str(), ios::out | ios::binary);
  if (!output.is_open())
    {
      cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
      exit(EXIT_FAILURE);
    }

Houtan Bastani's avatar
Houtan Bastani committed
122 123 124 125 126 127 128 129
  ExprNodeOutputType output_type = (julia ? oJuliaSteadyStateFile : oSteadyStateFile);

  if (!julia)
    output << "function [ys_, params, info] = " << basename << "_steadystate2("
           << "ys_, exo_, params)" << endl
           << "% Steady state generated by Dynare preprocessor" << endl
           << "    info = 0;" << endl;
  else
130 131 132 133 134
    output << "module " << basename << "SteadyState2" << endl
           << "#" << endl
           << "# NB: this file was automatically generated by Dynare" << endl
           << "#     from " << basename << ".mod" << endl
           << "#" << endl
135
           << "export steady_state!" << endl << endl
136 137
           << "function steady_state!(ys_::Vector{Float64}, exo_::Vector{Float64}, "
           << "params::Vector{Float64})" << endl;
138

139
  for (size_t i = 0; i < def_table.size(); i++)
140
    {
141
      const vector<int> &symb_ids = def_table[i].first;
142
      output << "    ";
143 144 145 146 147 148
      if (symb_ids.size() > 1)
        output << "[";
      for (size_t j = 0; j < symb_ids.size(); j++)
        {
          variable_node_map_t::const_iterator it = variable_node_map.find(make_pair(symb_ids[j], 0));
          assert(it != variable_node_map.end());
Houtan Bastani's avatar
Houtan Bastani committed
149
          dynamic_cast<ExprNode *>(it->second)->writeOutput(output, output_type);
150 151 152 153 154 155 156
          if (j < symb_ids.size()-1)
            output << ",";
        }
      if (symb_ids.size() > 1)
        output << "]";

      output << "=";
Houtan Bastani's avatar
Houtan Bastani committed
157
      def_table[i].second->writeOutput(output, output_type);
158 159
      output << ";" << endl;
    }
Houtan Bastani's avatar
Houtan Bastani committed
160 161 162 163
  if (!julia)
    output << "    % Auxiliary equations" << endl;
  else
    output << "    # Auxiliary equations" << endl;
164
  static_model.writeAuxVarRecursiveDefinitions(output, output_type);
Houtan Bastani's avatar
Houtan Bastani committed
165

166 167 168
  if (!julia)
    output << "    check_=0;" << endl;

Houtan Bastani's avatar
Houtan Bastani committed
169 170 171
  output << "end" << endl;
  if (julia)
    output << "end" << endl;
172 173
}

174 175 176 177
void
SteadyStateModel::writeSteadyStateFileC(const string &basename, bool ramsey_model) const
{
  string filename = basename + "_steadystate.c";
178

179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
  ofstream output;
  output.open(filename.c_str(), ios::out | ios::binary);
  if (!output.is_open())
    {
      cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
      exit(EXIT_FAILURE);
    }

  output << "#include <math.h>" << endl;

  output << "void steadystate("
	 << "const double *exo_, const double *params, double *ys_, int *info)" << endl
         << "// Steady state file generated by Dynare preprocessor" << endl
	 << "{" << endl
         << "    *info = 0;" << endl;

  if (def_table.size() == 0)
    {
      output << "    return;" << endl
	     << "}" << endl;
      return;
    }

  for (size_t i = 0; i < def_table.size(); i++)
    {
      const vector<int> &symb_ids = def_table[i].first;
      output << "    ";
      if (symb_ids.size() > 1)
	std::cout << "Error: in C, multiple returns are not permitted in steady_state_model" << std::endl;
      variable_node_map_t::const_iterator it = variable_node_map.find(make_pair(symb_ids[0], 0));
      assert(it != variable_node_map.end());
      if (it->second->get_type() == eModFileLocalVariable)
	output << "double ";
      dynamic_cast<ExprNode *>(it->second)->writeOutput(output, oCSteadyStateFile);
      output << "=";
      def_table[i].second->writeOutput(output, oCSteadyStateFile);
      output << ";" << endl;
    }
  output << "    // Auxiliary equations" << endl;
  static_model.writeAuxVarInitval(output, oCSteadyStateFile);
  output << "}" << endl;
}