ModFile.cc 25.8 KB
Newer Older
sebastien's avatar
sebastien committed
1
/*
2
 * Copyright (C) 2006-2011 Dynare Team
sebastien's avatar
sebastien committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * 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/>.
 */

20
#include <cstdlib>
sebastien's avatar
sebastien committed
21
22
#include <iostream>
#include <fstream>
23
#include <typeinfo>
24
#include <cassert>
25
#include "ModFile.hh"
26
#include "ConfigFile.hh"
27
#include "ComputingTasks.hh"
28

29
30
ModFile::ModFile() : expressions_tree(symbol_table, num_constants, external_functions_table),
                     dynamic_model(symbol_table, num_constants, external_functions_table),
31
                     trend_dynamic_model(symbol_table, num_constants, external_functions_table),
32
                     ramsey_FOC_equations_dynamic_model(symbol_table, num_constants, external_functions_table),
33
                     static_model(symbol_table, num_constants, external_functions_table),
34
                     steady_state_model(symbol_table, num_constants, external_functions_table, static_model),
35
                     linear(false), block(false), byte_code(false),
36
37
                     use_dll(false), no_static(false), nonstationary_variables(false),
                     ramsey_policy_orig_eqn_nbr(0)
38
39
{
}
sebastien's avatar
sebastien committed
40
41
42

ModFile::~ModFile()
{
43
44
  for (vector<Statement *>::iterator it = statements.begin();
       it != statements.end(); it++)
sebastien's avatar
sebastien committed
45
46
47
    delete (*it);
}

48
void
49
ModFile::evalAllExpressions(bool warn_uninit)
50
{
sebastien's avatar
sebastien committed
51
  cout << "Evaluating expressions...";
52

sebastien's avatar
sebastien committed
53
  // Loop over all statements, and fill global eval context if relevant
54
  for (vector<Statement *>::const_iterator it = statements.begin(); it != statements.end(); it++)
55
    {
sebastien's avatar
sebastien committed
56
57
58
59
60
61
62
63
64
65
66
      InitParamStatement *ips = dynamic_cast<InitParamStatement *>(*it);
      if (ips)
        ips->fillEvalContext(global_eval_context);

      InitOrEndValStatement *ies = dynamic_cast<InitOrEndValStatement *>(*it);
      if (ies)
        ies->fillEvalContext(global_eval_context);

      LoadParamsAndSteadyStateStatement *lpass = dynamic_cast<LoadParamsAndSteadyStateStatement *>(*it);
      if (lpass)
        lpass->fillEvalContext(global_eval_context);
67
    }
sebastien's avatar
sebastien committed
68
69

  // Evaluate model local variables
sebastien's avatar
sebastien committed
70
  dynamic_model.fillEvalContext(global_eval_context);
sebastien's avatar
sebastien committed
71
72
73
74

  cout << "done" << endl;

  // Check if some symbols are not initialized, and give them a zero value then
75
  for (int id = 0; id <= symbol_table.maxID(); id++)
76
    {
sebastien's avatar
sebastien committed
77
78
      SymbolType type = symbol_table.getType(id);
      if ((type == eEndogenous || type == eExogenous || type == eExogenousDet
79
           || type == eParameter || type == eModelLocalVariable)
sebastien's avatar
sebastien committed
80
          && global_eval_context.find(id) == global_eval_context.end())
81
        {
82
83
          if (warn_uninit)
            cerr << "WARNING: can't find a numeric initial value for " << symbol_table.getName(id) << ", using zero" << endl;
sebastien's avatar
sebastien committed
84
          global_eval_context[id] = 0;
85
86
87
88
        }
    }
}

sebastien's avatar
sebastien committed
89
90
91
92
93
94
void
ModFile::addStatement(Statement *st)
{
  statements.push_back(st);
}

95
96
97
98
99
100
void
ModFile::addStatementAtFront(Statement *st)
{
  statements.insert(statements.begin(), st);
}

sebastien's avatar
sebastien committed
101
102
103
void
ModFile::checkPass()
{
104
105
  for (vector<Statement *>::iterator it = statements.begin();
       it != statements.end(); it++)
sebastien's avatar
sebastien committed
106
107
    (*it)->checkPass(mod_file_struct);

108
109
110
  // Check the steady state block
  steady_state_model.checkPass(mod_file_struct.ramsey_policy_present);

111
112
113
114
  // If order option has not been set, default to 2
  if (!mod_file_struct.order_option)
    mod_file_struct.order_option = 2;

sebastien's avatar
sebastien committed
115
116
117
  bool stochastic_statement_present = mod_file_struct.stoch_simul_present
    || mod_file_struct.estimation_present
    || mod_file_struct.osr_present
118
119
    || mod_file_struct.ramsey_policy_present
    || mod_file_struct.discretionary_policy_present;
sebastien's avatar
sebastien committed
120

121
  // Allow empty model only when doing a standalone BVAR estimation
sebastien's avatar
sebastien committed
122
  if (dynamic_model.equation_number() == 0
123
124
      && (mod_file_struct.check_present
          || mod_file_struct.simul_present
sebastien's avatar
sebastien committed
125
126
127
          || stochastic_statement_present))
    {
      cerr << "ERROR: At least one model equation must be declared!" << endl;
128
      exit(EXIT_FAILURE);
sebastien's avatar
sebastien committed
129
130
    }

131
132
133
134
  if (((mod_file_struct.ramsey_policy_present || mod_file_struct.discretionary_policy_present) 
       && !mod_file_struct.planner_objective_present)
      || (!(mod_file_struct.ramsey_policy_present || mod_file_struct.discretionary_policy_present)
	  && mod_file_struct.planner_objective_present))
135
    {
136
      cerr << "ERROR: A planner_objective statement must be used with a ramsey_policy or a discretionary_policy statement and vice versa." << endl;
137
138
139
      exit(EXIT_FAILURE);
    }

140
141
142
143
144
145
146
147
  if ((mod_file_struct.osr_present && (!mod_file_struct.osr_params_present || !mod_file_struct.optim_weights_present))
      || ((!mod_file_struct.osr_present || !mod_file_struct.osr_params_present) && mod_file_struct.optim_weights_present)
      || ((!mod_file_struct.osr_present || !mod_file_struct.optim_weights_present) && mod_file_struct.osr_params_present))
    {
      cerr << "ERROR: The osr statement must be used with osr_params and optim_weights." << endl;
      exit(EXIT_FAILURE);
    }

148
  if (mod_file_struct.simul_present && stochastic_statement_present)
149
    {
150
      cerr << "ERROR: A .mod file cannot contain both a simul command and one of {stoch_simul, estimation, osr, ramsey_policy, discretionary_policy}" << endl;
151
      exit(EXIT_FAILURE);
152
153
    }

154
  if (mod_file_struct.k_order_solver && byte_code)
sebastien's avatar
sebastien committed
155
    {
156
      cerr << "ERROR: 'k_order_solver' (which is implicit if order >= 3), is not yet compatible with 'bytecode'." << endl;
sebastien's avatar
sebastien committed
157
158
159
      exit(EXIT_FAILURE);
    }

160
161
162
163
164
165
  if (use_dll && (block || byte_code))
    {
      cerr << "ERROR: In 'model' block, 'use_dll' option is not compatible with 'block' or 'bytecode'" << endl;
      exit(EXIT_FAILURE);
    }

166
167
168
169
170
171
172
  if (block || byte_code)
    if (dynamic_model.isModelLocalVariableUsed())
      {
        cerr << "ERROR: In 'model' block, 'block' or 'bytecode' options are not yet compatible with pound expressions" << endl;
        exit(EXIT_FAILURE);
      }

173
  if ((stochastic_statement_present || mod_file_struct.check_present || mod_file_struct.steady_present) && no_static)
174
    {
175
      cerr << "ERROR: no_static option is incompatible with stoch_simul, estimation, osr, ramsey_policy, discretionary_policy, steady and check commands" << endl;
176
177
      exit(EXIT_FAILURE);
    }
178

179
180
181
182
183
184
185
186
  if (mod_file_struct.dsge_var_estimated)
    if (!mod_file_struct.dsge_prior_weight_in_estimated_params)
      {
        cerr << "ERROR: When estimating a DSGE-VAR model and estimating the weight of the prior, dsge_prior_weight must "
             << "be referenced in the estimated_params block." << endl;
        exit(EXIT_FAILURE);
      }

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
  if (symbol_table.exists("dsge_prior_weight"))
    {
      if (symbol_table.getType("dsge_prior_weight") != eParameter)
        {
          cerr << "ERROR: dsge_prior_weight may only be used as a parameter." << endl;
          exit(EXIT_FAILURE);
        }
      else
        cout << "WARNING: When estimating a DSGE-Var, declaring dsge_prior_weight as a parameter is deprecated. "
             <<  "The preferred method is to do this via the dsge_var option in the estimation statement." << endl;

      if (mod_file_struct.dsge_var_estimated || !mod_file_struct.dsge_var_calibrated.empty())
        {
          cerr << "ERROR: dsge_prior_weight can either be declared as a parameter (deprecated) or via the dsge_var option "
               << "to the estimation statement (preferred), but not both." << endl;
          exit(EXIT_FAILURE);
        }

      if (!mod_file_struct.dsge_prior_weight_initialized && !mod_file_struct.dsge_prior_weight_in_estimated_params)
        {
          cerr << "ERROR: If dsge_prior_weight is declared as a parameter, it must either be initialized or placed in the "
               << "estimated_params block." << endl;
          exit(EXIT_FAILURE);
        }

      if (mod_file_struct.dsge_prior_weight_initialized && mod_file_struct.dsge_prior_weight_in_estimated_params)
        {
          cerr << "ERROR: dsge_prior_weight cannot be both initalized and estimated." << endl;
          exit(EXIT_FAILURE);
        }
    }

219
  if (mod_file_struct.dsge_prior_weight_in_estimated_params)
220
    if (!mod_file_struct.dsge_var_estimated && !mod_file_struct.dsge_var_calibrated.empty())
221
      {
222
        cerr << "ERROR: If dsge_prior_weight is in the estimated_params block, the prior weight cannot be calibrated "
223
224
225
             << "via the dsge_var option in the estimation statement." << endl;
        exit(EXIT_FAILURE);
      }
226
227
228
229
230
231
    else if (!mod_file_struct.dsge_var_estimated && !symbol_table.exists("dsge_prior_weight"))
      {
        cerr << "ERROR: If dsge_prior_weight is in the estimated_params block, it must either be declared as a parameter "
             << "(deprecated) or the dsge_var option must be passed to the estimation statement (preferred)." << endl;
        exit(EXIT_FAILURE);
      }
sebastien's avatar
sebastien committed
232
233
234
235
236
}

void
ModFile::transformPass()
{
sebastien's avatar
sebastien committed
237
238
  if (symbol_table.predeterminedNbr() > 0)
    dynamic_model.transformPredeterminedVariables();
239

240
241
242
  // Create auxiliary vars for Expectation operator
  dynamic_model.substituteExpectation(mod_file_struct.partial_information);

243
244
245
246
247
248
249
  if (nonstationary_variables)
    {
      dynamic_model.detrendEquations();
      dynamic_model.cloneDynamic(trend_dynamic_model);
      dynamic_model.removeTrendVariableFromEquations();
    }

250
251
252
253
254
255
256
257
258
  if (mod_file_struct.ramsey_policy_present)
    {
      StaticModel *planner_objective = NULL;
      for (vector<Statement *>::iterator it = statements.begin(); it != statements.end(); it++)
        {
          PlannerObjectiveStatement *pos = dynamic_cast<PlannerObjectiveStatement *>(*it);
          if (pos != NULL)
            planner_objective = pos->getPlannerObjective();
        }
259
      assert(planner_objective != NULL);
260
261
262
263
264
265
266
      ramsey_policy_orig_eqn_nbr = dynamic_model.equation_number();

      /*
        clone the model then clone the new equations back to the original because
        we have to call computeDerivIDs (in computeRamseyPolicyFOCs and computingPass)
       */
      dynamic_model.cloneDynamic(ramsey_FOC_equations_dynamic_model);
267
      ramsey_FOC_equations_dynamic_model.computeRamseyPolicyFOCs(*planner_objective);
268
269
270
      ramsey_FOC_equations_dynamic_model.replaceMyEquations(dynamic_model);
    }

sebastien's avatar
sebastien committed
271
272
273
  if (mod_file_struct.stoch_simul_present
      || mod_file_struct.estimation_present
      || mod_file_struct.osr_present
274
275
      || mod_file_struct.ramsey_policy_present
      || mod_file_struct.discretionary_policy_present)
sebastien's avatar
sebastien committed
276
    {
277
278
279
280
281
282
283
284
285
286
287
      // In stochastic models, create auxiliary vars for leads and lags greater than 2, on both endos and exos
      dynamic_model.substituteEndoLeadGreaterThanTwo(false);
      dynamic_model.substituteExoLead(false);
      dynamic_model.substituteEndoLagGreaterThanTwo(false);
      dynamic_model.substituteExoLag(false);
    }
  else
    {
      // In deterministic models, create auxiliary vars for leads and lags endogenous greater than 2, only on endos (useless on exos)
      dynamic_model.substituteEndoLeadGreaterThanTwo(true);
      dynamic_model.substituteEndoLagGreaterThanTwo(true);
sebastien's avatar
sebastien committed
288
    }
289

290
  if (mod_file_struct.dsge_var_estimated || !mod_file_struct.dsge_var_calibrated.empty())
291
292
    try
      {
293
294
        int sid = symbol_table.addSymbol("dsge_prior_weight", eParameter);
        if (!mod_file_struct.dsge_var_calibrated.empty())
295
          addStatementAtFront(new InitParamStatement(sid,
296
                                                     expressions_tree.AddNonNegativeConstant(mod_file_struct.dsge_var_calibrated),
297
                                                     symbol_table));
298
299
300
301
302
303
304
305
      }
    catch (SymbolTable::AlreadyDeclaredException &e)
      {
        cerr << "ERROR: dsge_prior_weight should not be declared as a model variable / parameter "
             << "when the dsge_var option is passed to the estimation statement." << endl;
        exit(EXIT_FAILURE);
      }

sebastien's avatar
sebastien committed
306
307
308
  // Freeze the symbol table
  symbol_table.freeze();

309
310
311
312
313
  /*
    Enforce the same number of equations and endogenous, except in two cases:
    - ramsey_policy is used
    - a BVAR command is used and there is no equation (standalone BVAR estimation)
  */
314
  if (!(mod_file_struct.ramsey_policy_present || mod_file_struct.discretionary_policy_present)
315
      && !(mod_file_struct.bvar_present && dynamic_model.equation_number() == 0)
sebastien's avatar
sebastien committed
316
      && (dynamic_model.equation_number() != symbol_table.endo_nbr()))
sebastien's avatar
sebastien committed
317
    {
sebastien's avatar
sebastien committed
318
      cerr << "ERROR: There are " << dynamic_model.equation_number() << " equations but " << symbol_table.endo_nbr() << " endogenous variables!" << endl;
319
      exit(EXIT_FAILURE);
sebastien's avatar
sebastien committed
320
    }
321

322
323
324
325
326
  if (symbol_table.exo_det_nbr() > 0 && mod_file_struct.simul_present)
    {
      cerr << "ERROR: A .mod file cannot contain both a simul command and varexo_det declaration (all exogenous variables are deterministic in this case)" << endl;
      exit(EXIT_FAILURE);
    }
327
328
329
330
331
332
333
334

  if (!mod_file_struct.ramsey_policy_present)
    cout << "Found " << dynamic_model.equation_number() << " equation(s)." << endl;
  else
    {
      cout << "Found " << ramsey_policy_orig_eqn_nbr  << " equation(s)." << endl;
      cout << "Found " << dynamic_model.equation_number() << " FOC equation(s) for Ramsey Problem." << endl;
    }
335

336
  if (symbol_table.exists("dsge_prior_weight"))
337
338
339
340
    if (mod_file_struct.bayesian_irf_present)
      {
        if (symbol_table.exo_nbr() != symbol_table.observedVariablesNbr())
          {
341
342
            cerr << "ERROR: When estimating a DSGE-Var and the bayesian_irf option is passed to the estimation "
                 << "statement, the number of shocks must equal the number of observed variables." << endl;
343
344
345
346
347
348
            exit(EXIT_FAILURE);
          }
      }
    else
      if (symbol_table.exo_nbr() < symbol_table.observedVariablesNbr())
        {
349
350
          cerr << "ERROR: When estimating a DSGE-Var, the number of shocks must be "
               << "greater than or equal to the number of observed variables." << endl;
351
352
          exit(EXIT_FAILURE);
        }
sebastien's avatar
sebastien committed
353
}
sebastien's avatar
sebastien committed
354

sebastien's avatar
sebastien committed
355
void
356
ModFile::computingPass(bool no_tmp_terms)
sebastien's avatar
sebastien committed
357
{
358
  // Mod file may have no equation (for example in a standalone BVAR estimation)
sebastien's avatar
sebastien committed
359
  if (dynamic_model.equation_number() > 0)
sebastien's avatar
sebastien committed
360
    {
361
362
363
      if (nonstationary_variables)
        trend_dynamic_model.runTrendTest(global_eval_context);

sebastien's avatar
sebastien committed
364
      // Compute static model and its derivatives
365
      dynamic_model.toStatic(static_model);
366
      if (!no_static)
367
        {
Ferhat Mihoubi's avatar
Ferhat Mihoubi committed
368
369
370
371
          if (mod_file_struct.stoch_simul_present
              || mod_file_struct.estimation_present || mod_file_struct.osr_present
              || mod_file_struct.ramsey_policy_present || mod_file_struct.identification_present)
            static_model.set_cutoff_to_zero();
372
373
374
375
          if (mod_file_struct.identification_present)
            static_model.computingPass(global_eval_context, no_tmp_terms, true, block, byte_code);
          else
            static_model.computingPass(global_eval_context, no_tmp_terms, false, block, byte_code);
376
        }
sebastien's avatar
sebastien committed
377
      // Set things to compute for dynamic model
378
379
380
381
      if (mod_file_struct.simul_present || mod_file_struct.check_present
          || mod_file_struct.stoch_simul_present
          || mod_file_struct.estimation_present || mod_file_struct.osr_present
          || mod_file_struct.ramsey_policy_present || mod_file_struct.identification_present)
sebastien's avatar
sebastien committed
382
        {
383
          if (mod_file_struct.simul_present)
384
            dynamic_model.computingPass(true, false, false, false, global_eval_context, no_tmp_terms, block, use_dll, byte_code);
385
          else
386
            {
Ferhat Mihoubi's avatar
Ferhat Mihoubi committed
387
388
389
390
              if (mod_file_struct.stoch_simul_present
                  || mod_file_struct.estimation_present || mod_file_struct.osr_present
                  || mod_file_struct.ramsey_policy_present || mod_file_struct.identification_present)
                dynamic_model.set_cutoff_to_zero();
391
392
393
394
395
              if (mod_file_struct.order_option < 1 || mod_file_struct.order_option > 3)
                {
                  cerr << "ERROR: Incorrect order option..." << endl;
                  exit(EXIT_FAILURE);
                }
396
              bool hessian = mod_file_struct.order_option >= 2 || mod_file_struct.identification_present;
397
398
              bool thirdDerivatives = mod_file_struct.order_option == 3;
              bool paramsDerivatives = mod_file_struct.identification_present;
399
              dynamic_model.computingPass(true, hessian, thirdDerivatives, paramsDerivatives, global_eval_context, no_tmp_terms, block, use_dll, byte_code);
400
            }
sebastien's avatar
sebastien committed
401
        }
402
403
      else // No computing task requested, compute derivatives up to 2nd order by default
        dynamic_model.computingPass(true, true, false, false, global_eval_context, no_tmp_terms, block, use_dll, byte_code);
404
    }
405

406
407
  for (vector<Statement *>::iterator it = statements.begin();
       it != statements.end(); it++)
sebastien's avatar
sebastien committed
408
    (*it)->computingPass();
sebastien's avatar
sebastien committed
409
410
}

sebastien's avatar
sebastien committed
411
void
412
ModFile::writeOutputFiles(const string &basename, bool clear_all, bool console, const ConfigFile &config_file
413
#if defined(_WIN32) || defined(__CYGWIN32__)
414
                          , bool cygwin, bool msvc
415
#endif
416
                          ) const
sebastien's avatar
sebastien committed
417
418
{
  ofstream mOutputFile;
419

sebastien's avatar
sebastien committed
420
421
422
  if (basename.size())
    {
      string fname(basename);
sebastien's avatar
sebastien committed
423
      fname += ".m";
sebastien's avatar
sebastien committed
424
425
426
      mOutputFile.open(fname.c_str(), ios::out | ios::binary);
      if (!mOutputFile.is_open())
        {
sebastien's avatar
sebastien committed
427
          cerr << "ERROR: Can't open file " << fname
sebastien's avatar
sebastien committed
428
               << " for writing" << endl;
429
          exit(EXIT_FAILURE);
sebastien's avatar
sebastien committed
430
431
432
433
        }
    }
  else
    {
sebastien's avatar
sebastien committed
434
      cerr << "ERROR: Missing file name" << endl;
435
      exit(EXIT_FAILURE);
sebastien's avatar
sebastien committed
436
437
    }

sebastien's avatar
sebastien committed
438
439
440
441
442
  mOutputFile << "%" << endl
              << "% Status : main Dynare file " << endl
              << "%" << endl
              << "% Warning : this file is generated automatically by Dynare" << endl
              << "%           from model file (.mod)" << endl << endl;
sebastien's avatar
sebastien committed
443
444
445

  if (clear_all)
    mOutputFile << "clear all" << endl;
446
447

  mOutputFile << "tic;" << endl
448
              << "global M_ oo_ options_ ys0_ ex0_" << endl
449
450
451
452
453
454
455
456
              << "options_ = [];" << endl
              << "M_.fname = '" << basename << "';" << endl
              << "%" << endl
              << "% Some global variables initialization" << endl
              << "%" << endl
              << "global_initialization;" << endl
              << "diary off;" << endl
              << "logname_ = '" << basename << ".log';" << endl
457
458
459
460
              << "if exist(logname_, 'file')" << endl
              << "    delete(logname_)" << endl
              << "end" << endl
              << "diary(logname_)" << endl;
461

462
463
464
  if (console)
    mOutputFile << "options_.console_mode = 1;" << endl;

465
  cout << "Processing outputs ...";
466

sebastien's avatar
sebastien committed
467
468
  symbol_table.writeOutput(mOutputFile);

Sébastien Villemot's avatar
Sébastien Villemot committed
469
470
471
472
473
474
475
476
477
478
  // Initialize M_.Sigma_e and M_.H
  mOutputFile << "M_.Sigma_e = zeros(" << symbol_table.exo_nbr() << ", "
              << symbol_table.exo_nbr() << ");" << endl;

  if (mod_file_struct.calibrated_measurement_errors)
    mOutputFile << "M_.H = zeros(" << symbol_table.observedVariablesNbr() << ", "
                << symbol_table.observedVariablesNbr() << ");" << endl;
  else
    mOutputFile << "M_.H = 0;" << endl;

sebastien's avatar
sebastien committed
479
480
481
  if (linear == 1)
    mOutputFile << "options_.linear = 1;" << endl;

482
  mOutputFile << "options_.block=" << block << ";" << endl
483
484
              << "options_.bytecode=" << byte_code << ";" << endl
              << "options_.use_dll=" << use_dll << ";" << endl;
485

486
487
  config_file.writeCluster(mOutputFile);

488
489
490
491
492
  if (byte_code)
    mOutputFile << "if exist('bytecode') ~= 3" << endl
                << "  error('DYNARE: Can''t find bytecode DLL. Please compile it or remove the ''bytecode'' option.')" << endl
                << "end" << endl;

493
  // Erase possible remnants of previous runs
494
495
  string dynfile = basename + "_dynamic.m";
  unlink(dynfile.c_str());
496

497
498
  string statfile = basename + "_static.m";
  unlink(statfile.c_str());
499
500

  if (!use_dll)
501
502
503
504
    {
      mOutputFile << "erase_compiled_function('" + basename + "_static');" << endl;
      mOutputFile << "erase_compiled_function('" + basename + "_dynamic');" << endl;
    }
505

506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
#if defined(_WIN32) || defined(__CYGWIN32__)
  // If using USE_DLL with MSVC, check that the user didn't use a function not supported by MSVC (because MSVC doesn't comply with C99 standard)
  if (use_dll && msvc)
    {
      if (dynamic_model.isUnaryOpUsed(oAcosh))
        {
          cerr << "ERROR: acosh() function is not supported with USE_DLL option and MSVC compiler; use Cygwin compiler instead." << endl;
          exit(EXIT_FAILURE);
        }
      if (dynamic_model.isUnaryOpUsed(oAsinh))
        {
          cerr << "ERROR: asinh() function is not supported with USE_DLL option and MSVC compiler; use Cygwin compiler instead." << endl;
          exit(EXIT_FAILURE);
        }
      if (dynamic_model.isUnaryOpUsed(oAtanh))
        {
          cerr << "ERROR: atanh() function is not supported with USE_DLL option and MSVC compiler; use Cygwin compiler instead." << endl;
          exit(EXIT_FAILURE);
        }
      if (dynamic_model.isTrinaryOpUsed(oNormcdf))
        {
          cerr << "ERROR: normcdf() function is not supported with USE_DLL option and MSVC compiler; use Cygwin compiler instead." << endl;
          exit(EXIT_FAILURE);
        }
    }
#endif

533
534
  // Compile the dynamic MEX file for use_dll option
  if (use_dll)
535
536
537
538
539
    {
      mOutputFile << "if ~exist('OCTAVE_VERSION')" << endl;
      // Some mex commands are enclosed in an eval(), because otherwise it will make Octave fail
#if defined(_WIN32) || defined(__CYGWIN32__)
      if (msvc)
540
541
542
        // MATLAB/Windows + Microsoft Visual C++
        mOutputFile << "    eval('mex -O LINKFLAGS=\"$LINKFLAGS /export:Dynamic\" " << basename << "_dynamic.c')" << endl
                    << "    eval('mex -O LINKFLAGS=\"$LINKFLAGS /export:Dynamic\" " << basename << "_static.c')" << endl;
543
      else if (cygwin)
544
545
546
        // MATLAB/Windows + Cygwin g++
        mOutputFile << "    eval('mex -O PRELINK_CMDS1=\"echo EXPORTS > mex.def & echo mexFunction >> mex.def & echo Dynamic >> mex.def\" " << basename << "_dynamic.c')" << endl
                    << "    eval('mex -O PRELINK_CMDS1=\"echo EXPORTS > mex.def & echo mexFunction >> mex.def & echo Dynamic >> mex.def\" " << basename << "_static.c')" << endl;
547
      else
548
        mOutputFile << "    error('When using the USE_DLL option, you must give either ''cygwin'' or ''msvc'' option to the ''dynare'' command')" << endl;
549
#else
550
# ifdef __linux__
551
552
553
      // MATLAB/Linux
      mOutputFile << "    eval('mex -O LDFLAGS=''-pthread -shared -Wl,--no-undefined'' " << basename << "_dynamic.c')" << endl
                  << "    eval('mex -O LDFLAGS=''-pthread -shared -Wl,--no-undefined'' " << basename << "_static.c')" << endl;
554
# else // MacOS
555
556
557
      // MATLAB/MacOS
      mOutputFile << "    eval('mex -O LDFLAGS=''-Wl,-twolevel_namespace -undefined error -arch \\$ARCHS -Wl,-syslibroot,\\$SDKROOT -mmacosx-version-min=\\$MACOSX_DEPLOYMENT_TARGET -bundle'' " << basename << "_dynamic.c')" << endl
                  << "    eval('mex -O LDFLAGS=''-Wl,-twolevel_namespace -undefined error -arch \\$ARCHS -Wl,-syslibroot,\\$SDKROOT -mmacosx-version-min=\\$MACOSX_DEPLOYMENT_TARGET -bundle'' " << basename << "_static.c')" << endl;
558
# endif
559
#endif
560
561
562
563
564
      mOutputFile << "else" << endl // Octave
                  << "    if ~octave_ver_less_than('3.2.0')" << endl // Workaround for bug in Octave >= 3.2, see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=550823
                  << "        sleep(2)" << endl
                  << "    end" << endl
                  << "    mex " << basename << "_dynamic.c" << endl
565
                  << "    mex " << basename << "_static.c" << endl
566
                  << "end" << endl;
567
    }
568
569
570
571
572

  // Add path for block option with M-files
  if (block && !byte_code)
    mOutputFile << "addpath " << basename << ";" << endl;

573
574
575
  if (mod_file_struct.ramsey_policy_present)
    mOutputFile << "M_.orig_eq_nbr = " << ramsey_policy_orig_eqn_nbr << ";" << endl;

sebastien's avatar
sebastien committed
576
  if (dynamic_model.equation_number() > 0)
577
    {
578
      dynamic_model.writeOutput(mOutputFile, basename, block, byte_code, use_dll, mod_file_struct.order_option, mod_file_struct.estimation_present);
579
      if (!no_static)
Houtan Bastani's avatar
Houtan Bastani committed
580
        static_model.writeOutput(mOutputFile, block);
581
    }
sebastien's avatar
sebastien committed
582
583

  // Print statements
584
585
  for (vector<Statement *>::const_iterator it = statements.begin();
       it != statements.end(); it++)
sebastien's avatar
sebastien committed
586
587
588
589
590
591
592
    {
      (*it)->writeOutput(mOutputFile, basename);

      // Special treatment for initval block: insert initial values for the auxiliary variables
      InitValStatement *ivs = dynamic_cast<InitValStatement *>(*it);
      if (ivs != NULL)
        {
593
          static_model.writeAuxVarInitval(mOutputFile, oMatlabOutsideModel);
sebastien's avatar
sebastien committed
594
595
596
597
598
          ivs->writeOutputPostInit(mOutputFile);
        }

      // Special treatment for load params and steady state statement: insert initial values for the auxiliary variables
      LoadParamsAndSteadyStateStatement *lpass = dynamic_cast<LoadParamsAndSteadyStateStatement *>(*it);
599
      if (lpass && !no_static)
600
        static_model.writeAuxVarInitval(mOutputFile, oMatlabOutsideModel);
sebastien's avatar
sebastien committed
601
    }
sebastien's avatar
sebastien committed
602

603
604
605
  // Remove path for block option with M-files
  if (block && !byte_code)
    mOutputFile << "rmpath " << basename << ";" << endl;
606

607
608
609
610
611
  mOutputFile << "save('" << basename << "_results.mat', 'oo_', 'M_', 'options_');" << endl;

  config_file.writeEndParallel(mOutputFile);

  mOutputFile << "diary off" << endl
612
              << endl << "disp(['Total computing time : ' dynsec2hms(toc) ]);" << endl;
sebastien's avatar
sebastien committed
613
614

  mOutputFile.close();
615

616
617
618
  // Create static and dynamic files
  if (dynamic_model.equation_number() > 0)
    {
619
      if (!no_static)
620
        static_model.writeStaticFile(basename, block, byte_code, use_dll);
621

622
623
      dynamic_model.writeDynamicFile(basename, block, byte_code, use_dll, mod_file_struct.order_option);
      dynamic_model.writeParamsDerivativesFile(basename);
624
625
    }

626
  // Create steady state file
627
  steady_state_model.writeSteadyStateFile(basename, mod_file_struct.ramsey_policy_present);
628

629
  cout << "done" << endl;
sebastien's avatar
sebastien committed
630
}