2009-04-14 16:39:53 +02:00
/*
2022-01-06 14:54:57 +01:00
* Copyright © 2003 - 2022 Dynare Team
2009-04-14 16:39:53 +02: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/>.
2009-04-14 16:39:53 +02:00
*/
# ifndef _DYNAMICMODEL_HH
# define _DYNAMICMODEL_HH
2009-07-06 12:36:36 +02:00
# include <fstream>
2019-04-04 17:01:37 +02:00
# include <filesystem>
2018-10-26 11:44:26 +02:00
2009-04-14 16:39:53 +02:00
# include "StaticModel.hh"
2022-06-23 14:28:13 +02:00
# include "Bytecode.hh"
2009-04-14 16:39:53 +02:00
2022-01-06 14:54:57 +01:00
using namespace std ;
2009-04-14 16:39:53 +02:00
//! Stores a dynamic model
class DynamicModel : public ModelTree
{
2018-09-14 17:04:06 +02:00
public :
//! A reference to the trend component model table
TrendComponentModelTable & trend_component_model_table ;
//! A reference to the VAR model table
VarModelTable & var_model_table ;
2019-11-14 17:51:16 +01:00
/* Used in the balanced growth test, for determining whether the
cross - derivative of a given equation , w . r . t . an endogenous and a trend
variable is zero . Controlled by option “ balanced_growth_test_tol ” of the
“ model ” block . The default should not be too small ( see dynare # 1389 ) . */
double balanced_growth_test_tol { 1e-6 } ;
2009-04-14 16:39:53 +02:00
private :
2019-11-14 17:51:16 +01:00
/* Used in the balanced growth test, for skipping equations where the test
cannot be performed ( i . e . when LHS = RHS at the initial values ) . Should not
be too large , otherwise the test becomes less powerful . */
2018-07-17 16:32:00 +02:00
constexpr static double zero_band { 1e-8 } ;
2013-04-11 17:07:39 +02:00
//! Stores equations declared as [static]
2018-10-10 17:08:54 +02:00
/*! They will be used in the conversion to StaticModel to replace equations marked as [dynamic] */
2013-04-11 17:07:39 +02:00
vector < BinaryOpNode * > static_only_equations ;
2014-01-27 16:41:43 +01:00
//! Stores line numbers of equations declared as [static]
2022-05-05 18:39:27 +02:00
vector < optional < int > > static_only_equations_lineno ;
2014-01-27 16:41:43 +01:00
2017-08-24 15:35:10 +02:00
//! Stores the equation tags of equations declared as [static]
2020-02-20 15:29:10 +01:00
EquationTags static_only_equations_equation_tags ;
2019-11-18 17:13:49 +01:00
2018-06-04 14:31:26 +02:00
using deriv_id_table_t = map < pair < int , int > , int > ;
2009-04-17 18:26:23 +02:00
//! Maps a pair (symbol_id, lag) to a deriv ID
deriv_id_table_t deriv_id_table ;
//! Maps a deriv ID to a pair (symbol_id, lag)
2018-06-04 14:17:36 +02:00
vector < pair < int , int > > inv_deriv_id_table ;
2009-04-17 18:26:23 +02:00
2022-09-14 17:07:08 +02:00
/* Maps a deriv_id to the column index of the dynamic Jacobian, in the legacy
representation .
Contains only endogenous , exogenous and exogenous deterministic */
2009-04-17 18:26:23 +02:00
map < int , int > dyn_jacobian_cols_table ;
//! Maximum lag and lead over all types of variables (positive values)
2009-09-30 17:10:31 +02:00
/*! Set by computeDerivIDs() */
2018-10-04 17:18:27 +02:00
int max_lag { 0 } , max_lead { 0 } ;
2009-04-17 18:26:23 +02:00
//! Maximum lag and lead over endogenous variables (positive values)
2009-09-30 17:10:31 +02:00
/*! Set by computeDerivIDs() */
2018-10-04 17:18:27 +02:00
int max_endo_lag { 0 } , max_endo_lead { 0 } ;
2009-04-17 18:26:23 +02:00
//! Maximum lag and lead over exogenous variables (positive values)
2009-09-30 17:10:31 +02:00
/*! Set by computeDerivIDs() */
2018-10-04 17:18:27 +02:00
int max_exo_lag { 0 } , max_exo_lead { 0 } ;
2009-04-17 18:26:23 +02:00
//! Maximum lag and lead over deterministic exogenous variables (positive values)
2009-09-30 17:10:31 +02:00
/*! Set by computeDerivIDs() */
2018-10-04 17:18:27 +02:00
int max_exo_det_lag { 0 } , max_exo_det_lead { 0 } ;
2017-07-27 18:33:19 +02:00
//! Maximum lag and lead over all types of variables (positive values) of original model
2018-12-11 17:26:50 +01:00
int max_lag_orig { 0 } , max_lead_orig { 0 } , max_lag_with_diffs_expanded_orig { 0 } ;
2017-07-27 18:33:19 +02:00
//! Maximum lag and lead over endogenous variables (positive values) of original model
2018-10-04 17:18:27 +02:00
int max_endo_lag_orig { 0 } , max_endo_lead_orig { 0 } ;
2017-07-27 18:33:19 +02:00
//! Maximum lag and lead over exogenous variables (positive values) of original model
2018-10-04 17:18:27 +02:00
int max_exo_lag_orig { 0 } , max_exo_lead_orig { 0 } ;
2017-07-27 18:33:19 +02:00
//! Maximum lag and lead over deterministic exogenous variables (positive values) of original model
2018-10-04 17:18:27 +02:00
int max_exo_det_lag_orig { 0 } , max_exo_det_lead_orig { 0 } ;
2009-04-17 18:26:23 +02:00
2022-06-01 21:55:08 +02:00
// Cross reference information: eq → set of (symb_id, lag) for each symbol type
2017-03-06 16:34:08 +01:00
map < int , ExprNode : : EquationInfo > xrefs ;
2022-06-01 21:55:08 +02:00
// Reverse cross reference information: (symb_id, lag) → eqs
map < pair < int , int > , set < int > > xref_param , xref_endo , xref_exo , xref_exo_det ;
2017-03-06 16:34:08 +01:00
2018-01-11 12:55:36 +01:00
//! Nonzero equations in the Hessian
2019-12-13 17:15:03 +01:00
set < int > nonzero_hessian_eqs ;
2018-01-11 12:55:36 +01:00
2019-10-16 17:34:27 +02:00
//! Creates mapping for variables and equations they are present in
map < int , set < int > > variableMapping ;
2020-04-30 16:00:16 +02:00
/* Derivatives of block equations with respect to: endogenous that do not
belong to the block , exogenous , deterministic exogenous .
Tuples are of the form ( equation no . within the block , type - specific ID , lag ) */
vector < map < tuple < int , int , int > , expr_t > > blocks_derivatives_other_endo ,
blocks_derivatives_exo , blocks_derivatives_exo_det ;
2020-05-06 14:02:58 +02:00
// For each block, gives type-specific other endos / exo / exo det that appear in it
vector < set < int > > blocks_other_endo , blocks_exo , blocks_exo_det ;
/* For each block, and for each variable type, maps (variable ID, lag) to
Jacobian column .
For the “ endo ” version , the variable ID is the index within the block . For
the three others , it ’ s the type - specific ID */
vector < map < pair < int , int > , int > > blocks_jacob_cols_endo , blocks_jacob_cols_other_endo , blocks_jacob_cols_exo , blocks_jacob_cols_exo_det ;
2021-07-21 12:26:46 +02:00
//! Used for var_expectation and var_model
map < string , set < int > > var_expectation_functions_to_write ;
2009-04-14 16:39:53 +02:00
//! Writes dynamic model file (Matlab version)
2018-06-27 15:01:31 +02:00
void writeDynamicMFile ( const string & basename ) const ;
2020-05-19 16:56:53 +02:00
//! Writes the main dynamic function of block decomposed model (MATLAB version)
void writeDynamicBlockMFile ( const string & basename ) const ;
2022-10-05 15:59:32 +02:00
/* Writes the main dynamic functions of block decomposed model (C version),
then compiles it with the per - block functions into a single MEX */
2022-10-05 18:34:21 +02:00
void writeDynamicBlockCFile ( const string & basename , vector < filesystem : : path > per_block_object_files , const string & mexext , const filesystem : : path & matlabroot , const filesystem : : path & dynareroot ) const ;
2020-06-23 15:13:04 +02:00
/* Computes the number of nonzero elements in deterministic Jacobian of
block - decomposed model */
int nzeDeterministicJacobianForBlock ( int blk ) const ;
2022-09-28 19:18:15 +02:00
// Helper for writing the per-block dynamic files of block decomposed models (legacy representation)
2022-07-12 14:13:27 +02:00
template < ExprNodeOutputType output_type >
void writeDynamicPerBlockHelper ( int blk , ostream & output , temporary_terms_t & temporary_terms , int nze_stochastic , int nze_deterministic , int nze_exo , int nze_exo_det , int nze_other_endo ) const ;
2020-05-19 16:56:53 +02:00
//! Writes the per-block dynamic files of block decomposed model (MATLAB version)
void writeDynamicPerBlockMFiles ( const string & basename ) const ;
2022-10-05 18:34:21 +02:00
/* Writes and compiles the per-block dynamic files of block decomposed model
( C version ) . Returns the list of paths to the compiled object files . */
vector < filesystem : : path > writeDynamicPerBlockCFiles ( const string & basename , const string & mexext , const filesystem : : path & matlabroot , const filesystem : : path & dynareroot ) const ;
2020-05-19 17:43:35 +02:00
//! Writes the code of the block-decomposed model in virtual machine bytecode
2021-01-25 18:03:37 +01:00
void writeDynamicBlockBytecode ( const string & basename ) const ;
2022-07-19 18:24:36 +02:00
// Writes derivatives w.r.t. exo, exo det and other endogenous
void writeBlockBytecodeAdditionalDerivatives ( BytecodeWriter & code_file , int block ,
const temporary_terms_t & temporary_terms_union ,
const deriv_node_temp_terms_t & tef_terms ) const override ;
2010-01-22 11:03:29 +01:00
//! Writes the code of the model in virtual machine bytecode
2020-05-19 17:43:35 +02:00
void writeDynamicBytecode ( const string & basename ) const ;
2010-01-22 11:03:29 +01:00
2019-12-16 19:42:59 +01:00
void writeSetAuxiliaryVariables ( const string & basename , bool julia ) const ;
2018-03-02 17:50:35 +01:00
void writeAuxVarRecursiveDefinitions ( ostream & output , ExprNodeOutputType output_type ) const ;
2020-05-20 11:35:14 +02:00
// Write the block structure of the model in the driver file
2021-04-19 14:51:34 +02:00
void writeBlockDriverOutput ( ostream & output , const string & basename ,
2020-05-20 11:35:14 +02:00
const vector < int > & state_var , bool estimation_present ) const ;
2020-04-24 12:29:02 +02:00
// Used by determineBlockDerivativesType()
enum class BlockDerivativeType
{
standard ,
chainRule ,
normalizedChainRule
} ;
/* For each tuple (lag, eq, var) within the given block, determine the type
of the derivative to be computed . Indices are within the block ( i . e .
between 0 and blocks [ blk ] . size - 1 ) . */
map < tuple < int , int , int > , BlockDerivativeType > determineBlockDerivativesType ( int blk ) ;
2022-09-28 16:31:51 +02:00
void computeChainRuleJacobian ( ) override ;
2009-12-16 14:21:31 +01:00
2019-12-16 19:42:59 +01:00
string reform ( const string & name ) const ;
2009-04-14 16:39:53 +02:00
2020-05-06 17:13:47 +02:00
void additionalBlockTemporaryTerms ( int blk ,
2020-05-13 16:58:19 +02:00
vector < vector < temporary_terms_t > > & blocks_temporary_terms ,
map < expr_t , tuple < int , int , int > > & reference_count ) const override ;
2010-01-22 11:03:29 +01:00
2018-06-04 12:53:26 +02:00
SymbolType getTypeByDerivID ( int deriv_id ) const noexcept ( false ) override ;
int getLagByDerivID ( int deriv_id ) const noexcept ( false ) override ;
int getSymbIDByDerivID ( int deriv_id ) const noexcept ( false ) override ;
2022-07-12 15:28:52 +02:00
int getTypeSpecificIDByDerivID ( int deriv_id ) const override ;
2009-04-17 18:26:23 +02:00
//! Compute the column indices of the dynamic Jacobian
2022-10-07 14:37:25 +02:00
void computeDynJacobianCols ( ) ;
2010-10-15 19:05:16 +02:00
//! Computes derivatives of the Jacobian w.r. to trend vars and tests that they are equal to zero
void testTrendDerivativesEqualToZero ( const eval_context_t & eval_context ) ;
2009-05-13 01:03:40 +02:00
2009-09-30 17:10:31 +02:00
//! Allocates the derivation IDs for all dynamic variables of the model
/*! Also computes max_{endo,exo}_{lead_lag}, and initializes dynJacobianColsNbr to the number of dynamic endos */
void computeDerivIDs ( ) ;
2020-05-06 14:02:58 +02:00
/* Compute the Jacobian column indices in the block decomposition case
( stored in blocks_jacob_cols_ * ) .
Also fills auxiliary structures related to “ other ” endogenous and
exogenous : blocks { , _derivatives } _ { other_endo , exo_exo_det } */
void computeBlockDynJacobianCols ( ) ;
2009-12-16 14:21:31 +01:00
2009-10-07 16:07:13 +02:00
//! Factorized code for substitutions of leads/lags
2013-05-17 16:51:34 +02:00
/*! \param[in] type determines which type of variables is concerned
\ param [ in ] deterministic_model whether we are in a deterministic model ( only for exogenous leads / lags )
\ param [ in ] subset variables to which to apply the transformation ( only for diff of forward vars )
*/
2018-12-20 17:04:28 +01:00
void substituteLeadLagInternal ( AuxVarType type , bool deterministic_model , const vector < string > & subset ) ;
2009-07-10 17:37:51 +02:00
2017-03-06 16:34:08 +01:00
//! Help computeXrefs to compute the reverse references (i.e. param->eqs, endo->eqs, etc)
2018-06-04 14:17:36 +02:00
void computeRevXref ( map < pair < int , int > , set < int > > & xrefset , const set < pair < int , int > > & eiref , int eqn ) ;
2017-03-06 16:34:08 +01:00
//! Write reverse cross references
2018-06-04 14:17:36 +02:00
void writeRevXrefs ( ostream & output , const map < pair < int , int > , set < int > > & xrefmap , const string & type ) const ;
2017-03-06 16:34:08 +01:00
2022-07-12 17:04:41 +02:00
// Writes MATLAB/Octave wrapper function for computing residuals and derivatives at the same time
void writeDynamicMWrapperFunction ( const string & name , const string & ending ) const ;
// Helper for writing MATLAB/Octave functions for residuals/derivatives and their temporary terms
void writeDynamicMFileHelper ( const string & basename ,
2018-06-27 15:01:31 +02:00
const string & name , const string & retvalname ,
2018-03-27 17:14:30 +02:00
const string & name_tt , size_t ttlen ,
const string & previous_tt_name ,
2022-07-12 17:04:41 +02:00
const ostringstream & init_s , const ostringstream & end_s ,
2018-03-27 17:14:30 +02:00
const ostringstream & s , const ostringstream & s_tt ) const ;
2022-07-12 17:04:41 +02:00
//! Create a legacy *_dynamic.m file for MATLAB/Octave not yet using the temporary terms array interface
void writeDynamicMCompatFile ( const string & basename ) const ;
2018-05-23 16:10:26 +02:00
2018-10-09 18:27:19 +02:00
//! Internal helper for the copy constructor and assignment operator
/*! Copies all the structures that contain ExprNode*, by the converting the
pointers into their equivalent in the new tree */
void copyHelper ( const DynamicModel & m ) ;
2021-12-14 17:24:14 +01:00
/* Handles parsing of argument passed to exclude_eqs/include_eqs.
The argument inc_exc_option_value should be of one of the following forms :
2019-11-18 17:13:49 +01:00
* filename . txt
* eq1
* [ ' eq 1 ' , ' eq 2 ' ]
* [ tagname = ' eq 1 ' ]
* [ tagname = ( ' eq 1 ' , ' eq 2 ' ) ]
2021-12-14 17:24:14 +01:00
If argument is a filename , the file should be formatted as :
2019-11-18 17:13:49 +01:00
eq 1
eq 2
OR
tagname =
X
Y
2021-12-14 17:24:14 +01:00
The boolean exclude_eqs should be true if we are in the exclude_eqs case ,
false in the include_eqs case ( this only affects error messages ) .
Returns a set of pairs ( tag name , tag value ) corresponding to the set of
equations to be included or excluded .
*/
static vector < pair < string , string > > parseIncludeExcludeEquations ( const string & inc_exc_option_value , bool exclude_eqs ) ;
/* Helper for the removeEquations() method.
listed_eqs_by_tag is the list of ( tag name , tag value ) pairs corresponding
to the option value , exclude_eqs is a boolean indicating whether we ’ re
excluding or including , and excluded_vars_change_type is a boolean
indicating whether to compute variables to be excluded .
The all_equations * arguments will be modified by the routine by excluding
equations . They are either the main structures for storing equations in
ModelTree , or their counterpart for static - only equations . The
static_equations boolean indicates when we are in the latter case .
The listed_eqs_by_tag structure will be updated by removing those tag
pairs that have been matched with equations in the all_equations *
argument * .
Returns a list of excluded variables ( empty if
excluded_vars_change_type = false ) */
vector < int > removeEquationsHelper ( set < pair < string , string > > & listed_eqs_by_tag ,
bool exclude_eqs , bool excluded_vars_change_type ,
vector < BinaryOpNode * > & all_equations ,
2022-05-05 18:39:27 +02:00
vector < optional < int > > & all_equations_lineno ,
2021-12-14 17:24:14 +01:00
EquationTags & all_equation_tags ,
bool static_equations ) const ;
2019-11-18 17:13:49 +01:00
2021-07-07 10:54:04 +02:00
//! Compute autoregressive matrices of trend component models
/* The algorithm uses matching rules over expression trees. It cannot handle
arbitrarily - written expressions . */
map < string , map < tuple < int , int , int > , expr_t > > computeAutoregressiveMatrices ( ) const ;
2021-07-01 16:16:04 +02:00
//! Compute error component matrices of trend component_models
/*! Returns a pair (A0r, A0starr) */
2022-01-28 16:38:50 +01:00
pair < map < string , map < tuple < int , int > , expr_t > > , map < string , map < tuple < int , int > , expr_t > > > computeErrorComponentMatrices ( const ExprNode : : subst_table_t & diff_subst_table ) const ;
2021-07-01 16:16:04 +02:00
2021-07-07 10:54:04 +02:00
/* For a VAR model, given the symbol ID of a LHS variable, and a (negative)
lag , returns all the corresponding deriv_ids ( by properly dealing with two
types of auxiliary variables : endo lags and diff lags ) . It returns a
vector because in some cases there may be sereval corresponding deriv_ids
( for example , in the deriv_id table , AUX_DIFF_nn ( - 1 ) may appear as itself
( with a lag ) , and also as a contemporaneous diff lag auxvar ) . */
vector < int > getVARDerivIDs ( int lhs_symb_id , int lead_lag ) const ;
2022-07-19 18:24:36 +02:00
int
getBlockJacobianEndoCol ( int blk , int var , int lag ) const override
{
return blocks_jacob_cols_endo [ blk ] . at ( { var , lag } ) ;
}
2022-09-14 17:48:33 +02:00
protected :
string
modelClassName ( ) const override
{
return " dynamic model " ;
}
2009-04-14 16:39:53 +02:00
public :
2018-08-21 11:46:59 +02:00
DynamicModel ( SymbolTable & symbol_table_arg ,
NumericalConstants & num_constants_arg ,
ExternalFunctionsTable & external_functions_table_arg ,
TrendComponentModelTable & trend_component_model_table_arg ,
VarModelTable & var_model_table_arg ) ;
2018-10-09 18:27:19 +02:00
DynamicModel ( const DynamicModel & m ) ;
2019-12-20 16:59:30 +01:00
DynamicModel & operator = ( const DynamicModel & m ) ;
2017-03-06 16:34:08 +01:00
//! Compute cross references
void computeXrefs ( ) ;
//! Write cross references
void writeXrefs ( ostream & output ) const ;
2022-09-13 15:43:13 +02:00
//! Execute computations (variable sorting + derivation + block decomposition)
2009-04-20 12:48:54 +02:00
/*!
2018-11-22 14:32:40 +01:00
\ param derivsOrder order of derivatives w . r . to exo , exo_det and endo should be computed ( implies jacobianExo = true when order > = 2 )
2016-05-18 12:26:19 +02:00
\ param paramsDerivsOrder order of derivatives w . r . to a pair ( endo / exo / exo_det , parameter ) to be computed ( > 0 implies jacobianExo = true )
2009-04-20 12:48:54 +02:00
\ param eval_context evaluation context for normalization
\ param no_tmp_terms if true , no temporary terms will be computed in the dynamic files
*/
2022-10-07 14:37:25 +02:00
void computingPass ( int derivsOrder , int paramsDerivsOrder , const eval_context_t & eval_context ,
bool no_tmp_terms , bool block , bool use_dll ) ;
2020-05-20 11:44:40 +02:00
//! Writes information about the dynamic model to the driver file
2022-09-28 16:54:03 +02:00
void writeDriverOutput ( ostream & output , const string & basename , bool estimation_present , bool compute_xrefs ) const ;
2009-09-02 15:36:56 +02:00
2018-09-18 14:50:31 +02:00
//! Write JSON AST
void writeJsonAST ( ostream & output ) const ;
2019-10-16 17:34:27 +02:00
//! Write JSON variable mapping
void writeJsonVariableMapping ( ostream & output ) const ;
2017-02-02 15:09:43 +01:00
//! Write JSON Output
void writeJsonOutput ( ostream & output ) const ;
2017-06-23 14:20:48 +02:00
//! Write JSON Output representation of original dynamic model
void writeJsonOriginalModelOutput ( ostream & output ) const ;
2017-06-28 17:11:24 +02:00
//! Write JSON Output representation of model info (useful stuff from M_)
void writeJsonDynamicModelInfo ( ostream & output ) const ;
2017-02-20 12:18:11 +01:00
//! Write JSON Output representation of dynamic model after computing pass
2017-03-02 18:34:18 +01:00
void writeJsonComputingPassOutput ( ostream & output , bool writeDetails ) const ;
2017-02-20 12:18:11 +01:00
2022-07-12 17:47:02 +02:00
//! Write JSON params derivatives
void writeJsonParamsDerivatives ( ostream & output , bool writeDetails ) const ;
2017-02-20 12:18:11 +01:00
2017-03-10 17:23:35 +01:00
//! Write cross reference output if the xref maps have been filed
void writeJsonXrefs ( ostream & output ) const ;
2022-06-01 21:57:04 +02:00
void writeJsonXrefsHelper ( ostream & output , const map < pair < int , int > , set < int > > & xrefmap ) const ;
2017-03-10 17:23:35 +01:00
2018-01-11 12:55:36 +01:00
//! Print equations that have non-zero second derivatives
void printNonZeroHessianEquations ( ostream & output ) const ;
2016-07-25 19:43:34 +02:00
2019-12-13 17:15:03 +01:00
//! Tells whether Hessian has been computed
/*! This is needed to know whether no non-zero equation in Hessian means a
2019-12-20 16:59:30 +01:00
zero Hessian or Hessian not computed */
2022-06-24 15:08:49 +02:00
bool
2019-12-20 16:59:30 +01:00
isHessianComputed ( ) const
2019-12-13 17:15:03 +01:00
{
2020-01-20 17:22:32 +01:00
return computed_derivs_order > = 2 ;
2019-12-13 17:15:03 +01:00
}
//! Returns equations that have non-zero second derivatives
2022-06-24 15:08:49 +02:00
set < int >
2019-12-20 16:59:30 +01:00
getNonZeroHessianEquations ( ) const
2019-12-13 17:15:03 +01:00
{
return nonzero_hessian_eqs ;
}
2016-07-27 21:01:54 +02:00
2021-07-01 16:16:04 +02:00
//! Fill the trend component model table with information available from the transformed model
2018-08-14 14:23:21 +02:00
void fillTrendComponentModelTable ( ) const ;
2021-07-01 16:16:04 +02:00
//! Fill the trend component model table with information available from the original model
2019-10-22 16:04:24 +02:00
void fillTrendComponentModelTableFromOrigModel ( ) const ;
2021-07-01 16:16:04 +02:00
/* Fill the trend component model table with information about AR/EC
components , available from the transformed model . Needs to be called after
fillTrendComponentModelTableFromOrigModel ( ) has been called on the
original model */
void fillTrendComponentModelTableAREC ( const ExprNode : : subst_table_t & diff_subst_table ) const ;
2018-02-08 13:07:15 +01:00
2021-07-01 16:16:04 +02:00
//! Fill the VAR model table with information available from the transformed model
2021-07-07 10:54:04 +02:00
// NB: Does not fill the AR and A0 matrices
2018-08-21 11:46:59 +02:00
void fillVarModelTable ( ) const ;
2021-07-01 16:16:04 +02:00
//! Fill the VAR model table with information available from the original model
2019-10-22 16:04:24 +02:00
void fillVarModelTableFromOrigModel ( ) const ;
2021-07-07 10:54:04 +02:00
//! Fill the AR and A0 matrices of the VAR model table
// Uses derivatives, hence must be called after computingPass()
void fillVarModelTableMatrices ( ) ;
2018-08-21 11:46:59 +02:00
2018-08-23 13:56:58 +02:00
//! Update the rhs references in the var model and trend component tables
2018-09-03 15:05:30 +02:00
//! after substitution of auxiliary variables and find the trend variables
//! in the trend_component model
void updateVarAndTrendModel ( ) const ;
2018-08-23 13:56:58 +02:00
2022-05-19 14:15:43 +02:00
//! Writes dynamic model file (+ bytecode)
void writeDynamicFile ( const string & basename , bool block , bool use_dll , const string & mexext , const filesystem : : path & matlabroot , const filesystem : : path & dynareroot , bool julia ) const ;
2022-07-12 12:27:22 +02:00
2009-04-20 15:58:15 +02:00
//! Writes file containing parameters derivatives
2022-07-12 12:27:22 +02:00
template < bool julia >
void writeParamsDerivativesFile ( const string & basename ) const ;
2014-05-09 10:02:05 +02:00
2019-05-03 19:24:55 +02:00
//! Writes file containing coordinates of non-zero elements in the Jacobian
2019-06-18 15:33:56 +02:00
/*! Used by the perfect_foresight_problem MEX */
2022-07-12 17:04:41 +02:00
void writeDynamicJacobianNonZeroEltsFile ( const string & basename ) const ;
2019-05-03 19:24:55 +02:00
2019-10-16 17:34:27 +02:00
//! Creates mapping for variables and equations they are present in
2021-11-23 12:35:43 +01:00
void createVariableMapping ( ) ;
2019-10-16 17:34:27 +02:00
//! Expands equation tags with default equation names (available "name" tag or LHS variable or equation ID)
void expandEqTags ( ) ;
2013-09-13 20:37:31 +02:00
//! Find endogenous variables not used in model
2013-11-29 15:32:49 +01:00
set < int > findUnusedEndogenous ( ) ;
2013-11-29 16:03:15 +01:00
//! Find exogenous variables not used in model
set < int > findUnusedExogenous ( ) ;
2013-09-13 20:37:31 +02:00
2017-07-27 18:33:19 +02:00
//! Set the max leads/lags of the original model
void setLeadsLagsOrig ( ) ;
2021-12-14 17:24:14 +01:00
//! Implements the include_eqs/exclude_eqs options
void includeExcludeEquations ( const string & inc_exc_option_value , bool exclude_eqs ) ;
/* Removes equations from the model (identified by their name tags).
Used for include_eqs / exclude_eqs options and for model_remove and
model_replace blocks */
void removeEquations ( const vector < pair < string , string > > & listed_eqs_by_tag , bool exclude_eqs ,
bool excluded_vars_change_type ) ;
2019-11-18 17:13:49 +01:00
2011-03-21 18:40:57 +01:00
//! Replaces model equations with derivatives of Lagrangian w.r.t. endogenous
2018-12-20 17:04:28 +01:00
void computeRamseyPolicyFOCs ( const StaticModel & static_model ) ;
2020-01-06 18:26:35 +01:00
//! Clears all equations
void clearEquations ( ) ;
2011-03-28 11:19:10 +02:00
//! Replaces the model equations in dynamic_model with those in this model
2011-03-21 18:40:57 +01:00
void replaceMyEquations ( DynamicModel & dynamic_model ) const ;
2013-04-11 17:07:39 +02:00
//! Adds an equation marked as [static]
2022-05-05 18:39:27 +02:00
void addStaticOnlyEquation ( expr_t eq , optional < int > lineno , const map < string , string > & eq_tags ) ;
2013-04-11 17:07:39 +02:00
//! Returns number of static only equations
size_t staticOnlyEquationsNbr ( ) const ;
2017-06-01 19:58:32 +02:00
2013-04-11 17:07:39 +02:00
//! Returns number of dynamic only equations
size_t dynamicOnlyEquationsNbr ( ) const ;
2021-07-20 18:18:24 +02:00
// Adds an occbin equation (with “bind” and/or “relax” tag)
/* This function assumes that there is a “name” tag, and that the relevant
auxiliary parameters have already been added to the symbol table .
It also assumes that the “ bind ” and “ relax ” tags have been cleared from
eq_tags . */
2022-05-05 18:39:27 +02:00
void addOccbinEquation ( expr_t eq , optional < int > lineno , const map < string , string > & eq_tags , const vector < string > & regimes_bind , const vector < string > & regimes_relax ) ;
2021-07-20 18:18:24 +02:00
2009-04-30 15:14:33 +02:00
//! Writes LaTeX file with the equations of the dynamic model
2019-12-16 19:42:59 +01:00
void writeLatexFile ( const string & basename , bool write_equation_tags ) const ;
2009-04-30 15:14:33 +02:00
2015-02-16 08:31:30 +01:00
//! Writes LaTeX file with the equations of the dynamic model (for the original model)
2019-12-16 19:42:59 +01:00
void writeLatexOriginalFile ( const string & basename , bool write_equation_tags ) const ;
2015-02-16 08:31:30 +01:00
2018-06-04 12:53:26 +02:00
int getDerivID ( int symb_id , int lag ) const noexcept ( false ) override ;
2022-07-11 17:33:09 +02:00
int
2022-09-14 17:07:08 +02:00
getJacobianCol ( int deriv_id , bool sparse ) const override
2022-07-11 17:33:09 +02:00
{
2022-09-14 17:07:08 +02:00
if ( sparse )
{
SymbolType type { getTypeByDerivID ( deriv_id ) } ;
int tsid { getTypeSpecificIDByDerivID ( deriv_id ) } ;
int lag { getLagByDerivID ( deriv_id ) } ;
if ( type = = SymbolType : : endogenous )
{
assert ( lag > = - 1 & & lag < = 1 ) ;
return tsid + ( lag + 1 ) * symbol_table . endo_nbr ( ) ;
}
else if ( type = = SymbolType : : exogenous )
{
assert ( lag = = 0 ) ;
return tsid + 3 * symbol_table . endo_nbr ( ) ;
}
else if ( type = = SymbolType : : exogenousDet )
{
assert ( lag = = 0 ) ;
return tsid + 3 * symbol_table . endo_nbr ( ) + symbol_table . exo_nbr ( ) ;
}
else
throw UnknownDerivIDException ( ) ;
}
2022-07-11 17:33:09 +02:00
else
2022-09-14 17:07:08 +02:00
{
if ( auto it = dyn_jacobian_cols_table . find ( deriv_id ) ;
it = = dyn_jacobian_cols_table . end ( ) )
throw UnknownDerivIDException ( ) ;
else
return it - > second ;
}
2022-07-11 17:33:09 +02:00
}
int
2022-09-14 17:07:08 +02:00
getJacobianColsNbr ( bool sparse ) const override
2022-07-11 17:33:09 +02:00
{
2022-09-14 17:07:08 +02:00
return sparse ?
3 * symbol_table . endo_nbr ( ) + symbol_table . exo_nbr ( ) + symbol_table . exo_det_nbr ( ) :
dyn_jacobian_cols_table . size ( ) ;
2022-07-11 17:33:09 +02:00
}
2018-06-04 12:53:26 +02:00
void addAllParamDerivId ( set < int > & deriv_id_set ) override ;
2009-12-16 14:21:31 +01:00
2009-09-10 22:09:16 +02:00
//! Returns true indicating that this is a dynamic model
2018-06-04 12:53:26 +02:00
bool
isDynamic ( ) const override
2009-12-16 18:13:23 +01:00
{
return true ;
} ;
2009-09-30 17:10:31 +02:00
2010-10-15 19:05:16 +02:00
//! Drive test of detrended equations
void runTrendTest ( const eval_context_t & eval_context ) ;
2009-10-07 16:07:13 +02:00
//! Transforms the model by removing all leads greater or equal than 2 on endos
2009-10-07 18:34:42 +02:00
/*! Note that this can create new lags on endos and exos */
2018-12-20 17:04:28 +01:00
void substituteEndoLeadGreaterThanTwo ( bool deterministic_model ) ;
2009-09-30 17:10:31 +02:00
2009-10-07 16:07:13 +02:00
//! Transforms the model by removing all lags greater or equal than 2 on endos
2018-12-20 17:04:28 +01:00
void substituteEndoLagGreaterThanTwo ( bool deterministic_model ) ;
2009-10-07 16:07:13 +02:00
2009-10-07 18:34:42 +02:00
//! Transforms the model by removing all leads on exos
/*! Note that this can create new lags on endos and exos */
2018-12-20 17:04:28 +01:00
void substituteExoLead ( bool deterministic_model ) ;
2009-10-07 18:34:42 +02:00
//! Transforms the model by removing all lags on exos
2018-12-20 17:04:28 +01:00
void substituteExoLag ( bool deterministic_model ) ;
2009-09-30 17:10:31 +02:00
2018-07-18 16:18:26 +02:00
//! Transforms the model by removing all UnaryOpcode::expectation
2018-12-20 17:04:28 +01:00
void substituteExpectation ( bool partial_information_model ) ;
2009-10-29 18:16:10 +01:00
2009-11-07 19:37:11 +01:00
//! Transforms the model by decreasing the lead/lag of predetermined variables in model equations by one
void transformPredeterminedVariables ( ) ;
2022-03-30 17:40:01 +02:00
// Performs the transformations associated to variables declared with “var(log)”
void substituteLogTransform ( ) ;
// Check that no variable was declared with “var(log)” in the given equations
void checkNoWithLogTransform ( const set < int > & eqnumbers ) ;
2010-10-15 19:05:16 +02:00
//! Transforms the model by removing trends specified by the user
void detrendEquations ( ) ;
2022-06-24 15:08:49 +02:00
const nonstationary_symbols_map_t &
2019-12-20 16:59:30 +01:00
getNonstationarySymbolsMap ( ) const
2019-12-04 15:48:33 +01:00
{
return nonstationary_symbols_map ;
}
2022-06-24 15:08:49 +02:00
const map < int , expr_t > &
2019-12-20 16:59:30 +01:00
getTrendSymbolsMap ( ) const
2019-12-04 15:48:33 +01:00
{
return trend_symbols_map ;
}
2018-01-30 10:06:56 +01:00
//! Substitutes adl operator
void substituteAdl ( ) ;
2020-11-10 18:04:05 +01:00
//! Substitutes out all model-local variables
void substituteModelLocalVariables ( ) ;
2022-01-19 15:53:45 +01:00
/* Creates aux vars for all unary operators in all equations. Also makes the
2022-01-20 16:15:43 +01:00
substitution in growth terms of pac_model / pac_target_info and in
expressions of var_expectation_model . */
pair < lag_equivalence_table_t , ExprNode : : subst_table_t > substituteUnaryOps ( VarExpectationModelTable & var_expectation_model_table , PacModelTable & pac_model_table ) ;
2018-06-07 12:53:00 +02:00
2022-01-19 15:53:45 +01:00
/* Creates aux vars for all unary operators in specified equations. Also makes the
2022-01-20 16:15:43 +01:00
substitution in growth terms of pac_model / pac_target_info and in
expressions of var_expectation_model . */
pair < lag_equivalence_table_t , ExprNode : : subst_table_t > substituteUnaryOps ( const set < int > & eqnumbers , VarExpectationModelTable & var_expectation_model_table , PacModelTable & pac_model_table ) ;
2018-06-07 12:53:00 +02:00
2018-01-30 10:06:56 +01:00
//! Substitutes diff operator
2022-01-20 16:15:43 +01:00
pair < lag_equivalence_table_t , ExprNode : : subst_table_t > substituteDiff ( VarExpectationModelTable & var_expectation_model_table , PacModelTable & pac_model_table ) ;
2018-03-28 18:46:15 +02:00
2018-08-01 19:41:44 +02:00
//! Substitute VarExpectation operators
void substituteVarExpectation ( const map < string , expr_t > & subst_table ) ;
2021-10-28 14:42:56 +02:00
void analyzePacEquationStructure ( const string & name , map < string , string > & pac_eq_name , PacModelTable : : equation_info_t & pac_equation_info ) ;
2021-10-27 18:17:14 +02:00
2020-07-23 14:45:32 +02:00
// Exception thrown by getPacTargetSymbId()
2022-07-20 13:22:21 +02:00
struct PacTargetNotIdentifiedException
2020-07-23 14:45:32 +02:00
{
const string model_name , message ;
} ;
2019-02-15 12:52:46 +01:00
//! Return target of the pac equation
int getPacTargetSymbId ( const string & pac_model_name ) const ;
2021-10-27 18:17:14 +02:00
/* For a PAC MCE model, fill pac_expectation_substitution with the
2021-11-16 17:58:20 +01:00
expression that will be substituted for the pac_expectation operator .
In the process , add the variable and the equation defining Z ₁ .
The symbol IDs of the new endogenous are added to pac_aux_var_symb_ids ,
and the new auxiliary parameters to pac_mce_alpha_symb_ids .
*/
2021-10-27 18:17:14 +02:00
void computePacModelConsistentExpectationSubstitution ( const string & name ,
2021-11-16 17:58:20 +01:00
int discount_symb_id , int pac_eq_max_lag ,
2021-10-28 14:42:56 +02:00
expr_t growth_correction_term ,
2021-11-18 17:08:08 +01:00
string auxname ,
2021-11-16 17:58:20 +01:00
ExprNode : : subst_table_t & diff_subst_table ,
map < string , int > & pac_aux_var_symb_ids ,
2021-11-17 18:12:29 +01:00
map < string , vector < int > > & pac_aux_param_symb_ids ,
2021-10-28 14:42:56 +02:00
map < string , expr_t > & pac_expectation_substitution ) ;
2021-10-27 18:17:14 +02:00
/* For a PAC backward model, fill pac_expectation_substitution with the
expression that will be substituted for the pac_expectation operator .
2021-12-02 18:15:12 +01:00
The symbol IDs of the new parameters are also added to pac_aux_param_symb_ids .
The symbol ID of the new auxiliary variable is added to pac_aux_var_symb_ids . */
2021-10-27 18:17:14 +02:00
void computePacBackwardExpectationSubstitution ( const string & name ,
const vector < int > & lhs ,
int max_lag ,
const string & aux_model_type ,
2021-10-28 14:42:56 +02:00
expr_t growth_correction_term ,
2021-11-18 17:08:08 +01:00
string auxname ,
2021-11-16 17:58:20 +01:00
map < string , int > & pac_aux_var_symb_ids ,
2021-11-17 18:12:29 +01:00
map < string , vector < int > > & pac_aux_param_symb_ids ,
2021-10-28 14:42:56 +02:00
map < string , expr_t > & pac_expectation_substitution ) ;
2021-10-27 18:17:14 +02:00
2021-10-26 18:06:26 +02:00
/* Same as above, but for PAC models which have an associated
pac_target_info .
Contrary to the above routine , this one will create the growth correction
parameters as needed .
Those parameter IDs , as well as the IDs for the h parameters , are stored
in target_components .
The routine also creates the auxiliary variables for the components , and
adds the corresponding equations . */
void computePacBackwardExpectationSubstitutionWithComponents ( const string & name ,
const vector < int > & lhs ,
int max_lag ,
const string & aux_model_type ,
vector < PacModelTable : : target_component_t > & pac_target_components ,
map < string , expr_t > & pac_expectation_substitution ) ;
2021-10-27 18:17:14 +02:00
//! Substitutes pac_expectation operator with expectation based on auxiliary model
2021-10-28 14:42:56 +02:00
void substitutePacExpectation ( const map < string , expr_t > & pac_expectation_substitution ,
const map < string , string > & pac_eq_name ) ;
2019-02-15 12:52:46 +01:00
2021-10-26 18:06:26 +02:00
//! Substitutes the pac_target_nonstationary operator of a given pac_model
void substitutePacTargetNonstationary ( const string & pac_model_name , expr_t substexpr ) ;
2018-03-28 18:46:15 +02:00
//! Table to undiff LHS variables for pac vector z
2018-08-14 14:23:21 +02:00
vector < int > getUndiffLHSForPac ( const string & aux_model_name ,
2019-08-19 14:51:21 +02:00
const ExprNode : : subst_table_t & diff_subst_table ) const ;
2017-06-12 14:56:44 +02:00
2010-10-15 19:05:16 +02:00
//! Transforms the model by replacing trend variables with a 1
void removeTrendVariableFromEquations ( ) ;
2013-04-25 18:09:31 +02:00
//! Transforms the model by creating aux vars for the diff of forward vars
2013-05-17 16:51:34 +02:00
/*! If subset is empty, does the transformation for all fwrd vars; otherwise
2017-06-01 19:58:32 +02:00
restrict it to the vars in subset */
2018-12-20 17:04:28 +01:00
void differentiateForwardVars ( const vector < string > & subset ) ;
2013-04-25 18:09:31 +02:00
2009-09-30 17:10:31 +02:00
//! Fills eval context with values of model local variables and auxiliary variables
2010-09-16 19:00:48 +02:00
void fillEvalContext ( eval_context_t & eval_context ) const ;
2009-12-16 14:21:31 +01:00
2020-09-10 14:24:20 +02:00
/*! Checks that all pac_expectation operators have been substituted, error
out otherwise */
void checkNoRemainingPacExpectation ( ) const ;
2021-10-26 18:06:26 +02:00
/*! Checks that all pac_target_nonstationary operators have been substituted, error
out otherwise */
void checkNoRemainingPacTargetNonstationary ( ) const ;
2019-12-20 16:59:30 +01:00
auto
getStaticOnlyEquationsInfo ( ) const
{
2022-06-02 10:50:21 +02:00
return tuple { static_only_equations , static_only_equations_lineno , static_only_equations_equation_tags } ;
2019-12-20 16:59:30 +01:00
} ;
2018-10-10 17:08:54 +02:00
2015-07-30 14:40:03 +02:00
//! Returns true if a parameter was used in the model block with a lead or lag
bool ParamUsedWithLeadLag ( ) const ;
2022-06-24 15:45:35 +02:00
bool isChecksumMatching ( const string & basename ) const ;
2021-12-06 16:29:24 +01:00
//! Simplify model equations: if a variable is equal to a constant, replace that variable elsewhere in the model
/*! Equations with MCP tags are excluded, see dynare#1697 */
void simplifyEquations ( ) ;
2022-01-19 15:53:45 +01:00
// Converts a set of equation tags into the corresponding set of equation numbers
set < int > getEquationNumbersFromTags ( const set < string > & eqtags ) const ;
// Returns the set of equations (as numbers) which have a pac_expectation operator
set < int > findPacExpectationEquationNumbers ( ) const ;
2009-04-14 16:39:53 +02:00
} ;
2022-07-12 12:27:22 +02:00
2022-07-12 14:13:27 +02:00
template < ExprNodeOutputType output_type >
void
DynamicModel : : writeDynamicPerBlockHelper ( int blk , ostream & output , temporary_terms_t & temporary_terms ,
int nze_stochastic , int nze_deterministic , int nze_exo ,
int nze_exo_det , int nze_other_endo ) const
{
2022-09-28 19:18:15 +02:00
static_assert ( ! isSparseModelOutput ( output_type ) ) ;
2022-07-12 14:13:27 +02:00
BlockSimulationType simulation_type { blocks [ blk ] . simulation_type } ;
int block_mfs_size { blocks [ blk ] . mfs_size } ;
int block_recursive_size { blocks [ blk ] . getRecursiveSize ( ) } ;
2022-07-21 18:20:35 +02:00
// Write residuals and temporary terms (incl. for derivatives)
writePerBlockHelper < output_type > ( blk , output , temporary_terms ) ;
2022-07-12 14:13:27 +02:00
if constexpr ( isCOutput ( output_type ) )
output < < " if (stochastic_mode) { " < < endl ;
else
output < < " if stochastic_mode " < < endl ;
ostringstream i_output , j_output , v_output ;
int line_counter { ARRAY_SUBSCRIPT_OFFSET ( output_type ) } ;
for ( const auto & [ indices , d ] : blocks_derivatives [ blk ] )
{
const auto & [ eq , var , lag ] { indices } ;
int jacob_col { blocks_jacob_cols_endo [ blk ] . at ( { var , lag } ) } ;
i_output < < " g1_i " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < eq + 1 < < ' ; ' < < endl ;
j_output < < " g1_j " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < jacob_col + 1 < < ' ; ' < < endl ;
v_output < < " g1_v " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' ;
d - > writeOutput ( v_output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
v_output < < ' ; ' < < endl ;
line_counter + + ;
}
assert ( line_counter = = nze_stochastic + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ) ;
output < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
i_output . str ( " " ) ;
j_output . str ( " " ) ;
v_output . str ( " " ) ;
line_counter = ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
for ( const auto & [ indices , d ] : blocks_derivatives_exo [ blk ] )
{
const auto & [ eq , var , lag ] { indices } ;
int jacob_col { blocks_jacob_cols_exo [ blk ] . at ( { var , lag } ) } ;
i_output < < " g1_x_i " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < eq + 1 < < ' ; ' < < endl ;
j_output < < " g1_x_j " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < jacob_col + 1 < < ' ; ' < < endl ;
v_output < < " g1_x_v " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' ;
d - > writeOutput ( v_output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
v_output < < ' ; ' < < endl ;
line_counter + + ;
}
assert ( line_counter = = nze_exo + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ) ;
output < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
i_output . str ( " " ) ;
j_output . str ( " " ) ;
v_output . str ( " " ) ;
line_counter = ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
for ( const auto & [ indices , d ] : blocks_derivatives_exo_det [ blk ] )
{
const auto & [ eq , var , lag ] { indices } ;
int jacob_col { blocks_jacob_cols_exo_det [ blk ] . at ( { var , lag } ) } ;
i_output < < " g1_xd_i " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < eq + 1 < < ' ; ' < < endl ;
j_output < < " g1_xd_j " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < jacob_col + 1 < < ' ; ' < < endl ;
v_output < < " g1_xd_v " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' ;
d - > writeOutput ( v_output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
v_output < < ' ; ' < < endl ;
line_counter + + ;
}
assert ( line_counter = = nze_exo_det + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ) ;
output < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
i_output . str ( " " ) ;
j_output . str ( " " ) ;
v_output . str ( " " ) ;
line_counter = ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
for ( const auto & [ indices , d ] : blocks_derivatives_other_endo [ blk ] )
{
const auto & [ eq , var , lag ] { indices } ;
int jacob_col { blocks_jacob_cols_other_endo [ blk ] . at ( { var , lag } ) } ;
i_output < < " g1_o_i " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < eq + 1 < < ' ; ' < < endl ;
j_output < < " g1_o_j " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < jacob_col + 1 < < ' ; ' < < endl ;
v_output < < " g1_o_v " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' ;
d - > writeOutput ( v_output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
v_output < < ' ; ' < < endl ;
line_counter + + ;
}
assert ( line_counter = = nze_other_endo + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ) ;
output < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
// Deterministic mode
if ( simulation_type ! = BlockSimulationType : : evaluateForward
& & simulation_type ! = BlockSimulationType : : evaluateBackward )
{
if constexpr ( isCOutput ( output_type ) )
output < < " } else { " < < endl ;
else
output < < " else " < < endl ;
i_output . str ( " " ) ;
j_output . str ( " " ) ;
v_output . str ( " " ) ;
line_counter = ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
if ( simulation_type = = BlockSimulationType : : solveBackwardSimple
| | simulation_type = = BlockSimulationType : : solveForwardSimple
| | simulation_type = = BlockSimulationType : : solveBackwardComplete
| | simulation_type = = BlockSimulationType : : solveForwardComplete )
for ( const auto & [ indices , d ] : blocks_derivatives [ blk ] )
{
const auto & [ eq , var , lag ] { indices } ;
if ( lag = = 0 & & eq > = block_recursive_size & & var > = block_recursive_size )
{
i_output < < " g1_i " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = '
< < eq + 1 - block_recursive_size < < ' ; ' < < endl ;
j_output < < " g1_j " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = '
< < var + 1 - block_recursive_size < < ' ; ' < < endl ;
v_output < < " g1_v " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' ;
d - > writeOutput ( v_output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
v_output < < ' ; ' < < endl ;
line_counter + + ;
}
}
else // solveTwoBoundariesSimple || solveTwoBoundariesComplete
for ( const auto & [ indices , d ] : blocks_derivatives [ blk ] )
{
const auto & [ eq , var , lag ] { indices } ;
assert ( lag > = - 1 & & lag < = 1 ) ;
if ( eq > = block_recursive_size & & var > = block_recursive_size )
{
i_output < < " g1_i " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = '
< < eq + 1 - block_recursive_size < < ' ; ' < < endl ;
j_output < < " g1_j " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = '
< < var + 1 - block_recursive_size + block_mfs_size * ( lag + 1 ) < < ' ; ' < < endl ;
v_output < < " g1_v " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' ;
d - > writeOutput ( v_output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
v_output < < ' ; ' < < endl ;
line_counter + + ;
}
}
assert ( line_counter = = nze_deterministic + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ) ;
output < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
}
if constexpr ( isCOutput ( output_type ) )
output < < " } " < < endl ;
else
output < < " end " < < endl ;
}
2022-07-12 12:27:22 +02:00
template < bool julia >
void
DynamicModel : : writeParamsDerivativesFile ( const string & basename ) const
{
if ( ! params_derivatives . size ( ) )
return ;
constexpr ExprNodeOutputType output_type { julia ? ExprNodeOutputType : : juliaDynamicModel : ExprNodeOutputType : : matlabDynamicModel } ;
auto [ tt_output , rp_output , gp_output , rpp_output , gpp_output , hp_output , g3p_output ]
{ writeParamsDerivativesFileHelper < output_type > ( ) } ;
2022-11-02 15:47:15 +01:00
const filesystem : : path filename { julia ? filesystem : : path { basename } / " model " / " julia " / " DynamicParamsDerivs.jl " : packageDir ( basename ) / " dynamic_params_derivs.m " } ;
2022-07-12 12:27:22 +02:00
ofstream paramsDerivsFile { filename , ios : : out | ios : : binary } ;
if ( ! paramsDerivsFile . is_open ( ) )
{
2022-10-11 15:59:56 +02:00
cerr < < " ERROR: Can't open file " < < filename . string ( ) < < " for writing " < < endl ;
2022-07-12 12:27:22 +02:00
exit ( EXIT_FAILURE ) ;
}
if constexpr ( ! julia )
{
paramsDerivsFile < < " function [rp, gp, rpp, gpp, hp, g3p] = dynamic_params_derivs(y, x, params, steady_state, it_, ss_param_deriv, ss_param_2nd_deriv) " < < endl
< < " % " < < endl
< < " % Compute the derivatives of the dynamic model with respect to the parameters " < < endl
< < " % Inputs : " < < endl
< < " % y [#dynamic variables by 1] double vector of endogenous variables in the order stored " < < endl
< < " % in M_.lead_lag_incidence; see the Manual " < < endl
< < " % x [nperiods by M_.exo_nbr] double matrix of exogenous variables (in declaration order) " < < endl
< < " % for all simulation periods " < < endl
< < " % params [M_.param_nbr by 1] double vector of parameter values in declaration order " < < endl
< < " % steady_state [M_.endo_nbr by 1] double vector of steady state values " < < endl
< < " % it_ scalar double time period for exogenous variables for which to evaluate the model " < < endl
< < " % ss_param_deriv [M_.eq_nbr by #params] Jacobian matrix of the steady states values with respect to the parameters " < < endl
< < " % ss_param_2nd_deriv [M_.eq_nbr by #params by #params] Hessian matrix of the steady states values with respect to the parameters " < < endl
< < " % " < < endl
< < " % Outputs: " < < endl
< < " % rp [M_.eq_nbr by #params] double Jacobian matrix of dynamic model equations with respect to parameters " < < endl
< < " % Dynare may prepend or append auxiliary equations, see M_.aux_vars " < < endl
< < " % gp [M_.endo_nbr by #dynamic variables by #params] double Derivative of the Jacobian matrix of the dynamic model equations with respect to the parameters " < < endl
< < " % rows: equations in order of declaration " < < endl
< < " % columns: variables in order stored in M_.lead_lag_incidence " < < endl
< < " % rpp [#second_order_residual_terms by 4] double Hessian matrix of second derivatives of residuals with respect to parameters; " < < endl
< < " % rows: respective derivative term " < < endl
< < " % 1st column: equation number of the term appearing " < < endl
< < " % 2nd column: number of the first parameter in derivative " < < endl
< < " % 3rd column: number of the second parameter in derivative " < < endl
< < " % 4th column: value of the Hessian term " < < endl
< < " % gpp [#second_order_Jacobian_terms by 5] double Hessian matrix of second derivatives of the Jacobian with respect to the parameters; " < < endl
< < " % rows: respective derivative term " < < endl
< < " % 1st column: equation number of the term appearing " < < endl
< < " % 2nd column: column number of variable in Jacobian of the dynamic model " < < endl
< < " % 3rd column: number of the first parameter in derivative " < < endl
< < " % 4th column: number of the second parameter in derivative " < < endl
< < " % 5th column: value of the Hessian term " < < endl
< < " % hp [#first_order_Hessian_terms by 5] double Jacobian matrix of derivatives of the dynamic Hessian with respect to the parameters; " < < endl
< < " % rows: respective derivative term " < < endl
< < " % 1st column: equation number of the term appearing " < < endl
< < " % 2nd column: column number of first variable in Hessian of the dynamic model " < < endl
< < " % 3rd column: column number of second variable in Hessian of the dynamic model " < < endl
< < " % 4th column: number of the parameter in derivative " < < endl
< < " % 5th column: value of the Hessian term " < < endl
< < " % g3p [#first_order_g3_terms by 6] double Jacobian matrix of derivatives of g3 (dynamic 3rd derivs) with respect to the parameters; " < < endl
< < " % rows: respective derivative term " < < endl
< < " % 1st column: equation number of the term appearing " < < endl
< < " % 2nd column: column number of first variable in g3 of the dynamic model " < < endl
< < " % 3rd column: column number of second variable in g3 of the dynamic model " < < endl
< < " % 4th column: column number of third variable in g3 of the dynamic model " < < endl
< < " % 5th column: number of the parameter in derivative " < < endl
< < " % 6th column: value of the Hessian term " < < endl
< < " % " < < endl
< < " % " < < endl
< < " % Warning : this file is generated automatically by Dynare " < < endl
< < " % from model file (.mod) " < < endl < < endl
< < " T = NaN( " < < params_derivs_temporary_terms_idxs . size ( ) < < " ,1); " < < endl
< < tt_output . str ( )
< < " rp = zeros( " < < equations . size ( ) < < " , "
< < symbol_table . param_nbr ( ) < < " ); " < < endl
< < rp_output . str ( )
2022-09-14 17:07:08 +02:00
< < " gp = zeros( " < < equations . size ( ) < < " , " < < getJacobianColsNbr ( false ) < < " , " < < symbol_table . param_nbr ( ) < < " ); " < < endl
2022-07-12 12:27:22 +02:00
< < gp_output . str ( )
< < " if nargout >= 3 " < < endl
2022-09-27 12:51:22 +02:00
< < " rpp = zeros( " < < params_derivatives . at ( { 0 , 2 } ) . size ( ) < < " ,4); " < < endl
2022-07-12 12:27:22 +02:00
< < rpp_output . str ( )
2022-09-27 12:51:22 +02:00
< < " gpp = zeros( " < < params_derivatives . at ( { 1 , 2 } ) . size ( ) < < " ,5); " < < endl
2022-07-12 12:27:22 +02:00
< < gpp_output . str ( )
< < " end " < < endl
< < " if nargout >= 5 " < < endl
2022-09-27 12:51:22 +02:00
< < " hp = zeros( " < < params_derivatives . at ( { 2 , 1 } ) . size ( ) < < " ,5); " < < endl
2022-07-12 12:27:22 +02:00
< < hp_output . str ( )
< < " end " < < endl
< < " if nargout >= 6 " < < endl
2022-09-27 12:51:22 +02:00
< < " g3p = zeros( " < < params_derivatives . at ( { 3 , 1 } ) . size ( ) < < " ,6); " < < endl
2022-07-12 12:27:22 +02:00
< < g3p_output . str ( )
< < " end " < < endl
< < " end " < < endl ;
}
else
paramsDerivsFile < < " module " < < basename < < " DynamicParamsDerivs " < < endl
< < " # " < < endl
< < " # NB: this file was automatically generated by Dynare " < < endl
< < " # from " < < basename < < " .mod " < < endl
< < " # " < < endl
< < " export params_derivs " < < endl < < endl
< < " function params_derivs(y, x, paramssteady_state, it_, "
< < " ss_param_deriv, ss_param_2nd_deriv) " < < endl
< < " @inbounds begin " < < endl
< < tt_output . str ( )
< < " end " < < endl
< < " rp = zeros( " < < equations . size ( ) < < " , "
< < symbol_table . param_nbr ( ) < < " ); " < < endl
< < " @inbounds begin " < < endl
< < rp_output . str ( )
< < " end " < < endl
2022-09-14 17:07:08 +02:00
< < " gp = zeros( " < < equations . size ( ) < < " , " < < getJacobianColsNbr ( false ) < < " , " < < symbol_table . param_nbr ( ) < < " ); " < < endl
2022-07-12 12:27:22 +02:00
< < " @inbounds begin " < < endl
< < gp_output . str ( )
< < " end " < < endl
2022-09-27 12:51:22 +02:00
< < " rpp = zeros( " < < params_derivatives . at ( { 0 , 2 } ) . size ( ) < < " ,4); " < < endl
2022-07-12 12:27:22 +02:00
< < " @inbounds begin " < < endl
< < rpp_output . str ( )
< < " end " < < endl
2022-09-27 12:51:22 +02:00
< < " gpp = zeros( " < < params_derivatives . at ( { 1 , 2 } ) . size ( ) < < " ,5); " < < endl
2022-07-12 12:27:22 +02:00
< < " @inbounds begin " < < endl
< < gpp_output . str ( )
< < " end " < < endl
2022-09-27 12:51:22 +02:00
< < " hp = zeros( " < < params_derivatives . at ( { 2 , 1 } ) . size ( ) < < " ,5); " < < endl
2022-07-12 12:27:22 +02:00
< < " @inbounds begin " < < endl
< < hp_output . str ( )
< < " end " < < endl
2022-09-27 12:51:22 +02:00
< < " g3p = zeros( " < < params_derivatives . at ( { 3 , 1 } ) . size ( ) < < " ,6); " < < endl
2022-07-12 12:27:22 +02:00
< < " @inbounds begin " < < endl
< < g3p_output . str ( )
< < " end " < < endl
< < " (rp, gp, rpp, gpp, hp, g3p) " < < endl
< < " end " < < endl
< < " end " < < endl ;
paramsDerivsFile . close ( ) ;
}
2009-04-14 16:39:53 +02:00
# endif