2009-04-14 16:39:53 +02:00
/*
2021-02-01 11:10:59 +01:00
* Copyright © 2003 - 2021 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
*/
2009-12-16 14:21:31 +01:00
# include <iostream>
# include <cmath>
2009-04-14 16:47:57 +02:00
# include <cstdlib>
2009-04-27 19:15:14 +02:00
# include <cassert>
2009-04-28 19:11:48 +02:00
# include <algorithm>
2021-04-23 17:30:38 +02:00
# include <sstream>
2009-12-16 14:21:31 +01:00
2018-06-27 15:01:31 +02:00
# include "StaticModel.hh"
2018-10-10 17:08:54 +02:00
# include "DynamicModel.hh"
2009-04-28 19:11:48 +02:00
2018-10-09 18:27:19 +02:00
void
StaticModel : : copyHelper ( const StaticModel & m )
{
}
2009-12-16 14:21:31 +01:00
StaticModel : : StaticModel ( SymbolTable & symbol_table_arg ,
2010-02-22 17:33:38 +01:00
NumericalConstants & num_constants_arg ,
2018-09-14 17:04:06 +02:00
ExternalFunctionsTable & external_functions_table_arg ) :
2018-10-04 17:18:27 +02:00
ModelTree { symbol_table_arg , num_constants_arg , external_functions_table_arg }
2009-12-16 14:21:31 +01:00
{
}
2009-04-14 16:47:57 +02:00
2018-10-09 18:27:19 +02:00
StaticModel : : StaticModel ( const StaticModel & m ) :
2020-05-06 17:13:47 +02:00
ModelTree { m }
2018-10-09 18:27:19 +02:00
{
copyHelper ( m ) ;
}
StaticModel &
StaticModel : : operator = ( const StaticModel & m )
{
ModelTree : : operator = ( m ) ;
copyHelper ( m ) ;
return * this ;
}
2018-10-10 17:08:54 +02:00
StaticModel : : StaticModel ( const DynamicModel & m ) :
2019-12-20 16:59:30 +01:00
ModelTree { m . symbol_table , m . num_constants , m . external_functions_table }
2018-10-10 17:08:54 +02:00
{
// Convert model local variables (need to be done first)
for ( int it : m . local_variables_vector )
AddLocalVariable ( it , m . local_variables_table . find ( it ) - > second - > toStatic ( * this ) ) ;
// Convert equations
int static_only_index = 0 ;
2020-02-20 15:29:10 +01:00
set < int > dynamic_equations = m . equation_tags . getDynamicEqns ( ) ;
2018-10-10 17:08:54 +02:00
for ( int i = 0 ; i < static_cast < int > ( m . equations . size ( ) ) ; i + + )
2020-02-20 15:29:10 +01:00
try
{
// If equation is dynamic, replace it by an equation marked [static]
if ( dynamic_equations . find ( i ) ! = dynamic_equations . end ( ) )
2018-10-10 17:08:54 +02:00
{
2020-02-20 15:29:10 +01:00
auto [ static_only_equations ,
static_only_equations_lineno ,
static_only_equations_equation_tags ] = m . getStaticOnlyEquationsInfo ( ) ;
addEquation ( static_only_equations [ static_only_index ] - > toStatic ( * this ) ,
static_only_equations_lineno [ static_only_index ] ,
static_only_equations_equation_tags . getTagsByEqn ( static_only_index ) ) ;
static_only_index + + ;
2018-10-10 17:08:54 +02:00
}
2020-02-20 15:29:10 +01:00
else
addEquation ( m . equations [ i ] - > toStatic ( * this ) ,
m . equations_lineno [ i ] ,
m . equation_tags . getTagsByEqn ( i ) ) ;
}
catch ( DataTree : : DivisionByZeroException )
{
cerr < < " ...division by zero error encountred when converting equation " < < i < < " to static " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-10-10 17:08:54 +02:00
// Convert auxiliary equations
for ( auto aux_eq : m . aux_equations )
addAuxEquation ( aux_eq - > toStatic ( * this ) ) ;
2019-12-02 19:21:14 +01:00
user_set_add_flags = m . user_set_add_flags ;
user_set_subst_flags = m . user_set_subst_flags ;
user_set_add_libs = m . user_set_add_libs ;
user_set_subst_libs = m . user_set_subst_libs ;
user_set_compiler = m . user_set_compiler ;
2018-10-10 17:08:54 +02:00
}
2009-12-16 14:21:31 +01:00
void
2020-05-13 12:53:47 +02:00
StaticModel : : compileDerivative ( ofstream & code_file , unsigned int & instruction_number , int eq , int symb_id , const temporary_terms_t & temporary_terms , const temporary_terms_idxs_t & temporary_terms_idxs ) const
2009-12-16 14:21:31 +01:00
{
2019-12-16 19:42:59 +01:00
if ( auto it = derivatives [ 1 ] . find ( { eq , getDerivID ( symbol_table . getID ( SymbolType : : endogenous , symb_id ) , 0 ) } ) ;
it ! = derivatives [ 1 ] . end ( ) )
2020-05-13 12:53:47 +02:00
it - > second - > compile ( code_file , instruction_number , false , temporary_terms , temporary_terms_idxs , false , false ) ;
2009-12-16 14:21:31 +01:00
else
{
FLDZ_ fldz ;
2010-07-23 11:20:24 +02:00
fldz . write ( code_file , instruction_number ) ;
2009-12-16 14:21:31 +01:00
}
}
2009-04-14 16:39:53 +02:00
2009-12-16 14:21:31 +01:00
void
2020-05-13 12:53:47 +02:00
StaticModel : : compileChainRuleDerivative ( ofstream & code_file , unsigned int & instruction_number , int blk , int eq , int var , int lag , const temporary_terms_t & temporary_terms , const temporary_terms_idxs_t & temporary_terms_idxs ) const
2009-12-16 14:21:31 +01:00
{
2020-04-24 12:29:02 +02:00
if ( auto it = blocks_derivatives [ blk ] . find ( { eq , var , lag } ) ;
it ! = blocks_derivatives [ blk ] . end ( ) )
2020-05-13 12:53:47 +02:00
it - > second - > compile ( code_file , instruction_number , false , temporary_terms , temporary_terms_idxs , false , false ) ;
2009-12-16 14:21:31 +01:00
else
{
FLDZ_ fldz ;
2010-07-23 11:20:24 +02:00
fldz . write ( code_file , instruction_number ) ;
2009-12-16 14:21:31 +01:00
}
}
2020-06-22 12:46:33 +02:00
void
StaticModel : : writeStaticPerBlockHelper ( int blk , ostream & output , ExprNodeOutputType output_type , temporary_terms_t & temporary_terms ) const
{
BlockSimulationType simulation_type = blocks [ blk ] . simulation_type ;
int block_recursive_size = blocks [ blk ] . getRecursiveSize ( ) ;
// The equations
deriv_node_temp_terms_t tef_terms ;
auto write_eq_tt = [ & ] ( int eq )
{
for ( auto it : blocks_temporary_terms [ blk ] [ eq ] )
{
if ( dynamic_cast < AbstractExternalFunctionNode * > ( it ) )
it - > writeExternalFunctionOutput ( output , output_type , temporary_terms , blocks_temporary_terms_idxs , tef_terms ) ;
output < < " " ;
it - > writeOutput ( output , output_type , blocks_temporary_terms [ blk ] [ eq ] , blocks_temporary_terms_idxs , tef_terms ) ;
output < < ' = ' ;
it - > writeOutput ( output , output_type , temporary_terms , blocks_temporary_terms_idxs , tef_terms ) ;
temporary_terms . insert ( it ) ;
output < < ' ; ' < < endl ;
}
} ;
for ( int eq = 0 ; eq < blocks [ blk ] . size ; eq + + )
{
write_eq_tt ( eq ) ;
EquationType equ_type = getBlockEquationType ( blk , eq ) ;
BinaryOpNode * e = getBlockEquationExpr ( blk , eq ) ;
expr_t lhs = e - > arg1 , rhs = e - > arg2 ;
switch ( simulation_type )
{
case BlockSimulationType : : evaluateBackward :
case BlockSimulationType : : evaluateForward :
evaluation :
if ( equ_type = = EquationType : : evaluateRenormalized )
{
e = getBlockEquationRenormalizedExpr ( blk , eq ) ;
lhs = e - > arg1 ;
rhs = e - > arg2 ;
}
else if ( equ_type ! = EquationType : : evaluate )
{
cerr < < " Type mismatch for equation " < < getBlockEquationID ( blk , eq ) + 1 < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " " ;
lhs - > writeOutput ( output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
output < < ' = ' ;
rhs - > writeOutput ( output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
output < < ' ; ' < < endl ;
break ;
case BlockSimulationType : : solveBackwardSimple :
case BlockSimulationType : : solveForwardSimple :
case BlockSimulationType : : solveBackwardComplete :
case BlockSimulationType : : solveForwardComplete :
if ( eq < block_recursive_size )
goto evaluation ;
output < < " residual " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < eq - block_recursive_size + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " =( " ;
lhs - > writeOutput ( output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
output < < " )-( " ;
rhs - > writeOutput ( output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
output < < " ); " < < endl ;
break ;
default :
cerr < < " Incorrect type for block " < < blk + 1 < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
// The Jacobian if we have to solve the block
if ( simulation_type ! = BlockSimulationType : : evaluateBackward
& & simulation_type ! = BlockSimulationType : : evaluateForward )
{
// Write temporary terms for derivatives
write_eq_tt ( blocks [ blk ] . size ) ;
ostringstream i_output , j_output , v_output ;
int line_counter = ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
for ( const auto & [ indices , d ] : blocks_derivatives [ blk ] )
{
auto [ eq , var , ignore ] = indices ;
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 + + ;
}
output < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
}
}
2009-12-16 14:21:31 +01:00
void
2020-05-19 16:56:53 +02:00
StaticModel : : writeStaticPerBlockMFiles ( const string & basename ) const
2009-12-16 18:13:23 +01:00
{
2020-05-06 17:13:47 +02:00
temporary_terms_t temporary_terms ; // Temp terms written so far
2020-05-05 17:49:58 +02:00
2020-05-19 16:56:53 +02:00
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
2009-12-16 18:13:23 +01:00
{
2020-05-19 16:56:53 +02:00
BlockSimulationType simulation_type = blocks [ blk ] . simulation_type ;
2009-12-16 18:13:23 +01:00
2020-05-19 16:56:53 +02:00
string filename = packageDir ( basename + " .block " ) + " /static_ " + to_string ( blk + 1 ) + " .m " ;
2020-05-05 17:49:58 +02:00
ofstream output ;
output . open ( filename , ios : : out | ios : : binary ) ;
2020-06-23 15:13:04 +02:00
if ( ! output . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-11-23 17:19:59 +01:00
output < < " % " < < endl
2020-05-19 16:56:53 +02:00
< < " % " < < filename < < " : Computes static version of one block " < < endl
2018-11-23 17:19:59 +01:00
< < " % " < < endl
< < " % Warning : this file is generated automatically by Dynare " < < endl
< < " % from model file (.mod) " < < endl < < endl
2020-05-19 16:56:53 +02:00
< < " % " < < endl ;
2020-03-20 17:31:14 +01:00
if ( simulation_type = = BlockSimulationType : : evaluateBackward
| | simulation_type = = BlockSimulationType : : evaluateForward )
2020-05-25 18:35:36 +02:00
output < < " function [y, T] = static_ " < < blk + 1 < < " (y, x, params, T) " < < endl ;
2009-12-16 18:13:23 +01:00
else
2020-10-06 17:16:50 +02:00
output < < " function [residual, y, T, g1] = static_ " < < blk + 1 < < " (y, x, params, T) " < < endl ;
2009-12-16 18:13:23 +01:00
output < < " % //////////////////////////////////////////////////////////////////////// " < < endl
2020-05-19 16:56:53 +02:00
< < " % // " < < string ( " Block " ) . substr ( static_cast < int > ( log10 ( blk + 1 ) ) ) < < blk + 1
2020-04-30 12:48:16 +02:00
< < " // " < < endl
2009-12-16 18:13:23 +01:00
< < " % // Simulation type "
< < BlockSim ( simulation_type ) < < " // " < < endl
2020-05-19 16:56:53 +02:00
< < " % //////////////////////////////////////////////////////////////////////// " < < endl ;
2020-03-20 17:31:14 +01:00
if ( simulation_type ! = BlockSimulationType : : evaluateBackward
& & simulation_type ! = BlockSimulationType : : evaluateForward )
2020-06-22 12:46:33 +02:00
output < < " residual=zeros( " < < blocks [ blk ] . mfs_size < < " ,1); " < < endl
< < " g1_i=zeros( " < < blocks_derivatives [ blk ] . size ( ) < < " ,1); " < < endl
< < " g1_j=zeros( " < < blocks_derivatives [ blk ] . size ( ) < < " ,1); " < < endl
< < " g1_v=zeros( " < < blocks_derivatives [ blk ] . size ( ) < < " ,1); " < < endl
< < endl ;
2020-05-13 16:58:19 +02:00
2020-06-22 12:46:33 +02:00
writeStaticPerBlockHelper ( blk , output , ExprNodeOutputType : : matlabStaticModel , temporary_terms ) ;
2020-05-13 16:58:19 +02:00
2020-06-22 12:46:33 +02:00
if ( simulation_type ! = BlockSimulationType : : evaluateBackward
& & simulation_type ! = BlockSimulationType : : evaluateForward )
output < < endl
< < " g1=sparse(g1_i, g1_j, g1_v, " < < blocks [ blk ] . mfs_size < < " , " < < blocks [ blk ] . mfs_size < < " ); " < < endl ;
2020-06-19 16:09:38 +02:00
2010-12-17 14:21:35 +01:00
output < < " end " < < endl ;
2009-12-16 18:13:23 +01:00
output . close ( ) ;
}
}
2009-12-16 14:21:31 +01:00
2020-06-23 15:13:04 +02:00
void
StaticModel : : writeStaticPerBlockCFiles ( const string & basename ) const
{
temporary_terms_t temporary_terms ; // Temp terms written so far
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
{
BlockSimulationType simulation_type = blocks [ blk ] . simulation_type ;
string filename = basename + " /model/src/static_ " + to_string ( blk + 1 ) + " .c " ;
ofstream output ;
output . open ( filename , ios : : out | ios : : binary ) ;
if ( ! output . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " /* Block " < < blk + 1 < < endl
< < " " < < BlockSim ( simulation_type ) < < " */ " < < endl
< < endl
< < " #include <math.h> " < < endl
< < " #include <stdlib.h> " < < endl
< < R " (#include " mex . h " ) " < < endl
< < endl ;
// Write function definition if BinaryOpcode::powerDeriv is used
writePowerDerivHeader ( output ) ;
output < < endl ;
if ( simulation_type = = BlockSimulationType : : evaluateBackward
| | simulation_type = = BlockSimulationType : : evaluateForward )
2020-09-03 17:52:12 +02:00
output < < " void static_ " < < blk + 1 < < " (double *restrict y, const double *restrict x, const double *restrict params, double *restrict T) " < < endl ;
2020-06-23 15:13:04 +02:00
else
2020-10-06 17:16:50 +02:00
output < < " void static_ " < < blk + 1 < < " (double *restrict y, const double *restrict x, const double *restrict params, double *restrict T, double *restrict residual, double *restrict g1_i, double *restrict g1_j, double *restrict g1_v) " < < endl ;
2020-06-23 15:13:04 +02:00
output < < ' { ' < < endl ;
writeStaticPerBlockHelper ( blk , output , ExprNodeOutputType : : CStaticModel , temporary_terms ) ;
output < < ' } ' < < endl
< < endl ;
ostringstream header ;
if ( simulation_type = = BlockSimulationType : : evaluateBackward
| | simulation_type = = BlockSimulationType : : evaluateForward )
{
header < < " void static_ " < < blk + 1 < < " _mx(mxArray *y, const mxArray *x, const mxArray *params, mxArray *T) " ;
output < < header . str ( ) < < endl
< < ' { ' < < endl
< < " static_ " < < blk + 1 < < " (mxGetPr(y), mxGetPr(x), mxGetPr(params), mxGetPr(T)); " < < endl
< < ' } ' < < endl ;
}
else
{
2020-10-06 17:16:50 +02:00
header < < " void static_ " < < blk + 1 < < " _mx(mxArray *y, const mxArray *x, const mxArray *params, mxArray *T, mxArray **residual, mxArray **g1) " ;
2020-06-23 15:13:04 +02:00
output < < header . str ( ) < < endl
< < ' { ' < < endl
< < " *residual = mxCreateDoubleMatrix( " < < blocks [ blk ] . mfs_size < < " ,1,mxREAL); " < < endl
< < " mxArray *g1_i = mxCreateDoubleMatrix( " < < blocks_derivatives [ blk ] . size ( ) < < " ,1,mxREAL); " < < endl
< < " mxArray *g1_j = mxCreateDoubleMatrix( " < < blocks_derivatives [ blk ] . size ( ) < < " ,1,mxREAL); " < < endl
< < " mxArray *g1_v = mxCreateDoubleMatrix( " < < blocks_derivatives [ blk ] . size ( ) < < " ,1,mxREAL); " < < endl
< < " static_ " < < blk + 1 < < " (mxGetPr(y), mxGetPr(x), mxGetPr(params), mxGetPr(T), mxGetPr(*residual), mxGetPr(g1_i), mxGetPr(g1_j), mxGetPr(g1_v)); " < < endl
< < " mxArray *plhs[1]; " < < endl
< < " mxArray *m = mxCreateDoubleScalar( " < < blocks [ blk ] . mfs_size < < " ); " < < endl
< < " mxArray *n = mxCreateDoubleScalar( " < < blocks [ blk ] . mfs_size < < " ); " < < endl
< < " mxArray *prhs[5] = { g1_i, g1_j, g1_v, m, n }; " < < endl
< < R " ( mexCallMATLAB(1, plhs, 5, prhs, " sparse " );) " < < endl
< < " *g1 = plhs[0]; " < < endl
< < " mxDestroyArray(g1_i); " < < endl
< < " mxDestroyArray(g1_j); " < < endl
< < " mxDestroyArray(g1_v); " < < endl
< < " mxDestroyArray(m); " < < endl
< < " mxDestroyArray(n); " < < endl
< < ' } ' < < endl ;
}
output . close ( ) ;
filename = basename + " /model/src/static_ " + to_string ( blk + 1 ) + " .h " ;
ofstream header_output ;
header_output . open ( filename , ios : : out | ios : : binary ) ;
if ( ! header_output . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
header_output < < header . str ( ) < < ' ; ' < < endl ;
header_output . close ( ) ;
}
}
2009-12-16 14:21:31 +01:00
void
2020-05-19 17:43:35 +02:00
StaticModel : : writeStaticBytecode ( const string & basename ) const
2010-01-22 11:03:29 +01:00
{
ostringstream tmp_output ;
ofstream code_file ;
2010-07-23 11:20:24 +02:00
unsigned int instruction_number = 0 ;
2010-01-22 11:03:29 +01:00
bool file_open = false ;
2018-06-27 15:01:31 +02:00
string main_name = basename + " /model/bytecode/static.cod " ;
2018-06-27 15:12:12 +02:00
code_file . open ( main_name , ios : : out | ios : : binary | ios : : ate ) ;
2010-01-22 11:03:29 +01:00
if ( ! code_file . is_open ( ) )
{
2019-04-03 16:32:52 +02:00
cerr < < R " (Error : Can't open file " ) " << main_name << R " ( " for writing) " < < endl ;
2010-01-22 11:03:29 +01:00
exit ( EXIT_FAILURE ) ;
}
int count_u ;
int u_count_int = 0 ;
2020-05-19 17:43:35 +02:00
writeBytecodeBinFile ( basename + " /model/bytecode/static.bin " , u_count_int , file_open , false ) ;
2010-01-22 11:03:29 +01:00
file_open = true ;
2020-05-06 17:13:47 +02:00
// Compute the union of temporary terms from residuals and 1st derivatives
temporary_terms_t temporary_terms = temporary_terms_derivatives [ 0 ] ;
copy ( temporary_terms_derivatives [ 1 ] . begin ( ) , temporary_terms_derivatives [ 1 ] . end ( ) ,
inserter ( temporary_terms , temporary_terms . end ( ) ) ) ;
2010-01-22 11:03:29 +01:00
//Temporary variables declaration
2010-10-11 19:21:32 +02:00
FDIMST_ fdimst ( temporary_terms . size ( ) ) ;
fdimst . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
FBEGINBLOCK_ fbeginblock ( symbol_table . endo_nbr ( ) ,
2020-03-20 17:31:14 +01:00
BlockSimulationType : : solveForwardComplete ,
2010-01-22 11:03:29 +01:00
0 ,
symbol_table . endo_nbr ( ) ,
2020-04-17 14:55:55 +02:00
endo_idx_block2orig ,
eq_idx_block2orig ,
2010-01-22 11:03:29 +01:00
false ,
symbol_table . endo_nbr ( ) ,
0 ,
0 ,
2010-07-23 11:20:24 +02:00
u_count_int ,
2019-12-16 19:42:59 +01:00
symbol_table . endo_nbr ( ) ) ;
2010-07-23 11:20:24 +02:00
fbeginblock . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
2020-05-13 12:53:47 +02:00
temporary_terms_t temporary_terms_union ;
compileTemporaryTerms ( code_file , instruction_number , false , false , temporary_terms_union , temporary_terms_idxs ) ;
2010-01-22 11:03:29 +01:00
2020-05-13 12:53:47 +02:00
compileModelEquations ( code_file , instruction_number , false , false , temporary_terms_union , temporary_terms_idxs ) ;
2010-01-22 11:03:29 +01:00
FENDEQU_ fendequ ;
2010-07-23 11:20:24 +02:00
fendequ . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
2010-10-18 17:28:21 +02:00
// Get the current code_file position and jump if eval = true
streampos pos1 = code_file . tellp ( ) ;
FJMPIFEVAL_ fjmp_if_eval ( 0 ) ;
fjmp_if_eval . write ( code_file , instruction_number ) ;
int prev_instruction_number = instruction_number ;
2018-11-23 17:19:59 +01:00
vector < vector < pair < int , int > > > my_derivatives ( symbol_table . endo_nbr ( ) ) ;
2010-01-22 11:03:29 +01:00
count_u = symbol_table . endo_nbr ( ) ;
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d1 ] : derivatives [ 1 ] )
2010-01-22 11:03:29 +01:00
{
2019-12-16 19:42:59 +01:00
int deriv_id = indices [ 1 ] ;
2018-07-17 18:34:07 +02:00
if ( getTypeByDerivID ( deriv_id ) = = SymbolType : : endogenous )
2010-01-22 11:03:29 +01:00
{
2020-03-24 18:26:06 +01:00
int eq = indices [ 0 ] ;
2010-01-22 11:03:29 +01:00
int symb = getSymbIDByDerivID ( deriv_id ) ;
2020-03-24 18:26:06 +01:00
int var = symbol_table . getTypeSpecificID ( symb ) ;
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstEndoDerivative , eq , var ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2018-11-15 16:39:53 +01:00
if ( ! my_derivatives [ eq ] . size ( ) )
my_derivatives [ eq ] . clear ( ) ;
my_derivatives [ eq ] . emplace_back ( var , count_u ) ;
2010-01-22 11:03:29 +01:00
2020-05-13 12:53:47 +02:00
d1 - > compile ( code_file , instruction_number , false , temporary_terms_union , temporary_terms_idxs , false , false ) ;
2010-01-22 11:03:29 +01:00
FSTPSU_ fstpsu ( count_u ) ;
2010-07-23 11:20:24 +02:00
fstpsu . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
count_u + + ;
}
}
for ( int i = 0 ; i < symbol_table . endo_nbr ( ) ; i + + )
{
FLDR_ fldr ( i ) ;
2010-07-23 11:20:24 +02:00
fldr . write ( code_file , instruction_number ) ;
2018-11-15 16:39:53 +01:00
if ( my_derivatives [ i ] . size ( ) )
2010-01-22 11:03:29 +01:00
{
2019-12-16 19:42:59 +01:00
for ( auto it = my_derivatives [ i ] . begin ( ) ; it ! = my_derivatives [ i ] . end ( ) ; + + it )
2010-01-22 11:03:29 +01:00
{
2010-11-20 16:06:07 +01:00
FLDSU_ fldsu ( it - > second ) ;
fldsu . write ( code_file , instruction_number ) ;
2018-07-18 15:12:00 +02:00
FLDSV_ fldsv { static_cast < int > ( SymbolType : : endogenous ) , static_cast < unsigned int > ( it - > first ) } ;
2010-11-20 16:06:07 +01:00
fldsv . write ( code_file , instruction_number ) ;
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : times ) } ;
2010-07-23 11:20:24 +02:00
fbinary . write ( code_file , instruction_number ) ;
2018-11-15 16:39:53 +01:00
if ( it ! = my_derivatives [ i ] . begin ( ) )
2010-11-20 16:06:07 +01:00
{
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : plus ) } ;
2010-11-20 16:06:07 +01:00
fbinary . write ( code_file , instruction_number ) ;
}
2010-01-22 11:03:29 +01:00
}
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : minus ) } ;
2010-11-20 16:06:07 +01:00
fbinary . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
}
FSTPSU_ fstpsu ( i ) ;
2010-07-23 11:20:24 +02:00
fstpsu . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
}
2010-10-18 17:28:21 +02:00
// Get the current code_file position and jump = true
streampos pos2 = code_file . tellp ( ) ;
FJMP_ fjmp ( 0 ) ;
fjmp . write ( code_file , instruction_number ) ;
// Set code_file position to previous JMPIFEVAL_ and set the number of instructions to jump
streampos pos3 = code_file . tellp ( ) ;
code_file . seekp ( pos1 ) ;
FJMPIFEVAL_ fjmp_if_eval1 ( instruction_number - prev_instruction_number ) ;
fjmp_if_eval1 . write ( code_file , instruction_number ) ;
code_file . seekp ( pos3 ) ;
2011-02-04 16:25:38 +01:00
prev_instruction_number = instruction_number ;
2010-10-18 17:28:21 +02:00
2018-11-23 17:19:59 +01:00
temporary_terms_t tt2 , tt3 ;
2010-10-18 17:28:21 +02:00
// The Jacobian if we have to solve the block determinsitic bloc
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d1 ] : derivatives [ 1 ] )
2010-10-18 17:28:21 +02:00
{
2019-12-16 19:42:59 +01:00
int deriv_id = indices [ 1 ] ;
2018-07-17 18:34:07 +02:00
if ( getTypeByDerivID ( deriv_id ) = = SymbolType : : endogenous )
2010-10-18 17:28:21 +02:00
{
2020-03-24 18:26:06 +01:00
int eq = indices [ 0 ] ;
2010-10-18 17:28:21 +02:00
int symb = getSymbIDByDerivID ( deriv_id ) ;
2020-03-24 18:26:06 +01:00
int var = symbol_table . getTypeSpecificID ( symb ) ;
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstEndoDerivative , eq , var ) ;
2010-10-18 17:28:21 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2018-11-15 16:39:53 +01:00
if ( ! my_derivatives [ eq ] . size ( ) )
my_derivatives [ eq ] . clear ( ) ;
my_derivatives [ eq ] . emplace_back ( var , count_u ) ;
2010-10-18 17:28:21 +02:00
2020-05-13 12:53:47 +02:00
d1 - > compile ( code_file , instruction_number , false , temporary_terms_union , temporary_terms_idxs , false , false ) ;
2011-02-04 16:25:38 +01:00
FSTPG2_ fstpg2 ( eq , var ) ;
2010-10-18 17:28:21 +02:00
fstpg2 . write ( code_file , instruction_number ) ;
}
}
// Set codefile position to previous JMP_ and set the number of instructions to jump
pos1 = code_file . tellp ( ) ;
code_file . seekp ( pos2 ) ;
FJMP_ fjmp1 ( instruction_number - prev_instruction_number ) ;
fjmp1 . write ( code_file , instruction_number ) ;
code_file . seekp ( pos1 ) ;
2010-01-22 11:03:29 +01:00
FENDBLOCK_ fendblock ;
2010-07-23 11:20:24 +02:00
fendblock . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
FEND_ fend ;
2010-07-23 11:20:24 +02:00
fend . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
code_file . close ( ) ;
}
void
2020-05-19 17:43:35 +02:00
StaticModel : : writeStaticBlockBytecode ( const string & basename ) const
2009-12-16 18:13:23 +01:00
{
struct Uff_l
2009-12-16 14:21:31 +01:00
{
2009-12-16 18:13:23 +01:00
int u , var , lag ;
Uff_l * pNext ;
} ;
2009-12-16 14:21:31 +01:00
2009-12-16 18:13:23 +01:00
struct Uff
{
Uff_l * Ufl , * Ufl_First ;
} ;
int i , v ;
string tmp_s ;
ostringstream tmp_output ;
ofstream code_file ;
2010-07-23 11:20:24 +02:00
unsigned int instruction_number = 0 ;
2018-06-04 12:52:14 +02:00
expr_t lhs = nullptr , rhs = nullptr ;
2009-12-16 18:13:23 +01:00
BinaryOpNode * eq_node ;
Uff Uf [ symbol_table . endo_nbr ( ) ] ;
2010-09-16 19:18:45 +02:00
map < expr_t , int > reference_count ;
2009-12-16 18:13:23 +01:00
vector < int > feedback_variables ;
bool file_open = false ;
2018-06-27 15:01:31 +02:00
string main_name = basename + " /model/bytecode/static.cod " ;
2018-06-27 15:12:12 +02:00
code_file . open ( main_name , ios : : out | ios : : binary | ios : : ate ) ;
2009-12-16 18:13:23 +01:00
if ( ! code_file . is_open ( ) )
{
2019-04-03 16:32:52 +02:00
cerr < < R " (Error : Can't open file " ) " << main_name << R " ( " for writing) " < < endl ;
2009-12-16 18:13:23 +01:00
exit ( EXIT_FAILURE ) ;
}
//Temporary variables declaration
2020-05-06 17:13:47 +02:00
FDIMST_ fdimst ( blocks_temporary_terms_idxs . size ( ) ) ;
2010-10-11 19:21:32 +02:00
fdimst . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
2020-05-13 12:53:47 +02:00
temporary_terms_t temporary_terms_union ;
2020-04-23 16:04:02 +02:00
for ( int block = 0 ; block < static_cast < int > ( blocks . size ( ) ) ; block + + )
2009-12-16 18:13:23 +01:00
{
feedback_variables . clear ( ) ;
if ( block > 0 )
{
FENDBLOCK_ fendblock ;
2010-07-23 11:20:24 +02:00
fendblock . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
int count_u ;
int u_count_int = 0 ;
2020-04-23 16:04:02 +02:00
BlockSimulationType simulation_type = blocks [ block ] . simulation_type ;
int block_size = blocks [ block ] . size ;
int block_mfs = blocks [ block ] . mfs_size ;
int block_recursive = blocks [ block ] . getRecursiveSize ( ) ;
2009-12-16 18:13:23 +01:00
2020-03-20 17:31:14 +01:00
if ( simulation_type = = BlockSimulationType : : solveTwoBoundariesSimple
| | simulation_type = = BlockSimulationType : : solveTwoBoundariesComplete
| | simulation_type = = BlockSimulationType : : solveBackwardComplete
| | simulation_type = = BlockSimulationType : : solveForwardComplete )
2009-12-16 18:13:23 +01:00
{
2020-05-19 17:43:35 +02:00
writeBlockBytecodeBinFile ( basename , block , u_count_int , file_open ) ;
2009-12-16 18:13:23 +01:00
file_open = true ;
}
FBEGINBLOCK_ fbeginblock ( block_mfs ,
simulation_type ,
2020-04-23 16:04:02 +02:00
blocks [ block ] . first_equation ,
2009-12-16 18:13:23 +01:00
block_size ,
2020-04-17 14:55:55 +02:00
endo_idx_block2orig ,
eq_idx_block2orig ,
2020-04-21 18:10:46 +02:00
blocks [ block ] . linear ,
2009-12-16 18:13:23 +01:00
symbol_table . endo_nbr ( ) ,
0 ,
0 ,
2010-07-23 11:20:24 +02:00
u_count_int ,
2019-12-16 19:42:59 +01:00
block_size ) ;
2010-10-11 19:21:32 +02:00
2010-07-23 11:20:24 +02:00
fbeginblock . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
2010-12-31 16:46:09 +01:00
// Get the current code_file position and jump if eval = true
streampos pos1 = code_file . tellp ( ) ;
FJMPIFEVAL_ fjmp_if_eval ( 0 ) ;
fjmp_if_eval . write ( code_file , instruction_number ) ;
int prev_instruction_number = instruction_number ;
2020-05-06 17:13:47 +02:00
//The Temporary terms
deriv_node_temp_terms_t tef_terms ;
2020-05-13 16:58:19 +02:00
/* Keep a backup of temporary_terms_union here, since temp. terms are
2020-05-13 12:53:47 +02:00
written a second time below . This is probably unwanted … */
2020-05-13 16:58:19 +02:00
temporary_terms_t ttu_old = temporary_terms_union ;
auto write_eq_tt = [ & ] ( int eq )
{
for ( auto it : blocks_temporary_terms [ block ] [ eq ] )
{
if ( dynamic_cast < AbstractExternalFunctionNode * > ( it ) )
it - > compileExternalFunctionOutput ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , false , false , tef_terms ) ;
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : TemporaryTerm , static_cast < int > ( blocks_temporary_terms_idxs . at ( it ) ) ) ;
2020-05-13 16:58:19 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
it - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , false , false , tef_terms ) ;
FSTPST_ fstpst ( static_cast < int > ( blocks_temporary_terms_idxs . at ( it ) ) ) ;
fstpst . write ( code_file , instruction_number ) ;
temporary_terms_union . insert ( it ) ;
}
} ;
2020-05-06 17:13:47 +02:00
for ( i = 0 ; i < block_size ; i + + )
{
2020-05-13 16:58:19 +02:00
write_eq_tt ( i ) ;
2010-10-11 19:21:32 +02:00
// The equations
2009-12-16 18:13:23 +01:00
int variable_ID , equation_ID ;
EquationType equ_type ;
switch ( simulation_type )
{
evaluation :
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : evaluateBackward :
case BlockSimulationType : : evaluateForward :
2009-12-16 18:13:23 +01:00
equ_type = getBlockEquationType ( block , i ) ;
2010-01-22 17:42:08 +01:00
{
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : ModelEquation , getBlockEquationID ( block , i ) ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2010-01-22 17:42:08 +01:00
}
2020-03-20 18:00:56 +01:00
if ( equ_type = = EquationType : : evaluate )
2009-12-16 18:13:23 +01:00
{
2020-05-07 15:20:11 +02:00
eq_node = getBlockEquationExpr ( block , i ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2020-05-13 16:58:19 +02:00
rhs - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , false , false ) ;
lhs - > compile ( code_file , instruction_number , true , temporary_terms_union , blocks_temporary_terms_idxs , false , false ) ;
2009-12-16 18:13:23 +01:00
}
2020-05-20 11:49:32 +02:00
else if ( equ_type = = EquationType : : evaluateRenormalized )
2009-12-16 18:13:23 +01:00
{
2020-05-07 15:20:11 +02:00
eq_node = getBlockEquationRenormalizedExpr ( block , i ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2020-05-13 16:58:19 +02:00
rhs - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , false , false ) ;
lhs - > compile ( code_file , instruction_number , true , temporary_terms_union , blocks_temporary_terms_idxs , false , false ) ;
2009-12-16 18:13:23 +01:00
}
break ;
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : solveBackwardComplete :
case BlockSimulationType : : solveForwardComplete :
2020-03-24 18:26:06 +01:00
if ( i < block_recursive )
2009-12-16 18:13:23 +01:00
goto evaluation ;
variable_ID = getBlockVariableID ( block , i ) ;
equation_ID = getBlockEquationID ( block , i ) ;
feedback_variables . push_back ( variable_ID ) ;
2018-06-04 12:52:14 +02:00
Uf [ equation_ID ] . Ufl = nullptr ;
2009-12-16 18:13:23 +01:00
goto end ;
default :
end :
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : ModelEquation , getBlockEquationID ( block , i ) ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2020-05-07 15:20:11 +02:00
eq_node = getBlockEquationExpr ( block , i ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2020-05-13 16:58:19 +02:00
lhs - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , false , false ) ;
rhs - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , false , false ) ;
2009-12-16 18:13:23 +01:00
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : minus ) } ;
2010-07-23 11:20:24 +02:00
fbinary . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
FSTPR_ fstpr ( i - block_recursive ) ;
2010-07-23 11:20:24 +02:00
fstpr . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
FENDEQU_ fendequ ;
2010-07-23 11:20:24 +02:00
fendequ . write ( code_file , instruction_number ) ;
2010-12-10 11:50:27 +01:00
2009-12-16 18:13:23 +01:00
// The Jacobian if we have to solve the block
2020-03-20 17:31:14 +01:00
if ( simulation_type ! = BlockSimulationType : : evaluateBackward
& & simulation_type ! = BlockSimulationType : : evaluateForward )
2009-12-16 18:13:23 +01:00
{
2020-05-13 16:58:19 +02:00
// Write temporary terms for derivatives
write_eq_tt ( blocks [ block ] . size ) ;
2009-12-16 18:13:23 +01:00
switch ( simulation_type )
{
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : solveBackwardSimple :
case BlockSimulationType : : solveForwardSimple :
2010-01-22 17:42:08 +01:00
{
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstEndoDerivative , 0 , 0 ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2010-01-22 17:42:08 +01:00
}
2020-05-13 16:58:19 +02:00
compileDerivative ( code_file , instruction_number , getBlockEquationID ( block , 0 ) , getBlockVariableID ( block , 0 ) , temporary_terms_union , blocks_temporary_terms_idxs ) ;
2009-12-16 14:21:31 +01:00
{
2009-12-16 18:13:23 +01:00
FSTPG_ fstpg ( 0 ) ;
2010-07-23 11:20:24 +02:00
fstpg . write ( code_file , instruction_number ) ;
2009-12-16 14:21:31 +01:00
}
2009-12-16 18:13:23 +01:00
break ;
2009-12-16 14:21:31 +01:00
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : solveBackwardComplete :
case BlockSimulationType : : solveForwardComplete :
2009-12-16 18:13:23 +01:00
count_u = feedback_variables . size ( ) ;
2020-04-24 12:29:02 +02:00
for ( const auto & [ indices , ignore2 ] : blocks_derivatives [ block ] )
2009-12-16 18:13:23 +01:00
{
2020-04-24 12:29:02 +02:00
auto [ eq , var , ignore ] = indices ;
2020-03-24 18:26:06 +01:00
int eqr = getBlockEquationID ( block , eq ) ;
int varr = getBlockVariableID ( block , var ) ;
2010-04-28 16:03:32 +02:00
if ( eq > = block_recursive & & var > = block_recursive )
2009-12-16 18:13:23 +01:00
{
if ( ! Uf [ eqr ] . Ufl )
{
2019-04-23 11:07:32 +02:00
Uf [ eqr ] . Ufl = static_cast < Uff_l * > ( malloc ( sizeof ( Uff_l ) ) ) ;
2009-12-16 18:13:23 +01:00
Uf [ eqr ] . Ufl_First = Uf [ eqr ] . Ufl ;
}
else
{
2019-04-23 11:07:32 +02:00
Uf [ eqr ] . Ufl - > pNext = static_cast < Uff_l * > ( malloc ( sizeof ( Uff_l ) ) ) ;
2009-12-16 18:13:23 +01:00
Uf [ eqr ] . Ufl = Uf [ eqr ] . Ufl - > pNext ;
}
2018-06-04 12:52:14 +02:00
Uf [ eqr ] . Ufl - > pNext = nullptr ;
2009-12-16 18:13:23 +01:00
Uf [ eqr ] . Ufl - > u = count_u ;
Uf [ eqr ] . Ufl - > var = varr ;
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstEndoDerivative , eqr , varr ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2020-05-13 16:58:19 +02:00
compileChainRuleDerivative ( code_file , instruction_number , block , eq , var , 0 , temporary_terms_union , blocks_temporary_terms_idxs ) ;
2009-12-16 18:13:23 +01:00
FSTPSU_ fstpsu ( count_u ) ;
2010-07-23 11:20:24 +02:00
fstpsu . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
count_u + + ;
}
}
2020-03-24 18:26:06 +01:00
for ( i = 0 ; i < block_size ; i + + )
2009-12-16 18:13:23 +01:00
{
2020-03-24 18:26:06 +01:00
if ( i > = block_recursive )
2009-12-16 18:13:23 +01:00
{
FLDR_ fldr ( i - block_recursive ) ;
2010-07-23 11:20:24 +02:00
fldr . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
FLDZ_ fldz ;
2010-07-23 11:20:24 +02:00
fldz . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
v = getBlockEquationID ( block , i ) ;
for ( Uf [ v ] . Ufl = Uf [ v ] . Ufl_First ; Uf [ v ] . Ufl ; Uf [ v ] . Ufl = Uf [ v ] . Ufl - > pNext )
{
FLDSU_ fldsu ( Uf [ v ] . Ufl - > u ) ;
2010-07-23 11:20:24 +02:00
fldsu . write ( code_file , instruction_number ) ;
2018-07-18 15:12:00 +02:00
FLDSV_ fldsv { static_cast < int > ( SymbolType : : endogenous ) , static_cast < unsigned int > ( Uf [ v ] . Ufl - > var ) } ;
2010-07-23 11:20:24 +02:00
fldsv . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : times ) } ;
2010-07-23 11:20:24 +02:00
fbinary . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
FCUML_ fcuml ;
2010-07-23 11:20:24 +02:00
fcuml . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
Uf [ v ] . Ufl = Uf [ v ] . Ufl_First ;
while ( Uf [ v ] . Ufl )
{
Uf [ v ] . Ufl_First = Uf [ v ] . Ufl - > pNext ;
free ( Uf [ v ] . Ufl ) ;
Uf [ v ] . Ufl = Uf [ v ] . Ufl_First ;
}
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : minus ) } ;
2010-07-23 11:20:24 +02:00
fbinary . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
FSTPSU_ fstpsu ( i - block_recursive ) ;
2010-07-23 11:20:24 +02:00
fstpsu . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
break ;
default :
break ;
}
}
2010-10-11 19:21:32 +02:00
// Get the current code_file position and jump = true
streampos pos2 = code_file . tellp ( ) ;
FJMP_ fjmp ( 0 ) ;
fjmp . write ( code_file , instruction_number ) ;
// Set code_file position to previous JMPIFEVAL_ and set the number of instructions to jump
streampos pos3 = code_file . tellp ( ) ;
code_file . seekp ( pos1 ) ;
FJMPIFEVAL_ fjmp_if_eval1 ( instruction_number - prev_instruction_number ) ;
fjmp_if_eval1 . write ( code_file , instruction_number ) ;
code_file . seekp ( pos3 ) ;
2011-02-04 16:25:38 +01:00
prev_instruction_number = instruction_number ;
2010-10-11 19:21:32 +02:00
2020-05-06 17:13:47 +02:00
tef_terms . clear ( ) ;
2020-05-13 16:58:19 +02:00
temporary_terms_union = ttu_old ;
2010-10-11 19:21:32 +02:00
2020-05-06 17:13:47 +02:00
for ( i = 0 ; i < block_size ; i + + )
{
2020-05-13 16:58:19 +02:00
write_eq_tt ( i ) ;
2010-10-11 19:21:32 +02:00
// The equations
int variable_ID , equation_ID ;
EquationType equ_type ;
switch ( simulation_type )
{
evaluation_l :
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : evaluateBackward :
case BlockSimulationType : : evaluateForward :
2010-10-11 19:21:32 +02:00
equ_type = getBlockEquationType ( block , i ) ;
{
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : ModelEquation , getBlockEquationID ( block , i ) ) ;
2010-10-11 19:21:32 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
}
2020-03-20 18:00:56 +01:00
if ( equ_type = = EquationType : : evaluate )
2010-10-11 19:21:32 +02:00
{
2020-05-07 15:20:11 +02:00
eq_node = getBlockEquationExpr ( block , i ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2020-05-13 12:53:47 +02:00
rhs - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , false , false ) ;
lhs - > compile ( code_file , instruction_number , true , temporary_terms_union , blocks_temporary_terms_idxs , false , false ) ;
2010-10-11 19:21:32 +02:00
}
2020-05-20 11:49:32 +02:00
else if ( equ_type = = EquationType : : evaluateRenormalized )
2010-10-11 19:21:32 +02:00
{
2020-05-07 15:20:11 +02:00
eq_node = getBlockEquationRenormalizedExpr ( block , i ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2020-05-13 12:53:47 +02:00
rhs - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , false , false ) ;
lhs - > compile ( code_file , instruction_number , true , temporary_terms_union , blocks_temporary_terms_idxs , false , false ) ;
2010-10-11 19:21:32 +02:00
}
break ;
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : solveBackwardComplete :
case BlockSimulationType : : solveForwardComplete :
2020-03-24 18:26:06 +01:00
if ( i < block_recursive )
2010-10-11 19:21:32 +02:00
goto evaluation_l ;
variable_ID = getBlockVariableID ( block , i ) ;
equation_ID = getBlockEquationID ( block , i ) ;
feedback_variables . push_back ( variable_ID ) ;
2018-06-04 12:52:14 +02:00
Uf [ equation_ID ] . Ufl = nullptr ;
2010-10-11 19:21:32 +02:00
goto end_l ;
default :
end_l :
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : ModelEquation , getBlockEquationID ( block , i ) ) ;
2010-10-11 19:21:32 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2020-05-07 15:20:11 +02:00
eq_node = getBlockEquationExpr ( block , i ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2020-05-13 12:53:47 +02:00
lhs - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , false , false ) ;
rhs - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , false , false ) ;
2010-10-11 19:21:32 +02:00
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : minus ) } ;
2010-10-11 19:21:32 +02:00
fbinary . write ( code_file , instruction_number ) ;
FSTPR_ fstpr ( i - block_recursive ) ;
fstpr . write ( code_file , instruction_number ) ;
}
}
FENDEQU_ fendequ_l ;
fendequ_l . write ( code_file , instruction_number ) ;
// The Jacobian if we have to solve the block determinsitic bloc
2020-05-13 16:58:19 +02:00
// Write temporary terms for derivatives
write_eq_tt ( blocks [ block ] . size ) ;
2010-10-11 19:21:32 +02:00
switch ( simulation_type )
{
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : solveBackwardSimple :
case BlockSimulationType : : solveForwardSimple :
2010-10-11 19:21:32 +02:00
{
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstEndoDerivative , 0 , 0 ) ;
2010-10-11 19:21:32 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
}
2020-05-13 12:53:47 +02:00
compileDerivative ( code_file , instruction_number , getBlockEquationID ( block , 0 ) , getBlockVariableID ( block , 0 ) , temporary_terms_union , blocks_temporary_terms_idxs ) ;
2010-10-11 19:21:32 +02:00
{
2011-02-04 16:25:38 +01:00
FSTPG2_ fstpg2 ( 0 , 0 ) ;
2010-10-11 19:21:32 +02:00
fstpg2 . write ( code_file , instruction_number ) ;
}
break ;
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : evaluateBackward :
case BlockSimulationType : : evaluateForward :
case BlockSimulationType : : solveBackwardComplete :
case BlockSimulationType : : solveForwardComplete :
2010-10-11 19:21:32 +02:00
count_u = feedback_variables . size ( ) ;
2020-04-24 12:29:02 +02:00
for ( const auto & [ indices , ignore2 ] : blocks_derivatives [ block ] )
2010-10-11 19:21:32 +02:00
{
2020-04-24 12:29:02 +02:00
auto & [ eq , var , ignore ] = indices ;
2020-03-24 18:26:06 +01:00
int eqr = getBlockEquationID ( block , eq ) ;
int varr = getBlockVariableID ( block , var ) ;
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstEndoDerivative , eqr , varr , 0 ) ;
2010-10-11 19:21:32 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2020-05-13 12:53:47 +02:00
compileChainRuleDerivative ( code_file , instruction_number , block , eq , var , 0 , temporary_terms_union , blocks_temporary_terms_idxs ) ;
2010-10-11 19:21:32 +02:00
2011-02-04 16:25:38 +01:00
FSTPG2_ fstpg2 ( eq , var ) ;
2010-10-11 19:21:32 +02:00
fstpg2 . write ( code_file , instruction_number ) ;
}
break ;
default :
break ;
}
// Set codefile position to previous JMP_ and set the number of instructions to jump
pos1 = code_file . tellp ( ) ;
code_file . seekp ( pos2 ) ;
FJMP_ fjmp1 ( instruction_number - prev_instruction_number ) ;
fjmp1 . write ( code_file , instruction_number ) ;
code_file . seekp ( pos1 ) ;
2009-12-16 18:13:23 +01:00
}
FENDBLOCK_ fendblock ;
2010-07-23 11:20:24 +02:00
fendblock . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
FEND_ fend ;
2010-07-23 11:20:24 +02:00
fend . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
code_file . close ( ) ;
}
2009-12-16 14:21:31 +01:00
void
2020-05-19 17:43:35 +02:00
StaticModel : : writeBlockBytecodeBinFile ( const string & basename , int num ,
int & u_count_int , bool & file_open ) const
2009-12-16 18:13:23 +01:00
{
int j ;
std : : ofstream SaveCode ;
2018-06-27 15:01:31 +02:00
string filename = basename + " /model/bytecode/static.bin " ;
2009-12-16 18:13:23 +01:00
if ( file_open )
2018-06-27 15:01:31 +02:00
SaveCode . open ( filename , ios : : out | ios : : in | ios : : binary | ios : : ate ) ;
2009-12-16 18:13:23 +01:00
else
2018-06-27 15:01:31 +02:00
SaveCode . open ( filename , ios : : out | ios : : binary ) ;
2009-12-16 18:13:23 +01:00
if ( ! SaveCode . is_open ( ) )
{
2018-06-27 15:01:31 +02:00
cerr < < " Error : Can't open file " < < filename < < " for writing " < < endl ;
2009-12-16 18:13:23 +01:00
exit ( EXIT_FAILURE ) ;
}
u_count_int = 0 ;
2020-04-23 16:04:02 +02:00
int block_size = blocks [ num ] . size ;
int block_mfs = blocks [ num ] . mfs_size ;
int block_recursive = blocks [ num ] . getRecursiveSize ( ) ;
2020-04-24 12:29:02 +02:00
for ( const auto & [ indices , ignore2 ] : blocks_derivatives [ num ] )
2009-12-16 18:13:23 +01:00
{
2020-04-24 12:29:02 +02:00
auto [ eq , var , ignore ] = indices ;
2009-12-16 18:13:23 +01:00
int lag = 0 ;
2010-04-28 16:03:32 +02:00
if ( eq > = block_recursive & & var > = block_recursive )
2009-12-16 18:13:23 +01:00
{
int v = eq - block_recursive ;
SaveCode . write ( reinterpret_cast < char * > ( & v ) , sizeof ( v ) ) ;
int varr = var - block_recursive ;
SaveCode . write ( reinterpret_cast < char * > ( & varr ) , sizeof ( varr ) ) ;
SaveCode . write ( reinterpret_cast < char * > ( & lag ) , sizeof ( lag ) ) ;
int u = u_count_int + block_mfs ;
SaveCode . write ( reinterpret_cast < char * > ( & u ) , sizeof ( u ) ) ;
u_count_int + + ;
}
}
2020-03-24 18:26:06 +01:00
for ( j = block_recursive ; j < block_size ; j + + )
2009-12-16 18:13:23 +01:00
{
2020-03-24 18:26:06 +01:00
int varr = getBlockVariableID ( num , j ) ;
2009-12-16 18:13:23 +01:00
SaveCode . write ( reinterpret_cast < char * > ( & varr ) , sizeof ( varr ) ) ;
}
2020-03-24 18:26:06 +01:00
for ( j = block_recursive ; j < block_size ; j + + )
2009-12-16 18:13:23 +01:00
{
2020-03-24 18:26:06 +01:00
int eqr = getBlockEquationID ( num , j ) ;
2009-12-16 18:13:23 +01:00
SaveCode . write ( reinterpret_cast < char * > ( & eqr ) , sizeof ( eqr ) ) ;
}
SaveCode . close ( ) ;
}
2009-12-16 14:21:31 +01:00
void
2018-12-20 17:04:28 +01:00
StaticModel : : computingPass ( int derivsOrder , int paramsDerivsOrder , const eval_context_t & eval_context , bool no_tmp_terms , bool block , bool bytecode )
2009-12-16 14:21:31 +01:00
{
2011-06-22 11:34:25 +02:00
initializeVariablesAndEquations ( ) ;
2016-03-18 14:55:14 +01:00
vector < BinaryOpNode * > neweqs ;
2020-03-24 18:26:06 +01:00
for ( int eq = 0 ; eq < static_cast < int > ( equations . size ( ) - aux_equations . size ( ) ) ; eq + + )
2016-03-21 11:51:48 +01:00
{
expr_t eq_tmp = equations [ eq ] - > substituteStaticAuxiliaryVariable ( ) ;
neweqs . push_back ( dynamic_cast < BinaryOpNode * > ( eq_tmp - > toStatic ( * this ) ) ) ;
}
2016-03-18 14:55:14 +01:00
2019-12-20 16:59:30 +01:00
for ( auto & aux_equation : aux_equations )
2016-03-21 20:42:35 +01:00
{
2018-06-04 12:26:16 +02:00
expr_t eq_tmp = aux_equation - > substituteStaticAuxiliaryDefinition ( ) ;
2016-03-21 20:42:35 +01:00
neweqs . push_back ( dynamic_cast < BinaryOpNode * > ( eq_tmp - > toStatic ( * this ) ) ) ;
}
2017-06-14 07:01:31 +02:00
2016-03-18 14:55:14 +01:00
equations . clear ( ) ;
2017-06-14 07:01:31 +02:00
copy ( neweqs . begin ( ) , neweqs . end ( ) , back_inserter ( equations ) ) ;
2009-12-16 14:21:31 +01:00
2018-11-22 14:32:40 +01:00
// Compute derivatives w.r. to all endogenous
set < int > vars ;
2009-12-16 18:13:23 +01:00
for ( int i = 0 ; i < symbol_table . endo_nbr ( ) ; i + + )
2016-03-21 11:51:48 +01:00
{
2018-07-17 18:34:07 +02:00
int id = symbol_table . getID ( SymbolType : : endogenous , i ) ;
2016-03-21 20:42:35 +01:00
// if (!symbol_table.isAuxiliaryVariableButNotMultiplier(id))
vars . insert ( getDerivID ( id , 0 ) ) ;
2017-06-14 07:01:31 +02:00
}
2009-12-16 14:21:31 +01:00
// Launch computations
2018-12-20 17:04:28 +01:00
cout < < " Computing static model derivatives (order " < < derivsOrder < < " ). " < < endl ;
2009-12-16 14:21:31 +01:00
2018-11-22 14:32:40 +01:00
computeDerivatives ( derivsOrder , vars ) ;
2013-11-22 21:09:04 +01:00
2016-05-18 12:26:19 +02:00
if ( paramsDerivsOrder > 0 )
2012-11-29 18:07:48 +01:00
{
2018-12-20 17:04:28 +01:00
cout < < " Computing static model derivatives w.r.t. parameters (order " < < paramsDerivsOrder < < " ). " < < endl ;
2016-05-18 12:26:19 +02:00
computeParamsDerivatives ( paramsDerivsOrder ) ;
2012-11-29 18:07:48 +01:00
}
2009-12-16 14:21:31 +01:00
if ( block )
{
2020-05-06 18:09:44 +02:00
auto contemporaneous_jacobian = evaluateAndReduceJacobian ( eval_context ) ;
2009-12-16 14:21:31 +01:00
2020-05-06 18:09:44 +02:00
computeNonSingularNormalization ( contemporaneous_jacobian ) ;
2009-12-16 14:21:31 +01:00
2020-04-30 12:48:16 +02:00
auto [ prologue , epilogue ] = computePrologueAndEpilogue ( ) ;
2009-12-16 14:21:31 +01:00
2020-03-30 14:51:53 +02:00
auto first_order_endo_derivatives = collectFirstOrderDerivativesEndogenous ( ) ;
2009-12-16 14:21:31 +01:00
2020-03-20 15:23:23 +01:00
equationTypeDetermination ( first_order_endo_derivatives , mfs ) ;
2009-12-16 14:21:31 +01:00
2018-12-20 17:04:28 +01:00
cout < < " Finding the optimal block decomposition of the model ... " < < endl ;
2009-12-16 14:21:31 +01:00
2020-04-30 12:48:16 +02:00
computeBlockDecomposition ( prologue , epilogue ) ;
2009-12-16 14:21:31 +01:00
2020-04-30 12:48:16 +02:00
reduceBlockDecomposition ( ) ;
2009-12-16 14:21:31 +01:00
2020-04-15 17:56:28 +02:00
printBlockDecomposition ( ) ;
2009-12-16 14:21:31 +01:00
2020-03-19 17:46:10 +01:00
computeChainRuleJacobian ( ) ;
2009-12-16 14:21:31 +01:00
2020-03-20 15:23:23 +01:00
determineLinearBlocks ( ) ;
2009-12-16 14:21:31 +01:00
if ( ! no_tmp_terms )
2020-05-06 17:13:47 +02:00
computeBlockTemporaryTerms ( ) ;
2009-12-16 14:21:31 +01:00
}
else
2010-01-22 11:03:29 +01:00
{
2018-09-25 15:56:52 +02:00
computeTemporaryTerms ( true , no_tmp_terms ) ;
2018-11-16 18:13:34 +01:00
/* Must be called after computeTemporaryTerms(), because it depends on
temporary_terms_mlv to be filled */
if ( paramsDerivsOrder > 0 & & ! no_tmp_terms )
computeParamsDerivativesTemporaryTerms ( ) ;
2010-01-22 11:03:29 +01:00
}
2009-04-14 16:39:53 +02:00
}
void
2018-06-27 15:01:31 +02:00
StaticModel : : writeStaticMFile ( const string & basename ) const
2009-04-14 16:39:53 +02:00
{
2018-06-27 15:01:31 +02:00
writeStaticModel ( basename , false , false ) ;
2018-03-27 17:14:30 +02:00
}
2009-12-16 14:21:31 +01:00
2018-03-27 17:14:30 +02:00
void
StaticModel : : writeWrapperFunctions ( const string & basename , const string & ending ) const
{
string name ;
if ( ending = = " g1 " )
2018-06-27 15:01:31 +02:00
name = " static_resid_g1 " ;
2018-03-27 17:14:30 +02:00
else if ( ending = = " g2 " )
2018-06-27 15:01:31 +02:00
name = " static_resid_g1_g2 " ;
2018-03-27 17:14:30 +02:00
else if ( ending = = " g3 " )
2018-06-27 15:01:31 +02:00
name = " static_resid_g1_g2_g3 " ;
2018-03-27 17:14:30 +02:00
2018-06-27 15:01:31 +02:00
string filename = packageDir ( basename ) + " / " + name + " .m " ;
2009-12-16 14:21:31 +01:00
ofstream output ;
2018-06-27 15:12:12 +02:00
output . open ( filename , ios : : out | ios : : binary ) ;
2009-12-16 14:21:31 +01:00
if ( ! output . is_open ( ) )
{
2018-03-27 17:14:30 +02:00
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( ending = = " g1 " )
2018-05-23 17:32:50 +02:00
output < < " function [residual, g1] = " < < name < < " (T, y, x, params, T_flag) " < < endl
< < " % function [residual, g1] = " < < name < < " (T, y, x, params, T_flag) " < < endl ;
2018-03-27 17:14:30 +02:00
else if ( ending = = " g2 " )
2018-05-23 17:32:50 +02:00
output < < " function [residual, g1, g2] = " < < name < < " (T, y, x, params, T_flag) " < < endl
< < " % function [residual, g1, g2] = " < < name < < " (T, y, x, params, T_flag) " < < endl ;
2018-03-27 17:14:30 +02:00
else if ( ending = = " g3 " )
2018-05-23 17:32:50 +02:00
output < < " function [residual, g1, g2, g3] = " < < name < < " (T, y, x, params, T_flag) " < < endl
< < " % function [residual, g1, g2, g3] = " < < name < < " (T, y, x, params, T_flag) " < < endl ;
2018-03-27 17:14:30 +02:00
output < < " % " < < endl
< < " % Wrapper function automatically created by Dynare " < < endl
2018-05-23 17:32:50 +02:00
< < " % " < < endl
< < endl
< < " if T_flag " < < endl
2018-06-27 15:01:31 +02:00
< < " T = " < < basename < < " .static_ " < < ending < < " _tt(T, y, x, params); " < < endl
2018-05-23 17:32:50 +02:00
< < " end " < < endl ;
2018-03-27 17:14:30 +02:00
if ( ending = = " g1 " )
2018-06-27 15:01:31 +02:00
output < < " residual = " < < basename < < " .static_resid(T, y, x, params, false); " < < endl
< < " g1 = " < < basename < < " .static_g1(T, y, x, params, false); " < < endl ;
2018-03-27 17:14:30 +02:00
else if ( ending = = " g2 " )
2018-06-27 15:01:31 +02:00
output < < " [residual, g1] = " < < basename < < " .static_resid_g1(T, y, x, params, false); " < < endl
< < " g2 = " < < basename < < " .static_g2(T, y, x, params, false); " < < endl ;
2018-03-27 17:14:30 +02:00
else if ( ending = = " g3 " )
2018-06-27 15:01:31 +02:00
output < < " [residual, g1, g2] = " < < basename < < " .static_resid_g1_g2(T, y, x, params, false); " < < endl
< < " g3 = " < < basename < < " .static_g3(T, y, x, params, false); " < < endl ;
2018-03-27 17:14:30 +02:00
output < < endl < < " end " < < endl ;
output . close ( ) ;
}
void
2018-06-27 15:01:31 +02:00
StaticModel : : writeStaticModelHelper ( const string & basename ,
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 ,
const ostringstream & init_s , const ostringstream & end_s ,
const ostringstream & s , const ostringstream & s_tt ) const
{
2018-06-27 15:01:31 +02:00
string filename = packageDir ( basename ) + " / " + name_tt + " .m " ;
2018-03-27 17:14:30 +02:00
ofstream output ;
2018-06-27 15:12:12 +02:00
output . open ( filename , ios : : out | ios : : binary ) ;
2018-03-27 17:14:30 +02:00
if ( ! output . is_open ( ) )
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
2009-12-16 14:21:31 +01:00
exit ( EXIT_FAILURE ) ;
}
2018-03-27 17:14:30 +02:00
output < < " function T = " < < name_tt < < " (T, y, x, params) " < < endl
< < " % function T = " < < name_tt < < " (T, y, x, params) " < < endl
2009-07-07 16:20:48 +02:00
< < " % " < < endl
2018-03-27 17:14:30 +02:00
< < " % File created by Dynare Preprocessor from .mod file " < < endl
2009-07-07 16:20:48 +02:00
< < " % " < < endl
2018-03-27 17:14:30 +02:00
< < " % Inputs: " < < endl
< < " % T [#temp variables by 1] double vector of temporary terms to be filled by function " < < endl
< < " % y [M_.endo_nbr by 1] double vector of endogenous variables in declaration order " < < endl
< < " % x [M_.exo_nbr by 1] double vector of exogenous variables in declaration order " < < endl
< < " % params [M_.param_nbr by 1] double vector of parameter values in declaration order " < < endl
2013-07-28 11:32:14 +02:00
< < " % " < < endl
2018-03-27 17:14:30 +02:00
< < " % Output: " < < endl
< < " % T [#temp variables by 1] double vector of temporary terms " < < endl
< < " % " < < endl < < endl
< < " assert(length(T) >= " < < ttlen < < " ); " < < endl
< < endl ;
if ( ! previous_tt_name . empty ( ) )
2018-06-27 15:01:31 +02:00
output < < " T = " < < basename < < " . " < < previous_tt_name < < " (T, y, x, params); " < < endl < < endl ;
2018-03-27 17:14:30 +02:00
output < < s_tt . str ( ) < < endl
< < " end " < < endl ;
output . close ( ) ;
2018-06-27 15:01:31 +02:00
filename = packageDir ( basename ) + " / " + name + " .m " ;
2018-06-27 15:12:12 +02:00
output . open ( filename , ios : : out | ios : : binary ) ;
2018-03-27 17:14:30 +02:00
if ( ! output . is_open ( ) )
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " function " < < retvalname < < " = " < < name < < " (T, y, x, params, T_flag) " < < endl
< < " % function " < < retvalname < < " = " < < name < < " (T, y, x, params, T_flag) " < < endl
2013-07-28 11:32:14 +02:00
< < " % " < < endl
2018-03-27 17:14:30 +02:00
< < " % File created by Dynare Preprocessor from .mod file " < < endl
2017-06-14 07:01:31 +02:00
< < " % " < < endl
2018-03-27 17:14:30 +02:00
< < " % Inputs: " < < endl
< < " % T [#temp variables by 1] double vector of temporary terms to be filled by function " < < endl
< < " % y [M_.endo_nbr by 1] double vector of endogenous variables in declaration order " < < endl
< < " % x [M_.exo_nbr by 1] double vector of exogenous variables in declaration order " < < endl
< < " % params [M_.param_nbr by 1] double vector of parameter values in declaration order " < < endl
< < " % to evaluate the model " < < endl
< < " % T_flag boolean boolean flag saying whether or not to calculate temporary terms " < < endl
< < " % " < < endl
< < " % Output: " < < endl
< < " % " < < retvalname < < endl
< < " % " < < endl < < endl ;
if ( ! name_tt . empty ( ) )
output < < " if T_flag " < < endl
2018-06-27 15:01:31 +02:00
< < " T = " < < basename < < " . " < < name_tt < < " (T, y, x, params); " < < endl
2018-03-27 17:14:30 +02:00
< < " end " < < endl ;
output < < init_s . str ( ) < < endl
< < s . str ( )
< < end_s . str ( ) < < endl
< < " end " < < endl ;
2011-08-18 12:44:11 +02:00
output . close ( ) ;
}
2018-05-23 16:10:26 +02:00
void
2018-06-27 15:01:31 +02:00
StaticModel : : writeStaticMatlabCompatLayer ( const string & basename ) const
2018-05-23 16:10:26 +02:00
{
2018-06-27 15:01:31 +02:00
string filename = packageDir ( basename ) + " /static.m " ;
2018-05-23 16:10:26 +02:00
ofstream output ;
2018-06-27 15:12:12 +02:00
output . open ( filename , ios : : out | ios : : binary ) ;
2018-05-23 16:10:26 +02:00
if ( ! output . is_open ( ) )
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-11-15 16:39:53 +01:00
int ntt = temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) + temporary_terms_derivatives [ 2 ] . size ( ) + temporary_terms_derivatives [ 3 ] . size ( ) ;
2018-05-23 16:10:26 +02:00
2018-06-27 15:01:31 +02:00
output < < " function [residual, g1, g2, g3] = static(y, x, params) " < < endl
2018-05-23 16:10:26 +02:00
< < " T = NaN( " < < ntt < < " , 1); " < < endl
< < " if nargout <= 1 " < < endl
2018-06-27 15:01:31 +02:00
< < " residual = " < < basename < < " .static_resid(T, y, x, params, true); " < < endl
2018-05-23 16:10:26 +02:00
< < " elseif nargout == 2 " < < endl
2018-06-27 15:01:31 +02:00
< < " [residual, g1] = " < < basename < < " .static_resid_g1(T, y, x, params, true); " < < endl
2018-05-23 16:10:26 +02:00
< < " elseif nargout == 3 " < < endl
2018-06-27 15:01:31 +02:00
< < " [residual, g1, g2] = " < < basename < < " .static_resid_g1_g2(T, y, x, params, true); " < < endl
2018-05-23 16:10:26 +02:00
< < " else " < < endl
2018-06-27 15:01:31 +02:00
< < " [residual, g1, g2, g3] = " < < basename < < " .static_resid_g1_g2_g3(T, y, x, params, true); " < < endl
2018-05-23 16:10:26 +02:00
< < " end " < < endl
< < " end " < < endl ;
output . close ( ) ;
}
2011-08-18 12:44:11 +02:00
void
2015-07-27 15:33:38 +02:00
StaticModel : : writeStaticModel ( ostream & StaticOutput , bool use_dll , bool julia ) const
2011-08-18 12:44:11 +02:00
{
2018-03-27 17:14:30 +02:00
writeStaticModel ( " " , StaticOutput , use_dll , julia ) ;
}
void
StaticModel : : writeStaticModel ( const string & basename , bool use_dll , bool julia ) const
{
ofstream StaticOutput ;
writeStaticModel ( basename , StaticOutput , use_dll , julia ) ;
}
void
StaticModel : : writeStaticModel ( const string & basename ,
ostream & StaticOutput , bool use_dll , bool julia ) const
{
2019-12-20 16:59:30 +01:00
vector < ostringstream > d_output ( derivatives . size ( ) ) ; // Derivatives output (at all orders, including 0=residual)
2019-04-12 15:41:52 +02:00
vector < ostringstream > tt_output ( derivatives . size ( ) ) ; // Temp terms output (at all orders)
2018-03-27 17:14:30 +02:00
2018-09-05 18:27:13 +02:00
ExprNodeOutputType output_type = ( use_dll ? ExprNodeOutputType : : CStaticModel :
julia ? ExprNodeOutputType : : juliaStaticModel : ExprNodeOutputType : : matlabStaticModel ) ;
2009-07-07 16:20:48 +02:00
2011-08-18 12:44:11 +02:00
deriv_node_temp_terms_t tef_terms ;
2018-03-27 17:14:30 +02:00
temporary_terms_t temp_term_union ;
2018-11-16 18:13:34 +01:00
writeModelLocalVariableTemporaryTerms ( temp_term_union , temporary_terms_idxs ,
2019-04-12 15:41:52 +02:00
tt_output [ 0 ] , output_type , tef_terms ) ;
2018-03-27 17:14:30 +02:00
2018-11-15 16:39:53 +01:00
writeTemporaryTerms ( temporary_terms_derivatives [ 0 ] ,
2018-05-24 19:29:53 +02:00
temp_term_union ,
2018-05-28 15:23:15 +02:00
temporary_terms_idxs ,
2019-04-12 15:41:52 +02:00
tt_output [ 0 ] , output_type , tef_terms ) ;
2018-03-27 17:14:30 +02:00
2019-04-12 15:41:52 +02:00
writeModelEquations ( d_output [ 0 ] , output_type , temp_term_union ) ;
2009-04-14 16:39:53 +02:00
2013-11-22 21:09:04 +01:00
int nrows = equations . size ( ) ;
int JacobianColsNbr = symbol_table . endo_nbr ( ) ;
int hessianColsNbr = JacobianColsNbr * JacobianColsNbr ;
2019-04-18 17:07:55 +02:00
auto getJacobCol = [ this ] ( int var ) { return symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( var ) ) ; } ;
2019-04-12 15:41:52 +02:00
2009-04-14 16:39:53 +02:00
// Write Jacobian w.r. to endogenous only
2018-11-15 16:39:53 +01:00
if ( ! derivatives [ 1 ] . empty ( ) )
2018-03-27 17:14:30 +02:00
{
2018-11-15 16:39:53 +01:00
writeTemporaryTerms ( temporary_terms_derivatives [ 1 ] ,
2018-05-24 19:29:53 +02:00
temp_term_union ,
2018-05-28 15:23:15 +02:00
temporary_terms_idxs ,
2019-04-12 15:41:52 +02:00
tt_output [ 1 ] , output_type , tef_terms ) ;
2018-11-16 16:53:07 +01:00
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d1 ] : derivatives [ 1 ] )
2018-11-16 16:53:07 +01:00
{
2019-12-16 19:42:59 +01:00
auto [ eq , var ] = vectorToTuple < 2 > ( indices ) ;
2018-11-16 16:53:07 +01:00
2019-04-12 15:41:52 +02:00
jacobianHelper ( d_output [ 1 ] , eq , getJacobCol ( var ) , output_type ) ;
d_output [ 1 ] < < " = " ;
d1 - > writeOutput ( d_output [ 1 ] , output_type ,
2018-11-16 16:53:07 +01:00
temp_term_union , temporary_terms_idxs , tef_terms ) ;
2019-04-12 15:41:52 +02:00
d_output [ 1 ] < < " ; " < < endl ;
2018-11-16 16:53:07 +01:00
}
2009-04-14 16:39:53 +02:00
}
2019-04-12 15:41:52 +02:00
// Write derivatives for order ≥ 2
for ( size_t i = 2 ; i < derivatives . size ( ) ; i + + )
if ( ! derivatives [ i ] . empty ( ) )
{
writeTemporaryTerms ( temporary_terms_derivatives [ i ] ,
temp_term_union ,
temporary_terms_idxs ,
tt_output [ i ] , output_type , tef_terms ) ;
/* When creating the sparse matrix (in MATLAB or C mode), since storage
is in column - major order , output the first column , then the second ,
then the third . This gives a significant performance boost in use_dll
mode ( at both compilation and runtime ) , because it facilitates memory
accesses and expression reusage . */
2020-06-23 17:50:50 +02:00
ostringstream i_output , j_output , v_output ;
2019-04-12 15:41:52 +02:00
int k = 0 ; // Current line index in the 3-column matrix
2019-12-16 19:42:59 +01:00
for ( const auto & [ vidx , d ] : derivatives [ i ] )
2019-04-12 15:41:52 +02:00
{
int eq = vidx [ 0 ] ;
2011-08-18 12:44:11 +02:00
2019-04-12 15:41:52 +02:00
int col_idx = 0 ;
for ( size_t j = 1 ; j < vidx . size ( ) ; j + + )
{
col_idx * = JacobianColsNbr ;
col_idx + = getJacobCol ( vidx [ j ] ) ;
}
2015-08-20 12:18:19 +02:00
2018-09-05 18:27:13 +02:00
if ( output_type = = ExprNodeOutputType : : juliaStaticModel )
2019-04-12 15:41:52 +02:00
{
d_output [ i ] < < " @inbounds " < < " g " < < i < < " [ " < < eq + 1 < < " , " < < col_idx + 1 < < " ] = " ;
d - > writeOutput ( d_output [ i ] , output_type , temp_term_union , temporary_terms_idxs , tef_terms ) ;
d_output [ i ] < < endl ;
}
2018-03-27 17:14:30 +02:00
else
{
2020-06-23 17:50:50 +02:00
i_output < < " g " < < i < < " _i " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " = " < < eq + 1 < < " ; " < < endl ;
j_output < < " g " < < i < < " _j " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " = " < < col_idx + 1 < < " ; " < < endl ;
v_output < < " g " < < i < < " _v " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
d - > writeOutput ( v_output , output_type , temp_term_union , temporary_terms_idxs , tef_terms ) ;
v_output < < " ; " < < endl ;
2015-08-20 12:18:19 +02:00
2018-03-27 17:14:30 +02:00
k + + ;
}
2018-11-19 15:18:09 +01:00
2019-06-17 15:28:33 +02:00
// Output symetric elements at order 2
2019-04-12 15:41:52 +02:00
if ( i = = 2 & & vidx [ 1 ] ! = vidx [ 2 ] )
{
int col_idx_sym = getJacobCol ( vidx [ 2 ] ) * JacobianColsNbr + getJacobCol ( vidx [ 1 ] ) ;
if ( output_type = = ExprNodeOutputType : : juliaStaticModel )
d_output [ 2 ] < < " @inbounds g2[ " < < eq + 1 < < " , " < < col_idx_sym + 1 < < " ] = "
< < " g2[ " < < eq + 1 < < " , " < < col_idx + 1 < < " ] " < < endl ;
else
{
2020-06-23 17:50:50 +02:00
i_output < < " g " < < i < < " _i " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " = " < < eq + 1 < < " ; " < < endl ;
j_output < < " g " < < i < < " _j " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " = " < < col_idx_sym + 1 < < " ; " < < endl ;
v_output < < " g " < < i < < " _v " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = "
< < " g " < < i < < " _v " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k - 1 + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " ; " < < endl ;
2019-04-12 15:41:52 +02:00
k + + ;
}
}
}
if ( output_type ! = ExprNodeOutputType : : juliaStaticModel )
2020-06-23 17:50:50 +02:00
d_output [ i ] < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
2019-04-12 15:41:52 +02:00
}
2013-11-22 21:09:04 +01:00
2018-09-05 18:27:13 +02:00
if ( output_type = = ExprNodeOutputType : : matlabStaticModel )
2011-08-18 12:44:11 +02:00
{
2016-12-28 14:02:50 +01:00
// Check that we don't have more than 32 nested parenthesis because Matlab does not suppor this. See Issue #1201
2016-12-30 11:26:56 +01:00
map < string , string > tmp_paren_vars ;
2017-01-05 15:19:13 +01:00
bool message_printed = false ;
2019-04-12 15:41:52 +02:00
for ( auto & it : tt_output )
fixNestedParenthesis ( it , tmp_paren_vars , message_printed ) ;
for ( auto & it : d_output )
fixNestedParenthesis ( it , tmp_paren_vars , message_printed ) ;
2018-03-27 17:14:30 +02:00
ostringstream init_output , end_output ;
init_output < < " residual = zeros( " < < equations . size ( ) < < " , 1); " ;
end_output < < " if ~isreal(residual) " < < endl
< < " residual = real(residual)+imag(residual).^2; " < < endl
< < " end " ;
2018-06-27 15:01:31 +02:00
writeStaticModelHelper ( basename , " static_resid " , " residual " , " static_resid_tt " ,
2018-11-15 16:39:53 +01:00
temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) ,
2018-03-27 17:14:30 +02:00
" " , init_output , end_output ,
2019-04-12 15:41:52 +02:00
d_output [ 0 ] , tt_output [ 0 ] ) ;
2018-03-27 17:14:30 +02:00
2019-04-12 15:41:52 +02:00
init_output . str ( " " ) ;
end_output . str ( " " ) ;
2018-03-27 17:14:30 +02:00
init_output < < " g1 = zeros( " < < equations . size ( ) < < " , " < < symbol_table . endo_nbr ( ) < < " ); " ;
end_output < < " if ~isreal(g1) " < < endl
< < " g1 = real(g1)+2*imag(g1); " < < endl
< < " end " ;
2018-06-27 15:01:31 +02:00
writeStaticModelHelper ( basename , " static_g1 " , " g1 " , " static_g1_tt " ,
2018-11-15 16:39:53 +01:00
temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) ,
2018-06-27 15:01:31 +02:00
" static_resid_tt " ,
2018-03-27 17:14:30 +02:00
init_output , end_output ,
2019-04-12 15:41:52 +02:00
d_output [ 1 ] , tt_output [ 1 ] ) ;
2018-06-27 15:01:31 +02:00
writeWrapperFunctions ( basename , " g1 " ) ;
2018-03-27 17:14:30 +02:00
2019-04-12 15:41:52 +02:00
// For order ≥ 2
int ncols = JacobianColsNbr ;
int ntt = temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) ;
for ( size_t i = 2 ; i < derivatives . size ( ) ; i + + )
2018-03-27 17:14:30 +02:00
{
2019-04-12 15:41:52 +02:00
ncols * = JacobianColsNbr ;
ntt + = temporary_terms_derivatives [ i ] . size ( ) ;
string gname = " g " + to_string ( i ) ;
string gprevname = " g " + to_string ( i - 1 ) ;
init_output . str ( " " ) ;
end_output . str ( " " ) ;
if ( derivatives [ i ] . size ( ) )
{
2020-06-23 17:50:50 +02:00
init_output < < gname < < " _i = zeros( " < < NNZDerivatives [ i ] < < " ,1); " < < endl
< < gname < < " _j = zeros( " < < NNZDerivatives [ i ] < < " ,1); " < < endl
< < gname < < " _v = zeros( " < < NNZDerivatives [ i ] < < " ,1); " < < endl ;
2019-04-12 15:41:52 +02:00
end_output < < gname < < " = sparse( "
2020-06-23 17:50:50 +02:00
< < gname < < " _i, " < < gname < < " _j, " < < gname < < " _v, "
2019-04-12 15:41:52 +02:00
< < nrows < < " , " < < ncols < < " ); " ;
}
else
init_output < < gname < < " = sparse([],[],[], " < < nrows < < " , " < < ncols < < " ); " ;
writeStaticModelHelper ( basename , " static_ " + gname , gname ,
" static_ " + gname + " _tt " ,
ntt ,
" static_ " + gprevname + " _tt " ,
init_output , end_output ,
d_output [ i ] , tt_output [ i ] ) ;
if ( i < = 3 )
writeWrapperFunctions ( basename , gname ) ;
2018-03-27 17:14:30 +02:00
}
2018-05-23 16:10:26 +02:00
2018-06-27 15:01:31 +02:00
writeStaticMatlabCompatLayer ( basename ) ;
2015-07-27 15:33:38 +02:00
}
2018-09-05 18:27:13 +02:00
else if ( output_type = = ExprNodeOutputType : : CStaticModel )
2011-08-18 12:44:11 +02:00
{
2019-04-12 15:41:52 +02:00
for ( size_t i = 0 ; i < d_output . size ( ) ; i + + )
{
string funcname = i = = 0 ? " resid " : " g " + to_string ( i ) ;
2020-09-03 17:52:12 +02:00
StaticOutput < < " void static_ " < < funcname < < " _tt(const double *restrict y, const double *restrict x, const double *restrict params, double *restrict T) " < < endl
2019-04-12 15:41:52 +02:00
< < " { " < < endl
< < tt_output [ i ] . str ( )
< < " } " < < endl
< < endl
2020-09-03 17:52:12 +02:00
< < " void static_ " < < funcname < < " (const double *restrict y, const double *restrict x, const double *restrict params, const double *restrict T, " ;
2020-06-23 17:50:50 +02:00
if ( i = = 0 )
2020-09-03 17:52:12 +02:00
StaticOutput < < " double *restrict residual " ;
2020-06-23 17:50:50 +02:00
else if ( i = = 1 )
2020-09-03 17:52:12 +02:00
StaticOutput < < " double *restrict g1 " ;
2020-06-23 17:50:50 +02:00
else
2020-09-03 17:52:12 +02:00
StaticOutput < < " double *restrict " < < funcname < < " _i, double *restrict " < < funcname < < " _j, double *restrict " < < funcname < < " _v " ;
2020-06-23 17:50:50 +02:00
StaticOutput < < " ) " < < endl
2019-04-12 15:41:52 +02:00
< < " { " < < endl ;
if ( i = = 0 )
StaticOutput < < " double lhs, rhs; " < < endl ;
StaticOutput < < d_output [ i ] . str ( )
< < " } " < < endl
< < endl ;
}
2011-08-18 12:44:11 +02:00
}
2015-08-18 15:41:27 +02:00
else
{
2021-04-22 18:03:47 +02:00
stringstream output ;
2018-03-27 17:14:30 +02:00
output < < " module " < < basename < < " Static " < < endl
< < " # " < < endl
< < " # NB: this file was automatically generated by Dynare " < < endl
< < " # from " < < basename < < " .mod " < < endl
< < " # " < < endl
2021-04-22 15:47:43 +02:00
< < " using StatsFuns " < < endl < < endl
2018-03-28 17:50:58 +02:00
< < " export tmp_nbr, static!, staticResid!, staticG1!, staticG2!, staticG3! " < < endl < < endl
2018-03-27 17:14:30 +02:00
< < " #= " < < endl
< < " # The comments below apply to all functions contained in this module # " < < endl
< < " NB: The arguments contained on the first line of the function " < < endl
< < " definition are those that are modified in place " < < endl < < endl
< < " ## Exported Functions ## " < < endl
< < " static! : Wrapper function; computes residuals, Jacobian, Hessian, " < < endl
2018-03-29 11:31:25 +02:00
< < " and third order derivatives matroces depending on the arguments provided " < < endl
2018-03-27 17:14:30 +02:00
< < " staticResid! : Computes the static model residuals " < < endl
< < " staticG1! : Computes the static model Jacobian " < < endl
< < " staticG2! : Computes the static model Hessian " < < endl
< < " staticG3! : Computes the static model third derivatives " < < endl < < endl
2018-03-29 11:31:25 +02:00
< < " ## Exported Variables ## " < < endl
< < " tmp_nbr : Vector{Int}(4) respectively the number of temporary variables " < < endl
< < " for the residuals, g1, g2 and g3. " < < endl < < endl
2018-03-27 17:14:30 +02:00
< < " ## Local Functions ## " < < endl
< < " staticResidTT! : Computes the static model temporary terms for the residuals " < < endl
< < " staticG1TT! : Computes the static model temporary terms for the Jacobian " < < endl
< < " staticG2TT! : Computes the static model temporary terms for the Hessian " < < endl
< < " staticG3TT! : Computes the static model temporary terms for the third derivatives " < < endl < < endl
< < " ## Function Arguments ## " < < endl
2018-03-29 11:31:25 +02:00
< < " T : Vector{Float64}(num_temp_terms) temporary terms " < < endl
< < " y : Vector{Float64}(model_.endo_nbr) endogenous variables in declaration order " < < endl
< < " x : Vector{Float64}(model_.exo_nbr) exogenous variables in declaration order " < < endl
< < " params : Vector{Float64}(model_.param) parameter values in declaration order " < < endl
< < " residual : Vector{Float64}(model_.eq_nbr) residuals of the static model equations " < < endl
< < " in order of declaration of the equations. Dynare may prepend auxiliary equations, " < < endl
< < " see model.aux_vars " < < endl
< < " g1 : Matrix{Float64}(model.eq_nbr,model_.endo_nbr) Jacobian matrix of the static model equations " < < endl
< < " The columns and rows respectively correspond to the variables in declaration order and the " < < endl
< < " equations in order of declaration " < < endl
< < " g2 : spzeros(model.eq_nbr, model_.endo^2) Hessian matrix of the static model equations " < < endl
< < " The columns and rows respectively correspond to the variables in declaration order and the " < < endl
< < " equations in order of declaration " < < endl
< < " g3 : spzeros(model.eq_nbr, model_.endo^3) Third order derivatives matrix of the static model equations " < < endl
< < " The columns and rows respectively correspond to the variables in declaration order and the " < < endl
< < " equations in order of declaration " < < endl < < endl
< < " ## Remarks ## " < < endl
2019-12-20 16:59:30 +01:00
< < " [1] The size of `T`, ie the value of `num_temp_terms`, depends on the version of the static model called. The number of temporary variables " < < endl
2018-03-29 11:31:25 +02:00
< < " used for the different returned objects (residuals, jacobian, hessian or third order derivatives) is given by the elements in `tmp_nbr` " < < endl
< < " exported vector. The first element is the number of temporaries used for the computation of the residuals, the second element is the " < < endl
< < " number of temporaries used for the evaluation of the jacobian matrix, etc. If one calls the version of the static model computing the " < < endl
< < " residuals, and the jacobian and hessian matrices, then `T` must have at least `sum(tmp_nbr[1:3])` elements. " < < endl
2018-03-27 17:14:30 +02:00
< < " =# " < < endl < < endl ;
2018-03-28 17:50:58 +02:00
// Write the number of temporary terms
output < < " tmp_nbr = zeros(Int,4) " < < endl
2018-11-15 16:39:53 +01:00
< < " tmp_nbr[1] = " < < temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) < < " # Number of temporary terms for the residuals " < < endl
< < " tmp_nbr[2] = " < < temporary_terms_derivatives [ 1 ] . size ( ) < < " # Number of temporary terms for g1 (jacobian) " < < endl
< < " tmp_nbr[3] = " < < temporary_terms_derivatives [ 2 ] . size ( ) < < " # Number of temporary terms for g2 (hessian) " < < endl
< < " tmp_nbr[4] = " < < temporary_terms_derivatives [ 3 ] . size ( ) < < " # Number of temporary terms for g3 (third order derivates) " < < endl < < endl ;
2018-03-28 17:50:58 +02:00
2018-03-27 17:14:30 +02:00
// staticResidTT!
output < < " function staticResidTT!(T::Vector{Float64}, " < < endl
< < " y::Vector{Float64}, x::Vector{Float64}, params::Vector{Float64}) " < < endl
2018-11-15 16:39:53 +01:00
< < " @assert length(T) >= " < < temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) < < endl
2019-04-12 15:41:52 +02:00
< < tt_output [ 0 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// static!
output < < " function staticResid!(T::Vector{Float64}, residual::Vector{Float64}, " < < endl
2018-04-10 09:45:40 +02:00
< < " y::Vector{Float64}, x::Vector{Float64}, params::Vector{Float64}, T0_flag::Bool) " < < endl
2018-03-27 17:14:30 +02:00
< < " @assert length(y) == " < < symbol_table . endo_nbr ( ) < < endl
< < " @assert length(x) == " < < symbol_table . exo_nbr ( ) < < endl
< < " @assert length(params) == " < < symbol_table . param_nbr ( ) < < endl
< < " @assert length(residual) == " < < equations . size ( ) < < endl
2018-04-10 09:45:40 +02:00
< < " if T0_flag " < < endl
2018-03-27 17:14:30 +02:00
< < " staticResidTT!(T, y, x, params) " < < endl
< < " end " < < endl
2019-04-12 15:41:52 +02:00
< < d_output [ 0 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " if ~isreal(residual) " < < endl
< < " residual = real(residual)+imag(residual).^2; " < < endl
< < " end " < < endl
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// staticG1TT!
output < < " function staticG1TT!(T::Vector{Float64}, " < < endl
2018-04-10 09:45:40 +02:00
< < " y::Vector{Float64}, x::Vector{Float64}, params::Vector{Float64}, T0_flag::Bool) " < < endl
< < " if T0_flag " < < endl
< < " staticResidTT!(T, y, x, params) " < < endl
< < " end " < < endl
2019-04-12 15:41:52 +02:00
< < tt_output [ 1 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// staticG1!
output < < " function staticG1!(T::Vector{Float64}, g1::Matrix{Float64}, " < < endl
2018-04-10 09:45:40 +02:00
< < " y::Vector{Float64}, x::Vector{Float64}, params::Vector{Float64}, T1_flag::Bool, T0_flag::Bool) " < < endl
2018-03-27 17:14:30 +02:00
< < " @assert length(T) >= "
2018-11-15 16:39:53 +01:00
< < temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) < < endl
2018-03-27 17:14:30 +02:00
< < " @assert size(g1) == ( " < < equations . size ( ) < < " , " < < symbol_table . endo_nbr ( ) < < " ) " < < endl
< < " @assert length(y) == " < < symbol_table . endo_nbr ( ) < < endl
< < " @assert length(x) == " < < symbol_table . exo_nbr ( ) < < endl
< < " @assert length(params) == " < < symbol_table . param_nbr ( ) < < endl
2018-04-10 09:45:40 +02:00
< < " if T1_flag " < < endl
< < " staticG1TT!(T, y, x, params, T0_flag) " < < endl
2018-03-27 17:14:30 +02:00
< < " end " < < endl
< < " fill!(g1, 0.0) " < < endl
2019-04-12 15:41:52 +02:00
< < d_output [ 1 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " if ~isreal(g1) " < < endl
< < " g1 = real(g1)+2*imag(g1); " < < endl
< < " end " < < endl
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// staticG2TT!
output < < " function staticG2TT!(T::Vector{Float64}, " < < endl
2018-04-10 09:45:40 +02:00
< < " y::Vector{Float64}, x::Vector{Float64}, params::Vector{Float64}, T1_flag::Bool, T0_flag::Bool) " < < endl
< < " if T1_flag " < < endl
< < " staticG1TT!(T, y, x, params, TO_flag) " < < endl
< < " end " < < endl
2019-04-12 15:41:52 +02:00
< < tt_output [ 2 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// staticG2!
output < < " function staticG2!(T::Vector{Float64}, g2::Matrix{Float64}, " < < endl
2018-04-10 09:45:40 +02:00
< < " y::Vector{Float64}, x::Vector{Float64}, params::Vector{Float64}, T2_flag::Bool, T1_flag::Bool, T0_flag::Bool) " < < endl
2018-03-27 17:14:30 +02:00
< < " @assert length(T) >= "
2018-11-15 16:39:53 +01:00
< < temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) + temporary_terms_derivatives [ 2 ] . size ( ) < < endl
2019-04-12 15:41:52 +02:00
< < " @assert size(g2) == ( " < < equations . size ( ) < < " , " < < hessianColsNbr < < " ) " < < endl
2018-03-27 17:14:30 +02:00
< < " @assert length(y) == " < < symbol_table . endo_nbr ( ) < < endl
< < " @assert length(x) == " < < symbol_table . exo_nbr ( ) < < endl
< < " @assert length(params) == " < < symbol_table . param_nbr ( ) < < endl
2018-04-10 09:45:40 +02:00
< < " if T2_flag " < < endl
< < " staticG2TT!(T, y, x, params, T1_flag, T0_flag) " < < endl
2018-03-27 17:14:30 +02:00
< < " end " < < endl
< < " fill!(g2, 0.0) " < < endl
2019-04-12 15:41:52 +02:00
< < d_output [ 2 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// staticG3TT!
output < < " function staticG3TT!(T::Vector{Float64}, " < < endl
2018-04-10 09:45:40 +02:00
< < " y::Vector{Float64}, x::Vector{Float64}, params::Vector{Float64}, T2_flag::Bool, T1_flag::Bool, T0_flag::Bool) " < < endl
< < " if T2_flag " < < endl
< < " staticG2TT!(T, y, x, params, T1_flag, T0_flag) " < < endl
< < " end " < < endl
2019-04-12 15:41:52 +02:00
< < tt_output [ 3 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// staticG3!
2015-08-20 11:32:26 +02:00
int ncols = hessianColsNbr * JacobianColsNbr ;
2018-03-27 17:14:30 +02:00
output < < " function staticG3!(T::Vector{Float64}, g3::Matrix{Float64}, " < < endl
2018-04-10 09:45:40 +02:00
< < " y::Vector{Float64}, x::Vector{Float64}, params::Vector{Float64}, T3_flag::Bool, T2_flag::Bool, T1_flag::Bool, T0_flag::Bool) " < < endl
2018-03-27 17:14:30 +02:00
< < " @assert length(T) >= "
2018-11-15 16:39:53 +01:00
< < temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) + temporary_terms_derivatives [ 2 ] . size ( ) + temporary_terms_derivatives [ 3 ] . size ( ) < < endl
2018-03-27 17:14:30 +02:00
< < " @assert size(g3) == ( " < < nrows < < " , " < < ncols < < " ) " < < endl
< < " @assert length(y) == " < < symbol_table . endo_nbr ( ) < < endl
< < " @assert length(x) == " < < symbol_table . exo_nbr ( ) < < endl
< < " @assert length(params) == " < < symbol_table . param_nbr ( ) < < endl
2018-04-10 09:45:40 +02:00
< < " if T3_flag " < < endl
< < " staticG3TT!(T, y, x, params, T2_flag, T1_flag, T0_flag) " < < endl
2018-03-27 17:14:30 +02:00
< < " end " < < endl
< < " fill!(g3, 0.0) " < < endl
2019-04-12 15:41:52 +02:00
< < d_output [ 3 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// static!
2018-04-10 09:45:40 +02:00
output < < " function static!(T::Vector{Float64}, residual::Vector{Float64}, " < < endl
2018-03-29 22:23:38 +02:00
< < " y::Vector{Float64}, x::Vector{Float64}, params::Vector{Float64}) " < < endl
2018-03-27 17:14:30 +02:00
< < " staticResid!(T, residual, y, x, params, true) " < < endl
< < " return nothing " < < endl
< < " end " < < endl
< < endl
< < " function static!(T::Vector{Float64}, residual::Vector{Float64}, g1::Matrix{Float64}, " < < endl
2018-03-29 22:23:38 +02:00
< < " y::Vector{Float64}, x::Vector{Float64}, params::Vector{Float64}) " < < endl
2020-10-21 16:36:12 +02:00
< < " staticG1!(T, g1, y, x, params, true, true) " < < endl
2018-03-27 17:14:30 +02:00
< < " staticResid!(T, residual, y, x, params, false) " < < endl
< < " return nothing " < < endl
< < " end " < < endl
< < endl
2018-04-10 09:45:40 +02:00
< < " function static!(T::Vector{Float64}, g1::Matrix{Float64}, " < < endl
2018-03-29 22:23:38 +02:00
< < " y::Vector{Float64}, x::Vector{Float64}, params::Vector{Float64}) " < < endl
2018-04-10 09:45:40 +02:00
< < " staticG1!(T, g1, y, x, params, true, false) " < < endl
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl
< < endl
2018-04-10 09:45:40 +02:00
< < " function static!(T::Vector{Float64}, residual::Vector{Float64}, g1::Matrix{Float64}, g2::Matrix{Float64}, " < < endl
2018-03-29 22:23:38 +02:00
< < " y::Vector{Float64}, x::Vector{Float64}, params::Vector{Float64}) " < < endl
2020-10-21 16:36:12 +02:00
< < " staticG2!(T, g2, y, x, params, true, true, true) " < < endl
< < " staticG1!(T, g1, y, x, params, false, false) " < < endl
2018-03-27 17:14:30 +02:00
< < " staticResid!(T, residual, y, x, params, false) " < < endl
< < " return nothing " < < endl
2021-04-26 12:52:18 +02:00
< < " end " < < endl
< < endl ;
// Write function definition if BinaryOpcode::powerDeriv is used
writePowerDerivJulia ( output ) ;
output < < " end " < < endl ;
2021-04-22 18:03:47 +02:00
writeToFileIfModified ( output , basename + " Static.jl " ) ;
2015-08-18 15:41:27 +02:00
}
2011-08-18 12:44:11 +02:00
}
void
2018-06-27 15:01:31 +02:00
StaticModel : : writeStaticCFile ( const string & basename ) const
2011-08-18 12:44:11 +02:00
{
// Writing comments and function definition command
2018-06-27 15:01:31 +02:00
string filename = basename + " /model/src/static.c " ;
2011-08-18 12:44:11 +02:00
2018-11-15 16:39:53 +01:00
int ntt = temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) + temporary_terms_derivatives [ 2 ] . size ( ) + temporary_terms_derivatives [ 3 ] . size ( ) ;
2018-09-25 19:15:22 +02:00
2011-08-18 12:44:11 +02:00
ofstream output ;
2018-06-27 15:12:12 +02:00
output . open ( filename , ios : : out | ios : : binary ) ;
2011-08-18 12:44:11 +02:00
if ( ! output . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " /* " < < endl
< < " * " < < filename < < " : Computes static model for Dynare " < < endl
< < " * " < < endl
< < " * Warning : this file is generated automatically by Dynare " < < endl
< < " * from model file (.mod) " < < endl < < endl
< < " */ " < < endl
2020-05-29 16:12:01 +02:00
< < endl
< < " #include <math.h> " < < endl
< < " #include <stdlib.h> " < < endl
< < R " (#include " mex . h " ) " < < endl
< < endl ;
2011-08-18 12:44:11 +02:00
2018-07-18 16:18:26 +02:00
// Write function definition if BinaryOpcode::powerDeriv is used
2020-05-29 16:12:01 +02:00
writePowerDeriv ( output ) ;
2011-08-18 12:44:11 +02:00
2018-09-25 19:15:22 +02:00
output < < endl ;
2015-07-27 15:33:38 +02:00
writeStaticModel ( output , true , false ) ;
2018-09-25 19:15:22 +02:00
2020-05-29 16:12:01 +02:00
output < < " void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) " < < endl
2011-08-18 12:44:11 +02:00
< < " { " < < endl
2020-06-23 16:30:21 +02:00
< < " if (nrhs > 3) " < < endl
< < R " ( mexErrMsgTxt( " Accepts at most 3 output arguments " );) " < < endl
< < " if (nrhs != 3) " < < endl
< < R " ( mexErrMsgTxt( " Requires exactly 3 input arguments " );) " < < endl
2018-09-25 19:15:22 +02:00
< < " double *y = mxGetPr(prhs[0]); " < < endl
< < " double *x = mxGetPr(prhs[1]); " < < endl
< < " double *params = mxGetPr(prhs[2]); " < < endl
< < endl
2020-05-29 16:12:01 +02:00
< < " double *T = (double *) malloc(sizeof(double)* " < < ntt < < " ); " < < endl
2011-08-18 12:44:11 +02:00
< < endl
< < " if (nlhs >= 1) " < < endl
< < " { " < < endl
< < " plhs[0] = mxCreateDoubleMatrix( " < < equations . size ( ) < < " ,1, mxREAL); " < < endl
2018-09-25 19:15:22 +02:00
< < " double *residual = mxGetPr(plhs[0]); " < < endl
2020-06-23 18:19:27 +02:00
< < " static_resid_tt(y, x, params, T); " < < endl
< < " static_resid(y, x, params, T, residual); " < < endl
2011-08-18 12:44:11 +02:00
< < " } " < < endl
< < endl
< < " if (nlhs >= 2) " < < endl
< < " { " < < endl
< < " plhs[1] = mxCreateDoubleMatrix( " < < equations . size ( ) < < " , " < < symbol_table . endo_nbr ( ) < < " , mxREAL); " < < endl
2018-09-25 19:15:22 +02:00
< < " double *g1 = mxGetPr(plhs[1]); " < < endl
2020-06-23 18:19:27 +02:00
< < " static_g1_tt(y, x, params, T); " < < endl
< < " static_g1(y, x, params, T, g1); " < < endl
2011-08-18 12:44:11 +02:00
< < " } " < < endl
< < endl
< < " if (nlhs >= 3) " < < endl
< < " { " < < endl
2020-06-23 17:50:50 +02:00
< < " mxArray *g2_i = mxCreateDoubleMatrix( " < < NNZDerivatives [ 2 ] < < " , " < < 1 < < " , mxREAL); " < < endl
< < " mxArray *g2_j = mxCreateDoubleMatrix( " < < NNZDerivatives [ 2 ] < < " , " < < 1 < < " , mxREAL); " < < endl
< < " mxArray *g2_v = mxCreateDoubleMatrix( " < < NNZDerivatives [ 2 ] < < " , " < < 1 < < " , mxREAL); " < < endl
2020-06-23 18:19:27 +02:00
< < " static_g2_tt(y, x, params, T); " < < endl
< < " static_g2(y, x, params, T, mxGetPr(g2_i), mxGetPr(g2_j), mxGetPr(g2_v)); " < < endl
2020-06-23 17:50:50 +02:00
< < " mxArray *m = mxCreateDoubleScalar( " < < equations . size ( ) < < " ); " < < endl
< < " mxArray *n = mxCreateDoubleScalar( " < < symbol_table . endo_nbr ( ) * symbol_table . endo_nbr ( ) < < " ); " < < endl
< < " mxArray *plhs_sparse[1], *prhs_sparse[5] = { g2_i, g2_j, g2_v, m, n }; " < < endl
< < R " ( mexCallMATLAB(1, plhs_sparse, 5, prhs_sparse, " sparse " );) " < < endl
< < " plhs[2] = plhs_sparse[0]; " < < endl
< < " mxDestroyArray(g2_i); " < < endl
< < " mxDestroyArray(g2_j); " < < endl
< < " mxDestroyArray(g2_v); " < < endl
< < " mxDestroyArray(m); " < < endl
< < " mxDestroyArray(n); " < < endl
2011-08-18 12:44:11 +02:00
< < " } " < < endl
< < endl
2018-09-25 19:15:22 +02:00
< < " free(T); " < < endl
< < " } " < < endl ;
2020-05-29 16:12:01 +02:00
2009-07-07 16:20:48 +02:00
output . close ( ) ;
2009-04-14 16:39:53 +02:00
}
2009-12-16 14:21:31 +01:00
void
2015-07-27 15:59:13 +02:00
StaticModel : : writeStaticJuliaFile ( const string & basename ) const
2015-07-27 15:33:38 +02:00
{
2018-03-27 17:14:30 +02:00
writeStaticModel ( basename , false , true ) ;
2015-07-27 15:33:38 +02:00
}
void
2019-04-04 17:01:37 +02:00
StaticModel : : writeStaticFile ( const string & basename , bool block , bool bytecode , bool use_dll , const string & mexext , const filesystem : : path & matlabroot , const filesystem : : path & dynareroot , bool julia ) const
2009-12-16 18:13:23 +01:00
{
2020-06-23 15:13:04 +02:00
filesystem : : path model_dir { basename } ;
model_dir / = " model " ;
if ( use_dll )
filesystem : : create_directories ( model_dir / " src " ) ;
if ( bytecode )
filesystem : : create_directories ( model_dir / " bytecode " ) ;
if ( block )
2009-12-16 18:13:23 +01:00
{
2020-06-23 15:13:04 +02:00
if ( bytecode )
writeStaticBlockBytecode ( basename ) ;
else if ( use_dll )
{
writeStaticPerBlockCFiles ( basename ) ;
writeStaticBlockCFile ( basename ) ;
vector < filesystem : : path > src_files { blocks . size ( ) + 1 } ;
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
src_files [ blk ] = model_dir / " src " / ( " static_ " + to_string ( blk + 1 ) + " .c " ) ;
src_files [ blocks . size ( ) ] = model_dir / " src " / " static.c " ;
compileMEX ( basename , " static " , mexext , src_files , matlabroot , dynareroot ) ;
}
else if ( julia )
{
cerr < < " 'block' option is not available with Julia " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else // M-files
{
writeStaticPerBlockMFiles ( basename ) ;
writeStaticBlockMFile ( basename ) ;
}
2009-12-16 18:13:23 +01:00
}
2020-06-23 15:13:04 +02:00
else
2018-10-26 11:44:26 +02:00
{
2020-06-23 15:13:04 +02:00
if ( bytecode )
writeStaticBytecode ( basename ) ;
else if ( use_dll )
{
writeStaticCFile ( basename ) ;
compileMEX ( basename , " static " , mexext , { model_dir / " src " / " static.c " } ,
matlabroot , dynareroot ) ;
}
else if ( julia )
writeStaticJuliaFile ( basename ) ;
else // M-files
writeStaticMFile ( basename ) ;
2018-10-26 11:44:26 +02:00
}
2020-06-23 15:13:04 +02:00
2016-04-04 17:11:03 +02:00
writeSetAuxiliaryVariables ( basename , julia ) ;
2009-12-16 18:13:23 +01:00
}
2009-04-27 19:15:14 +02:00
2016-08-12 11:50:57 +02:00
bool
StaticModel : : exoPresentInEqs ( ) const
{
2018-06-04 12:26:16 +02:00
for ( auto equation : equations )
2020-09-29 18:30:21 +02:00
{
set < int > result ;
equation - > collectVariables ( SymbolType : : exogenous , result ) ;
equation - > collectVariables ( SymbolType : : exogenousDet , result ) ;
if ( ! result . empty ( ) )
return true ;
}
2016-08-12 11:50:57 +02:00
return false ;
}
2009-04-27 19:15:14 +02:00
void
2020-05-19 16:56:53 +02:00
StaticModel : : writeStaticBlockMFile ( const string & basename ) const
2009-04-27 19:15:14 +02:00
{
2018-06-27 15:01:31 +02:00
string filename = packageDir ( basename ) + " /static.m " ;
2009-04-27 19:15:14 +02:00
2009-12-16 14:21:31 +01:00
ofstream output ;
2018-06-27 15:12:12 +02:00
output . open ( filename , ios : : out | ios : : binary ) ;
2009-12-16 14:21:31 +01:00
if ( ! output . is_open ( ) )
2009-04-27 19:15:14 +02:00
{
2009-12-16 14:21:31 +01:00
cerr < < " ERROR: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-04-27 19:15:14 +02:00
}
2020-06-19 18:33:53 +02:00
output < < " function [residual, y, T, g1] = static(nblock, y, x, params, T) " < < endl
2009-12-16 14:21:31 +01:00
< < " switch nblock " < < endl ;
2009-06-30 17:07:09 +02:00
2020-05-19 16:56:53 +02:00
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
2009-06-30 17:07:09 +02:00
{
2020-05-19 16:56:53 +02:00
output < < " case " < < blk + 1 < < endl ;
2009-04-27 19:15:14 +02:00
2020-05-19 16:56:53 +02:00
BlockSimulationType simulation_type = blocks [ blk ] . simulation_type ;
2009-12-16 14:21:31 +01:00
2020-03-20 17:31:14 +01:00
if ( simulation_type = = BlockSimulationType : : evaluateBackward
| | simulation_type = = BlockSimulationType : : evaluateForward )
2020-06-19 18:33:53 +02:00
output < < " [y, T] = " < < basename < < " .block.static_ " < < blk + 1 < < " (y, x, params, T); " < < endl
< < " residual = []; " < < endl
< < " g1 = []; " < < endl ;
2009-12-16 18:13:23 +01:00
else
2020-10-06 17:16:50 +02:00
output < < " [residual, y, T, g1] = " < < basename < < " .block.static_ " < < blk + 1 < < " (y, x, params, T); " < < endl ;
2010-09-17 16:53:27 +02:00
2009-04-28 19:11:48 +02:00
}
2009-12-16 14:21:31 +01:00
output < < " end " < < endl
< < " end " < < endl ;
output . close ( ) ;
}
2009-04-28 19:11:48 +02:00
2020-06-23 15:13:04 +02:00
void
StaticModel : : writeStaticBlockCFile ( const string & basename ) const
{
string filename = basename + " /model/src/static.c " ;
ofstream output ;
output . open ( filename , ios : : out | ios : : binary ) ;
if ( ! output . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " #include <math.h> " < < endl
< < R " (#include " mex . h " ) " < < endl ;
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
output < < R " (#include " static_ ) " << blk+1 << R " ( . h " ) " < < endl ;
output < < endl ;
writePowerDeriv ( output ) ;
output < < endl
< < " void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) " < < endl
< < " { " < < endl
< < " if (nrhs != 5) " < < endl
< < R " ( mexErrMsgTxt( " Requires exactly 5 input arguments " );) " < < endl
< < " if (nlhs > 4) " < < endl
< < R " ( mexErrMsgTxt( " Accepts at most 4 output arguments " );) " < < endl
< < " int nblock = (int) mxGetScalar(prhs[0]); " < < endl
< < " const mxArray *y = prhs[1], *x = prhs[2], *params = prhs[3], *T = prhs[4]; " < < endl
< < " mxArray *T_new = mxDuplicateArray(T); " < < endl
< < " mxArray *y_new = mxDuplicateArray(y); " < < endl
< < " mxArray *residual, *g1; " < < endl
< < " switch (nblock) " < < endl
< < " { " < < endl ;
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
{
output < < " case " < < blk + 1 < < ' : ' < < endl ;
BlockSimulationType simulation_type = blocks [ blk ] . simulation_type ;
if ( simulation_type = = BlockSimulationType : : evaluateBackward
| | simulation_type = = BlockSimulationType : : evaluateForward )
output < < " static_ " < < blk + 1 < < " _mx(y_new, x, params, T_new); " < < endl
< < " residual = mxCreateDoubleMatrix(0,0,mxREAL); " < < endl
< < " g1 = mxCreateDoubleMatrix(0,0,mxREAL); " < < endl ;
else
2020-10-06 17:16:50 +02:00
output < < " static_ " < < blk + 1 < < " _mx(y_new, x, params, T_new, &residual, &g1); " < < endl ;
2020-06-23 15:13:04 +02:00
output < < " break; " < < endl ;
}
output < < " } " < < endl
< < endl
< < " if (nlhs >= 1) " < < endl
< < " plhs[0] = residual; " < < endl
< < " else " < < endl
< < " mxDestroyArray(residual); " < < endl
< < " if (nlhs >= 2) " < < endl
< < " plhs[1] = y_new; " < < endl
< < " else " < < endl
< < " mxDestroyArray(y_new); " < < endl
< < " if (nlhs >= 3) " < < endl
< < " plhs[2] = T_new; " < < endl
< < " else " < < endl
< < " mxDestroyArray(T_new); " < < endl
< < " if (nlhs >= 4) " < < endl
< < " plhs[3] = g1; " < < endl
< < " else " < < endl
< < " mxDestroyArray(g1); " < < endl
< < " } " < < endl ;
output . close ( ) ;
}
2009-12-16 14:21:31 +01:00
void
2020-05-20 11:44:40 +02:00
StaticModel : : writeDriverOutput ( ostream & output , bool block ) const
2009-12-16 14:21:31 +01:00
{
2019-04-12 15:41:52 +02:00
output < < " M_.static_tmp_nbr = [ " ;
2019-12-20 16:59:30 +01:00
for ( const auto & temporary_terms_derivative : temporary_terms_derivatives )
2019-12-16 19:42:59 +01:00
output < < temporary_terms_derivative . size ( ) < < " ; " ;
2019-04-12 15:41:52 +02:00
output < < " ]; " < < endl ;
2018-03-28 18:53:02 +02:00
2020-06-05 17:11:29 +02:00
/* Write mapping between model local variables and indices in the temporary
terms vector ( dynare # 1722 ) */
output < < " M_.model_local_variables_static_tt_idxs = { " < < endl ;
for ( auto [ mlv , value ] : temporary_terms_mlv )
output < < " ' " < < symbol_table . getName ( mlv - > symb_id ) < < " ', "
< < temporary_terms_idxs . at ( mlv ) + 1 < < ' ; ' < < endl ;
output < < " }; " < < endl ;
2009-12-16 14:21:31 +01:00
if ( ! block )
return ;
2009-06-30 17:07:09 +02:00
2020-05-20 11:35:14 +02:00
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
2012-06-06 16:36:56 +02:00
{
2020-05-20 11:35:14 +02:00
output < < " block_structure_stat.block( " < < blk + 1 < < " ).Simulation_Type = " < < static_cast < int > ( blocks [ blk ] . simulation_type ) < < " ; " < < endl
< < " block_structure_stat.block( " < < blk + 1 < < " ).endo_nbr = " < < blocks [ blk ] . size < < " ; " < < endl
< < " block_structure_stat.block( " < < blk + 1 < < " ).mfs = " < < blocks [ blk ] . mfs_size < < " ; " < < endl
< < " block_structure_stat.block( " < < blk + 1 < < " ).equation = [ " ;
for ( int eq = 0 ; eq < blocks [ blk ] . size ; eq + + )
output < < " " < < getBlockEquationID ( blk , eq ) + 1 ;
2020-05-05 17:49:58 +02:00
output < < " ]; " < < endl
2020-05-20 11:35:14 +02:00
< < " block_structure_stat.block( " < < blk + 1 < < " ).variable = [ " ;
for ( int var = 0 ; var < blocks [ blk ] . size ; var + + )
output < < " " < < getBlockVariableID ( blk , var ) + 1 ;
2020-05-05 17:49:58 +02:00
output < < " ]; " < < endl ;
2012-06-06 16:36:56 +02:00
}
2020-05-05 17:49:58 +02:00
output < < " M_.block_structure_stat.block = block_structure_stat.block; " < < endl
< < " M_.block_structure_stat.variable_reordered = [ " ;
for ( int i = 0 ; i < symbol_table . endo_nbr ( ) ; i + + )
2020-04-17 14:55:55 +02:00
output < < " " < < endo_idx_block2orig [ i ] + 1 ;
2018-11-23 17:19:59 +01:00
output < < " ]; " < < endl
< < " M_.block_structure_stat.equation_reordered = [ " ;
2020-05-05 17:49:58 +02:00
for ( int i = 0 ; i < symbol_table . endo_nbr ( ) ; i + + )
2020-04-17 14:55:55 +02:00
output < < " " < < eq_idx_block2orig [ i ] + 1 ;
2018-11-23 17:19:59 +01:00
output < < " ]; " < < endl ;
2017-06-14 07:01:31 +02:00
2020-05-05 17:49:58 +02:00
set < pair < int , int > > row_incidence ;
for ( const auto & [ indices , d1 ] : derivatives [ 1 ] )
if ( int deriv_id = indices [ 1 ] ;
getTypeByDerivID ( deriv_id ) = = SymbolType : : endogenous )
{
int eq = indices [ 0 ] ;
2020-05-20 11:35:14 +02:00
int var = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( deriv_id ) ) ;
2020-05-05 17:49:58 +02:00
row_incidence . emplace ( eq , var ) ;
}
2020-05-20 11:35:14 +02:00
output < < " M_.block_structure_stat.incidence.sparse_IM = [ " < < endl ;
2020-05-05 17:49:58 +02:00
for ( auto [ eq , var ] : row_incidence )
2020-05-20 11:35:14 +02:00
output < < " " < < eq + 1 < < " " < < var + 1 < < " ; " < < endl ;
2020-05-25 18:35:36 +02:00
output < < " ]; " < < endl
< < " M_.block_structure_stat.tmp_nbr = " < < blocks_temporary_terms_idxs . size ( )
< < " ; " < < endl ;
2009-04-28 19:11:48 +02:00
}
2009-12-16 14:21:31 +01:00
SymbolType
2018-06-04 12:50:53 +02:00
StaticModel : : getTypeByDerivID ( int deriv_id ) const noexcept ( false )
2009-12-16 14:21:31 +01:00
{
2012-11-29 18:07:48 +01:00
if ( deriv_id < symbol_table . endo_nbr ( ) )
2018-07-17 18:34:07 +02:00
return SymbolType : : endogenous ;
2012-11-29 18:07:48 +01:00
else if ( deriv_id < symbol_table . endo_nbr ( ) + symbol_table . param_nbr ( ) )
2018-07-17 18:34:07 +02:00
return SymbolType : : parameter ;
2012-11-29 18:07:48 +01:00
else
throw UnknownDerivIDException ( ) ;
2009-04-27 19:15:14 +02:00
}
2009-04-30 15:14:33 +02:00
2009-12-16 14:21:31 +01:00
int
2018-06-04 12:50:53 +02:00
StaticModel : : getLagByDerivID ( int deriv_id ) const noexcept ( false )
2009-04-30 15:14:33 +02:00
{
2009-12-16 14:21:31 +01:00
return 0 ;
2009-04-30 15:14:33 +02:00
}
2009-06-30 17:07:09 +02:00
2009-12-16 14:21:31 +01:00
int
2018-06-04 12:50:53 +02:00
StaticModel : : getSymbIDByDerivID ( int deriv_id ) const noexcept ( false )
2009-06-30 17:07:09 +02:00
{
2012-11-29 18:07:48 +01:00
if ( deriv_id < symbol_table . endo_nbr ( ) )
2018-07-17 18:34:07 +02:00
return symbol_table . getID ( SymbolType : : endogenous , deriv_id ) ;
2012-11-29 18:07:48 +01:00
else if ( deriv_id < symbol_table . endo_nbr ( ) + symbol_table . param_nbr ( ) )
2018-07-17 18:34:07 +02:00
return symbol_table . getID ( SymbolType : : parameter , deriv_id - symbol_table . endo_nbr ( ) ) ;
2012-11-29 18:07:48 +01:00
else
throw UnknownDerivIDException ( ) ;
2009-06-30 17:07:09 +02:00
}
2009-12-16 14:21:31 +01:00
int
2018-06-04 12:50:53 +02:00
StaticModel : : getDerivID ( int symb_id , int lag ) const noexcept ( false )
2009-06-30 17:07:09 +02:00
{
2018-07-17 18:34:07 +02:00
if ( symbol_table . getType ( symb_id ) = = SymbolType : : endogenous )
2012-11-29 18:07:48 +01:00
return symbol_table . getTypeSpecificID ( symb_id ) ;
2018-07-17 18:34:07 +02:00
else if ( symbol_table . getType ( symb_id ) = = SymbolType : : parameter )
2012-11-29 18:07:48 +01:00
return symbol_table . getTypeSpecificID ( symb_id ) + symbol_table . endo_nbr ( ) ;
2009-12-16 14:21:31 +01:00
else
return - 1 ;
}
2009-06-30 17:07:09 +02:00
2012-11-29 18:07:48 +01:00
void
StaticModel : : addAllParamDerivId ( set < int > & deriv_id_set )
{
for ( int i = 0 ; i < symbol_table . param_nbr ( ) ; i + + )
deriv_id_set . insert ( i + symbol_table . endo_nbr ( ) ) ;
}
2009-07-07 16:20:48 +02:00
void
2020-03-19 17:46:10 +01:00
StaticModel : : computeChainRuleJacobian ( )
2009-07-07 16:20:48 +02:00
{
2020-04-23 16:04:02 +02:00
int nb_blocks = blocks . size ( ) ;
2020-03-19 17:46:10 +01:00
blocks_derivatives . resize ( nb_blocks ) ;
2020-04-24 12:29:02 +02:00
for ( int blk = 0 ; blk < nb_blocks ; blk + + )
2009-07-07 16:20:48 +02:00
{
2020-04-24 12:29:02 +02:00
int nb_recursives = blocks [ blk ] . getRecursiveSize ( ) ;
2020-10-02 18:31:55 +02:00
map < int , BinaryOpNode * > recursive_vars ;
2020-04-24 12:29:02 +02:00
for ( int i = 0 ; i < nb_recursives ; i + + )
2009-07-10 16:22:40 +02:00
{
2020-04-24 12:29:02 +02:00
int deriv_id = getDerivID ( symbol_table . getID ( SymbolType : : endogenous , getBlockVariableID ( blk , i ) ) , 0 ) ;
2020-05-20 11:49:32 +02:00
if ( getBlockEquationType ( blk , i ) = = EquationType : : evaluateRenormalized )
2020-04-24 12:29:02 +02:00
recursive_vars [ deriv_id ] = getBlockEquationRenormalizedExpr ( blk , i ) ;
else
recursive_vars [ deriv_id ] = getBlockEquationExpr ( blk , i ) ;
2009-07-10 16:22:40 +02:00
}
2020-04-24 12:29:02 +02:00
assert ( blocks [ blk ] . simulation_type ! = BlockSimulationType : : solveTwoBoundariesSimple
& & blocks [ blk ] . simulation_type ! = BlockSimulationType : : solveTwoBoundariesComplete ) ;
int size = blocks [ blk ] . size ;
for ( int eq = nb_recursives ; eq < size ; eq + + )
2009-07-07 16:20:48 +02:00
{
2020-04-24 12:29:02 +02:00
int eq_orig = getBlockEquationID ( blk , eq ) ;
for ( int var = nb_recursives ; var < size ; var + + )
2009-12-16 14:21:31 +01:00
{
2020-04-24 12:29:02 +02:00
int var_orig = getBlockVariableID ( blk , var ) ;
expr_t d1 = equations [ eq_orig ] - > getChainRuleDerivative ( getDerivID ( symbol_table . getID ( SymbolType : : endogenous , var_orig ) , 0 ) , recursive_vars ) ;
2020-05-06 14:21:33 +02:00
if ( d1 ! = Zero )
blocks_derivatives [ blk ] [ { eq , var , 0 } ] = d1 ;
2009-07-07 17:58:17 +02:00
}
2009-07-07 16:20:48 +02:00
}
}
}
2009-12-16 14:21:31 +01:00
void
2017-08-24 15:35:10 +02:00
StaticModel : : writeLatexFile ( const string & basename , bool write_equation_tags ) const
2009-12-16 18:13:23 +01:00
{
2019-07-11 17:33:53 +02:00
writeLatexModelFile ( basename , " static " , ExprNodeOutputType : : latexStaticModel , write_equation_tags ) ;
2009-12-16 18:13:23 +01:00
}
2009-07-07 17:58:17 +02:00
2009-09-30 17:10:31 +02:00
void
2010-04-27 17:04:52 +02:00
StaticModel : : writeAuxVarInitval ( ostream & output , ExprNodeOutputType output_type ) const
2009-09-30 17:10:31 +02:00
{
2018-06-04 12:26:16 +02:00
for ( auto aux_equation : aux_equations )
2009-09-30 17:10:31 +02:00
{
2018-06-04 12:26:16 +02:00
dynamic_cast < ExprNode * > ( aux_equation ) - > writeOutput ( output , output_type ) ;
2009-09-30 17:10:31 +02:00
output < < " ; " < < endl ;
}
}
2011-07-24 20:52:03 +02:00
2017-06-14 07:01:31 +02:00
void
2019-12-16 19:42:59 +01:00
StaticModel : : writeSetAuxiliaryVariables ( const string & basename , bool julia ) const
2011-07-24 20:52:03 +02:00
{
2017-08-29 10:58:39 +02:00
ostringstream output_func_body ;
2021-01-09 14:45:31 +01:00
ExprNodeOutputType output_type = julia ? ExprNodeOutputType : : juliaStaticModel : ExprNodeOutputType : : matlabStaticModel ;
writeAuxVarRecursiveDefinitions ( output_func_body , output_type ) ;
2017-08-29 10:58:39 +02:00
if ( output_func_body . str ( ) . empty ( ) )
return ;
2017-06-14 07:01:31 +02:00
2021-04-23 17:55:28 +02:00
string func_name = julia ? basename + " _set_auxiliary_variables! " : " set_auxiliary_variables " ;
2015-08-17 15:36:18 +02:00
string comment = julia ? " # " : " % " ;
2011-07-24 20:52:03 +02:00
2021-04-23 17:30:38 +02:00
stringstream output ;
2021-04-23 17:55:28 +02:00
if ( julia )
output < < " module " < < basename < < " SetAuxiliaryVariables " < < endl
< < " export " < < func_name < < endl ;
2021-01-09 14:45:31 +01:00
output < < " function " ;
if ( ! julia )
output < < " y = " ;
2021-04-23 17:55:28 +02:00
output < < func_name < < " (y, x, params) " < < endl
2015-08-17 15:36:18 +02:00
< < comment < < endl
< < comment < < " Status : Computes static model for Dynare " < < endl
< < comment < < endl
< < comment < < " Warning : this file is generated automatically by Dynare " < < endl
2017-08-29 10:58:39 +02:00
< < comment < < " from model file (.mod) " < < endl < < endl
2021-04-23 17:55:28 +02:00
< < output_func_body . str ( )
< < " end " < < endl ;
2021-01-09 14:45:31 +01:00
if ( julia )
output < < " end " < < endl ;
2018-03-02 18:39:16 +01:00
2021-04-23 17:55:28 +02:00
writeToFileIfModified ( output , julia ? basename + " SetAuxiliaryVariables.jl " : packageDir ( basename ) + " / " + func_name + " .m " ) ;
2016-04-04 17:11:03 +02:00
}
2015-05-12 16:36:03 +02:00
2016-04-04 17:11:03 +02:00
void
StaticModel : : writeAuxVarRecursiveDefinitions ( ostream & output , ExprNodeOutputType output_type ) const
{
deriv_node_temp_terms_t tef_terms ;
2018-06-04 12:26:16 +02:00
for ( auto aux_equation : aux_equations )
if ( dynamic_cast < ExprNode * > ( aux_equation ) - > containsExternalFunction ( ) )
2018-09-05 18:27:13 +02:00
dynamic_cast < ExprNode * > ( aux_equation ) - > writeExternalFunctionOutput ( output , ExprNodeOutputType : : matlabStaticModel , { } , { } , tef_terms ) ;
2018-06-04 12:26:16 +02:00
for ( auto aux_equation : aux_equations )
2011-07-24 20:52:03 +02:00
{
2018-06-04 12:26:16 +02:00
dynamic_cast < ExprNode * > ( aux_equation - > substituteStaticAuxiliaryDefinition ( ) ) - > writeOutput ( output , output_type ) ;
2011-07-24 20:52:03 +02:00
output < < " ; " < < endl ;
}
}
2012-11-29 18:07:48 +01:00
2017-08-30 11:32:01 +02:00
void
StaticModel : : writeLatexAuxVarRecursiveDefinitions ( ostream & output ) const
{
deriv_node_temp_terms_t tef_terms ;
temporary_terms_t temporary_terms ;
2019-12-20 16:59:30 +01:00
temporary_terms_idxs_t temporary_terms_idxs ;
2018-06-04 12:26:16 +02:00
for ( auto aux_equation : aux_equations )
if ( dynamic_cast < ExprNode * > ( aux_equation ) - > containsExternalFunction ( ) )
2018-09-05 18:27:13 +02:00
dynamic_cast < ExprNode * > ( aux_equation ) - > writeExternalFunctionOutput ( output , ExprNodeOutputType : : latexStaticModel ,
2019-12-20 16:59:30 +01:00
temporary_terms , temporary_terms_idxs , tef_terms ) ;
2018-06-04 12:26:16 +02:00
for ( auto aux_equation : aux_equations )
2017-08-30 11:32:01 +02:00
{
2019-04-03 16:32:52 +02:00
output < < R " ( \b egin{dmath}) " < < endl ;
2018-09-05 18:27:13 +02:00
dynamic_cast < ExprNode * > ( aux_equation - > substituteStaticAuxiliaryDefinition ( ) ) - > writeOutput ( output , ExprNodeOutputType : : latexStaticModel ) ;
2019-04-03 16:32:52 +02:00
output < < endl < < R " ( \ end{dmath}) " < < endl ;
2017-08-30 11:32:01 +02:00
}
}
2017-10-16 17:24:55 +02:00
void
StaticModel : : writeJsonAuxVarRecursiveDefinitions ( ostream & output ) const
{
deriv_node_temp_terms_t tef_terms ;
temporary_terms_t temporary_terms ;
2018-06-04 12:26:16 +02:00
for ( auto aux_equation : aux_equations )
if ( dynamic_cast < ExprNode * > ( aux_equation ) - > containsExternalFunction ( ) )
2017-10-16 17:24:55 +02:00
{
vector < string > efout ;
2018-06-04 12:26:16 +02:00
dynamic_cast < ExprNode * > ( aux_equation ) - > writeJsonExternalFunctionOutput ( efout ,
2019-12-16 19:42:59 +01:00
temporary_terms ,
tef_terms ,
false ) ;
for ( auto it = efout . begin ( ) ; it ! = efout . end ( ) ; + + it )
2017-10-16 17:24:55 +02:00
{
if ( it ! = efout . begin ( ) )
output < < " , " ;
output < < * it ;
}
}
2018-06-04 12:26:16 +02:00
for ( auto aux_equation : aux_equations )
2017-10-16 17:24:55 +02:00
{
2019-04-03 16:32:52 +02:00
output < < R " (, { " lhs " : " ) " ;
2018-11-28 14:32:26 +01:00
aux_equation - > arg1 - > writeJsonOutput ( output , temporary_terms , tef_terms , false ) ;
2019-04-03 16:32:52 +02:00
output < < R " ( " , " rhs " : " ) " ;
2018-11-28 14:32:26 +01:00
dynamic_cast < BinaryOpNode * > ( aux_equation - > substituteStaticAuxiliaryDefinition ( ) ) - > arg2 - > writeJsonOutput ( output , temporary_terms , tef_terms , false ) ;
2019-04-03 16:32:52 +02:00
output < < R " ( " } ) " ;
2017-10-16 17:24:55 +02:00
}
}
2012-11-29 18:07:48 +01:00
void
2015-07-28 12:29:42 +02:00
StaticModel : : writeParamsDerivativesFile ( const string & basename , bool julia ) const
2012-11-29 18:07:48 +01:00
{
2018-11-15 16:39:53 +01:00
if ( ! params_derivatives . size ( ) )
2012-11-29 18:07:48 +01:00
return ;
2018-09-05 18:27:13 +02:00
ExprNodeOutputType output_type = ( julia ? ExprNodeOutputType : : juliaStaticModel : ExprNodeOutputType : : matlabStaticModel ) ;
2015-07-28 12:29:42 +02:00
2019-12-20 16:59:30 +01:00
ostringstream tt_output ; // Used for storing temporary terms
ostringstream jacobian_output ; // Used for storing jacobian equations
ostringstream hessian_output ; // Used for storing Hessian equations
ostringstream hessian1_output ; // Used for storing Hessian equations
ostringstream third_derivs_output ; // Used for storing third order derivatives equations
ostringstream third_derivs1_output ; // Used for storing third order derivatives equations
2012-11-29 18:07:48 +01:00
2018-11-16 16:53:07 +01:00
temporary_terms_t temp_term_union ;
2012-11-29 18:07:48 +01:00
deriv_node_temp_terms_t tef_terms ;
2018-11-16 18:13:34 +01:00
writeModelLocalVariableTemporaryTerms ( temp_term_union , params_derivs_temporary_terms_idxs , tt_output , output_type , tef_terms ) ;
2018-11-30 12:22:13 +01:00
for ( const auto & it : params_derivs_temporary_terms )
writeTemporaryTerms ( it . second , temp_term_union , params_derivs_temporary_terms_idxs , tt_output , output_type , tef_terms ) ;
2012-11-29 18:07:48 +01:00
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d1 ] : params_derivatives . find ( { 0 , 1 } ) - > second )
2012-11-29 18:07:48 +01:00
{
2019-12-16 19:42:59 +01:00
auto [ eq , param ] = vectorToTuple < 2 > ( indices ) ;
2012-11-29 18:07:48 +01:00
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
2017-01-05 17:31:48 +01:00
jacobian_output < < " rp " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < eq + 1 < < " , " < < param_col
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
2018-11-16 18:13:34 +01:00
d1 - > writeOutput ( jacobian_output , output_type , temp_term_union , params_derivs_temporary_terms_idxs , tef_terms ) ;
2017-01-05 17:31:48 +01:00
jacobian_output < < " ; " < < endl ;
2012-11-29 18:07:48 +01:00
}
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d2 ] : params_derivatives . find ( { 1 , 1 } ) - > second )
2012-11-29 18:07:48 +01:00
{
2019-12-16 19:42:59 +01:00
auto [ eq , var , param ] = vectorToTuple < 3 > ( indices ) ;
2012-11-29 18:07:48 +01:00
int var_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( var ) ) + 1 ;
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
2017-01-05 17:31:48 +01:00
hessian_output < < " gp " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < eq + 1 < < " , " < < var_col < < " , " < < param_col
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
2018-11-16 18:13:34 +01:00
d2 - > writeOutput ( hessian_output , output_type , temp_term_union , params_derivs_temporary_terms_idxs , tef_terms ) ;
2017-01-05 17:31:48 +01:00
hessian_output < < " ; " < < endl ;
2012-11-29 18:07:48 +01:00
}
int i = 1 ;
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d2 ] : params_derivatives . find ( { 0 , 2 } ) - > second )
2012-11-29 18:07:48 +01:00
{
2019-12-16 19:42:59 +01:00
auto [ eq , param1 , param2 ] = vectorToTuple < 3 > ( indices ) ;
2012-11-29 18:07:48 +01:00
int param1_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param1 ) ) + 1 ;
int param2_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param2 ) ) + 1 ;
2017-01-05 17:31:48 +01:00
hessian1_output < < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param1_col < < " ; " < < endl
< < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param2_col < < " ; " < < endl
< < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
2018-11-16 18:13:34 +01:00
d2 - > writeOutput ( hessian1_output , output_type , temp_term_union , params_derivs_temporary_terms_idxs , tef_terms ) ;
2017-01-05 17:31:48 +01:00
hessian1_output < < " ; " < < endl ;
2018-06-05 15:34:34 +02:00
i + + ;
2018-11-22 15:41:11 +01:00
if ( param1 ! = param2 )
{
// Treat symmetric elements
hessian1_output < < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param2_col < < " ; " < < endl
< < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param1_col < < " ; " < < endl
< < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " =rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i - 1 < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " ; " < < endl ;
i + + ;
}
2012-11-29 18:07:48 +01:00
}
i = 1 ;
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d2 ] : params_derivatives . find ( { 1 , 2 } ) - > second )
2012-11-29 18:07:48 +01:00
{
2019-12-16 19:42:59 +01:00
auto [ eq , var , param1 , param2 ] = vectorToTuple < 4 > ( indices ) ;
2012-11-29 18:07:48 +01:00
int var_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( var ) ) + 1 ;
int param1_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param1 ) ) + 1 ;
int param2_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param2 ) ) + 1 ;
2017-01-05 17:31:48 +01:00
third_derivs_output < < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var_col < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param1_col < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param2_col < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
2018-11-16 18:13:34 +01:00
d2 - > writeOutput ( third_derivs_output , output_type , temp_term_union , params_derivs_temporary_terms_idxs , tef_terms ) ;
2017-01-05 17:31:48 +01:00
third_derivs_output < < " ; " < < endl ;
2018-06-05 15:34:34 +02:00
i + + ;
2018-11-22 15:41:11 +01:00
if ( param1 ! = param2 )
{
// Treat symmetric elements
third_derivs_output < < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var_col < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param2_col < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param1_col < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " =gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i - 1 < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " ; " < < endl ;
i + + ;
}
2012-11-29 18:07:48 +01:00
}
i = 1 ;
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d2 ] : params_derivatives . find ( { 2 , 1 } ) - > second )
2012-11-29 18:07:48 +01:00
{
2019-12-16 19:42:59 +01:00
auto [ eq , var1 , var2 , param ] = vectorToTuple < 4 > ( indices ) ;
2012-11-29 18:07:48 +01:00
int var1_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( var1 ) ) + 1 ;
int var2_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( var2 ) ) + 1 ;
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
2017-01-05 17:31:48 +01:00
third_derivs1_output < < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var1_col < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var2_col < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param_col < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
2018-11-16 18:13:34 +01:00
d2 - > writeOutput ( third_derivs1_output , output_type , temp_term_union , params_derivs_temporary_terms_idxs , tef_terms ) ;
2017-01-05 17:31:48 +01:00
third_derivs1_output < < " ; " < < endl ;
2018-06-05 15:34:34 +02:00
i + + ;
2018-11-22 17:49:47 +01:00
if ( var1 ! = var2 )
{
// Treat symmetric elements
third_derivs1_output < < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var2_col < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var1_col < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param_col < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " =hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i - 1 < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " ; " < < endl ;
i + + ;
}
2012-11-29 18:07:48 +01:00
}
2017-01-05 17:31:48 +01:00
ofstream paramsDerivsFile ;
2018-06-27 15:01:31 +02:00
string filename = julia ? basename + " StaticParamsDerivs.jl " : packageDir ( basename ) + " /static_params_derivs.m " ;
2018-06-27 15:12:12 +02:00
paramsDerivsFile . open ( filename , ios : : out | ios : : binary ) ;
2017-01-05 17:31:48 +01:00
if ( ! paramsDerivsFile . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( ! julia )
{
// Check that we don't have more than 32 nested parenthesis because Matlab does not suppor this. See Issue #1201
map < string , string > tmp_paren_vars ;
bool message_printed = false ;
2018-11-16 18:13:34 +01:00
fixNestedParenthesis ( tt_output , tmp_paren_vars , message_printed ) ;
2017-01-05 17:31:48 +01:00
fixNestedParenthesis ( jacobian_output , tmp_paren_vars , message_printed ) ;
fixNestedParenthesis ( hessian_output , tmp_paren_vars , message_printed ) ;
fixNestedParenthesis ( hessian1_output , tmp_paren_vars , message_printed ) ;
fixNestedParenthesis ( third_derivs_output , tmp_paren_vars , message_printed ) ;
fixNestedParenthesis ( third_derivs1_output , tmp_paren_vars , message_printed ) ;
2018-06-27 15:01:31 +02:00
paramsDerivsFile < < " function [rp, gp, rpp, gpp, hp] = static_params_derivs(y, x, params) " < < endl
2017-01-05 17:31:48 +01:00
< < " % " < < endl
< < " % Status : Computes derivatives of the static model with respect to the parameters " < < endl
< < " % " < < endl
< < " % Inputs : " < < endl
< < " % y [M_.endo_nbr by 1] double vector of endogenous variables in declaration order " < < endl
< < " % x [M_.exo_nbr by 1] double vector of exogenous variables in declaration order " < < endl
< < " % params [M_.param_nbr by 1] double vector of parameter values in declaration order " < < endl
< < " % " < < endl
< < " % Outputs: " < < endl
< < " % rp [M_.eq_nbr by #params] double Jacobian matrix of static model equations with respect to parameters " < < endl
< < " % Dynare may prepend or append auxiliary equations, see M_.aux_vars " < < endl
< < " % gp [M_.endo_nbr by M_.endo_nbr by #params] double Derivative of the Jacobian matrix of the static model equations with respect to the parameters " < < endl
< < " % rows: variables in declaration order " < < endl
< < " % rows: equations in order of declaration " < < 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 static 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
< < " % " < < endl
< < " % " < < endl
< < " % Warning : this file is generated automatically by Dynare " < < endl
< < " % from model file (.mod) " < < endl < < endl
2018-05-28 15:23:15 +02:00
< < " T = NaN( " < < params_derivs_temporary_terms_idxs . size ( ) < < " ,1); " < < endl
2018-11-16 18:13:34 +01:00
< < tt_output . str ( )
2017-02-24 11:20:54 +01:00
< < " rp = zeros( " < < equations . size ( ) < < " , "
2017-01-05 17:31:48 +01:00
< < symbol_table . param_nbr ( ) < < " ); " < < endl
< < jacobian_output . str ( )
2017-02-24 11:20:54 +01:00
< < " gp = zeros( " < < equations . size ( ) < < " , " < < symbol_table . endo_nbr ( ) < < " , "
2017-01-05 17:31:48 +01:00
< < symbol_table . param_nbr ( ) < < " ); " < < endl
< < hessian_output . str ( )
< < " if nargout >= 3 " < < endl
2018-11-15 16:39:53 +01:00
< < " rpp = zeros( " < < params_derivatives . find ( { 0 , 2 } ) - > second . size ( ) < < " ,4); " < < endl
2017-01-05 17:31:48 +01:00
< < hessian1_output . str ( )
2018-11-15 16:39:53 +01:00
< < " gpp = zeros( " < < params_derivatives . find ( { 1 , 2 } ) - > second . size ( ) < < " ,5); " < < endl
2017-01-05 17:31:48 +01:00
< < third_derivs_output . str ( )
< < " end " < < endl
< < " if nargout >= 5 " < < endl
2018-11-15 16:39:53 +01:00
< < " hp = zeros( " < < params_derivatives . find ( { 2 , 1 } ) - > second . size ( ) < < " ,5); " < < endl
2017-01-05 17:31:48 +01:00
< < third_derivs1_output . str ( )
< < " end " < < endl
< < " end " < < endl ;
}
else
paramsDerivsFile < < " module " < < basename < < " StaticParamsDerivs " < < 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, params) " < < endl
2018-11-16 18:13:34 +01:00
< < tt_output . str ( )
2017-02-24 11:20:54 +01:00
< < " rp = zeros( " < < equations . size ( ) < < " , "
2017-01-05 17:31:48 +01:00
< < symbol_table . param_nbr ( ) < < " ); " < < endl
< < jacobian_output . str ( )
2017-02-24 11:20:54 +01:00
< < " gp = zeros( " < < equations . size ( ) < < " , " < < symbol_table . endo_nbr ( ) < < " , "
2017-01-05 17:31:48 +01:00
< < symbol_table . param_nbr ( ) < < " ); " < < endl
< < hessian_output . str ( )
2018-11-15 16:39:53 +01:00
< < " rpp = zeros( " < < params_derivatives . find ( { 0 , 2 } ) - > second . size ( ) < < " ,4); " < < endl
2017-01-05 17:31:48 +01:00
< < hessian1_output . str ( )
2018-11-15 16:39:53 +01:00
< < " gpp = zeros( " < < params_derivatives . find ( { 1 , 2 } ) - > second . size ( ) < < " ,5); " < < endl
2017-01-05 17:31:48 +01:00
< < third_derivs_output . str ( )
2018-11-15 16:39:53 +01:00
< < " hp = zeros( " < < params_derivatives . find ( { 2 , 1 } ) - > second . size ( ) < < " ,5); " < < endl
2017-01-05 17:31:48 +01:00
< < third_derivs1_output . str ( )
< < " (rp, gp, rpp, gpp, hp) " < < endl
< < " end " < < endl
< < " end " < < endl ;
2012-11-29 18:07:48 +01:00
paramsDerivsFile . close ( ) ;
}
2017-02-20 12:18:11 +01:00
2017-02-27 15:40:34 +01:00
void
StaticModel : : writeJsonOutput ( ostream & output ) const
{
2020-06-05 16:07:52 +02:00
deriv_node_temp_terms_t tef_terms ;
writeJsonModelLocalVariables ( output , false , tef_terms ) ;
output < < " , " ;
2017-02-27 15:40:34 +01:00
writeJsonModelEquations ( output , false ) ;
}
2017-02-20 12:18:11 +01:00
void
2017-03-02 18:34:18 +01:00
StaticModel : : writeJsonComputingPassOutput ( ostream & output , bool writeDetails ) const
2017-02-20 12:18:11 +01:00
{
2019-12-20 16:59:30 +01:00
ostringstream model_local_vars_output ; // Used for storing model local vars
vector < ostringstream > d_output ( derivatives . size ( ) ) ; // Derivatives output (at all orders, including 0=residual)
2017-02-20 12:18:11 +01:00
deriv_node_temp_terms_t tef_terms ;
2019-04-18 14:34:48 +02:00
temporary_terms_t temp_term_union ;
2017-02-20 12:18:11 +01:00
2020-06-05 16:07:52 +02:00
writeJsonModelLocalVariables ( model_local_vars_output , true , tef_terms ) ;
2017-02-20 12:18:11 +01:00
2019-04-18 17:07:55 +02:00
writeJsonTemporaryTerms ( temporary_terms_derivatives [ 0 ] , temp_term_union , d_output [ 0 ] , tef_terms , " " ) ;
d_output [ 0 ] < < " , " ;
writeJsonModelEquations ( d_output [ 0 ] , true ) ;
2017-06-29 12:42:28 +02:00
2019-04-18 17:07:55 +02:00
auto getJacobCol = [ this ] ( int var ) { return symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( var ) ) ; } ;
int ncols = symbol_table . endo_nbr ( ) ;
for ( size_t i = 1 ; i < derivatives . size ( ) ; i + + )
2017-02-20 12:18:11 +01:00
{
2019-04-18 17:07:55 +02:00
string matrix_name = i = = 1 ? " jacobian " : i = = 2 ? " hessian " : i = = 3 ? " third_derivative " : to_string ( i ) + " th_derivative " ;
writeJsonTemporaryTerms ( temporary_terms_derivatives [ i ] , temp_term_union , d_output [ i ] , tef_terms , matrix_name ) ;
temp_term_union . insert ( temporary_terms_derivatives [ i ] . begin ( ) , temporary_terms_derivatives [ i ] . end ( ) ) ;
d_output [ i ] < < R " (, " ) " << matrix_name << R " ( " : {) "
< < R " ( " nrows " : ) " < < equations . size ( )
< < R " (, " ncols " : ) " < < ncols
< < R " (, " entries " : [) " ;
2017-02-20 12:18:11 +01:00
2019-04-18 17:07:55 +02:00
for ( auto it = derivatives [ i ] . begin ( ) ; it ! = derivatives [ i ] . end ( ) ; + + it )
{
if ( it ! = derivatives [ i ] . begin ( ) )
d_output [ i ] < < " , " ;
2017-03-02 18:34:18 +01:00
2019-04-18 17:07:55 +02:00
const vector < int > & vidx = it - > first ;
expr_t d = it - > second ;
int eq = vidx [ 0 ] ;
2017-03-02 18:34:18 +01:00
2019-04-18 17:07:55 +02:00
int col_idx = 0 ;
for ( size_t j = 1 ; j < vidx . size ( ) ; j + + )
{
col_idx * = symbol_table . endo_nbr ( ) ;
col_idx + = getJacobCol ( vidx [ j ] ) ;
}
2017-03-02 18:34:18 +01:00
2019-04-18 17:07:55 +02:00
if ( writeDetails )
d_output [ i ] < < R " ({ " eq " : ) " < < eq + 1 ;
else
d_output [ i ] < < R " ({ " row " : ) " < < eq + 1 ;
2017-06-29 12:42:28 +02:00
2019-04-18 17:07:55 +02:00
d_output [ i ] < < R " (, " col " : ) " < < ( i > 1 ? " [ " : " " ) < < col_idx + 1 ;
2017-06-29 12:42:28 +02:00
2019-04-18 17:07:55 +02:00
if ( i = = 2 & & vidx [ 1 ] ! = vidx [ 2 ] ) // Symmetric elements in hessian
{
int col_idx_sym = getJacobCol ( vidx [ 2 ] ) * symbol_table . endo_nbr ( ) + getJacobCol ( vidx [ 1 ] ) ;
d_output [ i ] < < " , " < < col_idx_sym + 1 ;
}
if ( i > 1 )
d_output [ i ] < < " ] " ;
2017-02-20 12:18:11 +01:00
2019-04-18 17:07:55 +02:00
if ( writeDetails )
for ( size_t j = 1 ; j < vidx . size ( ) ; j + + )
d_output [ i ] < < R " (, " var ) " << (i > 1 ? to_string(j) : " " ) << R " ( " : " ) " << symbol_table.getName(getSymbIDByDerivID(vidx[j])) << R " ( " ) " ;
2017-02-20 12:18:11 +01:00
2019-04-18 17:07:55 +02:00
d_output [ i ] < < R " (, " val " : " ) " ;
d - > writeJsonOutput ( d_output [ i ] , temp_term_union , tef_terms ) ;
d_output [ i ] < < R " ( " } ) " << endl;
2017-03-02 18:34:18 +01:00
}
2019-12-20 16:59:30 +01:00
d_output [ i ] < < " ]} " ;
2017-06-29 12:42:28 +02:00
2019-12-20 16:59:30 +01:00
ncols * = symbol_table . endo_nbr ( ) ;
2017-02-20 12:18:11 +01:00
}
2017-03-02 18:34:18 +01:00
if ( writeDetails )
2019-04-03 16:32:52 +02:00
output < < R " ( " static_model " : {) " ;
2017-03-02 18:34:18 +01:00
else
2019-04-03 16:32:52 +02:00
output < < R " ( " static_model_simple " : {) " ;
2019-04-18 17:07:55 +02:00
output < < model_local_vars_output . str ( ) ;
for ( const auto & it : d_output )
output < < " , " < < it . str ( ) ;
output < < " } " ;
2017-02-20 12:18:11 +01:00
}
void
2017-03-02 18:34:18 +01:00
StaticModel : : writeJsonParamsDerivativesFile ( ostream & output , bool writeDetails ) const
2017-02-20 12:18:11 +01:00
{
2018-11-15 16:39:53 +01:00
if ( ! params_derivatives . size ( ) )
2017-02-20 12:18:11 +01:00
return ;
2019-12-20 16:59:30 +01:00
ostringstream model_local_vars_output ; // Used for storing model local vars
ostringstream model_output ; // Used for storing model temp vars and equations
ostringstream jacobian_output ; // Used for storing jacobian equations
ostringstream hessian_output ; // Used for storing Hessian equations
ostringstream hessian1_output ; // Used for storing Hessian equations
ostringstream third_derivs_output ; // Used for storing third order derivatives equations
ostringstream third_derivs1_output ; // Used for storing third order derivatives equations
2017-02-20 12:18:11 +01:00
deriv_node_temp_terms_t tef_terms ;
2020-06-05 16:07:52 +02:00
writeJsonModelLocalVariables ( model_local_vars_output , true , tef_terms ) ;
2017-02-20 12:18:11 +01:00
2018-11-16 18:24:06 +01:00
temporary_terms_t temp_term_union ;
2018-11-30 12:22:13 +01:00
for ( const auto & it : params_derivs_temporary_terms )
2019-04-18 14:34:48 +02:00
writeJsonTemporaryTerms ( it . second , temp_term_union , model_output , tef_terms , " all " ) ;
2018-11-16 18:24:06 +01:00
2019-04-03 16:32:52 +02:00
jacobian_output < < R " ( " deriv_wrt_params " : {) "
< < R " ( " neqs " : ) " < < equations . size ( )
< < R " (, " nparamcols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " entries " : [) " ;
2018-11-15 16:39:53 +01:00
auto & rp = params_derivatives . find ( { 0 , 1 } ) - > second ;
2019-12-16 19:42:59 +01:00
for ( auto it = rp . begin ( ) ; it ! = rp . end ( ) ; + + it )
2017-02-20 12:18:11 +01:00
{
2018-11-15 16:39:53 +01:00
if ( it ! = rp . begin ( ) )
2017-02-20 12:18:11 +01:00
jacobian_output < < " , " ;
2019-09-11 15:59:23 +02:00
auto [ eq , param ] = vectorToTuple < 2 > ( it - > first ) ;
2017-02-20 12:18:11 +01:00
expr_t d1 = it - > second ;
2017-03-02 18:34:18 +01:00
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
if ( writeDetails )
2019-04-03 16:32:52 +02:00
jacobian_output < < R " ({ " eq " : ) " < < eq + 1 ;
2017-03-02 18:34:18 +01:00
else
2019-04-03 16:32:52 +02:00
jacobian_output < < R " ({ " row " : ) " < < eq + 1 ;
2017-06-29 12:42:28 +02:00
if ( writeDetails )
2019-04-03 16:32:52 +02:00
jacobian_output < < R " (, " param_col " : ) " < < param_col ;
2017-06-29 12:42:28 +02:00
2019-04-03 16:32:52 +02:00
jacobian_output < < R " (, " param " : " ) " << symbol_table.getName(getSymbIDByDerivID(param)) << R " ( " ) " ;
2017-06-29 12:42:28 +02:00
2019-04-03 16:32:52 +02:00
jacobian_output < < R " (, " val " : " ) " ;
2018-11-16 18:24:06 +01:00
d1 - > writeJsonOutput ( jacobian_output , temp_term_union , tef_terms ) ;
2019-04-03 16:32:52 +02:00
jacobian_output < < R " ( " } ) " << endl;
2017-02-20 12:18:11 +01:00
}
jacobian_output < < " ]} " ;
2018-11-15 16:39:53 +01:00
2019-04-03 16:32:52 +02:00
hessian_output < < R " ( " deriv_jacobian_wrt_params " : {) "
< < R " ( " neqs " : ) " < < equations . size ( )
< < R " (, " nvarcols " : ) " < < symbol_table . endo_nbr ( )
< < R " (, " nparamcols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " entries " : [) " ;
2018-11-15 16:39:53 +01:00
auto & gp = params_derivatives . find ( { 1 , 1 } ) - > second ;
2019-12-16 19:42:59 +01:00
for ( auto it = gp . begin ( ) ; it ! = gp . end ( ) ; + + it )
2017-02-20 12:18:11 +01:00
{
2018-11-15 16:39:53 +01:00
if ( it ! = gp . begin ( ) )
2017-02-20 12:18:11 +01:00
hessian_output < < " , " ;
2019-09-11 15:59:23 +02:00
auto [ eq , var , param ] = vectorToTuple < 3 > ( it - > first ) ;
2017-02-20 12:18:11 +01:00
expr_t d2 = it - > second ;
2017-03-02 18:34:18 +01:00
int var_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( var ) ) + 1 ;
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
if ( writeDetails )
2019-04-03 16:32:52 +02:00
hessian_output < < R " ({ " eq " : ) " < < eq + 1 ;
2017-03-02 18:34:18 +01:00
else
2019-04-03 16:32:52 +02:00
hessian_output < < R " ({ " row " : ) " < < eq + 1 ;
2017-06-29 12:42:28 +02:00
if ( writeDetails )
2019-04-03 16:32:52 +02:00
hessian_output < < R " (, " var " : " ) " << symbol_table.getName(getSymbIDByDerivID(var)) << R " ( " ) "
< < R " (, " param " : " ) " << symbol_table.getName(getSymbIDByDerivID(param)) << R " ( " ) " ;
2017-06-29 12:42:28 +02:00
2019-04-03 16:32:52 +02:00
hessian_output < < R " (, " var_col " : ) " < < var_col
< < R " (, " param_col " : ) " < < param_col
< < R " (, " val " : " ) " ;
2018-11-16 18:24:06 +01:00
d2 - > writeJsonOutput ( hessian_output , temp_term_union , tef_terms ) ;
2019-04-03 16:32:52 +02:00
hessian_output < < R " ( " } ) " << endl;
2017-02-20 12:18:11 +01:00
}
hessian_output < < " ]} " ;
2019-04-03 16:32:52 +02:00
hessian1_output < < R " ( " second_deriv_residuals_wrt_params " : {) "
< < R " ( " nrows " : ) " < < equations . size ( )
< < R " (, " nparam1cols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " nparam2cols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " entries " : [) " ;
2018-11-15 16:39:53 +01:00
auto & rpp = params_derivatives . find ( { 0 , 2 } ) - > second ;
for ( auto it = rpp . begin ( ) ; it ! = rpp . end ( ) ; + + it )
2017-02-20 12:18:11 +01:00
{
2018-11-15 16:39:53 +01:00
if ( it ! = rpp . begin ( ) )
2017-02-20 12:18:11 +01:00
hessian1_output < < " , " ;
2019-09-11 15:59:23 +02:00
auto [ eq , param1 , param2 ] = vectorToTuple < 3 > ( it - > first ) ;
2017-02-20 12:18:11 +01:00
expr_t d2 = it - > second ;
2017-03-02 18:34:18 +01:00
int param1_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param1 ) ) + 1 ;
int param2_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param2 ) ) + 1 ;
if ( writeDetails )
2019-04-03 16:32:52 +02:00
hessian1_output < < R " ({ " eq " : ) " < < eq + 1 ;
2017-03-02 18:34:18 +01:00
else
2019-04-03 16:32:52 +02:00
hessian1_output < < R " ({ " row " : ) " < < eq + 1 ;
2017-06-29 12:42:28 +02:00
2019-04-03 16:32:52 +02:00
hessian1_output < < R " (, " param1_col " : ) " < < param1_col
< < R " (, " param2_col " : ) " < < param2_col ;
2017-06-29 12:42:28 +02:00
if ( writeDetails )
2019-04-03 16:32:52 +02:00
hessian1_output < < R " (, " param1 " : " ) " << symbol_table.getName(getSymbIDByDerivID(param1)) << R " ( " ) "
< < R " (, " param2 " : " ) " << symbol_table.getName(getSymbIDByDerivID(param2)) << R " ( " ) " ;
2017-06-29 12:42:28 +02:00
2019-04-03 16:32:52 +02:00
hessian1_output < < R " (, " val " : " ) " ;
2018-11-16 18:24:06 +01:00
d2 - > writeJsonOutput ( hessian1_output , temp_term_union , tef_terms ) ;
2019-04-03 16:32:52 +02:00
hessian1_output < < R " ( " } ) " << endl;
2017-02-20 12:18:11 +01:00
}
hessian1_output < < " ]} " ;
2018-11-15 16:39:53 +01:00
2019-04-03 16:32:52 +02:00
third_derivs_output < < R " ( " second_deriv_jacobian_wrt_params " : {) "
< < R " ( " neqs " : ) " < < equations . size ( )
< < R " (, " nvarcols " : ) " < < symbol_table . endo_nbr ( )
< < R " (, " nparam1cols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " nparam2cols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " entries " : [) " ;
2018-11-15 16:39:53 +01:00
auto & gpp = params_derivatives . find ( { 1 , 2 } ) - > second ;
for ( auto it = gpp . begin ( ) ; it ! = gpp . end ( ) ; + + it )
2017-02-20 12:18:11 +01:00
{
2018-11-15 16:39:53 +01:00
if ( it ! = gpp . begin ( ) )
2017-02-20 12:18:11 +01:00
third_derivs_output < < " , " ;
2019-09-11 15:59:23 +02:00
auto [ eq , var , param1 , param2 ] = vectorToTuple < 4 > ( it - > first ) ;
2017-02-20 12:18:11 +01:00
expr_t d2 = it - > second ;
2017-03-02 18:34:18 +01:00
int var_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( var ) ) + 1 ;
int param1_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param1 ) ) + 1 ;
int param2_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param2 ) ) + 1 ;
if ( writeDetails )
2019-04-03 16:32:52 +02:00
third_derivs_output < < R " ({ " eq " : ) " < < eq + 1 ;
2017-03-02 18:34:18 +01:00
else
2019-04-03 16:32:52 +02:00
third_derivs_output < < R " ({ " row " : ) " < < eq + 1 ;
third_derivs_output < < R " (, " var_col " : ) " < < var_col
< < R " (, " param1_col " : ) " < < param1_col
< < R " (, " param2_col " : ) " < < param2_col ;
2017-06-29 12:42:28 +02:00
if ( writeDetails )
2019-04-03 16:32:52 +02:00
third_derivs_output < < R " (, " var " : " ) " << symbol_table.getName(var) << R " ( " ) "
< < R " (, " param1 " : " ) " << symbol_table.getName(getSymbIDByDerivID(param1)) << R " ( " ) "
< < R " (, " param2 " : " ) " << symbol_table.getName(getSymbIDByDerivID(param2)) << R " ( " ) " ;
2017-06-29 12:42:28 +02:00
2019-04-03 16:32:52 +02:00
third_derivs_output < < R " (, " val " : " ) " ;
2018-11-16 18:24:06 +01:00
d2 - > writeJsonOutput ( third_derivs_output , temp_term_union , tef_terms ) ;
2019-04-03 16:32:52 +02:00
third_derivs_output < < R " ( " } ) " << endl;
2017-02-20 12:18:11 +01:00
}
third_derivs_output < < " ]} " < < endl ;
2019-04-03 16:32:52 +02:00
third_derivs1_output < < R " ( " derivative_hessian_wrt_params " : {) "
< < R " ( " neqs " : ) " < < equations . size ( )
< < R " (, " nvar1cols " : ) " < < symbol_table . endo_nbr ( )
< < R " (, " nvar2cols " : ) " < < symbol_table . endo_nbr ( )
< < R " (, " nparamcols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " entries " : [) " ;
2018-11-15 16:39:53 +01:00
auto & hp = params_derivatives . find ( { 2 , 1 } ) - > second ;
for ( auto it = hp . begin ( ) ; it ! = hp . end ( ) ; + + it )
2017-02-20 12:18:11 +01:00
{
2018-11-15 16:39:53 +01:00
if ( it ! = hp . begin ( ) )
2017-02-20 12:18:11 +01:00
third_derivs1_output < < " , " ;
2019-09-11 15:59:23 +02:00
auto [ eq , var1 , var2 , param ] = vectorToTuple < 4 > ( it - > first ) ;
2017-02-20 12:18:11 +01:00
expr_t d2 = it - > second ;
2017-03-02 18:34:18 +01:00
int var1_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( var1 ) ) + 1 ;
int var2_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( var2 ) ) + 1 ;
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
if ( writeDetails )
2019-04-03 16:32:52 +02:00
third_derivs1_output < < R " ({ " eq " : ) " < < eq + 1 ;
2017-03-02 18:34:18 +01:00
else
2019-04-03 16:32:52 +02:00
third_derivs1_output < < R " ({ " row " : ) " < < eq + 1 ;
2017-06-29 12:42:28 +02:00
2019-04-03 16:32:52 +02:00
third_derivs1_output < < R " (, " var1_col " : ) " < < var1_col
< < R " (, " var2_col " : ) " < < var2_col
< < R " (, " param_col " : ) " < < param_col ;
2017-06-29 12:42:28 +02:00
if ( writeDetails )
2019-04-03 16:32:52 +02:00
third_derivs1_output < < R " (, " var1 " : " ) " << symbol_table.getName(getSymbIDByDerivID(var1)) << R " ( " ) "
< < R " (, " var2 " : " ) " << symbol_table.getName(getSymbIDByDerivID(var2)) << R " ( " ) "
< < R " (, " param1 " : " ) " << symbol_table.getName(getSymbIDByDerivID(param)) << R " ( " ) " ;
2017-06-29 12:42:28 +02:00
2019-04-03 16:32:52 +02:00
third_derivs1_output < < R " (, " val " : " ) " ;
2018-11-16 18:24:06 +01:00
d2 - > writeJsonOutput ( third_derivs1_output , temp_term_union , tef_terms ) ;
2019-04-03 16:32:52 +02:00
third_derivs1_output < < R " ( " } ) " << endl;
2017-02-20 12:18:11 +01:00
}
third_derivs1_output < < " ]} " < < endl ;
2017-03-02 18:34:18 +01:00
if ( writeDetails )
2019-04-03 16:32:52 +02:00
output < < R " ( " static_model_params_derivative " : {) " ;
2017-03-02 18:34:18 +01:00
else
2019-04-03 16:32:52 +02:00
output < < R " ( " static_model_params_derivatives_simple " : {) " ;
2017-03-02 18:34:18 +01:00
output < < model_local_vars_output . str ( )
2017-02-20 12:18:11 +01:00
< < " , " < < model_output . str ( )
< < " , " < < jacobian_output . str ( )
< < " , " < < hessian_output . str ( )
< < " , " < < hessian1_output . str ( )
< < " , " < < third_derivs_output . str ( )
< < " , " < < third_derivs1_output . str ( )
< < " } " ;
}