2008-02-03 11:28:36 +01:00
/*
2023-01-04 16:18:53 +01:00
* Copyright © 2006 - 2023 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
2021-06-09 16:52:20 +02:00
* along with Dynare . If not , see < https : //www.gnu.org/licenses/>.
2008-02-03 11:28:36 +01:00
*/
2023-11-30 15:28:57 +01:00
# include <cassert>
2008-06-28 13:20:45 +02:00
# include <cstdlib>
2008-02-03 11:28:36 +01:00
# include <fstream>
2023-11-30 15:28:57 +01:00
# include <iostream>
2019-04-04 17:01:37 +02:00
# include <random>
2023-11-30 15:28:57 +01:00
# include <typeinfo>
2018-06-27 15:01:31 +02:00
2019-04-04 17:01:37 +02:00
# include <filesystem>
2012-05-08 16:02:22 +02:00
2011-03-21 18:40:57 +01:00
# include "ComputingTasks.hh"
2023-11-30 15:28:57 +01:00
# include "ModFile.hh"
2018-11-07 15:24:57 +01:00
# include "Shocks.hh"
2008-02-03 11:28:36 +01:00
2023-11-30 15:28:57 +01:00
ModFile : : ModFile ( WarningConsolidation & warnings_arg ) :
var_model_table { symbol_table } ,
trend_component_model_table { symbol_table } ,
var_expectation_model_table { symbol_table } ,
pac_model_table { symbol_table } ,
expressions_tree { symbol_table , num_constants , external_functions_table } ,
original_model { symbol_table , num_constants , external_functions_table ,
trend_component_model_table , var_model_table } ,
dynamic_model { symbol_table , num_constants , external_functions_table ,
2018-10-04 17:18:27 +02:00
trend_component_model_table , var_model_table } ,
2023-11-30 15:28:57 +01:00
trend_dynamic_model { symbol_table , num_constants , external_functions_table ,
trend_component_model_table , var_model_table } ,
orig_ramsey_dynamic_model { symbol_table , num_constants , external_functions_table ,
trend_component_model_table , var_model_table } ,
epilogue { symbol_table , num_constants , external_functions_table , trend_component_model_table ,
var_model_table } ,
static_model { symbol_table , num_constants , external_functions_table } ,
steady_state_model { symbol_table , num_constants , external_functions_table , static_model } ,
warnings { warnings_arg }
2008-02-03 11:28:36 +01:00
{
}
2008-12-19 11:24:31 +01:00
void
2018-12-20 17:04:28 +01:00
ModFile : : evalAllExpressions ( bool warn_uninit )
2008-12-19 11:24:31 +01:00
{
2022-10-07 17:34:19 +02:00
cout < < " Evaluating expressions... " < < endl ;
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
2023-11-30 15:28:57 +01:00
for ( auto & st : statements )
2008-12-19 11:24:31 +01:00
{
2023-11-30 15:28:57 +01:00
if ( auto ips = dynamic_cast < InitParamStatement * > ( st . get ( ) ) ; ips )
2009-02-27 13:19:25 +01:00
ips - > fillEvalContext ( global_eval_context ) ;
2023-11-30 15:28:57 +01:00
if ( auto ies = dynamic_cast < InitOrEndValStatement * > ( st . get ( ) ) ; ies )
2009-02-27 13:19:25 +01:00
ies - > fillEvalContext ( global_eval_context ) ;
2023-11-30 15:28:57 +01:00
if ( auto lpass = dynamic_cast < LoadParamsAndSteadyStateStatement * > ( st . get ( ) ) ; lpass )
2009-02-27 13:19:25 +01:00
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
// Check if some symbols are not initialized, and give them a zero value then
2009-12-16 18:13:23 +01:00
for ( int id = 0 ; id < = symbol_table . maxID ( ) ; id + + )
2019-10-28 11:09:36 +01:00
if ( auto type = symbol_table . getType ( id ) ;
2023-11-30 15:28:57 +01:00
( type = = SymbolType : : endogenous | | type = = SymbolType : : exogenous
| | type = = SymbolType : : exogenousDet | | type = = SymbolType : : parameter
| | type = = SymbolType : : modelLocalVariable )
2022-05-04 16:01:34 +02:00
& & ! global_eval_context . contains ( id ) )
2019-10-28 11:09:36 +01:00
{
if ( warn_uninit )
2023-11-30 15:28:57 +01:00
warnings < < " WARNING: Can't find a numeric initial value for " < < symbol_table . getName ( id )
< < " , using zero " < < endl ;
2019-10-28 11:09:36 +01:00
global_eval_context [ id ] = 0 ;
}
2008-12-19 11:24:31 +01:00
}
2008-02-03 11:28:36 +01:00
void
2018-09-05 15:17:21 +02:00
ModFile : : addStatement ( unique_ptr < Statement > st )
2008-02-03 11:28:36 +01:00
{
2018-09-05 15:17:21 +02:00
statements . push_back ( move ( st ) ) ;
2008-02-03 11:28:36 +01:00
}
2010-06-24 15:07:15 +02:00
void
2018-09-05 15:17:21 +02:00
ModFile : : addStatementAtFront ( unique_ptr < Statement > st )
2010-06-24 15:07:15 +02:00
{
2018-09-05 15:17:21 +02:00
statements . insert ( statements . begin ( ) , move ( st ) ) ;
2010-06-24 15:07:15 +02:00
}
2008-02-03 11:28:36 +01:00
void
2017-08-31 10:19:43 +02:00
ModFile : : checkPass ( bool nostrict , bool stochastic )
2008-02-03 11:28:36 +01:00
{
2023-11-30 15:28:57 +01:00
for ( auto & statement : statements )
2018-06-04 12:26:16 +02:00
statement - > checkPass ( mod_file_struct , warnings ) ;
2008-02-03 11:28:36 +01:00
2010-05-31 17:43:17 +02:00
// Check the steady state block
2017-08-30 15:46:17 +02:00
steady_state_model . checkPass ( mod_file_struct , warnings ) ;
2018-09-03 17:16:28 +02:00
// Check epilogue block
2022-06-24 15:45:35 +02:00
epilogue . checkPass ( mod_file_struct ) ;
2018-09-03 17:16:28 +02:00
2022-06-24 15:45:35 +02:00
pac_model_table . checkPass ( mod_file_struct ) ;
2021-10-27 16:26:52 +02:00
2019-12-20 16:59:30 +01:00
if ( mod_file_struct . write_latex_steady_state_model_present
& & ! mod_file_struct . steady_state_model_present )
2017-08-30 15:46:17 +02:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: You cannot have a write_latex_steady_state_model statement without a "
" steady_state_model block. "
< < endl ;
2017-08-30 15:46:17 +02:00
exit ( EXIT_FAILURE ) ;
}
2010-05-31 17:43:17 +02:00
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 ;
2015-07-30 14:40:03 +02:00
param_used_with_lead_lag = dynamic_model . ParamUsedWithLeadLag ( ) ;
if ( param_used_with_lead_lag )
warnings < < " WARNING: A parameter was used with a lead or a lag in the model block " < < endl ;
2023-11-30 15:28:57 +01:00
bool stochastic_statement_present
= mod_file_struct . stoch_simul_present | | mod_file_struct . estimation_present
| | mod_file_struct . osr_present | | mod_file_struct . discretionary_policy_present
| | mod_file_struct . calib_smoother_present | | mod_file_struct . identification_present
| | mod_file_struct . mom_estimation_present | | mod_file_struct . sensitivity_present
| | stochastic ;
2008-09-29 12:16:13 +02:00
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
2023-11-30 15:28:57 +01:00
& & ( mod_file_struct . check_present | | mod_file_struct . perfect_foresight_solver_present
2022-04-20 16:57:39 +02:00
| | mod_file_struct . perfect_foresight_with_expectation_errors_solver_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
}
2023-03-29 16:14:59 +02:00
if ( mod_file_struct . ramsey_model_present & & mod_file_struct . discretionary_policy_present )
2015-09-03 17:04:34 +02:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: You cannot use the discretionary_policy command when you use either "
" ramsey_model or ramsey_policy and vice versa "
< < endl ;
2015-09-03 17:04:34 +02:00
exit ( EXIT_FAILURE ) ;
}
2017-06-01 19:58:32 +02:00
if ( ( ( mod_file_struct . ramsey_model_present | | mod_file_struct . discretionary_policy_present )
2011-03-17 15:15:13 +01:00
& & ! mod_file_struct . planner_objective_present )
2014-03-09 09:52:44 +01:00
| | ( ! ( mod_file_struct . ramsey_model_present | | mod_file_struct . discretionary_policy_present )
2017-06-01 19:58:32 +02:00
& & mod_file_struct . planner_objective_present ) )
2011-03-03 16:03:21 +01:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: A planner_objective statement must be used with a ramsey_model, a "
" ramsey_policy or a discretionary_policy statement and vice versa. "
< < endl ;
2011-03-03 16:03:21 +01:00
exit ( EXIT_FAILURE ) ;
}
2023-03-29 16:14:59 +02:00
if ( mod_file_struct . ramsey_constraints_present & & ! mod_file_struct . ramsey_model_present )
2022-04-11 12:26:14 +02:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: A ramsey_constraints block requires the presence of a ramsey_model or "
" ramsey_policy statement "
< < endl ;
2022-04-11 12:26:14 +02:00
exit ( EXIT_FAILURE ) ;
}
2023-11-30 15:28:57 +01:00
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 ) )
2011-03-03 16:30:53 +01:00
{
cerr < < " ERROR: The osr statement must be used with osr_params and optim_weights. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2023-11-30 15:28:57 +01:00
if ( ( mod_file_struct . perfect_foresight_solver_present
| | mod_file_struct . perfect_foresight_with_expectation_errors_solver_present )
2022-04-20 16:57:39 +02:00
& & stochastic_statement_present )
2008-02-03 11:28:36 +01:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul, "
" perfect_foresight_with_expectation_errors_solver} and one of {stoch_simul, "
" estimation, osr, ramsey_policy, discretionary_policy}. This is not possible: one "
" cannot mix perfect foresight context with stochastic context in the same file. "
< < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2020-06-23 15:13:04 +02:00
if ( use_dll & & bytecode )
2018-09-21 17:13:19 +02:00
{
2020-06-23 15:13:04 +02:00
cerr < < " ERROR: In 'model' block, 'use_dll' option is not compatible with 'bytecode' " < < endl ;
2018-09-21 17:13:19 +02:00
exit ( EXIT_FAILURE ) ;
}
2009-09-02 15:36:56 +02:00
2023-11-30 15:28:57 +01:00
if ( ( stochastic_statement_present | | mod_file_struct . check_present
| | mod_file_struct . steady_present )
& & no_static )
2010-01-08 12:06:25 +01:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: no_static option is incompatible with stoch_simul, estimation, osr, "
" ramsey_policy, discretionary_policy, steady and check commands "
< < endl ;
2010-01-08 12:06:25 +01:00
exit ( EXIT_FAILURE ) ;
}
2010-02-22 17:33:38 +01:00
2019-12-16 19:42:59 +01:00
if ( mod_file_struct . dsge_var_estimated & & ! mod_file_struct . dsge_prior_weight_in_estimated_params )
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: When estimating a DSGE-VAR model and estimating the weight of the prior, "
" dsge_prior_weight must "
2019-12-16 19:42:59 +01:00
< < " be referenced in the estimated_params block. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2010-06-11 21:19:30 +02:00
2010-06-21 18:40:36 +02:00
if ( symbol_table . exists ( " dsge_prior_weight " ) )
{
2018-07-17 18:34:07 +02:00
if ( symbol_table . getType ( " dsge_prior_weight " ) ! = SymbolType : : parameter )
2010-06-21 18:40:36 +02:00
{
cerr < < " ERROR: dsge_prior_weight may only be used as a parameter. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else
2012-01-23 16:52:27 +01:00
warnings < < " 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 ;
2010-06-21 18:40:36 +02:00
if ( mod_file_struct . dsge_var_estimated | | ! mod_file_struct . dsge_var_calibrated . empty ( ) )
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: dsge_prior_weight can either be declared as a parameter (deprecated) or "
" via the dsge_var option "
2010-06-21 18:40:36 +02:00
< < " to the estimation statement (preferred), but not both. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2023-11-30 15:28:57 +01:00
if ( ! mod_file_struct . dsge_prior_weight_initialized
& & ! mod_file_struct . dsge_prior_weight_in_estimated_params )
2010-06-21 18:40:36 +02:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: If dsge_prior_weight is declared as a parameter, it must either be "
" initialized or placed in the "
2010-06-21 18:40:36 +02:00
< < " estimated_params block. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2023-11-30 15:28:57 +01:00
if ( mod_file_struct . dsge_prior_weight_initialized
& & mod_file_struct . dsge_prior_weight_in_estimated_params )
2010-06-21 18:40:36 +02:00
{
2017-06-28 15:06:54 +02:00
cerr < < " ERROR: dsge_prior_weight cannot be both initialized and estimated. " < < endl ;
2010-06-21 18:40:36 +02:00
exit ( EXIT_FAILURE ) ;
}
}
2010-06-11 21:19:30 +02:00
if ( mod_file_struct . dsge_prior_weight_in_estimated_params )
2023-04-11 14:21:17 +02:00
{
if ( ! mod_file_struct . dsge_var_estimated & & ! mod_file_struct . dsge_var_calibrated . empty ( ) )
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: If dsge_prior_weight is in the estimated_params block, the prior weight "
" cannot be calibrated "
2023-04-11 14:21:17 +02:00
< < " via the dsge_var option in the estimation statement. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else if ( ! mod_file_struct . dsge_var_estimated & & ! symbol_table . exists ( " dsge_prior_weight " ) )
{
2023-11-30 15:28:57 +01:00
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 ;
2023-04-11 14:21:17 +02:00
exit ( EXIT_FAILURE ) ;
}
}
2013-04-11 17:07:39 +02:00
if ( dynamic_model . staticOnlyEquationsNbr ( ) ! = dynamic_model . dynamicOnlyEquationsNbr ( ) )
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: the number of equations marked [static] must be equal to the number of "
" equations marked [dynamic] "
< < endl ;
2013-04-11 17:07:39 +02:00
exit ( EXIT_FAILURE ) ;
}
2017-06-01 19:58:32 +02:00
if ( dynamic_model . staticOnlyEquationsNbr ( ) > 0
& & ( mod_file_struct . ramsey_model_present | | mod_file_struct . discretionary_policy_present ) )
2013-04-11 17:07:39 +02:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: marking equations as [static] or [dynamic] is not possible with "
" ramsey_model, ramsey_policy or discretionary_policy "
< < endl ;
2013-04-11 17:07:39 +02:00
exit ( EXIT_FAILURE ) ;
}
2013-05-17 14:14:15 +02:00
2017-06-01 19:58:32 +02:00
if ( stochastic_statement_present
2018-07-18 16:18:26 +02:00
& & ( dynamic_model . isUnaryOpUsed ( UnaryOpcode : : sign )
| | dynamic_model . isUnaryOpUsed ( UnaryOpcode : : abs )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : max )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : min )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : greater )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : less )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : greaterEqual )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : lessEqual )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : equalEqual )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : different ) ) )
2023-11-30 15:28:57 +01:00
warnings
< < R " (WARNING: you are using a function (max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) which is unsuitable for a stochastic context; see the reference manual, section about " Expressions " , for more details.) "
< < endl ;
2013-11-29 14:50:58 +01:00
2017-06-01 19:58:32 +02:00
if ( linear
2019-09-10 12:37:11 +02:00
& & ( dynamic_model . isUnaryOpUsedOnType ( SymbolType : : endogenous , UnaryOpcode : : sign )
| | dynamic_model . isUnaryOpUsedOnType ( SymbolType : : endogenous , UnaryOpcode : : abs )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : max )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : min )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : greater )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : less )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : greaterEqual )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : lessEqual )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : equalEqual )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : different ) ) )
{
cerr < < " ERROR: you have declared your model 'linear' but you are using a function "
< < " (max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) on an "
< < " endogenous variable. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2023-11-30 15:28:57 +01:00
if ( linear & & ! mod_file_struct . perfect_foresight_solver_present
2022-04-20 16:57:39 +02:00
& & ! mod_file_struct . perfect_foresight_with_expectation_errors_solver_present
2019-09-10 12:37:11 +02:00
& & ( dynamic_model . isUnaryOpUsedOnType ( SymbolType : : exogenous , UnaryOpcode : : sign )
| | dynamic_model . isUnaryOpUsedOnType ( SymbolType : : exogenous , UnaryOpcode : : abs )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : max )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : min )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : greater )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : less )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : greaterEqual )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : lessEqual )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : equalEqual )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : different ) ) )
{
cerr < < " ERROR: you have declared your model 'linear' but you are using a function "
< < " (max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) on an "
< < " exogenous variable in a non-perfect-foresight context. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2017-04-05 11:07:34 +02:00
2013-11-29 14:50:58 +01:00
// Test if some estimated parameters are used within the values of shocks
// statements (see issue #469)
set < int > parameters_intersect ;
set_intersection ( mod_file_struct . parameters_within_shocks_values . begin ( ) ,
mod_file_struct . parameters_within_shocks_values . end ( ) ,
mod_file_struct . estimated_parameters . begin ( ) ,
mod_file_struct . estimated_parameters . end ( ) ,
inserter ( parameters_intersect , parameters_intersect . begin ( ) ) ) ;
if ( parameters_intersect . size ( ) > 0 )
{
cerr < < " ERROR: some estimated parameters ( " ;
2023-11-30 15:28:57 +01:00
for ( bool printed_something { false } ; int symb_id : parameters_intersect )
2013-11-29 14:50:58 +01:00
{
2022-06-03 16:24:26 +02:00
if ( exchange ( printed_something , true ) )
2013-11-29 14:50:58 +01:00
cerr < < " , " ;
2022-06-03 16:24:26 +02:00
cerr < < symbol_table . getName ( symb_id ) ;
2013-11-29 14:50:58 +01:00
}
2023-11-30 15:28:57 +01:00
cerr < < " ) also appear in the expressions defining the variance/covariance matrix of shocks; "
" this is not allowed. "
< < endl ;
2013-11-29 14:50:58 +01:00
exit ( EXIT_FAILURE ) ;
}
2013-11-29 16:03:15 +01:00
2015-08-24 12:54:05 +02:00
// Check if some exogenous is not used in the model block, Issue #841
2018-03-28 18:46:15 +02:00
set < int > unusedExo0 = dynamic_model . findUnusedExogenous ( ) ;
set < int > unusedExo ;
2023-11-30 15:28:57 +01:00
set_difference ( unusedExo0 . begin ( ) , unusedExo0 . end ( ) , mod_file_struct . pac_params . begin ( ) ,
mod_file_struct . pac_params . end ( ) , inserter ( unusedExo , unusedExo . begin ( ) ) ) ;
2015-03-06 09:49:11 +01:00
if ( unusedExo . size ( ) > 0 )
2013-11-29 16:03:15 +01:00
{
2015-08-24 12:54:05 +02:00
ostringstream unused_exos ;
2018-06-04 12:26:16 +02:00
for ( int it : unusedExo )
unused_exos < < symbol_table . getName ( it ) < < " " ;
2015-08-24 12:54:05 +02:00
if ( nostrict )
warnings < < " WARNING: " < < unused_exos . str ( )
< < " not used in model block, removed by nostrict command-line option " < < endl ;
else
2013-11-29 16:03:15 +01:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: " < < unused_exos . str ( )
< < " not used in model block. To bypass this error, use the `nostrict` option. This "
" may lead to crashes or unexpected behavior. "
< < endl ;
2015-08-24 12:54:05 +02:00
exit ( EXIT_FAILURE ) ;
2013-11-29 16:03:15 +01:00
}
}
2009-09-30 17:10:31 +02:00
}
void
2019-12-16 19:42:59 +01:00
ModFile : : transformPass ( bool nostrict , bool stochastic , bool compute_xrefs , bool transform_unary_ops ,
2023-11-30 15:28:57 +01:00
const string & exclude_eqs , const string & include_eqs )
2009-09-30 17:10:31 +02:00
{
2019-08-20 12:50:41 +02:00
/* Save the original model (must be done before any model transformations by preprocessor)
2022-02-17 12:57:54 +01:00
— except predetermined variables ( which must be handled before the call to
setLeadsLagsOrig ( ) , see # 47 , and also before equation simplification ,
since the latter uses leads / lags , see # 83 )
2019-08-20 12:50:41 +02:00
— except substituting out variables which we know are constant ( they
appear in an equation of the form : X = constant )
— except adl operators which we always want expanded
— except diff operators with a lead which have been expanded by
DataTree : AddDiff ( )
*/
2019-11-18 17:13:49 +01:00
dynamic_model . includeExcludeEquations ( exclude_eqs , true ) ;
dynamic_model . includeExcludeEquations ( include_eqs , false ) ;
2020-03-02 17:09:09 +01:00
if ( symbol_table . predeterminedNbr ( ) > 0 )
dynamic_model . transformPredeterminedVariables ( ) ;
2022-02-17 12:57:54 +01:00
dynamic_model . simplifyEquations ( ) ;
dynamic_model . substituteAdl ( ) ;
2017-07-27 23:14:50 +02:00
dynamic_model . setLeadsLagsOrig ( ) ;
2018-10-09 18:27:19 +02:00
original_model = dynamic_model ;
2019-10-16 17:34:27 +02:00
dynamic_model . expandEqTags ( ) ;
2015-02-16 08:31:30 +01:00
2020-11-10 18:04:05 +01:00
// Replace all model-local variables by their expression
dynamic_model . substituteModelLocalVariables ( ) ;
2019-09-25 12:00:40 +02:00
// Check that all declared endogenous are used in equations
2019-09-05 11:24:36 +02:00
set < int > unusedEndogs = dynamic_model . findUnusedEndogenous ( ) ;
bool unusedEndogsIsErr = ! nostrict & & ! mod_file_struct . bvar_present & & unusedEndogs . size ( ) ;
for ( int unusedEndog : unusedEndogs )
if ( nostrict )
{
symbol_table . changeType ( unusedEndog , SymbolType : : unusedEndogenous ) ;
warnings < < " WARNING: ' " < < symbol_table . getName ( unusedEndog )
< < " ' not used in model block, removed by nostrict command-line option " < < endl ;
}
else if ( unusedEndogsIsErr )
2023-11-30 15:28:57 +01:00
cerr < < " Error: " < < symbol_table . getName ( unusedEndog ) < < " not used in the model block "
< < endl ;
2019-09-05 11:24:36 +02:00
if ( unusedEndogsIsErr )
exit ( EXIT_FAILURE ) ;
2013-09-13 20:37:31 +02:00
2022-01-19 15:53:45 +01:00
/* Get the list of equations in which to scan for and substitute unary ops:
– equations which are part of VARs and Trend Component Models
– PAC equations ( those with a pac_expectation operator ) */
set < string > var_tcm_eqtags ;
2023-11-30 15:28:57 +01:00
for ( const auto & [ name , tags ] : trend_component_model_table . getEqTags ( ) )
for ( auto & tag : tags )
2022-01-19 15:53:45 +01:00
var_tcm_eqtags . insert ( tag ) ;
2023-11-30 15:28:57 +01:00
for ( const auto & [ name , tags ] : var_model_table . getEqTags ( ) )
for ( auto & tag : tags )
2022-01-19 15:53:45 +01:00
var_tcm_eqtags . insert ( tag ) ;
set < int > unary_ops_eqs = dynamic_model . getEquationNumbersFromTags ( var_tcm_eqtags ) ;
unary_ops_eqs . merge ( dynamic_model . findPacExpectationEquationNumbers ( ) ) ;
2018-08-21 11:46:59 +02:00
2022-03-30 17:40:01 +02:00
// Check that no variable in VAR/TCM/PAC equations was declared with “var(log)”
dynamic_model . checkNoWithLogTransform ( unary_ops_eqs ) ;
2019-10-22 14:56:28 +02:00
// Create auxiliary variables and equations for unary ops
lag_equivalence_table_t unary_ops_nodes ;
2018-11-29 16:01:49 +01:00
ExprNode : : subst_table_t unary_ops_subst_table ;
2018-05-30 16:48:08 +02:00
if ( transform_unary_ops )
2023-11-30 15:28:57 +01:00
tie ( unary_ops_nodes , unary_ops_subst_table )
= dynamic_model . substituteUnaryOps ( var_expectation_model_table , pac_model_table ) ;
2018-06-07 12:53:00 +02:00
else
2022-01-19 15:53:45 +01:00
// substitute only those unary ops that appear in VAR, TCM and PAC model equations
2023-11-30 15:28:57 +01:00
tie ( unary_ops_nodes , unary_ops_subst_table ) = dynamic_model . substituteUnaryOps (
unary_ops_eqs , var_expectation_model_table , pac_model_table ) ;
2018-05-30 16:48:08 +02:00
2019-02-19 16:36:10 +01:00
// Create auxiliary variable and equations for Diff operators
2023-11-30 15:28:57 +01:00
auto [ diff_nodes , diff_subst_table ]
= dynamic_model . substituteDiff ( var_expectation_model_table , pac_model_table ) ;
2018-02-08 13:07:15 +01:00
2021-07-01 16:16:04 +02:00
// Fill trend component and VAR model tables
2018-08-14 14:23:21 +02:00
dynamic_model . fillTrendComponentModelTable ( ) ;
2019-10-22 16:04:24 +02:00
original_model . fillTrendComponentModelTableFromOrigModel ( ) ;
2021-07-01 16:16:04 +02:00
dynamic_model . fillTrendComponentModelTableAREC ( diff_subst_table ) ;
2018-08-21 11:46:59 +02:00
dynamic_model . fillVarModelTable ( ) ;
2019-10-22 16:04:24 +02:00
original_model . fillVarModelTableFromOrigModel ( ) ;
2018-08-14 14:23:21 +02:00
2022-01-20 16:15:43 +01:00
// VAR expectation models
var_expectation_model_table . transformPass ( diff_subst_table , dynamic_model , var_model_table ,
trend_component_model_table ) ;
2021-10-27 16:26:52 +02:00
// PAC model
2023-11-30 15:28:57 +01:00
pac_model_table . transformPass ( unary_ops_nodes , unary_ops_subst_table , diff_nodes ,
diff_subst_table , dynamic_model , var_model_table ,
2021-10-27 16:26:52 +02:00
trend_component_model_table ) ;
2018-08-21 11:46:59 +02:00
2011-03-21 18:36:38 +01:00
// Create auxiliary vars for Expectation operator
2018-12-20 17:04:28 +01:00
dynamic_model . substituteExpectation ( mod_file_struct . partial_information ) ;
2011-03-21 18:36:38 +01:00
2010-10-15 19:05:16 +02:00
if ( nonstationary_variables )
{
dynamic_model . detrendEquations ( ) ;
2018-10-09 18:27:19 +02:00
trend_dynamic_model = dynamic_model ;
2010-10-15 19:05:16 +02:00
dynamic_model . removeTrendVariableFromEquations ( ) ;
2023-11-30 15:28:57 +01:00
const auto & trend_symbols = dynamic_model . getTrendSymbolsMap ( ) ;
const auto & nonstationary_symbols = dynamic_model . getNonstationarySymbolsMap ( ) ;
2019-12-04 15:48:33 +01:00
epilogue . detrend ( trend_symbols , nonstationary_symbols ) ;
2010-10-15 19:05:16 +02:00
}
2019-12-11 15:49:29 +01:00
epilogue . toStatic ( ) ;
2014-03-09 09:52:44 +01:00
if ( mod_file_struct . ramsey_model_present )
2011-03-21 18:40:57 +01:00
{
2023-03-28 18:45:16 +02:00
mod_file_struct . ramsey_orig_eq_nbr = dynamic_model . equation_number ( ) ;
2023-11-30 15:28:57 +01:00
PlannerObjectiveStatement * pos = nullptr ;
for ( auto & statement : statements )
if ( auto pos2 = dynamic_cast < PlannerObjectiveStatement * > ( statement . get ( ) ) ; pos2 )
2023-04-11 14:21:17 +02:00
{
if ( pos )
{
cerr < < " ERROR: there can only be one planner_objective statement " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else
pos = pos2 ;
}
2019-12-16 19:42:59 +01:00
assert ( pos ) ;
2023-11-30 15:28:57 +01:00
const PlannerObjective & planner_objective = pos - > getPlannerObjective ( ) ;
2011-03-21 18:40:57 +01:00
/*
clone the model then clone the new equations back to the original because
we have to call computeDerivIDs ( in computeRamseyPolicyFOCs and computingPass )
2017-06-01 19:58:32 +02:00
*/
2016-11-29 14:20:53 +01:00
if ( linear )
2018-10-09 18:27:19 +02:00
orig_ramsey_dynamic_model = dynamic_model ;
2023-11-30 15:28:57 +01:00
DynamicModel ramsey_FOC_equations_dynamic_model {
symbol_table , num_constants , external_functions_table , trend_component_model_table ,
var_model_table } ;
2018-10-09 18:27:19 +02:00
ramsey_FOC_equations_dynamic_model = dynamic_model ;
2023-11-30 15:28:57 +01:00
mod_file_struct . ramsey_orig_endo_nbr
= ramsey_FOC_equations_dynamic_model . computeRamseyPolicyFOCs ( planner_objective ) ;
2011-03-21 18:40:57 +01:00
ramsey_FOC_equations_dynamic_model . replaceMyEquations ( dynamic_model ) ;
}
2021-11-23 12:35:43 +01:00
dynamic_model . createVariableMapping ( ) ;
2018-08-01 19:41:44 +02:00
2022-03-30 17:40:01 +02:00
// Must come after detrending of variables and Ramsey policy transformation
dynamic_model . substituteLogTransform ( ) ;
2020-11-09 16:28:32 +01:00
/* Create auxiliary vars for leads and lags greater than 2, on both endos and
exos . The transformation is not exactly the same on stochastic and
deterministic models , because there is no need to take into account the
Jensen inequality on the latter . */
2023-11-30 15:28:57 +01:00
bool deterministic_model
= ! ( mod_file_struct . stoch_simul_present | | mod_file_struct . estimation_present
| | mod_file_struct . osr_present | | mod_file_struct . discretionary_policy_present
| | mod_file_struct . calib_smoother_present | | mod_file_struct . identification_present
| | mod_file_struct . mom_estimation_present | | mod_file_struct . sensitivity_present
| | stochastic ) ;
2020-11-09 16:28:32 +01:00
dynamic_model . substituteEndoLeadGreaterThanTwo ( deterministic_model ) ;
dynamic_model . substituteExoLead ( deterministic_model ) ;
dynamic_model . substituteEndoLagGreaterThanTwo ( deterministic_model ) ;
dynamic_model . substituteExoLag ( deterministic_model ) ;
2009-09-02 15:36:56 +02:00
2018-09-03 15:05:30 +02:00
dynamic_model . updateVarAndTrendModel ( ) ;
2018-08-21 11:46:59 +02:00
2013-04-25 18:09:31 +02:00
if ( differentiate_forward_vars )
2018-12-20 17:04:28 +01:00
dynamic_model . differentiateForwardVars ( differentiate_forward_vars_subset ) ;
2013-04-25 18:09:31 +02:00
2010-06-21 18:40:36 +02:00
if ( mod_file_struct . dsge_var_estimated | | ! mod_file_struct . dsge_var_calibrated . empty ( ) )
2010-06-11 21:19:30 +02:00
try
{
2018-07-17 18:34:07 +02:00
int sid = symbol_table . addSymbol ( " dsge_prior_weight " , SymbolType : : parameter ) ;
2010-06-21 18:40:36 +02:00
if ( ! mod_file_struct . dsge_var_calibrated . empty ( ) )
2023-11-30 15:28:57 +01:00
addStatementAtFront ( make_unique < InitParamStatement > (
sid , expressions_tree . AddNonNegativeConstant ( mod_file_struct . dsge_var_calibrated ) ,
symbol_table ) ) ;
2010-06-11 21:19:30 +02:00
}
2023-11-30 15:28:57 +01:00
catch ( SymbolTable : : AlreadyDeclaredException & e )
2010-06-11 21:19:30 +02:00
{
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 ) ;
}
2019-12-03 14:19:32 +01:00
dynamic_model . reorderAuxiliaryEquations ( ) ;
2009-02-27 13:19:25 +01:00
// Freeze the symbol table
symbol_table . freeze ( ) ;
2017-03-06 16:34:08 +01:00
if ( compute_xrefs )
dynamic_model . computeXrefs ( ) ;
2008-10-17 14:52:08 +02:00
/*
2013-09-13 20:37:31 +02:00
Enforce the same number of equations and endogenous , except in three cases :
2014-03-09 09:52:44 +01:00
- ramsey_model , ramsey_policy or discretionary_policy is used
2008-10-17 14:52:08 +02:00
- a BVAR command is used and there is no equation ( standalone BVAR estimation )
2013-09-13 20:37:31 +02:00
- nostrict option is passed and there are more endogs than equations ( dealt with before freeze )
2008-10-17 14:52:08 +02:00
*/
2014-03-09 09:52:44 +01:00
if ( ! ( mod_file_struct . ramsey_model_present | | mod_file_struct . discretionary_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
{
2023-11-30 15:28:57 +01: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
}
2011-03-21 18:40:57 +01:00
2022-04-20 16:57:39 +02:00
if ( symbol_table . exo_det_nbr ( ) > 0
2023-11-30 15:28:57 +01:00
& & ( mod_file_struct . perfect_foresight_solver_present
| | mod_file_struct . perfect_foresight_with_expectation_errors_solver_present ) )
2011-03-18 12:47:06 +01:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul, "
" perfect_foresight_with_expectation_errors_solver} and varexo_det declaration (all "
" exogenous variables are deterministic in this case) "
< < endl ;
2011-03-18 12:47:06 +01:00
exit ( EXIT_FAILURE ) ;
}
2011-03-21 18:40:57 +01:00
2023-03-29 16:14:59 +02:00
if ( mod_file_struct . ramsey_model_present & & symbol_table . exo_det_nbr ( ) > 0 )
2013-02-07 11:52:59 +01:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: ramsey_model and ramsey_policy are incompatible with deterministic exogenous "
" variables "
< < endl ;
2013-02-07 11:52:59 +01:00
exit ( EXIT_FAILURE ) ;
}
2014-07-30 17:28:45 +02:00
if ( mod_file_struct . identification_present & & symbol_table . exo_det_nbr ( ) > 0 )
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: identification is incompatible with deterministic exogenous variables "
< < endl ;
2014-07-30 17:28:45 +02:00
exit ( EXIT_FAILURE ) ;
}
2021-07-15 16:24:21 +02:00
if ( mod_file_struct . occbin_constraints_present
2021-05-28 12:01:19 +02:00
& & ( mod_file_struct . osr_present | | mod_file_struct . mom_estimation_present
2023-11-30 15:28:57 +01:00
| | mod_file_struct . ramsey_model_present | | mod_file_struct . discretionary_policy_present
| | mod_file_struct . extended_path_present | | mod_file_struct . identification_present
| | mod_file_struct . sensitivity_present ) )
2021-02-22 18:26:21 +01:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: the 'occbin_constraints' block is not compatible with commands other than "
" 'estimation', 'stoch_simul', and 'calib_smoother'. "
< < endl ;
2021-02-22 18:26:21 +01:00
exit ( EXIT_FAILURE ) ;
}
2021-07-15 16:24:21 +02:00
if ( mod_file_struct . shocks_surprise_present & & ! mod_file_struct . occbin_constraints_present )
2021-07-13 17:07:53 +02:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: the 'shocks(surprise)' block can only be used in conjunction with the "
" 'occbin_constraints' block. "
< < endl ;
2021-07-13 17:07:53 +02:00
exit ( EXIT_FAILURE ) ;
}
2023-11-30 15:28:57 +01:00
if ( mod_file_struct . shocks_learnt_in_present
& & ! mod_file_struct . perfect_foresight_with_expectation_errors_solver_present )
2022-04-20 16:57:39 +02:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: the 'shocks(learnt_in=…)' block can only be used in conjunction with the "
" 'perfect_foresight_with_expectation_errors_solver' command. "
< < endl ;
2022-04-20 16:57:39 +02:00
exit ( EXIT_FAILURE ) ;
}
2023-11-30 15:28:57 +01:00
if ( mod_file_struct . endval_learnt_in_present
& & ! mod_file_struct . perfect_foresight_with_expectation_errors_solver_present )
2022-04-20 16:57:39 +02:00
{
2023-11-30 15:28:57 +01:00
cerr < < " ERROR: the 'endval(learnt_in=…)' block can only be used in conjunction with the "
" 'perfect_foresight_with_expectation_errors_solver' command. "
< < endl ;
2022-04-20 16:57:39 +02:00
exit ( EXIT_FAILURE ) ;
}
2018-12-20 17:04:28 +01:00
if ( ! mod_file_struct . ramsey_model_present )
cout < < " Found " < < dynamic_model . equation_number ( ) < < " equation(s). " < < endl ;
else
{
2023-11-30 15:28:57 +01:00
cout < < " Found " < < mod_file_struct . ramsey_orig_eq_nbr < < " equation(s). " < < endl ;
cout < < " Found " < < dynamic_model . equation_number ( ) < < " FOC equation(s) for Ramsey Problem. "
< < endl ;
2018-12-20 17:04:28 +01:00
}
2010-06-11 21:19:30 +02:00
2010-06-21 18:40:36 +02:00
if ( symbol_table . exists ( " dsge_prior_weight " ) )
2023-04-11 14:21:17 +02:00
{
if ( mod_file_struct . bayesian_irf_present )
{
if ( symbol_table . exo_nbr ( ) ! = symbol_table . observedVariablesNbr ( ) )
{
2023-11-30 15:28:57 +01:00
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 ;
2023-04-11 14:21:17 +02:00
exit ( EXIT_FAILURE ) ;
}
}
else if ( symbol_table . exo_nbr ( ) < symbol_table . observedVariablesNbr ( ) )
2010-06-11 21:19:30 +02:00
{
2010-06-21 18:40:36 +02:00
cerr < < " ERROR: When estimating a DSGE-Var, the number of shocks must be "
< < " greater than or equal to the number of observed variables. " < < endl ;
2010-06-11 21:19:30 +02:00
exit ( EXIT_FAILURE ) ;
}
2023-04-11 14:21:17 +02:00
}
2008-02-03 11:28:36 +01:00
}
void
2021-01-08 14:55:15 +01:00
ModFile : : computingPass ( bool no_tmp_terms , OutputType output , int params_derivs_order )
2008-02-03 11:28:36 +01:00
{
// Mod file may have no equation (for example in 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
{
2013-10-29 11:46:54 +01:00
if ( nonstationary_variables )
trend_dynamic_model . runTrendTest ( global_eval_context ) ;
2010-10-15 19:05:16 +02:00
2009-04-14 16:39:53 +02:00
// Compute static model and its derivatives
2018-10-10 17:08:54 +02:00
static_model = static_cast < StaticModel > ( dynamic_model ) ;
2011-02-04 16:25:38 +01:00
if ( ! no_static )
2017-06-01 19:58:32 +02:00
{
2023-11-30 15:28:57 +01:00
if ( mod_file_struct . stoch_simul_present | | mod_file_struct . estimation_present
| | mod_file_struct . osr_present | | mod_file_struct . ramsey_model_present
| | mod_file_struct . identification_present | | mod_file_struct . calib_smoother_present
| | mod_file_struct . mom_estimation_present )
2017-06-01 19:58:32 +02:00
static_model . set_cutoff_to_zero ( ) ;
2018-11-22 14:32:40 +01:00
int derivsOrder = 1 ;
2016-05-18 12:26:19 +02:00
int paramsDerivsOrder = 0 ;
2023-11-30 15:28:57 +01:00
if ( mod_file_struct . identification_present
| | mod_file_struct . estimation_analytic_derivation )
2020-12-11 13:27:23 +01:00
derivsOrder = 2 ;
2023-11-30 15:28:57 +01:00
if ( mod_file_struct . identification_present
2020-12-11 13:27:23 +01:00
| | mod_file_struct . estimation_analytic_derivation
2023-09-11 17:34:11 +02:00
| | mod_file_struct . osr_analytic_derivation
2023-11-30 15:28:57 +01:00
| | ( mod_file_struct . GMM_present
& & ( mod_file_struct . analytic_standard_errors_present
| | mod_file_struct . analytic_jacobian_present ) ) )
2020-12-11 13:27:23 +01:00
paramsDerivsOrder = params_derivs_order ;
2023-11-30 15:28:57 +01:00
static_model . computingPass ( derivsOrder , paramsDerivsOrder , global_eval_context ,
no_tmp_terms , block , use_dll ) ;
Ramsey: write derivatives of static model w.r.t. Lagrange multipliers in a new file
The computing of the Ramsey steady state relies on the fact that Lagrange
multipliers appear linearly in the system to be solved. Instead of directly
solving for the Lagrange multipliers along with the other variables,
dyn_ramsey_static.m reduces the size of the problem by always computing the
value of the multipliers that minimizes the residuals, given the other
variables (using a minimum norm solution, easy to compute because of the
linearity property). That function thus needs the derivatives of the optimality
FOCs with respect to the multipliers. The problem is that, when multipliers
appear in an auxiliary variable related to a lead/lag, then those derivatives
need to be retrieved by a chain rule derivation, which cannot be easily done
with the regular static file.
This commit implements the creation of a new file,
ramsey_multipliers_static_g1.{m,mex}, that provides exactly the needed
derivatives w.r.t. Lagrange multipliers through chain rule derivation.
Ref. dynare#633, dynare#1119, dynare#1133
2023-03-24 18:58:12 +01:00
if ( mod_file_struct . ramsey_model_present )
static_model . computeRamseyMultipliersDerivatives ( mod_file_struct . ramsey_orig_endo_nbr ,
! use_dll , no_tmp_terms ) ;
2017-06-01 19:58:32 +02:00
}
2009-04-14 16:39:53 +02:00
// Set things to compute for dynamic model
2022-04-20 16:57:39 +02:00
if ( mod_file_struct . perfect_foresight_solver_present
| | mod_file_struct . perfect_foresight_with_expectation_errors_solver_present
2023-11-30 15:28:57 +01:00
| | mod_file_struct . check_present | | mod_file_struct . stoch_simul_present
2017-06-01 19:58:32 +02:00
| | mod_file_struct . estimation_present | | mod_file_struct . osr_present
| | mod_file_struct . ramsey_model_present | | mod_file_struct . identification_present
2020-07-08 18:42:14 +02:00
| | mod_file_struct . calib_smoother_present | | mod_file_struct . mom_estimation_present )
2017-06-01 19:58:32 +02:00
{
2022-04-20 16:57:39 +02:00
if ( mod_file_struct . perfect_foresight_solver_present
| | mod_file_struct . perfect_foresight_with_expectation_errors_solver_present )
2021-01-08 14:55:15 +01:00
{
int derivsOrder = 1 ;
if ( output = = OutputType : : second )
derivsOrder = 2 ;
2023-11-30 15:28:57 +01:00
else if ( output = = OutputType : : third )
2021-01-08 14:55:15 +01:00
derivsOrder = 3 ;
2023-11-30 15:28:57 +01:00
dynamic_model . computingPass ( derivsOrder , 0 , global_eval_context , no_tmp_terms , block ,
use_dll ) ;
2021-01-08 14:55:15 +01:00
}
2017-06-01 19:58:32 +02:00
else
{
2023-11-30 15:28:57 +01:00
if ( mod_file_struct . stoch_simul_present | | mod_file_struct . estimation_present
| | mod_file_struct . osr_present | | mod_file_struct . ramsey_model_present
| | mod_file_struct . identification_present
| | mod_file_struct . calib_smoother_present
| | mod_file_struct . mom_estimation_present )
2017-06-01 19:58:32 +02:00
dynamic_model . set_cutoff_to_zero ( ) ;
2019-04-12 15:41:52 +02:00
if ( mod_file_struct . order_option < 1 )
2017-06-01 19:58:32 +02:00
{
cerr < < " ERROR: Incorrect order option... " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2023-11-30 15:28:57 +01:00
int derivsOrder
= max ( mod_file_struct . order_option ,
mod_file_struct . identification_order + 1 ) ; // See preprocessor#40
if ( mod_file_struct . GMM_present
& & ( mod_file_struct . analytic_standard_errors_present
| | mod_file_struct . analytic_jacobian_present ) ) // analytic_standard_errors or
// analytic_jacobian require
// one order more
derivsOrder
= max ( mod_file_struct . order_option ,
max ( mod_file_struct . identification_order , mod_file_struct . mom_order )
+ 1 ) ; // See preprocessor#40
2020-12-11 13:27:23 +01:00
2021-01-08 14:55:15 +01:00
if ( mod_file_struct . sensitivity_present | | linear | | output = = OutputType : : second )
2018-11-22 14:32:40 +01:00
derivsOrder = max ( derivsOrder , 2 ) ;
2021-01-08 14:55:15 +01:00
if ( mod_file_struct . estimation_analytic_derivation | | output = = OutputType : : third )
2018-11-22 14:32:40 +01:00
derivsOrder = max ( derivsOrder , 3 ) ;
2017-06-01 19:58:32 +02:00
int paramsDerivsOrder = 0 ;
2023-11-30 15:28:57 +01:00
if ( mod_file_struct . identification_present
2020-12-11 13:27:23 +01:00
| | mod_file_struct . estimation_analytic_derivation
2023-09-11 17:34:11 +02:00
| | mod_file_struct . osr_analytic_derivation
2023-11-30 15:28:57 +01:00
| | ( mod_file_struct . GMM_present
& & ( mod_file_struct . analytic_standard_errors_present
| | mod_file_struct . analytic_jacobian_present ) ) )
2017-06-01 19:58:32 +02:00
paramsDerivsOrder = params_derivs_order ;
2023-11-30 15:28:57 +01:00
dynamic_model . computingPass ( derivsOrder , paramsDerivsOrder , global_eval_context ,
no_tmp_terms , block , use_dll ) ;
2017-06-01 19:58:32 +02:00
if ( linear & & mod_file_struct . ramsey_model_present )
2023-11-30 15:28:57 +01:00
orig_ramsey_dynamic_model . computingPass ( 2 , paramsDerivsOrder , global_eval_context ,
no_tmp_terms , block , use_dll ) ;
2017-06-01 19:58:32 +02:00
}
}
else // No computing task requested, compute derivatives up to 2nd order by default
2022-10-07 14:37:25 +02:00
dynamic_model . computingPass ( 2 , 0 , global_eval_context , no_tmp_terms , block , use_dll ) ;
2017-06-01 19:58:32 +02:00
2019-12-13 17:15:03 +01:00
if ( linear )
2023-04-11 14:21:17 +02:00
{
if ( mod_file_struct . ramsey_model_present )
orig_ramsey_dynamic_model . checkIsLinear ( ) ;
else
dynamic_model . checkIsLinear ( ) ;
}
2008-02-03 11:28:36 +01:00
}
2009-04-20 12:48:54 +02:00
2021-07-07 10:54:04 +02:00
// Those matrices can only be filled here, because we use derivatives
dynamic_model . fillVarModelTableMatrices ( ) ;
2023-11-30 15:28:57 +01:00
for ( auto & statement : statements )
2021-06-04 16:20:29 +02:00
statement - > computingPass ( mod_file_struct ) ;
2018-09-03 17:16:28 +02:00
2018-12-20 17:04:28 +01:00
// Compute epilogue derivatives (but silence standard output)
2023-11-30 15:28:57 +01:00
streambuf * oldcout = cout . rdbuf ( ) ;
2018-12-20 17:04:28 +01:00
cout . rdbuf ( nullptr ) ;
2022-10-07 14:37:25 +02:00
epilogue . computingPass ( 2 , 0 , global_eval_context , true , false , false ) ;
2018-12-20 17:04:28 +01:00
cout . rdbuf ( oldcout ) ;
2008-02-03 11:28:36 +01:00
}
2022-10-11 17:25:19 +02:00
void
2023-11-30 15:28:57 +01:00
ModFile : : remove_directory_with_matlab_lock ( const filesystem : : path & dir )
2022-10-11 17:25:19 +02:00
{
2023-01-10 11:49:39 +01:00
auto dirStatus { status ( dir ) } ;
if ( ! exists ( dirStatus ) )
2022-10-11 17:25:19 +02:00
return ;
2023-01-10 11:49:39 +01:00
if ( is_directory ( dirStatus ) )
2023-11-30 15:28:57 +01:00
for ( const auto & e : filesystem : : directory_iterator { dir } )
2023-01-10 11:49:39 +01:00
if ( e . is_directory ( ) )
2022-10-11 17:25:19 +02:00
remove_directory_with_matlab_lock ( e ) ;
auto tmp { unique_path ( ) } ;
rename ( dir , tmp ) ;
remove_all ( tmp ) ;
}
2008-02-03 11:28:36 +01:00
void
2023-11-30 15:28:57 +01:00
ModFile : : writeMOutput ( const string & basename , bool clear_all , bool clear_global , bool no_warn ,
2023-12-11 17:16:49 +01:00
bool console , bool nograph , bool nointeractive , const Configuration & config ,
2021-01-08 14:55:15 +01:00
bool check_model_changes , bool minimal_workspace , bool compute_xrefs ,
2023-11-30 15:28:57 +01:00
const string & mexext , const filesystem : : path & matlabroot , bool onlymodel ,
bool gui , bool notime ) const
2008-02-03 11:28:36 +01:00
{
2022-10-11 15:59:56 +02:00
if ( basename . empty ( ) )
{
cerr < < " ERROR: Missing file name " < < endl ;
exit ( EXIT_FAILURE ) ;
}
auto plusfolder { DataTree : : packageDir ( basename ) } ;
2022-06-24 15:45:35 +02:00
bool hasModelChanged = ! dynamic_model . isChecksumMatching ( basename ) | | ! check_model_changes ;
2018-06-27 15:01:31 +02:00
if ( hasModelChanged )
{
// Erase possible remnants of previous runs
2022-10-11 17:25:19 +02:00
2018-07-09 18:18:26 +02:00
/* Under MATLAB+Windows (but not under Octave nor under GNU/Linux or
macOS ) , if we directly remove the " + " subdirectory , then the
preprocessor is not able to recreate it afterwards ( presumably because
2022-10-11 17:25:19 +02:00
MATLAB maintains some sort of lock on it ) . So we use a hack . */
remove_directory_with_matlab_lock ( plusfolder ) ;
2019-12-06 15:19:23 +01:00
2019-04-04 17:01:37 +02:00
filesystem : : remove_all ( basename + " /model/src " ) ;
filesystem : : remove_all ( basename + " /model/bytecode " ) ;
2023-11-30 15:28:57 +01:00
// Do not remove basename/model/julia/, otherwise it would break calls to
// writeToFileIfModified()
2018-06-27 15:01:31 +02:00
}
2022-10-11 15:59:56 +02:00
create_directory ( plusfolder ) ;
filesystem : : path fname { plusfolder / " driver.m " } ;
2023-11-30 15:28:57 +01:00
ofstream mOutputFile { fname , ios : : out | ios : : binary } ;
2022-07-11 16:09:07 +02:00
if ( ! mOutputFile . is_open ( ) )
2008-02-03 11:28:36 +01:00
{
2022-10-11 15:59:56 +02:00
cerr < < " ERROR: Can't open file " < < fname . string ( ) < < " for writing " < < 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
2015-06-30 12:12:49 +02:00
< < " % Status : main Dynare file " < < endl
2008-06-16 18:33:28 +02:00
< < " % " < < endl
< < " % Warning : this file is generated automatically by Dynare " < < endl
2023-11-30 15:28:57 +01:00
< < " % from model file (.mod) " < < endl
< < endl ;
2008-02-03 11:28:36 +01:00
2013-02-26 16:50:05 +01:00
if ( no_warn )
mOutputFile < < " warning off " < < endl ; // This will be executed *after* function warning_config()
2008-02-03 11:28:36 +01:00
if ( clear_all )
2023-11-22 12:06:34 +01:00
mOutputFile < < " clearvars -global " < < endl
< < " clear_persistent_variables(fileparts(which('dynare')), false) " < < endl ;
2014-12-30 21:51:33 +01:00
else if ( clear_global )
2023-11-30 15:28:57 +01:00
mOutputFile
< < " clear M_ options_ oo_ estim_params_ bayestopt_ dataset_ dataset_info estimation_info; "
< < endl ;
2009-04-30 15:05:21 +02:00
2020-04-06 09:29:57 +02:00
if ( ! notime )
mOutputFile < < " tic0 = tic; " < < endl ;
2023-11-30 15:28:57 +01:00
mOutputFile
< < " % Define global variables. " < < endl
< < " global M_ options_ oo_ estim_params_ bayestopt_ dataset_ dataset_info estimation_info "
< < endl
< < " options_ = []; " < < endl
< < " M_.fname = ' " < < basename < < " '; " < < endl
< < " M_.dynare_version = ' " < < PACKAGE_VERSION < < " '; " < < endl
< < " oo_.dynare_version = ' " < < PACKAGE_VERSION < < " '; " < < endl
< < " options_.dynare_version = ' " < < PACKAGE_VERSION < < " '; " < < endl
< < " % " < < endl
< < " % Some global variables initialization " < < endl
< < " % " < < endl ;
2018-11-07 15:24:57 +01:00
if ( ! onlymodel )
2023-12-11 17:16:49 +01:00
config . writeHooks ( mOutputFile ) ;
2021-01-06 14:19:33 +01:00
mOutputFile < < " global_initialization; " < < endl ;
2009-04-30 15:05:21 +02:00
2010-10-28 11:19:11 +02:00
if ( console )
2023-11-30 15:28:57 +01:00
mOutputFile < < " options_.console_mode = true; " < < endl < < " options_.nodisplay = true; " < < endl ;
2013-07-10 11:03:48 +02:00
if ( nograph )
2019-03-19 14:05:41 +01:00
mOutputFile < < " options_.nograph = true; " < < endl ;
2013-07-10 12:02:12 +02:00
if ( nointeractive )
2019-03-19 14:05:41 +01:00
mOutputFile < < " options_.nointeractive = true; " < < endl ;
2015-07-30 14:40:03 +02:00
if ( param_used_with_lead_lag )
mOutputFile < < " M_.parameter_used_with_lead_lag = true; " < < endl ;
2008-02-03 11:28:36 +01:00
symbol_table . writeOutput ( mOutputFile ) ;
2018-09-06 17:53:07 +02:00
var_model_table . writeOutput ( basename , mOutputFile ) ;
2018-09-07 10:56:40 +02:00
trend_component_model_table . writeOutput ( basename , mOutputFile ) ;
2022-06-24 15:45:35 +02:00
var_expectation_model_table . writeOutput ( mOutputFile ) ;
pac_model_table . writeOutput ( mOutputFile ) ;
2018-08-14 14:23:21 +02:00
2013-10-28 15:29:41 +01:00
// Initialize M_.Sigma_e, M_.Correlation_matrix, M_.H, and M_.Correlation_matrix_ME
2023-11-30 15:28:57 +01:00
mOutputFile < < " M_.Sigma_e = zeros( " < < symbol_table . exo_nbr ( ) < < " , " < < symbol_table . exo_nbr ( )
< < " ); " < < endl
2013-10-28 15:29:41 +01:00
< < " M_.Correlation_matrix = eye( " < < symbol_table . exo_nbr ( ) < < " , "
2010-04-14 15:03:41 +02:00
< < symbol_table . exo_nbr ( ) < < " ); " < < endl ;
if ( mod_file_struct . calibrated_measurement_errors )
mOutputFile < < " M_.H = zeros( " < < symbol_table . observedVariablesNbr ( ) < < " , "
2013-10-28 15:29:41 +01:00
< < symbol_table . observedVariablesNbr ( ) < < " ); " < < endl
< < " M_.Correlation_matrix_ME = eye( " < < symbol_table . observedVariablesNbr ( ) < < " , "
2010-04-14 15:03:41 +02:00
< < symbol_table . observedVariablesNbr ( ) < < " ); " < < endl ;
else
2023-11-30 15:28:57 +01:00
mOutputFile < < " M_.H = 0; " < < endl < < " M_.Correlation_matrix_ME = 1; " < < endl ;
2010-04-14 15:03:41 +02:00
2014-04-10 11:43:26 +02:00
// May be later modified by a shocks block
2019-03-19 14:05:41 +01:00
mOutputFile < < " M_.sigma_e_is_diagonal = true; " < < endl ;
2014-04-10 11:43:26 +02:00
2023-12-19 16:09:41 +01:00
/* Initialize the structures created for several blocks, as part of the implementation of the
“ overwrite ” option */
2021-06-15 12:53:40 +02:00
mOutputFile < < " M_.det_shocks = []; " < < endl
2021-07-13 17:07:53 +02:00
< < " M_.surprise_shocks = []; " < < endl
2022-04-20 16:57:39 +02:00
< < " M_.learnt_shocks = []; " < < endl
< < " M_.learnt_endval = []; " < < endl
2021-06-15 12:53:40 +02:00
< < " M_.heteroskedastic_shocks.Qvalue_orig = []; " < < endl
2023-12-19 16:09:41 +01:00
< < " M_.heteroskedastic_shocks.Qscale_orig = []; " < < endl
< < " M_.matched_irfs = {}; " < < endl
< < " M_.matched_irfs_weights = {}; " < < endl ;
2014-04-09 18:33:24 +02:00
2023-03-28 18:15:32 +02:00
// NB: options_.{ramsey,discretionary}_policy should rather be fields of M_
2023-11-30 15:28:57 +01:00
mOutputFile < < boolalpha < < " options_.linear = " < < linear < < " ; " < < endl
2022-05-16 12:26:21 +02:00
< < " options_.block = " < < block < < " ; " < < endl
< < " options_.bytecode = " < < bytecode < < " ; " < < endl
2023-03-28 18:15:32 +02:00
< < " options_.use_dll = " < < use_dll < < " ; " < < endl
2023-03-29 16:14:59 +02:00
< < " options_.ramsey_policy = " < < mod_file_struct . ramsey_model_present < < " ; " < < endl
2023-11-30 15:28:57 +01:00
< < " options_.discretionary_policy = " < < mod_file_struct . discretionary_policy_present
< < " ; " < < endl ;
2009-09-02 15:36:56 +02:00
2023-03-28 18:46:06 +02:00
if ( mod_file_struct . discretionary_policy_present )
2023-11-30 15:28:57 +01:00
mOutputFile < < " M_.discretionary_orig_eq_nbr = " < < original_model . equation_number ( ) < < " ; "
< < endl ;
2023-03-28 18:46:06 +02:00
2013-05-31 14:47:28 +02:00
if ( parallel_local_files . size ( ) > 0 )
{
mOutputFile < < " options_.parallel_info.local_files = { " < < endl ;
2023-11-30 15:28:57 +01:00
for ( const auto & parallel_local_file : parallel_local_files )
2013-05-31 14:47:28 +02:00
{
2019-04-03 16:32:52 +02:00
size_t j = parallel_local_file . find_last_of ( R " (/ \ ) " ) ;
2013-05-31 14:47:28 +02:00
if ( j = = string : : npos )
2018-06-04 12:26:16 +02:00
mOutputFile < < " '', ' " < < parallel_local_file < < " '; " < < endl ;
2013-05-31 14:47:28 +02:00
else
2023-11-30 15:28:57 +01:00
mOutputFile < < " ' " < < parallel_local_file . substr ( 0 , j + 1 ) < < " ', ' "
< < parallel_local_file . substr ( j + 1 ) < < " '; " < < endl ;
2013-05-31 14:47:28 +02:00
}
mOutputFile < < " }; " < < endl ;
}
2019-12-13 17:15:03 +01:00
if ( dynamic_model . isHessianComputed ( ) )
{
mOutputFile < < " M_.nonzero_hessian_eqs = " ;
dynamic_model . printNonZeroHessianEquations ( mOutputFile ) ;
2023-11-30 15:28:57 +01:00
mOutputFile < < " ; " < < endl < < " M_.hessian_eq_zero = isempty(M_.nonzero_hessian_eqs); " < < endl ;
2019-12-13 17:15:03 +01:00
}
2016-11-14 12:30:52 +01:00
2018-11-07 15:24:57 +01:00
if ( ! onlymodel )
2023-12-11 17:16:49 +01:00
config . writeCluster ( mOutputFile ) ;
2010-10-25 18:20:58 +02:00
2020-05-20 11:39:59 +02:00
if ( bytecode )
2009-09-03 18:34:15 +02:00
mOutputFile < < " if exist('bytecode') ~= 3 " < < endl
2023-11-30 15:28:57 +01:00
< < " error('DYNARE: Can''t find bytecode DLL. Please compile it or remove the "
" ''bytecode'' option.') "
< < endl
2009-09-03 18:34:15 +02:00
< < " end " < < endl ;
2023-03-28 18:45:16 +02:00
mOutputFile < < " M_.eq_nbr = " < < dynamic_model . equation_number ( ) < < " ; " < < endl
< < " M_.ramsey_orig_eq_nbr = " < < mod_file_struct . ramsey_orig_eq_nbr < < " ; " < < endl
< < " M_.ramsey_orig_endo_nbr = " < < mod_file_struct . ramsey_orig_endo_nbr < < " ; " < < endl
2023-11-30 15:28:57 +01:00
< < " M_.set_auxiliary_variables = exist(['./+' M_.fname "
" '/set_auxiliary_variables.m'], 'file') == 2; "
< < endl ;
2011-03-21 18:40:57 +01:00
2019-12-11 12:20:13 +01:00
epilogue . writeOutput ( mOutputFile ) ;
2009-04-14 16:39:53 +02:00
if ( dynamic_model . equation_number ( ) > 0 )
2008-02-03 11:28:36 +01:00
{
2023-01-13 12:05:04 +01:00
dynamic_model . writeDriverOutput ( mOutputFile , compute_xrefs ) ;
2010-09-17 11:23:00 +02:00
if ( ! no_static )
Ramsey: write derivatives of static model w.r.t. Lagrange multipliers in a new file
The computing of the Ramsey steady state relies on the fact that Lagrange
multipliers appear linearly in the system to be solved. Instead of directly
solving for the Lagrange multipliers along with the other variables,
dyn_ramsey_static.m reduces the size of the problem by always computing the
value of the multipliers that minimizes the residuals, given the other
variables (using a minimum norm solution, easy to compute because of the
linearity property). That function thus needs the derivatives of the optimality
FOCs with respect to the multipliers. The problem is that, when multipliers
appear in an auxiliary variable related to a lead/lag, then those derivatives
need to be retrieved by a chain rule derivation, which cannot be easily done
with the regular static file.
This commit implements the creation of a new file,
ramsey_multipliers_static_g1.{m,mex}, that provides exactly the needed
derivatives w.r.t. Lagrange multipliers through chain rule derivation.
Ref. dynare#633, dynare#1119, dynare#1133
2023-03-24 18:58:12 +01:00
{
static_model . writeDriverOutput ( mOutputFile ) ;
if ( mod_file_struct . ramsey_model_present )
static_model . writeDriverRamseyMultipliersDerivativesSparseIndices ( mOutputFile ) ;
}
2008-02-03 11:28:36 +01:00
}
2020-02-06 15:25:14 +01:00
if ( onlymodel | | gui )
2023-11-30 15:28:57 +01:00
for ( const auto & statement : statements )
2018-11-07 15:24:57 +01:00
{
2018-12-27 12:06:39 +01:00
/* Special treatment for initval block: insert initial values for the
auxiliary variables and initialize exo det */
2023-11-30 15:28:57 +01:00
if ( auto ivs = dynamic_cast < InitValStatement * > ( statement . get ( ) ) ; ivs )
2018-12-27 12:06:39 +01:00
{
ivs - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
static_model . writeAuxVarInitval ( mOutputFile , ExprNodeOutputType : : matlabOutsideModel ) ;
ivs - > writeOutputPostInit ( mOutputFile ) ;
}
// Special treatment for endval block: insert initial values for the auxiliary variables
2023-11-30 15:28:57 +01:00
if ( auto evs = dynamic_cast < EndValStatement * > ( statement . get ( ) ) ; evs )
2018-12-27 12:06:39 +01:00
{
evs - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
static_model . writeAuxVarInitval ( mOutputFile , ExprNodeOutputType : : matlabOutsideModel ) ;
}
2023-11-30 15:28:57 +01:00
if ( auto ips = dynamic_cast < InitParamStatement * > ( statement . get ( ) ) ; ips )
2018-11-07 15:24:57 +01:00
ips - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
2009-09-30 17:10:31 +02:00
2023-11-30 15:28:57 +01:00
if ( auto ss = dynamic_cast < ShocksStatement * > ( statement . get ( ) ) ; ss )
2018-11-07 15:24:57 +01:00
ss - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
2018-12-27 19:07:51 +01:00
2023-11-30 15:28:57 +01:00
if ( auto eps = dynamic_cast < EstimatedParamsStatement * > ( statement . get ( ) ) ; eps )
2018-12-27 19:07:51 +01:00
eps - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
2019-07-22 23:18:01 +02:00
2023-11-30 15:28:57 +01:00
if ( auto sgs = dynamic_cast < ShockGroupsStatement * > ( statement . get ( ) ) ; sgs )
2019-07-22 23:18:01 +02:00
sgs - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
2020-02-06 15:25:14 +01:00
if ( gui )
2023-11-30 15:28:57 +01:00
if ( auto it = dynamic_cast < NativeStatement * > ( statement . get ( ) ) ; it )
2020-02-06 15:25:14 +01:00
it - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
2018-11-07 15:24:57 +01:00
}
else
{
2023-11-30 15:28:57 +01:00
for ( const auto & statement : statements )
2009-09-30 17:10:31 +02:00
{
2018-11-07 15:24:57 +01:00
statement - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
/* Special treatment for initval block: insert initial values for the
auxiliary variables and initialize exo det */
2023-11-30 15:28:57 +01:00
if ( auto ivs = dynamic_cast < InitValStatement * > ( statement . get ( ) ) ; ivs )
2018-11-07 15:24:57 +01:00
{
static_model . writeAuxVarInitval ( mOutputFile , ExprNodeOutputType : : matlabOutsideModel ) ;
ivs - > writeOutputPostInit ( mOutputFile ) ;
}
2009-09-30 17:10:31 +02:00
2018-11-07 15:24:57 +01:00
// Special treatment for endval block: insert initial values for the auxiliary variables
2023-11-30 15:28:57 +01:00
if ( auto evs = dynamic_cast < EndValStatement * > ( statement . get ( ) ) ; evs )
2018-11-07 15:24:57 +01:00
static_model . writeAuxVarInitval ( mOutputFile , ExprNodeOutputType : : matlabOutsideModel ) ;
2013-04-22 17:29:59 +02:00
2023-11-30 15:28:57 +01:00
// Special treatment for load params and steady state statement: insert initial values for
// the auxiliary variables
if ( auto lpass = dynamic_cast < LoadParamsAndSteadyStateStatement * > ( statement . get ( ) ) ;
lpass & & ! no_static )
2018-11-07 15:24:57 +01:00
static_model . writeAuxVarInitval ( mOutputFile , ExprNodeOutputType : : matlabOutsideModel ) ;
}
2008-02-03 11:28:36 +01:00
2021-02-04 10:48:59 +01:00
if ( ! notime )
2023-11-30 15:28:57 +01:00
mOutputFile < < endl
< < endl
< < " oo_.time = toc(tic0); " < < endl
< < " disp(['Total computing time : ' dynsec2hms(oo_.time) ]); " < < endl ;
2021-02-04 10:48:59 +01:00
2021-07-22 17:34:42 +02:00
mOutputFile < < " if ~exist([M_.dname filesep 'Output'],'dir') " < < endl
< < " mkdir(M_.dname,'Output'); " < < endl
< < " end " < < endl
2023-11-30 15:28:57 +01:00
< < " save([M_.dname filesep 'Output' filesep ' " < < basename
< < " _results.mat'], 'oo_', 'M_', 'options_'); " < < endl
2018-11-07 15:24:57 +01:00
< < " if exist('estim_params_', 'var') == 1 " < < endl
2023-11-30 15:28:57 +01:00
< < " save([M_.dname filesep 'Output' filesep ' " < < basename
< < " _results.mat'], 'estim_params_', '-append'); " < < endl
< < " end " < < endl
2018-11-07 15:24:57 +01:00
< < " if exist('bayestopt_', 'var') == 1 " < < endl
2023-11-30 15:28:57 +01:00
< < " save([M_.dname filesep 'Output' filesep ' " < < basename
< < " _results.mat'], 'bayestopt_', '-append'); " < < endl
< < " end " < < endl
2018-11-07 15:24:57 +01:00
< < " if exist('dataset_', 'var') == 1 " < < endl
2023-11-30 15:28:57 +01:00
< < " save([M_.dname filesep 'Output' filesep ' " < < basename
< < " _results.mat'], 'dataset_', '-append'); " < < endl
< < " end " < < endl
2018-11-07 15:24:57 +01:00
< < " if exist('estimation_info', 'var') == 1 " < < endl
2023-11-30 15:28:57 +01:00
< < " save([M_.dname filesep 'Output' filesep ' " < < basename
< < " _results.mat'], 'estimation_info', '-append'); " < < endl
< < " end " < < endl
2018-11-07 15:24:57 +01:00
< < " if exist('dataset_info', 'var') == 1 " < < endl
2023-11-30 15:28:57 +01:00
< < " save([M_.dname filesep 'Output' filesep ' " < < basename
< < " _results.mat'], 'dataset_info', '-append'); " < < endl
< < " end " < < endl
2018-11-07 15:24:57 +01:00
< < " if exist('oo_recursive_', 'var') == 1 " < < endl
2023-11-30 15:28:57 +01:00
< < " save([M_.dname filesep 'Output' filesep ' " < < basename
< < " _results.mat'], 'oo_recursive_', '-append'); " < < endl
< < " end " < < endl
2023-09-13 16:07:27 +02:00
< < " if exist('options_mom_', 'var') == 1 " < < endl
2023-11-30 15:28:57 +01:00
< < " save([M_.dname filesep 'Output' filesep ' " < < basename
< < " _results.mat'], 'options_mom_', '-append'); " < < endl
< < " end " < < endl ;
2018-11-07 15:24:57 +01:00
2023-12-11 17:16:49 +01:00
config . writeEndParallel ( mOutputFile ) ;
2020-04-06 09:29:57 +02:00
2018-11-07 15:24:57 +01:00
if ( ! no_warn )
{
if ( warnings . countWarnings ( ) > 0 )
2023-11-30 15:28:57 +01:00
mOutputFile < < " disp('Note: " < < warnings . countWarnings ( )
< < " warning(s) encountered in the preprocessor') " < < endl ;
2013-03-05 12:53:37 +01:00
2018-11-07 15:24:57 +01:00
mOutputFile < < " if ~isempty(lastwarn) " < < endl
< < " disp('Note: warning(s) encountered in MATLAB/Octave code') " < < endl
< < " end " < < endl ;
}
2013-02-26 16:50:05 +01:00
}
2012-01-23 16:52:27 +01:00
2008-02-03 11:28:36 +01:00
mOutputFile . close ( ) ;
2009-04-30 15:05:21 +02:00
2015-05-10 18:16:11 +02:00
if ( hasModelChanged )
2009-07-07 16:20:48 +02:00
{
2015-05-10 18:16:11 +02:00
// Create static and dynamic files
if ( dynamic_model . equation_number ( ) > 0 )
2017-06-01 19:58:32 +02:00
{
if ( ! no_static )
{
2023-03-20 17:54:32 +01:00
static_model . writeStaticFile ( basename , use_dll , mexext , matlabroot , false ) ;
2022-07-12 12:27:22 +02:00
static_model . writeParamsDerivativesFile < false > ( basename ) ;
Ramsey: write derivatives of static model w.r.t. Lagrange multipliers in a new file
The computing of the Ramsey steady state relies on the fact that Lagrange
multipliers appear linearly in the system to be solved. Instead of directly
solving for the Lagrange multipliers along with the other variables,
dyn_ramsey_static.m reduces the size of the problem by always computing the
value of the multipliers that minimizes the residuals, given the other
variables (using a minimum norm solution, easy to compute because of the
linearity property). That function thus needs the derivatives of the optimality
FOCs with respect to the multipliers. The problem is that, when multipliers
appear in an auxiliary variable related to a lead/lag, then those derivatives
need to be retrieved by a chain rule derivation, which cannot be easily done
with the regular static file.
This commit implements the creation of a new file,
ramsey_multipliers_static_g1.{m,mex}, that provides exactly the needed
derivatives w.r.t. Lagrange multipliers through chain rule derivation.
Ref. dynare#633, dynare#1119, dynare#1133
2023-03-24 18:58:12 +01:00
if ( mod_file_struct . ramsey_model_present )
{
if ( use_dll )
2023-11-30 15:28:57 +01:00
static_model . writeRamseyMultipliersDerivativesCFile (
basename , mexext , matlabroot , mod_file_struct . ramsey_orig_endo_nbr ) ;
Ramsey: write derivatives of static model w.r.t. Lagrange multipliers in a new file
The computing of the Ramsey steady state relies on the fact that Lagrange
multipliers appear linearly in the system to be solved. Instead of directly
solving for the Lagrange multipliers along with the other variables,
dyn_ramsey_static.m reduces the size of the problem by always computing the
value of the multipliers that minimizes the residuals, given the other
variables (using a minimum norm solution, easy to compute because of the
linearity property). That function thus needs the derivatives of the optimality
FOCs with respect to the multipliers. The problem is that, when multipliers
appear in an auxiliary variable related to a lead/lag, then those derivatives
need to be retrieved by a chain rule derivation, which cannot be easily done
with the regular static file.
This commit implements the creation of a new file,
ramsey_multipliers_static_g1.{m,mex}, that provides exactly the needed
derivatives w.r.t. Lagrange multipliers through chain rule derivation.
Ref. dynare#633, dynare#1119, dynare#1133
2023-03-24 18:58:12 +01:00
else
2023-11-30 15:28:57 +01:00
static_model . writeRamseyMultipliersDerivativesMFile (
basename , mod_file_struct . ramsey_orig_endo_nbr ) ;
Ramsey: write derivatives of static model w.r.t. Lagrange multipliers in a new file
The computing of the Ramsey steady state relies on the fact that Lagrange
multipliers appear linearly in the system to be solved. Instead of directly
solving for the Lagrange multipliers along with the other variables,
dyn_ramsey_static.m reduces the size of the problem by always computing the
value of the multipliers that minimizes the residuals, given the other
variables (using a minimum norm solution, easy to compute because of the
linearity property). That function thus needs the derivatives of the optimality
FOCs with respect to the multipliers. The problem is that, when multipliers
appear in an auxiliary variable related to a lead/lag, then those derivatives
need to be retrieved by a chain rule derivation, which cannot be easily done
with the regular static file.
This commit implements the creation of a new file,
ramsey_multipliers_static_g1.{m,mex}, that provides exactly the needed
derivatives w.r.t. Lagrange multipliers through chain rule derivation.
Ref. dynare#633, dynare#1119, dynare#1133
2023-03-24 18:58:12 +01:00
}
2017-06-01 19:58:32 +02:00
}
2009-12-16 14:21:31 +01:00
2023-03-20 17:54:32 +01:00
dynamic_model . writeDynamicFile ( basename , use_dll , mexext , matlabroot , false ) ;
2018-09-21 17:13:19 +02:00
2022-07-12 12:27:22 +02:00
dynamic_model . writeParamsDerivativesFile < false > ( basename ) ;
2017-06-01 19:58:32 +02:00
}
2010-04-23 18:39:07 +02:00
2015-05-10 18:16:11 +02:00
// Create steady state file
2022-06-24 15:45:35 +02:00
steady_state_model . writeSteadyStateFile ( basename , false ) ;
2018-09-03 17:16:28 +02:00
// Create epilogue file
epilogue . writeEpilogueFile ( basename ) ;
2021-10-26 18:06:26 +02:00
pac_model_table . writeTargetCoefficientsFile ( basename ) ;
2015-05-10 18:16:11 +02:00
}
2008-02-03 11:28:36 +01:00
}
2015-07-21 17:26:08 +02:00
void
2023-11-30 15:28:57 +01:00
ModFile : : writeJuliaOutput ( const string & basename ) const
2015-07-21 17:47:56 +02:00
{
2015-07-27 15:33:38 +02:00
if ( dynamic_model . equation_number ( ) > 0 )
2015-07-27 17:02:51 +02:00
{
if ( ! no_static )
2015-07-28 12:29:42 +02:00
{
2023-03-20 17:54:32 +01:00
static_model . writeStaticFile ( basename , false , " " , { } , true ) ;
2022-07-12 12:27:22 +02:00
static_model . writeParamsDerivativesFile < true > ( basename ) ;
2015-07-28 12:29:42 +02:00
}
2023-03-20 17:54:32 +01:00
dynamic_model . writeDynamicFile ( basename , use_dll , " " , { } , true ) ;
2022-07-12 12:27:22 +02:00
dynamic_model . writeParamsDerivativesFile < true > ( basename ) ;
2015-07-27 17:02:51 +02:00
}
2022-06-24 15:45:35 +02:00
steady_state_model . writeSteadyStateFile ( basename , true ) ;
2015-07-21 17:47:56 +02:00
}
2017-02-02 15:09:43 +01:00
void
2023-11-30 15:28:57 +01:00
ModFile : : writeJsonOutput ( const string & basename , JsonOutputPointType json ,
JsonFileOutputType json_output_mode , bool onlyjson , bool jsonderivsimple )
2017-02-20 12:18:11 +01:00
{
2018-07-18 17:28:05 +02:00
if ( json = = JsonOutputPointType : : nojson )
2017-02-20 12:18:11 +01:00
return ;
2018-07-18 17:28:05 +02:00
if ( json = = JsonOutputPointType : : parsing | | json = = JsonOutputPointType : : checkpass )
2017-02-20 12:18:11 +01:00
symbol_table . freeze ( ) ;
2018-07-18 17:28:05 +02:00
if ( json_output_mode = = JsonFileOutputType : : standardout )
2023-11-30 15:28:57 +01:00
cout < < " //-- BEGIN JSON --// " < < endl < < " { " < < endl ;
2017-06-29 13:15:32 +02:00
2023-11-30 15:28:57 +01:00
writeJsonOutputParsingCheck ( basename , json_output_mode ,
json = = JsonOutputPointType : : transformpass ,
json = = JsonOutputPointType : : computingpass ) ;
2017-02-20 12:18:11 +01:00
2018-07-18 17:28:05 +02:00
if ( json = = JsonOutputPointType : : parsing | | json = = JsonOutputPointType : : checkpass )
2017-02-20 12:18:11 +01:00
symbol_table . unfreeze ( ) ;
2018-07-18 17:28:05 +02:00
if ( json = = JsonOutputPointType : : computingpass )
2017-06-29 12:42:28 +02:00
writeJsonComputingPassOutput ( basename , json_output_mode , jsonderivsimple ) ;
2017-02-20 12:18:11 +01:00
2018-07-18 17:28:05 +02:00
if ( json_output_mode = = JsonFileOutputType : : standardout )
2023-11-30 15:28:57 +01:00
cout < < " } " < < endl < < " //-- END JSON --// " < < endl ;
2017-02-20 12:18:11 +01:00
2018-12-20 17:04:28 +01:00
switch ( json )
{
case JsonOutputPointType : : parsing :
cout < < " JSON written after Parsing step. " < < endl ;
break ;
case JsonOutputPointType : : checkpass :
cout < < " JSON written after Check step. " < < endl ;
break ;
case JsonOutputPointType : : transformpass :
cout < < " JSON written after Transform step. " < < endl ;
break ;
case JsonOutputPointType : : computingpass :
cout < < " JSON written after Computing step. " < < endl ;
break ;
case JsonOutputPointType : : nojson :
cerr < < " ModFile::writeJsonOutput: should not arrive here. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2017-02-28 14:34:22 +01:00
if ( onlyjson )
exit ( EXIT_SUCCESS ) ;
2017-02-20 12:18:11 +01:00
}
void
2023-11-30 15:28:57 +01:00
ModFile : : writeJsonOutputParsingCheck ( const string & basename , JsonFileOutputType json_output_mode ,
bool transformpass , bool computingpass ) const
2017-02-02 15:09:43 +01:00
{
ostringstream output ;
output < < " { " < < endl ;
symbol_table . writeJsonOutput ( output ) ;
2017-02-27 15:40:34 +01:00
output < < " , " ;
2017-02-02 15:09:43 +01:00
dynamic_model . writeJsonOutput ( output ) ;
2022-09-14 17:07:08 +02:00
output < < " , " ;
static_model . writeJsonOutput ( output ) ;
2017-02-02 15:09:43 +01:00
2023-11-30 15:28:57 +01:00
if ( ! statements . empty ( ) | | ! var_model_table . empty ( ) | | ! trend_component_model_table . empty ( ) )
2017-02-02 15:09:43 +01:00
{
2019-04-03 16:32:52 +02:00
output < < R " (, " statements " : [) " ;
2018-08-21 11:46:59 +02:00
if ( ! var_model_table . empty ( ) )
{
var_model_table . writeJsonOutput ( output ) ;
2019-12-20 16:59:30 +01:00
output < < " , " ;
2018-08-21 11:46:59 +02:00
}
2018-08-22 09:15:00 +02:00
if ( ! trend_component_model_table . empty ( ) )
{
trend_component_model_table . writeJsonOutput ( output ) ;
output < < " , " ;
}
2022-01-20 16:15:43 +01:00
if ( ! var_expectation_model_table . empty ( ) )
{
var_expectation_model_table . writeJsonOutput ( output ) ;
output < < " , " ;
}
2021-10-27 16:26:52 +02:00
if ( ! pac_model_table . empty ( ) )
{
pac_model_table . writeJsonOutput ( output ) ;
output < < " , " ;
}
2023-11-30 15:28:57 +01:00
for ( bool printed_something { false } ; auto & it : statements )
2017-02-02 15:09:43 +01:00
{
2022-06-03 16:24:26 +02:00
if ( exchange ( printed_something , true ) )
2017-02-08 18:29:57 +01:00
output < < " , " < < endl ;
2022-06-03 16:24:26 +02:00
it - > writeJsonOutput ( output ) ;
2017-02-02 15:09:43 +01:00
}
output < < " ] " < < endl ;
}
2017-06-28 17:11:24 +02:00
if ( computingpass )
{
output < < " , " ;
dynamic_model . writeJsonDynamicModelInfo ( output ) ;
}
2023-12-18 10:57:06 +01:00
output < < R " (, " steady_state_model " : ) " < < mod_file_struct . steady_state_model_present < < endl ;
2017-02-02 15:09:43 +01:00
output < < " } " < < endl ;
2017-06-28 12:04:04 +02:00
ostringstream original_model_output ;
original_model_output < < " " ;
2017-06-29 13:15:32 +02:00
if ( transformpass | | computingpass )
2017-06-28 12:04:04 +02:00
{
original_model_output < < " { " ;
original_model . writeJsonOriginalModelOutput ( original_model_output ) ;
2019-03-06 11:43:23 +01:00
if ( ! statements . empty ( ) | | ! var_model_table . empty ( ) | | ! trend_component_model_table . empty ( ) )
{
2019-04-03 16:32:52 +02:00
original_model_output < < endl < < R " (, " statements " : [) " ;
2019-03-06 11:43:23 +01:00
if ( ! var_model_table . empty ( ) )
{
var_model_table . writeJsonOutput ( original_model_output ) ;
original_model_output < < " , " ;
}
if ( ! trend_component_model_table . empty ( ) )
{
trend_component_model_table . writeJsonOutput ( original_model_output ) ;
original_model_output < < " , " ;
}
2021-10-27 16:26:52 +02:00
if ( ! pac_model_table . empty ( ) )
{
pac_model_table . writeJsonOutput ( original_model_output ) ;
original_model_output < < " , " ;
}
2023-11-30 15:28:57 +01:00
for ( bool printed_something { false } ; const auto & it : statements )
2019-03-06 11:43:23 +01:00
{
2022-06-03 16:24:26 +02:00
original_model_output < < ( exchange ( printed_something , true ) ? " , " : " " ) < < endl ;
2019-03-06 11:43:23 +01:00
it - > writeJsonOutput ( original_model_output ) ;
}
original_model_output < < " ] " < < endl ;
}
2017-06-28 12:04:04 +02:00
original_model_output < < " } " < < endl ;
}
2017-10-16 17:24:55 +02:00
ostringstream steady_state_model_output ;
steady_state_model_output < < " " ;
if ( dynamic_model . equation_number ( ) > 0 )
steady_state_model . writeJsonSteadyStateFile ( steady_state_model_output ,
transformpass | | computingpass ) ;
2018-07-18 17:28:05 +02:00
if ( json_output_mode = = JsonFileOutputType : : standardout )
2017-06-28 12:04:04 +02:00
{
2017-06-29 13:15:32 +02:00
if ( transformpass | | computingpass )
2019-04-03 16:32:52 +02:00
cout < < R " ( " transformed_modfile " : ) " ;
2017-06-29 13:15:32 +02:00
else
2019-04-03 16:32:52 +02:00
cout < < R " ( " modfile " : ) " ;
2017-06-28 12:04:04 +02:00
cout < < output . str ( ) ;
if ( ! original_model_output . str ( ) . empty ( ) )
2019-04-03 16:32:52 +02:00
cout < < R " (, " original_model " : ) " < < original_model_output . str ( ) ;
2017-10-16 17:24:55 +02:00
if ( ! steady_state_model_output . str ( ) . empty ( ) )
2019-04-03 16:32:52 +02:00
cout < < R " (, " steady_state_model " : ) " < < steady_state_model_output . str ( ) ;
2017-06-28 12:04:04 +02:00
}
2017-02-02 15:09:43 +01:00
else
{
2022-07-11 16:09:07 +02:00
if ( ! basename . size ( ) )
2017-02-02 15:09:43 +01:00
{
2022-07-11 16:09:07 +02:00
cerr < < " ERROR: Missing file name " < < endl ;
exit ( EXIT_FAILURE ) ;
2017-02-02 15:09:43 +01:00
}
2022-07-11 16:09:07 +02:00
filesystem : : create_directories ( basename + " /model/json " ) ;
2023-01-05 16:40:04 +01:00
const filesystem : : path fname { basename + " /model/json/modfile.json " } ;
2023-11-30 15:28:57 +01:00
ofstream jsonOutputFile { fname , ios : : out | ios : : binary } ;
2022-07-11 16:09:07 +02:00
if ( ! jsonOutputFile . is_open ( ) )
2017-06-14 07:01:31 +02:00
{
2023-01-05 16:40:04 +01:00
cerr < < " ERROR: Can't open file " < < fname . string ( ) < < " for writing " < < endl ;
2017-06-14 07:01:31 +02:00
exit ( EXIT_FAILURE ) ;
}
2017-02-02 15:09:43 +01:00
jsonOutputFile < < output . str ( ) ;
jsonOutputFile . close ( ) ;
2017-06-28 12:04:04 +02:00
if ( ! original_model_output . str ( ) . empty ( ) )
{
if ( basename . size ( ) )
{
2023-01-05 16:40:04 +01:00
const filesystem : : path fname { basename + " /model/json/modfile-original.json " } ;
2018-06-27 15:12:12 +02:00
jsonOutputFile . open ( fname , ios : : out | ios : : binary ) ;
2017-06-28 12:04:04 +02:00
if ( ! jsonOutputFile . is_open ( ) )
{
2023-01-05 16:40:04 +01:00
cerr < < " ERROR: Can't open file " < < fname . string ( ) < < " for writing " < < endl ;
2017-06-28 12:04:04 +02:00
exit ( EXIT_FAILURE ) ;
}
}
else
{
cerr < < " ERROR: Missing file name " < < endl ;
exit ( EXIT_FAILURE ) ;
}
jsonOutputFile < < original_model_output . str ( ) ;
jsonOutputFile . close ( ) ;
}
2017-10-16 17:24:55 +02:00
if ( ! steady_state_model_output . str ( ) . empty ( ) )
{
if ( basename . size ( ) )
{
2023-01-05 16:40:04 +01:00
const filesystem : : path fname { basename + " /model/json/steady_state_model.json " } ;
2018-06-27 15:12:12 +02:00
jsonOutputFile . open ( fname , ios : : out | ios : : binary ) ;
2017-10-16 17:24:55 +02:00
if ( ! jsonOutputFile . is_open ( ) )
{
2023-01-05 16:40:04 +01:00
cerr < < " ERROR: Can't open file " < < fname . string ( ) < < " for writing " < < endl ;
2017-10-16 17:24:55 +02:00
exit ( EXIT_FAILURE ) ;
}
}
else
{
cerr < < " ERROR: Missing file name " < < endl ;
exit ( EXIT_FAILURE ) ;
}
jsonOutputFile < < steady_state_model_output . str ( ) ;
jsonOutputFile . close ( ) ;
}
2017-02-02 15:09:43 +01:00
}
}
2017-02-20 12:18:11 +01:00
void
2023-11-30 15:28:57 +01:00
ModFile : : writeJsonComputingPassOutput ( const string & basename , JsonFileOutputType json_output_mode ,
bool jsonderivsimple ) const
2017-02-20 12:18:11 +01:00
{
2018-07-18 17:28:05 +02:00
if ( basename . empty ( ) & & json_output_mode ! = JsonFileOutputType : : standardout )
2017-06-29 15:03:31 +02:00
{
cerr < < " ERROR: Missing file name " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2023-11-30 15:28:57 +01:00
ostringstream tmp_out , static_output , dynamic_output , static_paramsd_output ,
dynamic_paramsd_output ;
2017-06-29 15:03:31 +02:00
2017-02-20 12:18:11 +01:00
static_output < < " { " ;
2017-06-29 15:03:31 +02:00
static_model . writeJsonComputingPassOutput ( static_output , ! jsonderivsimple ) ;
static_output < < " } " ;
2017-02-20 12:18:11 +01:00
dynamic_output < < " { " ;
2017-06-29 15:03:31 +02:00
dynamic_model . writeJsonComputingPassOutput ( dynamic_output , ! jsonderivsimple ) ;
dynamic_output < < " } " ;
2017-02-20 12:18:11 +01:00
2022-07-12 17:47:02 +02:00
static_model . writeJsonParamsDerivatives ( tmp_out , ! jsonderivsimple ) ;
2017-02-20 12:18:11 +01:00
if ( ! tmp_out . str ( ) . empty ( ) )
static_paramsd_output < < " { " < < tmp_out . str ( ) < < " } " < < endl ;
2017-06-29 15:03:31 +02:00
tmp_out . str ( " " ) ;
2022-07-12 17:47:02 +02:00
dynamic_model . writeJsonParamsDerivatives ( tmp_out , ! jsonderivsimple ) ;
2017-06-29 15:03:31 +02:00
if ( ! tmp_out . str ( ) . empty ( ) )
dynamic_paramsd_output < < " { " < < tmp_out . str ( ) < < " } " < < endl ;
2017-03-02 18:34:18 +01:00
2018-07-18 17:28:05 +02:00
if ( json_output_mode = = JsonFileOutputType : : standardout )
2017-02-20 12:18:11 +01:00
{
2019-04-03 16:32:52 +02:00
cout < < R " (, " static_model " : ) " < < static_output . str ( ) < < endl
< < R " (, " dynamic_model " : ) " < < dynamic_output . str ( ) < < endl ;
2017-03-02 18:34:18 +01:00
2017-02-20 12:18:11 +01:00
if ( ! static_paramsd_output . str ( ) . empty ( ) )
2019-04-03 16:32:52 +02:00
cout < < R " (, " static_params_deriv " : ) " < < static_paramsd_output . str ( ) < < endl ;
2017-03-02 18:34:18 +01:00
if ( ! dynamic_paramsd_output . str ( ) . empty ( ) )
2019-04-03 16:32:52 +02:00
cout < < R " (, " dynamic_params_deriv " : ) " < < dynamic_paramsd_output . str ( ) < < endl ;
2017-02-20 12:18:11 +01:00
}
else
{
2019-04-04 17:01:37 +02:00
filesystem : : create_directories ( basename + " /model/json " ) ;
2017-02-20 12:18:11 +01:00
2018-06-27 16:08:31 +02:00
writeJsonFileHelper ( basename + " /model/json/static.json " , static_output ) ;
writeJsonFileHelper ( basename + " /model/json/dynamic.json " , dynamic_output ) ;
2017-02-20 12:18:11 +01:00
if ( ! static_paramsd_output . str ( ) . empty ( ) )
2023-11-30 15:28:57 +01:00
writeJsonFileHelper ( basename + " /model/json/static_params_derivs.json " ,
static_paramsd_output ) ;
2017-02-20 12:18:11 +01:00
if ( ! dynamic_paramsd_output . str ( ) . empty ( ) )
2018-06-27 16:08:31 +02:00
writeJsonFileHelper ( basename + " /model/json/params_derivs.json " , dynamic_paramsd_output ) ;
2017-02-20 12:18:11 +01:00
}
}
2017-03-02 18:34:18 +01:00
void
2023-11-30 15:28:57 +01:00
ModFile : : writeJsonFileHelper ( const filesystem : : path & fname , ostringstream & output ) const
2017-03-02 18:34:18 +01:00
{
2023-11-30 15:28:57 +01:00
ofstream jsonOutput { fname , ios : : out | ios : : binary } ;
2017-03-02 18:34:18 +01:00
if ( ! jsonOutput . is_open ( ) )
{
2023-01-05 16:40:04 +01:00
cerr < < " ERROR: Can't open file " < < fname . string ( ) < < " for writing " < < endl ;
2017-03-02 18:34:18 +01:00
exit ( EXIT_FAILURE ) ;
}
jsonOutput < < output . str ( ) ;
jsonOutput . close ( ) ;
}
2019-04-04 17:01:37 +02:00
filesystem : : path
ModFile : : unique_path ( )
{
filesystem : : path path ;
string possible_characters = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz " ;
random_device rd ;
mt19937 generator ( rd ( ) ) ;
2023-11-30 15:28:57 +01:00
uniform_int_distribution distribution { 0 , static_cast < int > ( possible_characters . size ( ) ) - 1 } ;
2019-04-04 17:01:37 +02:00
do
{
constexpr int rand_length = 10 ;
string rand_str ( rand_length , ' \0 ' ) ;
2023-11-30 15:28:57 +01:00
for ( auto & dis : rand_str )
2019-04-04 17:01:37 +02:00
dis = possible_characters [ distribution ( generator ) ] ;
2019-09-11 17:03:37 +02:00
path = rand_str ;
2019-04-04 17:01:37 +02:00
}
2022-10-11 11:23:26 +02:00
while ( exists ( path ) ) ;
2019-04-04 17:01:37 +02:00
return path ;
}