2008-02-03 11:28:36 +01:00
/*
2009-01-21 15:39:24 +01:00
* Copyright ( C ) 2006 - 2009 Dynare Team
2008-02-03 11:28:36 +01:00
*
* 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/>.
*/
2008-06-28 13:20:45 +02:00
# include <cstdlib>
2008-02-03 11:28:36 +01:00
# include <iostream>
# include <fstream>
2008-12-19 11:24:31 +01:00
# include <typeinfo>
2008-02-03 11:28:36 +01:00
# include "ModFile.hh"
ModFile : : ModFile ( ) : expressions_tree ( symbol_table , num_constants ) ,
2009-04-14 16:39:53 +02:00
static_model ( symbol_table , num_constants ) ,
2009-08-25 11:43:01 +02:00
static_dll_model ( symbol_table , num_constants ) ,
2009-04-14 16:39:53 +02:00
dynamic_model ( symbol_table , num_constants ) ,
2009-09-02 15:36:56 +02:00
linear ( false ) , block ( false ) , byte_code ( false ) ,
use_dll ( false )
2008-02-03 11:28:36 +01:00
{
}
ModFile : : ~ ModFile ( )
{
for ( vector < Statement * > : : iterator it = statements . begin ( ) ;
it ! = statements . end ( ) ; it + + )
delete ( * it ) ;
}
2008-12-19 11:24:31 +01:00
void
2009-11-06 19:31:03 +01:00
ModFile : : evalAllExpressions ( bool warn_uninit )
2008-12-19 11:24:31 +01:00
{
2009-02-27 13:19:25 +01:00
cout < < " Evaluating expressions... " ;
2008-12-31 20:29:17 +01:00
2009-02-27 13:19:25 +01:00
// Loop over all statements, and fill global eval context if relevant
for ( vector < Statement * > : : const_iterator it = statements . begin ( ) ; it ! = statements . end ( ) ; it + + )
2008-12-19 11:24:31 +01:00
{
2009-02-27 13:19:25 +01:00
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 ) ;
2008-12-19 11:24:31 +01:00
}
2009-02-27 13:19:25 +01:00
// Evaluate model local variables
2009-04-14 16:39:53 +02:00
dynamic_model . fillEvalContext ( global_eval_context ) ;
2009-02-27 13:19:25 +01:00
cout < < " done " < < endl ;
// Check if some symbols are not initialized, and give them a zero value then
for ( int id = 0 ; id < = symbol_table . maxID ( ) ; id + + )
2008-12-19 11:24:31 +01:00
{
2009-02-27 13:19:25 +01:00
SymbolType type = symbol_table . getType ( id ) ;
if ( ( type = = eEndogenous | | type = = eExogenous | | type = = eExogenousDet
| | type = = eParameter | | type = = eModelLocalVariable )
& & global_eval_context . find ( id ) = = global_eval_context . end ( ) )
2008-12-19 11:24:31 +01:00
{
2009-11-06 19:31:03 +01:00
if ( warn_uninit )
cerr < < " WARNING: can't find a numeric initial value for " < < symbol_table . getName ( id ) < < " , using zero " < < endl ;
2009-02-27 13:19:25 +01:00
global_eval_context [ id ] = 0 ;
2008-12-19 11:24:31 +01:00
}
}
}
2008-02-03 11:28:36 +01:00
void
ModFile : : addStatement ( Statement * st )
{
statements . push_back ( st ) ;
}
void
ModFile : : checkPass ( )
{
for ( vector < Statement * > : : iterator it = statements . begin ( ) ;
it ! = statements . end ( ) ; it + + )
( * it ) - > checkPass ( mod_file_struct ) ;
2008-04-24 12:55:26 +02:00
// If order option has not been set, default to 2
if ( ! mod_file_struct . order_option )
mod_file_struct . order_option = 2 ;
2008-09-29 12:16:13 +02:00
bool stochastic_statement_present = mod_file_struct . stoch_simul_present
| | mod_file_struct . estimation_present
| | mod_file_struct . osr_present
| | mod_file_struct . ramsey_policy_present ;
2008-02-03 11:28:36 +01:00
// Allow empty model only when doing a standalone BVAR estimation
2009-04-14 16:39:53 +02:00
if ( dynamic_model . equation_number ( ) = = 0
2008-02-03 11:28:36 +01:00
& & ( mod_file_struct . check_present
| | mod_file_struct . simul_present
2008-09-29 12:16:13 +02:00
| | stochastic_statement_present ) )
{
cerr < < " ERROR: At least one model equation must be declared! " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-09-29 12:16:13 +02:00
}
2009-04-29 13:35:44 +02:00
if ( mod_file_struct . simul_present & & stochastic_statement_present )
2008-02-03 11:28:36 +01:00
{
2009-10-20 18:17:27 +02:00
cerr < < " ERROR: A .mod file cannot contain both a simul command and one of {stoch_simul, estimation, osr, ramsey_policy} " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-12-09 12:50:58 +01:00
if ( mod_file_struct . k_order_solver & & ! use_dll )
{
cerr < < " ERROR: When using option 'k_order_solver' (which is implicit if order >= 3), you must specify option 'use_dll' on the 'model' block " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2009-09-02 15:36:56 +02:00
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 ) ;
}
if ( byte_code & & ! block )
{
cerr < < " ERROR: In 'model' block, can't use option 'bytecode' without option 'block' " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2009-09-30 17:10:31 +02:00
}
void
ModFile : : transformPass ( )
{
2009-11-09 12:03:18 +01:00
if ( symbol_table . predeterminedNbr ( ) > 0 )
dynamic_model . transformPredeterminedVariables ( ) ;
2009-11-07 19:37:11 +01:00
2009-11-09 16:13:47 +01:00
// Create auxiliary vars for Expectation operator
dynamic_model . substituteExpectation ( mod_file_struct . partial_information ) ;
2009-09-30 17:10:31 +02:00
if ( mod_file_struct . stoch_simul_present
| | mod_file_struct . estimation_present
| | mod_file_struct . osr_present
| | mod_file_struct . ramsey_policy_present )
{
2009-10-29 18:16:10 +01:00
// In stochastic models, create auxiliary vars for leads and lags greater than 2
2009-10-07 16:07:13 +02:00
dynamic_model . substituteEndoLeadGreaterThanTwo ( ) ;
2009-10-07 18:34:42 +02:00
dynamic_model . substituteExoLead ( ) ;
2009-10-07 16:07:13 +02:00
dynamic_model . substituteEndoLagGreaterThanTwo ( ) ;
2009-10-07 18:34:42 +02:00
dynamic_model . substituteExoLag ( ) ;
2009-09-30 17:10:31 +02:00
}
2009-09-02 15:36:56 +02:00
2009-02-27 13:19:25 +01:00
// Freeze the symbol table
symbol_table . freeze ( ) ;
2008-10-17 14:52:08 +02:00
/*
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 )
*/
if ( ! mod_file_struct . ramsey_policy_present
2009-11-26 18:25:04 +01:00
& & ! ( mod_file_struct . bvar_present & & dynamic_model . equation_number ( ) = = 0 )
2009-04-14 16:39:53 +02:00
& & ( dynamic_model . equation_number ( ) ! = symbol_table . endo_nbr ( ) ) )
2008-02-03 11:28:36 +01:00
{
2009-04-14 16:39:53 +02:00
cerr < < " ERROR: There are " < < dynamic_model . equation_number ( ) < < " equations but " < < symbol_table . endo_nbr ( ) < < " endogenous variables! " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-04-14 16:39:53 +02:00
cout < < " Found " < < dynamic_model . equation_number ( ) < < " equation(s). " < < endl ;
2008-02-03 11:28:36 +01:00
}
void
2008-10-29 16:10:51 +01:00
ModFile : : computingPass ( bool no_tmp_terms )
2008-02-03 11:28:36 +01:00
{
// Mod file may have no equation (for example in a standalone BVAR estimation)
2009-09-02 18:44:15 +02:00
bool dynamic_model_needed = mod_file_struct . simul_present | | mod_file_struct . check_present | | mod_file_struct . stoch_simul_present
2009-10-20 18:17:27 +02:00
| | mod_file_struct . estimation_present | | mod_file_struct . osr_present
2009-10-06 10:56:02 +02:00
| | mod_file_struct . ramsey_policy_present | | mod_file_struct . identification_present ;
2009-04-14 16:39:53 +02:00
if ( dynamic_model . equation_number ( ) > 0 )
2008-02-03 11:28:36 +01:00
{
2009-04-14 16:39:53 +02:00
// Compute static model and its derivatives
2009-08-29 17:04:11 +02:00
if ( byte_code )
2009-08-25 11:43:01 +02:00
{
dynamic_model . toStaticDll ( static_dll_model ) ;
2009-08-29 17:04:11 +02:00
static_dll_model . computingPass ( global_eval_context , no_tmp_terms , block ) ;
2009-08-25 11:43:01 +02:00
}
else
{
dynamic_model . toStatic ( static_model ) ;
2009-08-29 17:04:11 +02:00
static_model . computingPass ( block , false , no_tmp_terms ) ;
2009-08-25 11:43:01 +02:00
}
2009-04-14 16:39:53 +02:00
// Set things to compute for dynamic model
2009-09-02 18:44:15 +02:00
if ( dynamic_model_needed )
2008-02-03 11:28:36 +01:00
{
2009-09-02 18:44:15 +02:00
if ( mod_file_struct . simul_present )
dynamic_model . computingPass ( false , false , false , false , global_eval_context , no_tmp_terms , block , use_dll ) ;
else
2008-02-03 11:28:36 +01:00
{
2009-09-02 18:44:15 +02:00
if ( mod_file_struct . order_option < 1 | | mod_file_struct . order_option > 3 )
{
cerr < < " ERROR: Incorrect order option... " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2009-10-01 10:03:40 +02:00
bool hessian = mod_file_struct . order_option > = 2 | | mod_file_struct . identification_present ;
2009-09-02 18:44:15 +02:00
bool thirdDerivatives = mod_file_struct . order_option = = 3 ;
bool paramsDerivatives = mod_file_struct . identification_present ;
dynamic_model . computingPass ( true , hessian , thirdDerivatives , paramsDerivatives , global_eval_context , no_tmp_terms , false , use_dll ) ;
2008-02-03 11:28:36 +01:00
}
}
2009-09-02 18:44:15 +02:00
else
2009-11-12 18:01:26 +01:00
dynamic_model . computingPass ( true , true , false , false , global_eval_context , no_tmp_terms , false , false ) ;
2008-02-03 11:28:36 +01:00
}
2009-04-20 12:48:54 +02:00
2008-02-03 11:28:36 +01:00
for ( vector < Statement * > : : iterator it = statements . begin ( ) ;
it ! = statements . end ( ) ; it + + )
( * it ) - > computingPass ( ) ;
}
void
ModFile : : writeOutputFiles ( const string & basename , bool clear_all ) const
{
ofstream mOutputFile ;
2009-09-02 18:44:15 +02:00
bool dynamic_model_needed = mod_file_struct . simul_present | | mod_file_struct . check_present | | mod_file_struct . stoch_simul_present
2009-10-20 18:17:27 +02:00
| | mod_file_struct . estimation_present | | mod_file_struct . osr_present
2009-10-06 10:56:02 +02:00
| | mod_file_struct . ramsey_policy_present | | mod_file_struct . identification_present ;
2008-02-03 11:28:36 +01:00
if ( basename . size ( ) )
{
string fname ( basename ) ;
2008-06-16 18:33:28 +02:00
fname + = " .m " ;
2008-02-03 11:28:36 +01:00
mOutputFile . open ( fname . c_str ( ) , ios : : out | ios : : binary ) ;
if ( ! mOutputFile . is_open ( ) )
{
2008-09-29 12:16:13 +02:00
cerr < < " ERROR: Can't open file " < < fname
2008-02-03 11:28:36 +01:00
< < " for writing " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
}
else
{
2008-09-29 12:16:13 +02:00
cerr < < " ERROR: Missing file name " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2008-06-16 18:33:28 +02:00
mOutputFile < < " % " < < endl
< < " % Status : main Dynare file " < < endl
< < " % " < < endl
< < " % Warning : this file is generated automatically by Dynare " < < endl
< < " % from model file (.mod) " < < endl < < endl ;
2008-02-03 11:28:36 +01:00
if ( clear_all )
mOutputFile < < " clear all " < < endl ;
2009-04-30 15:05:21 +02:00
mOutputFile < < " tic; " < < endl
2009-12-01 17:30:56 +01:00
< < " global M_ oo_ options_ ys0_ ex0_ " < < endl
2009-04-30 15:05:21 +02:00
< < " options_ = []; " < < endl
< < " M_.fname = ' " < < basename < < " '; " < < endl
< < " % " < < endl
< < " % Some global variables initialization " < < endl
< < " % " < < endl
< < " global_initialization; " < < endl
< < " diary off; " < < endl
2008-06-24 20:20:48 +02:00
< < " warning_old_state = warning; " < < endl
< < " warning off; " < < endl
< < " delete " < < basename < < " .log; " < < endl
2009-04-30 15:05:21 +02:00
< < " warning warning_old_state " < < endl
< < " logname_ = ' " < < basename < < " .log'; " < < endl
2009-07-07 16:20:48 +02:00
< < " diary " < < basename < < " .log " < < endl ;
2009-04-30 15:05:21 +02:00
2008-12-24 16:49:01 +01:00
cout < < " Processing outputs ... " ;
2008-02-03 11:28:36 +01:00
symbol_table . writeOutput ( mOutputFile ) ;
if ( linear = = 1 )
mOutputFile < < " options_.linear = 1; " < < endl ;
2009-09-02 15:36:56 +02:00
mOutputFile < < " options_.block= " < < block < < " ; " < < endl
< < " options_.bytecode= " < < byte_code < < " ; " < < endl ;
2009-09-03 18:34:15 +02:00
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 ;
2009-09-02 15:36:56 +02:00
// Erase possible remnants of previous runs
if ( block | | byte_code )
mOutputFile < < " delete(' " < < basename < < " _dynamic.m'); " < < endl ;
if ( byte_code )
mOutputFile < < " delete(' " < < basename < < " _static.m'); " < < endl ;
if ( ! use_dll )
mOutputFile < < " erase_compiled_function(' " + basename + " _dynamic'); " < < endl ;
// Compile the dynamic MEX file for use_dll option
if ( use_dll )
2009-12-08 15:02:02 +01:00
mOutputFile < < " if ~exist('OCTAVE_VERSION') " < < endl
< < " if ispc " < < endl
2009-12-08 19:45:33 +01:00
< < " eval('mex -O LINKER=''echo EXPORTS > mex.def & echo mexFunction >> mex.def & echo Dynamic >> mex.def & gcc-3'' LDFLAGS=''-pthread -shared -Wl,--no-undefined'' " < < basename < < " _dynamic.c') " < < endl // This command is enclosed in an eval(), because otherwise it will make Octave fail
2009-12-08 15:02:02 +01:00
< < " else " < < endl
2009-12-08 16:12:59 +01:00
< < " eval('mex -O LDFLAGS=''-pthread -shared -Wl,--no-undefined'' " < < basename < < " _dynamic.c') " < < endl // This command is enclosed in an eval(), because otherwise it will make Octave fail
2009-12-08 15:02:02 +01:00
< < " end " < < endl
2009-11-30 17:36:00 +01:00
< < " else " < < endl
< < " mex " < < basename < < " _dynamic.c " < < endl
< < " end " < < endl ;
2009-09-02 15:36:56 +02:00
// Add path for block option with M-files
if ( block & & ! byte_code )
mOutputFile < < " addpath " < < basename < < " ; " < < endl ;
2009-04-14 16:39:53 +02:00
if ( dynamic_model . equation_number ( ) > 0 )
2008-02-03 11:28:36 +01:00
{
2009-09-02 18:44:15 +02:00
if ( dynamic_model_needed )
dynamic_model . writeOutput ( mOutputFile , basename , block , byte_code , use_dll ) ;
else
dynamic_model . writeOutput ( mOutputFile , basename , false , false , false ) ;
2009-09-02 15:36:56 +02:00
if ( ! byte_code )
2009-08-29 17:04:11 +02:00
static_model . writeOutput ( mOutputFile , block ) ;
2008-02-03 11:28:36 +01:00
}
// Print statements
for ( vector < Statement * > : : const_iterator it = statements . begin ( ) ;
it ! = statements . end ( ) ; it + + )
2009-09-30 17:10:31 +02:00
{
( * 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 )
{
if ( ! byte_code )
static_model . writeAuxVarInitval ( mOutputFile ) ;
else
static_dll_model . writeAuxVarInitval ( mOutputFile ) ;
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 ) ;
if ( lpass )
{
if ( ! byte_code )
static_model . writeAuxVarInitval ( mOutputFile ) ;
else
static_dll_model . writeAuxVarInitval ( mOutputFile ) ;
}
}
2008-02-03 11:28:36 +01:00
2009-09-02 15:36:56 +02:00
// Remove path for block option with M-files
if ( block & & ! byte_code )
mOutputFile < < " rmpath " < < basename < < " ; " < < endl ;
2008-12-05 12:27:28 +01:00
2009-07-07 16:20:48 +02:00
mOutputFile < < " save(' " < < basename < < " _results.mat', 'oo_', 'M_', 'options_'); " < < endl
< < " diary off " < < endl
< < endl < < " disp(['Total computing time : ' dynsec2hms(toc) ]); " < < endl ;
2008-02-03 11:28:36 +01:00
mOutputFile . close ( ) ;
2009-04-30 15:05:21 +02:00
2009-07-07 16:20:48 +02:00
// Create static and dynamic files
if ( dynamic_model . equation_number ( ) > 0 )
{
2009-08-29 17:04:11 +02:00
if ( byte_code )
static_dll_model . writeStaticFile ( basename , block ) ;
2009-08-25 11:43:01 +02:00
else
2009-08-29 17:04:11 +02:00
static_model . writeStaticFile ( basename , block ) ;
2009-09-02 18:44:15 +02:00
if ( dynamic_model_needed )
{
dynamic_model . writeDynamicFile ( basename , block , byte_code , use_dll ) ;
dynamic_model . writeParamsDerivativesFile ( basename ) ;
}
else
{
2009-11-05 10:59:30 +01:00
dynamic_model . writeDynamicFile ( basename , false , false , false ) ;
dynamic_model . writeParamsDerivativesFile ( basename ) ;
2009-09-02 18:44:15 +02:00
}
2009-07-07 16:20:48 +02:00
}
2009-04-30 15:05:21 +02:00
cout < < " done " < < endl ;
2008-02-03 11:28:36 +01:00
}