2015-09-22 12:45:27 +02:00
/*
2023-01-09 15:19:36 +01:00
* Copyright © 2007 - 2023 Dynare Team
2008-01-11 14:42:14 +01:00
*
* This file is part of Dynare .
*
* Dynare is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Dynare is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2021-06-09 17:33:48 +02:00
* along with Dynare . If not , see < https : //www.gnu.org/licenses/>.
2008-01-11 14:42:14 +01:00
*/
2009-07-21 17:50:12 +02:00
# include <sstream>
2021-02-03 18:10:01 +01:00
# include <algorithm>
2023-01-09 15:19:36 +01:00
# include <filesystem>
2023-01-24 12:21:08 +01:00
# include <type_traits>
2023-06-13 16:55:24 +02:00
# include <chrono>
2021-02-03 18:10:01 +01:00
2007-11-21 00:27:30 +01:00
# include "SparseMatrix.hh"
2023-06-13 16:34:22 +02:00
dynSparseMatrix : : dynSparseMatrix ( Evaluate & evaluator_arg , int y_size_arg , int y_kmin_arg , int y_kmax_arg , bool steady_state_arg , bool block_decomposed_arg , int periods_arg ,
int minimal_solving_periods_arg , const BasicSymbolTable & symbol_table_arg , int verbosity_arg ) :
2023-04-18 15:59:03 +02:00
symbol_table { symbol_table_arg } ,
steady_state { steady_state_arg } ,
2023-02-17 19:46:41 +01:00
block_decomposed { block_decomposed_arg } ,
2023-04-18 17:53:27 +02:00
evaluator { evaluator_arg } ,
2023-02-17 19:46:41 +01:00
minimal_solving_periods { minimal_solving_periods_arg } ,
2023-04-18 15:49:56 +02:00
y_size { y_size_arg } ,
y_kmin { y_kmin_arg } ,
y_kmax { y_kmax_arg } ,
periods { periods_arg } ,
2023-06-13 16:34:22 +02:00
verbosity { verbosity_arg }
2007-11-21 00:27:30 +01:00
{
2021-02-01 13:49:27 +01:00
pivotva = nullptr ;
g_save_op = nullptr ;
2009-08-25 11:43:01 +02:00
g_nop_all = 0 ;
2007-11-21 00:27:30 +01:00
mem_mngr . init_Mem ( ) ;
2009-08-25 11:43:01 +02:00
symbolic = true ;
alt_symbolic = false ;
alt_symbolic_count = 0 ;
max_u = 0 ;
min_u = 0x7FFFFFFF ;
res1a = 9.0e60 ;
tbreak_g = 0 ;
start_compare = 0 ;
2009-07-21 17:50:12 +02:00
restart = 0 ;
2009-10-30 17:29:16 +01:00
IM_i . clear ( ) ;
2010-07-23 11:20:24 +02:00
lu_inc_tol = 1e-10 ;
2021-02-01 13:49:27 +01:00
Symbolic = nullptr ;
Numeric = nullptr ;
2007-11-21 00:27:30 +01:00
}
2009-08-25 11:43:01 +02:00
int
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : NRow ( int r ) const
2007-11-21 00:27:30 +01:00
{
return NbNZRow [ r ] ;
}
2009-08-25 11:43:01 +02:00
int
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : NCol ( int c ) const
2007-11-21 00:27:30 +01:00
{
return NbNZCol [ c ] ;
}
2009-08-25 11:43:01 +02:00
int
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : At_Row ( int r , NonZeroElem * * first ) const
2007-11-21 00:27:30 +01:00
{
2021-02-03 18:10:01 +01:00
* first = FNZE_R [ r ] ;
2007-11-21 00:27:30 +01:00
return NbNZRow [ r ] ;
}
int
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Union_Row ( int row1 , int row2 ) const
2007-11-21 00:27:30 +01:00
{
NonZeroElem * first1 , * first2 ;
2009-08-25 11:43:01 +02:00
int n1 = At_Row ( row1 , & first1 ) ;
int n2 = At_Row ( row2 , & first2 ) ;
int i1 = 0 , i2 = 0 , nb_elem = 0 ;
while ( i1 < n1 & & i2 < n2 )
2007-11-21 00:27:30 +01:00
{
2009-08-25 11:43:01 +02:00
if ( first1 - > c_index = = first2 - > c_index )
2007-11-21 00:27:30 +01:00
{
nb_elem + + ;
i1 + + ;
i2 + + ;
2009-08-25 11:43:01 +02:00
first1 = first1 - > NZE_R_N ;
first2 = first2 - > NZE_R_N ;
2007-11-21 00:27:30 +01:00
}
2009-08-25 11:43:01 +02:00
else if ( first1 - > c_index < first2 - > c_index )
2007-11-21 00:27:30 +01:00
{
nb_elem + + ;
i1 + + ;
2009-08-25 11:43:01 +02:00
first1 = first1 - > NZE_R_N ;
2007-11-21 00:27:30 +01:00
}
else
{
nb_elem + + ;
i2 + + ;
2009-08-25 11:43:01 +02:00
first2 = first2 - > NZE_R_N ;
2007-11-21 00:27:30 +01:00
}
}
return nb_elem ;
}
int
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : At_Pos ( int r , int c , NonZeroElem * * first ) const
2007-11-21 00:27:30 +01:00
{
2021-02-03 18:10:01 +01:00
* first = FNZE_R [ r ] ;
2009-08-25 11:43:01 +02:00
while ( ( * first ) - > c_index ! = c )
2021-02-03 18:10:01 +01:00
* first = ( * first ) - > NZE_R_N ;
2007-11-21 00:27:30 +01:00
return NbNZRow [ r ] ;
}
2009-08-25 11:43:01 +02:00
int
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : At_Col ( int c , NonZeroElem * * first ) const
2007-11-21 00:27:30 +01:00
{
2021-02-03 18:10:01 +01:00
* first = FNZE_C [ c ] ;
2007-11-21 00:27:30 +01:00
return NbNZCol [ c ] ;
}
2009-08-25 11:43:01 +02:00
int
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : At_Col ( int c , int lag , NonZeroElem * * first ) const
2007-11-21 00:27:30 +01:00
{
2021-02-03 18:10:01 +01:00
* first = FNZE_C [ c ] ;
2009-08-25 11:43:01 +02:00
int i = 0 ;
2021-02-03 18:10:01 +01:00
while ( ( * first ) - > lag_index ! = lag & & * first )
* first = ( * first ) - > NZE_C_N ;
if ( * first )
2007-11-21 00:27:30 +01:00
{
2021-02-03 18:10:01 +01:00
NonZeroElem * firsta = * first ;
2007-11-21 00:27:30 +01:00
if ( ! firsta - > NZE_C_N )
i + + ;
else
{
2009-08-25 11:43:01 +02:00
while ( firsta - > lag_index = = lag & & firsta - > NZE_C_N )
2007-11-21 00:27:30 +01:00
{
2009-08-25 11:43:01 +02:00
firsta = firsta - > NZE_C_N ;
2007-11-21 00:27:30 +01:00
i + + ;
}
2011-02-04 16:53:12 +01:00
if ( firsta - > lag_index = = lag )
i + + ;
2007-11-21 00:27:30 +01:00
}
}
return i ;
}
2009-08-25 11:43:01 +02:00
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Delete ( int r , int c )
2007-11-21 00:27:30 +01:00
{
2021-02-01 13:49:27 +01:00
NonZeroElem * first = FNZE_R [ r ] , * firsta = nullptr ;
2009-08-25 11:43:01 +02:00
while ( first - > c_index ! = c )
{
firsta = first ;
first = first - > NZE_R_N ;
}
2021-02-09 15:55:36 +01:00
if ( firsta )
2009-08-25 11:43:01 +02:00
firsta - > NZE_R_N = first - > NZE_R_N ;
if ( first = = FNZE_R [ r ] )
FNZE_R [ r ] = first - > NZE_R_N ;
2007-11-21 00:27:30 +01:00
NbNZRow [ r ] - - ;
2009-08-25 11:43:01 +02:00
first = FNZE_C [ c ] ;
2021-02-01 13:49:27 +01:00
firsta = nullptr ;
2009-08-25 11:43:01 +02:00
while ( first - > r_index ! = r )
2007-11-21 00:27:30 +01:00
{
2009-08-25 11:43:01 +02:00
firsta = first ;
first = first - > NZE_C_N ;
2007-11-21 00:27:30 +01:00
}
2009-08-25 11:43:01 +02:00
2021-02-09 15:55:36 +01:00
if ( firsta )
2009-08-25 11:43:01 +02:00
firsta - > NZE_C_N = first - > NZE_C_N ;
if ( first = = FNZE_C [ c ] )
2009-12-16 18:18:38 +01:00
FNZE_C [ c ] = first - > NZE_C_N ;
2009-08-25 11:43:01 +02:00
2007-11-21 00:27:30 +01:00
u_liste . push_back ( first - > u_index ) ;
mem_mngr . mxFree_NZE ( first ) ;
NbNZCol [ c ] - - ;
}
2009-08-25 11:43:01 +02:00
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Insert ( int r , int c , int u_index , int lag_index )
2007-11-21 00:27:30 +01:00
{
2009-08-25 11:43:01 +02:00
NonZeroElem * firstn , * first , * firsta , * a ;
firstn = mem_mngr . mxMalloc_NZE ( ) ;
first = FNZE_R [ r ] ;
2021-02-01 13:49:27 +01:00
firsta = nullptr ;
2009-08-25 11:43:01 +02:00
while ( first - > c_index < c & & ( a = first - > NZE_R_N ) )
2009-01-30 12:36:15 +01:00
{
2009-08-25 11:43:01 +02:00
firsta = first ;
first = a ;
2007-11-21 00:27:30 +01:00
}
2009-08-25 11:43:01 +02:00
firstn - > u_index = u_index ;
firstn - > r_index = r ;
firstn - > c_index = c ;
firstn - > lag_index = lag_index ;
if ( first - > c_index > c )
2009-01-30 12:36:15 +01:00
{
2009-08-25 11:43:01 +02:00
if ( first = = FNZE_R [ r ] )
FNZE_R [ r ] = firstn ;
2021-02-09 15:55:36 +01:00
if ( firsta )
2009-08-25 11:43:01 +02:00
firsta - > NZE_R_N = firstn ;
firstn - > NZE_R_N = first ;
2007-11-21 00:27:30 +01:00
}
2009-12-16 14:21:31 +01:00
else
2009-01-30 12:36:15 +01:00
{
2009-08-25 11:43:01 +02:00
first - > NZE_R_N = firstn ;
2021-02-01 13:49:27 +01:00
firstn - > NZE_R_N = nullptr ;
2009-01-30 12:36:15 +01:00
}
NbNZRow [ r ] + + ;
2009-08-25 11:43:01 +02:00
first = FNZE_C [ c ] ;
2021-02-01 13:49:27 +01:00
firsta = nullptr ;
2009-08-25 11:43:01 +02:00
while ( first - > r_index < r & & ( a = first - > NZE_C_N ) )
2007-11-21 00:27:30 +01:00
{
2009-08-25 11:43:01 +02:00
firsta = first ;
first = a ;
2007-11-21 00:27:30 +01:00
}
2009-08-25 11:43:01 +02:00
if ( first - > r_index > r )
2007-11-21 00:27:30 +01:00
{
2009-08-25 11:43:01 +02:00
if ( first = = FNZE_C [ c ] )
FNZE_C [ c ] = firstn ;
2021-02-09 15:55:36 +01:00
if ( firsta )
2009-08-25 11:43:01 +02:00
firsta - > NZE_C_N = firstn ;
firstn - > NZE_C_N = first ;
2007-11-21 00:27:30 +01:00
}
2009-12-16 14:21:31 +01:00
else
2007-11-21 00:27:30 +01:00
{
2009-08-25 11:43:01 +02:00
first - > NZE_C_N = firstn ;
2021-02-01 13:49:27 +01:00
firstn - > NZE_C_N = nullptr ;
2007-11-21 00:27:30 +01:00
}
2009-08-25 11:43:01 +02:00
2007-11-21 00:27:30 +01:00
NbNZCol [ c ] + + ;
}
2015-09-22 12:45:27 +02:00
void
dynSparseMatrix : : Close_SaveCode ( )
{
SaveCode . close ( ) ;
}
2009-08-25 11:43:01 +02:00
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Read_SparseMatrix ( const string & file_name , int Size , int periods , int y_kmin , int y_kmax , bool two_boundaries , int stack_solve_algo , int solve_algo )
2007-11-21 00:27:30 +01:00
{
2009-12-16 14:21:31 +01:00
unsigned int eq , var ;
2013-03-22 15:44:34 +01:00
int lag ;
2007-11-21 00:27:30 +01:00
mem_mngr . fixe_file_name ( file_name ) ;
if ( ! SaveCode . is_open ( ) )
{
2023-01-09 15:19:36 +01:00
filesystem : : path binfile { file_name + " /model/bytecode/ " + ( block_decomposed ? " block/ " : " " )
+ ( steady_state ? " static " : " dynamic " ) + " .bin " } ;
SaveCode . open ( binfile , ios : : in | ios : : binary ) ;
2007-11-21 00:27:30 +01:00
if ( ! SaveCode . is_open ( ) )
2023-01-09 15:19:36 +01:00
throw FatalException { " In Read_SparseMatrix, " + binfile . string ( ) + " cannot be opened " } ;
2007-11-21 00:27:30 +01:00
}
IM_i . clear ( ) ;
2009-12-16 18:18:38 +01:00
if ( two_boundaries )
{
2010-07-23 11:20:24 +02:00
if ( stack_solve_algo = = 5 )
2009-08-29 18:04:06 +02:00
{
2013-03-22 15:44:34 +01:00
for ( int i = 0 ; i < u_count_init - Size ; i + + )
2010-07-23 11:20:24 +02:00
{
2013-03-22 15:44:34 +01:00
int val ;
2010-07-23 11:20:24 +02:00
SaveCode . read ( reinterpret_cast < char * > ( & eq ) , sizeof ( eq ) ) ;
SaveCode . read ( reinterpret_cast < char * > ( & var ) , sizeof ( var ) ) ;
SaveCode . read ( reinterpret_cast < char * > ( & lag ) , sizeof ( lag ) ) ;
2013-03-22 15:44:34 +01:00
SaveCode . read ( reinterpret_cast < char * > ( & val ) , sizeof ( val ) ) ;
2021-02-03 18:10:01 +01:00
IM_i [ { eq , var , lag } ] = val ;
2010-07-23 11:20:24 +02:00
}
2013-03-22 15:44:34 +01:00
for ( int j = 0 ; j < Size ; j + + )
2021-02-03 18:10:01 +01:00
IM_i [ { j , Size * ( periods + y_kmax ) , 0 } ] = j ;
2009-08-29 18:04:06 +02:00
}
2022-06-15 14:46:44 +02:00
else if ( ( stack_solve_algo > = 0 & & stack_solve_algo < = 4 )
| | stack_solve_algo = = 6 )
2013-03-22 15:44:34 +01:00
{
for ( int i = 0 ; i < u_count_init - Size ; i + + )
{
int val ;
SaveCode . read ( reinterpret_cast < char * > ( & eq ) , sizeof ( eq ) ) ;
SaveCode . read ( reinterpret_cast < char * > ( & var ) , sizeof ( var ) ) ;
SaveCode . read ( reinterpret_cast < char * > ( & lag ) , sizeof ( lag ) ) ;
SaveCode . read ( reinterpret_cast < char * > ( & val ) , sizeof ( val ) ) ;
2021-02-03 18:10:01 +01:00
IM_i [ { var - lag * Size , - lag , eq } ] = val ;
2013-03-22 15:44:34 +01:00
}
for ( int j = 0 ; j < Size ; j + + )
2021-02-03 18:10:01 +01:00
IM_i [ { Size * ( periods + y_kmax ) , 0 , j } ] = j ;
2013-03-22 15:44:34 +01:00
}
2022-06-15 14:28:41 +02:00
else
2022-07-29 12:42:50 +02:00
throw FatalException { " Invalid value for solve_algo or stack_solve_algo " } ;
2009-12-16 18:18:38 +01:00
}
else
{
2010-10-22 16:49:47 +02:00
if ( ( stack_solve_algo = = 5 & & ! steady_state ) | | ( solve_algo = = 5 & & steady_state ) )
2010-07-23 11:20:24 +02:00
{
2013-03-22 15:44:34 +01:00
for ( int i = 0 ; i < u_count_init ; i + + )
2010-07-23 11:20:24 +02:00
{
2013-03-22 15:44:34 +01:00
int val ;
2010-07-23 11:20:24 +02:00
SaveCode . read ( reinterpret_cast < char * > ( & eq ) , sizeof ( eq ) ) ;
SaveCode . read ( reinterpret_cast < char * > ( & var ) , sizeof ( var ) ) ;
SaveCode . read ( reinterpret_cast < char * > ( & lag ) , sizeof ( lag ) ) ;
2013-03-22 15:44:34 +01:00
SaveCode . read ( reinterpret_cast < char * > ( & val ) , sizeof ( val ) ) ;
2021-02-03 18:10:01 +01:00
IM_i [ { eq , var , lag } ] = val ;
2010-07-23 11:20:24 +02:00
}
}
2022-06-15 14:46:44 +02:00
else if ( ( ( ( stack_solve_algo > = 0 & & stack_solve_algo < = 4 )
| | stack_solve_algo = = 6 ) & & ! steady_state )
2021-02-03 18:10:01 +01:00
| | ( ( solve_algo > = 6 | | solve_algo < = 8 ) & & steady_state ) )
2009-08-29 18:04:06 +02:00
{
2013-03-22 15:44:34 +01:00
for ( int i = 0 ; i < u_count_init ; i + + )
2010-07-23 11:20:24 +02:00
{
2013-03-22 15:44:34 +01:00
int val ;
2010-07-23 11:20:24 +02:00
SaveCode . read ( reinterpret_cast < char * > ( & eq ) , sizeof ( eq ) ) ;
SaveCode . read ( reinterpret_cast < char * > ( & var ) , sizeof ( var ) ) ;
SaveCode . read ( reinterpret_cast < char * > ( & lag ) , sizeof ( lag ) ) ;
2013-03-22 15:44:34 +01:00
SaveCode . read ( reinterpret_cast < char * > ( & val ) , sizeof ( val ) ) ;
2021-02-03 18:10:01 +01:00
IM_i [ { var - lag * Size , - lag , eq } ] = val ;
2010-07-23 11:20:24 +02:00
}
2009-08-29 18:04:06 +02:00
}
2022-06-15 14:28:41 +02:00
else
2022-07-29 12:42:50 +02:00
throw FatalException { " Invalid value for solve_algo or stack_solve_algo " } ;
2009-12-16 18:18:38 +01:00
}
2019-04-23 12:58:38 +02:00
index_vara = static_cast < int * > ( mxMalloc ( Size * ( periods + y_kmin + y_kmax ) * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( index_vara , __LINE__ , __FILE__ , __func__ , Size * ( periods + y_kmin + y_kmax ) * sizeof ( int ) ) ;
2013-03-22 15:44:34 +01:00
for ( int j = 0 ; j < Size ; j + + )
2009-08-25 11:43:01 +02:00
SaveCode . read ( reinterpret_cast < char * > ( & index_vara [ j ] ) , sizeof ( * index_vara ) ) ;
if ( periods + y_kmin + y_kmax > 1 )
2013-03-22 15:44:34 +01:00
for ( int i = 1 ; i < periods + y_kmin + y_kmax ; i + + )
2021-02-03 18:10:01 +01:00
for ( int j = 0 ; j < Size ; j + + )
index_vara [ j + Size * i ] = index_vara [ j + Size * ( i - 1 ) ] + y_size ;
2019-04-23 12:58:38 +02:00
index_equa = static_cast < int * > ( mxMalloc ( Size * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( index_equa , __LINE__ , __FILE__ , __func__ , Size * sizeof ( int ) ) ;
2013-03-22 15:44:34 +01:00
for ( int j = 0 ; j < Size ; j + + )
2010-01-22 11:03:29 +01:00
SaveCode . read ( reinterpret_cast < char * > ( & index_equa [ j ] ) , sizeof ( * index_equa ) ) ;
2007-11-21 00:27:30 +01:00
}
2009-08-25 11:43:01 +02:00
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Simple_Init ( int Size , const map < tuple < int , int , int > , int > & IM , bool & zero_solution )
2009-01-20 23:04:37 +01:00
{
2019-04-23 12:58:38 +02:00
pivot = static_cast < int * > ( mxMalloc ( Size * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivot , __LINE__ , __FILE__ , __func__ , Size * sizeof ( int ) ) ;
2019-04-23 12:58:38 +02:00
pivot_save = static_cast < int * > ( mxMalloc ( Size * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivot_save , __LINE__ , __FILE__ , __func__ , Size * sizeof ( int ) ) ;
2019-04-23 12:58:38 +02:00
pivotk = static_cast < int * > ( mxMalloc ( Size * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivotk , __LINE__ , __FILE__ , __func__ , Size * sizeof ( int ) ) ;
2019-04-23 12:58:38 +02:00
pivotv = static_cast < double * > ( mxMalloc ( Size * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivotv , __LINE__ , __FILE__ , __func__ , Size * sizeof ( double ) ) ;
2019-04-23 12:58:38 +02:00
pivotva = static_cast < double * > ( mxMalloc ( Size * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivotva , __LINE__ , __FILE__ , __func__ , Size * sizeof ( double ) ) ;
2019-04-23 12:58:38 +02:00
b = static_cast < int * > ( mxMalloc ( Size * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( b , __LINE__ , __FILE__ , __func__ , Size * sizeof ( int ) ) ;
2019-04-23 12:58:38 +02:00
line_done = static_cast < bool * > ( mxMalloc ( Size * sizeof ( bool ) ) ) ;
2017-05-16 16:30:27 +02:00
test_mxMalloc ( line_done , __LINE__ , __FILE__ , __func__ , Size * sizeof ( bool ) ) ;
2009-01-30 12:36:15 +01:00
2009-01-20 23:04:37 +01:00
mem_mngr . init_CHUNK_BLCK_SIZE ( u_count ) ;
2021-02-01 13:49:27 +01:00
g_save_op = nullptr ;
2009-08-25 11:43:01 +02:00
g_nop_all = 0 ;
2021-02-03 18:10:01 +01:00
int i = Size * sizeof ( NonZeroElem * ) ;
2019-04-23 12:58:38 +02:00
FNZE_R = static_cast < NonZeroElem * * > ( mxMalloc ( i ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( FNZE_R , __LINE__ , __FILE__ , __func__ , i ) ;
2019-04-23 12:58:38 +02:00
FNZE_C = static_cast < NonZeroElem * * > ( mxMalloc ( i ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( FNZE_C , __LINE__ , __FILE__ , __func__ , i ) ;
2021-02-01 12:39:34 +01:00
auto * * temp_NZE_R = static_cast < NonZeroElem * * > ( mxMalloc ( i ) ) ;
2017-06-05 18:51:43 +02:00
test_mxMalloc ( temp_NZE_R , __LINE__ , __FILE__ , __func__ , i ) ;
2021-02-01 12:39:34 +01:00
auto * * temp_NZE_C = static_cast < NonZeroElem * * > ( mxMalloc ( i ) ) ;
2017-06-05 18:51:43 +02:00
test_mxMalloc ( temp_NZE_C , __LINE__ , __FILE__ , __func__ , i ) ;
2009-08-25 11:43:01 +02:00
i = Size * sizeof ( int ) ;
2019-04-23 12:58:38 +02:00
NbNZRow = static_cast < int * > ( mxMalloc ( i ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( NbNZRow , __LINE__ , __FILE__ , __func__ , i ) ;
2019-04-23 12:58:38 +02:00
NbNZCol = static_cast < int * > ( mxMalloc ( i ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( NbNZCol , __LINE__ , __FILE__ , __func__ , i ) ;
2009-08-25 11:43:01 +02:00
for ( i = 0 ; i < Size ; i + + )
2009-01-30 12:36:15 +01:00
{
2021-02-01 12:40:35 +01:00
line_done [ i ] = false ;
2021-02-01 13:49:27 +01:00
FNZE_C [ i ] = nullptr ;
FNZE_R [ i ] = nullptr ;
temp_NZE_C [ i ] = nullptr ;
temp_NZE_R [ i ] = nullptr ;
2009-08-25 11:43:01 +02:00
NbNZRow [ i ] = 0 ;
NbNZCol [ i ] = 0 ;
2009-01-30 12:36:15 +01:00
}
2009-08-25 11:43:01 +02:00
int u_count1 = Size ;
2021-02-03 18:10:01 +01:00
for ( auto & [ key , value ] : IM )
2009-01-20 23:04:37 +01:00
{
2021-02-03 18:10:01 +01:00
auto & [ eq , var , lag ] = key ;
2019-12-20 14:50:19 +01:00
if ( lag = = 0 ) /*Build the index for sparse matrix containing the jacobian : u*/
2009-01-20 23:04:37 +01:00
{
NbNZRow [ eq ] + + ;
NbNZCol [ var ] + + ;
2021-02-03 18:10:01 +01:00
NonZeroElem * first = mem_mngr . mxMalloc_NZE ( ) ;
2021-02-01 13:49:27 +01:00
first - > NZE_C_N = nullptr ;
first - > NZE_R_N = nullptr ;
2009-12-16 14:21:31 +01:00
first - > u_index = u_count1 ;
2009-08-25 11:43:01 +02:00
first - > r_index = eq ;
first - > c_index = var ;
first - > lag_index = lag ;
2021-02-09 15:55:36 +01:00
if ( ! FNZE_R [ eq ] )
2009-08-25 11:43:01 +02:00
FNZE_R [ eq ] = first ;
2021-02-09 15:55:36 +01:00
if ( ! FNZE_C [ var ] )
2009-08-25 11:43:01 +02:00
FNZE_C [ var ] = first ;
2021-02-09 15:55:36 +01:00
if ( temp_NZE_R [ eq ] )
2009-08-25 11:43:01 +02:00
temp_NZE_R [ eq ] - > NZE_R_N = first ;
2021-02-09 15:55:36 +01:00
if ( temp_NZE_C [ var ] )
2009-08-25 11:43:01 +02:00
temp_NZE_C [ var ] - > NZE_C_N = first ;
temp_NZE_R [ eq ] = first ;
temp_NZE_C [ var ] = first ;
2009-01-20 23:04:37 +01:00
u_count1 + + ;
}
}
2010-10-18 17:28:21 +02:00
double cum_abs_sum = 0 ;
2013-03-22 15:44:34 +01:00
for ( int i = 0 ; i < Size ; i + + )
2010-10-18 17:28:21 +02:00
{
b [ i ] = i ;
cum_abs_sum + = fabs ( u [ i ] ) ;
}
if ( cum_abs_sum < 1e-20 )
zero_solution = true ;
else
zero_solution = false ;
2009-01-20 23:04:37 +01:00
mxFree ( temp_NZE_R ) ;
mxFree ( temp_NZE_C ) ;
2009-12-16 14:21:31 +01:00
u_count = u_count1 ;
2009-01-20 23:04:37 +01:00
}
2009-08-25 11:43:01 +02:00
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Init_Matlab_Sparse_Simple ( int Size , const map < tuple < int , int , int > , int > & IM , const mxArray * A_m , const mxArray * b_m , bool & zero_solution , const mxArray * x0_m ) const
2010-07-23 11:20:24 +02:00
{
double * b = mxGetPr ( b_m ) ;
if ( ! b )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, can't retrieve b vector " } ;
2011-01-03 14:15:12 +01:00
double * x0 = mxGetPr ( x0_m ) ;
if ( ! x0 )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, can't retrieve x0 vector " } ;
2010-07-23 11:20:24 +02:00
mwIndex * Ai = mxGetIr ( A_m ) ;
if ( ! Ai )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, can't allocate Ai index vector " } ;
2010-07-23 11:20:24 +02:00
mwIndex * Aj = mxGetJc ( A_m ) ;
if ( ! Aj )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, can't allocate Aj index vector " } ;
2010-07-23 11:20:24 +02:00
double * A = mxGetPr ( A_m ) ;
if ( ! A )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, can't retrieve A matrix " } ;
2021-02-03 18:10:01 +01:00
2013-03-22 15:44:34 +01:00
for ( int i = 0 ; i < y_size * ( periods + y_kmin ) ; i + + )
2010-07-23 11:20:24 +02:00
ya [ i ] = y [ i ] ;
2010-12-31 16:29:39 +01:00
# ifdef DEBUG
2010-07-23 11:20:24 +02:00
unsigned int max_nze = mxGetNzmax ( A_m ) ;
2010-09-17 09:57:38 +02:00
# endif
2010-07-23 11:20:24 +02:00
unsigned int NZE = 0 ;
int last_var = 0 ;
2010-10-18 17:28:21 +02:00
double cum_abs_sum = 0 ;
2013-03-22 15:44:34 +01:00
for ( int i = 0 ; i < Size ; i + + )
2010-10-18 17:28:21 +02:00
{
b [ i ] = u [ i ] ;
cum_abs_sum + = fabs ( b [ i ] ) ;
2011-01-03 14:15:12 +01:00
x0 [ i ] = y [ i ] ;
2010-10-18 17:28:21 +02:00
}
if ( cum_abs_sum < 1e-20 )
zero_solution = true ;
else
zero_solution = false ;
2010-07-23 11:20:24 +02:00
Aj [ 0 ] = 0 ;
2013-03-22 15:44:34 +01:00
last_var = 0 ;
2021-02-03 18:10:01 +01:00
for ( auto & [ key , index ] : IM )
2010-07-23 11:20:24 +02:00
{
2021-02-03 18:10:01 +01:00
auto & [ var , ignore , eq ] = key ;
2010-07-23 11:20:24 +02:00
if ( var ! = last_var )
{
2019-12-20 14:50:19 +01:00
Aj [ 1 + last_var ] = NZE ;
2010-07-23 11:20:24 +02:00
last_var = var ;
}
2010-12-31 16:29:39 +01:00
# ifdef DEBUG
2011-02-04 16:53:12 +01:00
if ( index < 0 | | index > = u_count_alloc | | index > Size + Size * Size )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, index ( " + to_string ( index )
+ " ) out of range for u vector max = "
+ to_string ( Size + Size * Size )
+ " allocated = " + to_string ( u_count_alloc ) } ;
2010-07-23 11:20:24 +02:00
if ( NZE > = max_nze )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, exceeds the capacity of A_m sparse matrix " } ;
2010-07-23 11:20:24 +02:00
# endif
A [ NZE ] = u [ index ] ;
Ai [ NZE ] = eq ;
NZE + + ;
2010-12-31 16:29:39 +01:00
# ifdef DEBUG
2010-08-18 13:51:57 +02:00
if ( eq < 0 | | eq > = Size )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, index ( " + to_string ( eq )
+ " ) out of range for b vector " } ;
2010-08-18 13:51:57 +02:00
if ( var < 0 | | var > = Size )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, index ( " + to_string ( var )
+ " ) out of range for index_vara vector " } ;
2010-08-18 13:51:57 +02:00
if ( index_vara [ var ] < 0 | | index_vara [ var ] > = y_size )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, index ( "
+ to_string ( index_vara [ var ] )
+ " ) out of range for y vector max= " + to_string ( y_size )
+ " (0) " } ;
2010-07-23 11:20:24 +02:00
# endif
2011-02-04 16:53:12 +01:00
}
2010-07-23 11:20:24 +02:00
Aj [ Size ] = NZE ;
}
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Init_UMFPACK_Sparse_Simple ( int Size , const map < tuple < int , int , int > , int > & IM , SuiteSparse_long * * Ap , SuiteSparse_long * * Ai , double * * Ax , double * * b , bool & zero_solution , const mxArray * x0_m ) const
2010-07-23 11:20:24 +02:00
{
2019-04-23 12:58:38 +02:00
* b = static_cast < double * > ( mxMalloc ( Size * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( * b , __LINE__ , __FILE__ , __func__ , Size * sizeof ( double ) ) ;
2013-03-22 15:44:34 +01:00
if ( ! ( * b ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, can't retrieve b vector " } ;
2011-01-03 14:15:12 +01:00
double * x0 = mxGetPr ( x0_m ) ;
if ( ! x0 )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse_Simple, can't retrieve x0 vector " } ;
2019-04-23 12:58:38 +02:00
* Ap = static_cast < SuiteSparse_long * > ( mxMalloc ( ( Size + 1 ) * sizeof ( SuiteSparse_long ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( * Ap , __LINE__ , __FILE__ , __func__ , ( Size + 1 ) * sizeof ( SuiteSparse_long ) ) ;
2013-03-22 15:44:34 +01:00
if ( ! ( * Ap ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, can't allocate Ap index vector " } ;
2013-03-22 15:44:34 +01:00
size_t prior_nz = IM . size ( ) ;
2019-04-23 12:58:38 +02:00
* Ai = static_cast < SuiteSparse_long * > ( mxMalloc ( prior_nz * sizeof ( SuiteSparse_long ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( * Ai , __LINE__ , __FILE__ , __func__ , prior_nz * sizeof ( SuiteSparse_long ) ) ;
2013-03-22 15:44:34 +01:00
if ( ! ( * Ai ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, can't allocate Ai index vector " } ;
2019-04-23 12:58:38 +02:00
* Ax = static_cast < double * > ( mxMalloc ( prior_nz * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( * Ax , __LINE__ , __FILE__ , __func__ , prior_nz * sizeof ( double ) ) ;
2013-03-22 15:44:34 +01:00
if ( ! ( * Ax ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, can't retrieve Ax matrix " } ;
2013-03-22 15:44:34 +01:00
for ( int i = 0 ; i < Size ; i + + )
{
int eq = index_vara [ i ] ;
ya [ eq + it_ * y_size ] = y [ eq + it_ * y_size ] ;
}
2010-12-31 16:29:39 +01:00
# ifdef DEBUG
2019-12-20 14:50:19 +01:00
unsigned int max_nze = prior_nz ; //mxGetNzmax(A_m);
2010-07-23 11:20:24 +02:00
# endif
unsigned int NZE = 0 ;
int last_var = 0 ;
2013-03-22 15:44:34 +01:00
double cum_abs_sum = 0 ;
for ( int i = 0 ; i < Size ; i + + )
2011-01-03 14:15:12 +01:00
{
2013-03-22 15:44:34 +01:00
( * b ) [ i ] = u [ i ] ;
cum_abs_sum + = fabs ( ( * b ) [ i ] ) ;
x0 [ i ] = y [ i ] ;
2011-01-03 14:15:12 +01:00
}
2013-03-22 15:44:34 +01:00
if ( cum_abs_sum < 1e-20 )
zero_solution = true ;
else
zero_solution = false ;
( * Ap ) [ 0 ] = 0 ;
last_var = 0 ;
2021-02-03 18:10:01 +01:00
for ( auto & [ key , index ] : IM )
2010-07-23 11:20:24 +02:00
{
2021-02-03 18:10:01 +01:00
auto & [ var , ignore , eq ] = key ;
2013-03-22 15:44:34 +01:00
if ( var ! = last_var )
2010-07-23 11:20:24 +02:00
{
2019-12-20 14:50:19 +01:00
( * Ap ) [ 1 + last_var ] = NZE ;
2013-03-22 15:44:34 +01:00
last_var = var ;
}
2010-12-31 16:29:39 +01:00
# ifdef DEBUG
2013-03-22 15:44:34 +01:00
if ( index < 0 | | index > = u_count_alloc | | index > Size + Size * Size )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, index ( " + to_string ( index )
+ " ) out of range for u vector max = "
+ to_string ( Size + Size * Size )
+ " allocated = " + to_string ( u_count_alloc ) } ;
2013-03-22 15:44:34 +01:00
if ( NZE > = max_nze )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, exceeds the capacity of A_m sparse matrix " } ;
2013-03-22 15:44:34 +01:00
# endif
( * Ax ) [ NZE ] = u [ index ] ;
( * Ai ) [ NZE ] = eq ;
NZE + + ;
# ifdef DEBUG
if ( eq < 0 | | eq > = Size )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, index ( " + to_string ( eq )
+ " ) out of range for b vector " } ;
2013-03-22 15:44:34 +01:00
if ( var < 0 | | var > = Size )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, index ( " + to_string ( var )
+ " ) out of range for index_vara vector " } ;
2013-03-22 15:44:34 +01:00
if ( index_vara [ var ] < 0 | | index_vara [ var ] > = y_size )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, index ( "
+ to_string ( index_vara [ var ] )
+ " ) out of range for y vector max= " + to_string ( y_size )
+ " (0) " } ;
2013-03-22 15:44:34 +01:00
# endif
}
( * Ap ) [ Size ] = NZE ;
}
2015-09-22 12:45:27 +02:00
int
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : find_exo_num ( const vector < s_plan > & sconstrained_extended_path , int value )
2015-09-22 12:45:27 +02:00
{
2021-02-03 18:10:01 +01:00
auto it = find_if ( sconstrained_extended_path . begin ( ) , sconstrained_extended_path . end ( ) ,
[ = ] ( auto v ) { return v . exo_num = = value ; } ) ;
if ( it ! = sconstrained_extended_path . end ( ) )
return it - sconstrained_extended_path . begin ( ) ;
else
return - 1 ;
2015-09-22 12:45:27 +02:00
}
int
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : find_int_date ( const vector < pair < int , double > > & per_value , int value )
2015-09-22 12:45:27 +02:00
{
2021-02-03 18:10:01 +01:00
auto it = find_if ( per_value . begin ( ) , per_value . end ( ) , [ = ] ( auto v ) { return v . first = = value ; } ) ;
if ( it ! = per_value . end ( ) )
return it - per_value . begin ( ) ;
else
return - 1 ;
2015-09-22 12:45:27 +02:00
}
2013-03-22 15:44:34 +01:00
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Init_UMFPACK_Sparse ( int periods , int y_kmin , int y_kmax , int Size , const map < tuple < int , int , int > , int > & IM , SuiteSparse_long * * Ap , SuiteSparse_long * * Ai , double * * Ax , double * * b , const mxArray * x0_m , const vector_table_conditional_local_type & vector_table_conditional_local , int block_num ) const
2013-03-22 15:44:34 +01:00
{
int n = periods * Size ;
2019-04-23 12:58:38 +02:00
* b = static_cast < double * > ( mxMalloc ( n * sizeof ( double ) ) ) ;
2013-03-22 15:44:34 +01:00
if ( ! ( * b ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, can't retrieve b vector " } ;
2013-03-22 15:44:34 +01:00
double * x0 = mxGetPr ( x0_m ) ;
if ( ! x0 )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse_Simple, can't retrieve x0 vector " } ;
2019-04-23 12:58:38 +02:00
* Ap = static_cast < SuiteSparse_long * > ( mxMalloc ( ( n + 1 ) * sizeof ( SuiteSparse_long ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( * Ap , __LINE__ , __FILE__ , __func__ , ( n + 1 ) * sizeof ( SuiteSparse_long ) ) ;
2013-03-22 15:44:34 +01:00
if ( ! ( * Ap ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, can't allocate Ap index vector " } ;
2013-03-22 15:44:34 +01:00
size_t prior_nz = IM . size ( ) * periods ;
2019-04-23 12:58:38 +02:00
* Ai = static_cast < SuiteSparse_long * > ( mxMalloc ( prior_nz * sizeof ( SuiteSparse_long ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( * Ai , __LINE__ , __FILE__ , __func__ , prior_nz * sizeof ( SuiteSparse_long ) ) ;
2013-03-22 15:44:34 +01:00
if ( ! ( * Ai ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, can't allocate Ai index vector " } ;
2019-04-23 12:58:38 +02:00
* Ax = static_cast < double * > ( mxMalloc ( prior_nz * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( * Ax , __LINE__ , __FILE__ , __func__ , prior_nz * sizeof ( double ) ) ;
2013-03-22 15:44:34 +01:00
if ( ! ( * Ax ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, can't retrieve Ax matrix " } ;
2013-03-22 15:44:34 +01:00
for ( int i = 0 ; i < y_size * ( periods + y_kmin ) ; i + + )
ya [ i ] = y [ i ] ;
unsigned int NZE = 0 ;
int last_var = 0 ;
for ( int i = 0 ; i < periods * Size ; i + + )
{
( * b ) [ i ] = 0 ;
x0 [ i ] = y [ index_vara [ Size * y_kmin + i ] ] ;
}
2021-02-03 18:10:01 +01:00
double * jacob_exo ;
int row_x = 0 ;
# ifdef DEBUG
int col_x ;
# endif
2015-09-22 12:45:27 +02:00
if ( vector_table_conditional_local . size ( ) )
{
jacob_exo = mxGetPr ( jacobian_exo_block [ block_num ] ) ;
row_x = mxGetM ( jacobian_exo_block [ block_num ] ) ;
2015-10-19 17:59:46 +02:00
# ifdef DEBUG
2015-09-22 12:45:27 +02:00
col_x = mxGetN ( jacobian_exo_block [ block_num ] ) ;
2015-10-19 17:59:46 +02:00
# endif
2017-05-16 16:30:27 +02:00
}
else
2021-02-03 18:10:01 +01:00
jacob_exo = nullptr ;
2015-10-19 17:59:46 +02:00
# ifdef DEBUG
2015-09-22 12:45:27 +02:00
int local_index ;
2015-10-19 17:59:46 +02:00
# endif
2017-03-24 23:15:25 +01:00
2015-09-22 12:45:27 +02:00
bool fliped = false ;
bool fliped_exogenous_derivatives_updated = false ;
int flip_exo ;
2013-03-22 15:44:34 +01:00
( * Ap ) [ 0 ] = 0 ;
2021-02-03 18:10:01 +01:00
for ( int t = 0 ; t < periods ; t + + )
2013-03-22 15:44:34 +01:00
{
last_var = - 1 ;
2021-02-03 18:10:01 +01:00
int var = 0 ;
for ( auto & [ key , value ] : IM )
2017-05-16 16:30:27 +02:00
{
2021-02-03 18:10:01 +01:00
var = get < 0 > ( key ) ;
int eq = get < 2 > ( key ) + Size * t ;
int lag = - get < 1 > ( key ) ;
int index = value + ( t - lag ) * u_count_init ;
2013-03-22 15:44:34 +01:00
if ( var ! = last_var )
{
( * Ap ) [ 1 + last_var + t * Size ] = NZE ;
last_var = var ;
2015-09-22 12:45:27 +02:00
if ( var < Size * ( periods + y_kmax ) )
{
if ( t = = 0 & & vector_table_conditional_local . size ( ) )
{
fliped = vector_table_conditional_local [ var ] . is_cond ;
fliped_exogenous_derivatives_updated = false ;
}
else
fliped = false ;
}
else
fliped = false ;
}
if ( fliped )
{
2021-02-03 18:10:01 +01:00
if ( t = = 0 & & var < ( periods + y_kmax ) * Size
& & lag = = 0 & & vector_table_conditional_local . size ( ) )
2015-09-22 12:45:27 +02:00
{
2017-05-16 16:30:27 +02:00
flip_exo = vector_table_conditional_local [ var ] . var_exo ;
2015-10-19 17:59:46 +02:00
# ifdef DEBUG
2015-09-22 12:45:27 +02:00
local_index = eq ;
2015-10-19 17:59:46 +02:00
# endif
2015-09-22 12:45:27 +02:00
if ( ! fliped_exogenous_derivatives_updated )
{
fliped_exogenous_derivatives_updated = true ;
for ( int k = 0 ; k < row_x ; k + + )
{
if ( jacob_exo [ k + row_x * flip_exo ] ! = 0 )
{
( * Ax ) [ NZE ] = jacob_exo [ k + row_x * flip_exo ] ;
( * Ai ) [ NZE ] = k ;
NZE + + ;
2017-03-24 23:15:25 +01:00
2015-09-22 12:45:27 +02:00
# ifdef DEBUG
if ( local_index < 0 | | local_index > = Size * periods )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, index ( "
+ to_string ( local_index )
+ " ) out of range for b vector " } ;
2017-05-16 16:30:27 +02:00
if ( k + row_x * flip_exo < 0 | | k + row_x * flip_exo > = row_x * col_x )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, index ( "
+ to_string ( var + Size * ( y_kmin + t + lag ) )
+ " ) out of range for jacob_exo vector " } ;
2021-02-03 18:10:01 +01:00
if ( t + y_kmin + flip_exo * nb_row_x < 0
| | t + y_kmin + flip_exo * nb_row_x > = nb_row_x * this - > col_x )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, index ( "
+ to_string ( index_vara [ var + Size * ( y_kmin + t + lag ) ] )
+ " ) out of range for x vector max= "
+ to_string ( nb_row_x * this - > col_x ) } ;
2017-03-24 23:15:25 +01:00
# endif
2019-12-20 14:50:19 +01:00
u [ k ] - = jacob_exo [ k + row_x * flip_exo ] * x [ t + y_kmin + flip_exo * nb_row_x ] ;
2015-09-22 12:45:27 +02:00
}
}
}
}
2013-03-22 15:44:34 +01:00
}
2017-03-24 23:15:25 +01:00
2013-03-22 15:44:34 +01:00
if ( var < ( periods + y_kmax ) * Size )
{
2021-02-03 18:10:01 +01:00
int ti_y_kmin = - min ( t , y_kmin ) ;
int ti_y_kmax = min ( periods - ( t + 1 ) , y_kmax ) ;
2013-03-22 15:44:34 +01:00
int ti_new_y_kmax = min ( t , y_kmax ) ;
int ti_new_y_kmin = - min ( periods - ( t + 1 ) , y_kmin ) ;
2019-12-20 14:50:19 +01:00
if ( lag < = ti_new_y_kmax & & lag > = ti_new_y_kmin ) /*Build the index for sparse matrix containing the jacobian : u*/
2013-03-22 15:44:34 +01:00
{
# ifdef DEBUG
2023-04-03 18:30:40 +02:00
if ( NZE > = prior_nz )
throw FatalException { " In Init_UMFPACK_Sparse, exceeds the capacity of allocated sparse matrix " } ;
2013-03-22 15:44:34 +01:00
# endif
2021-02-03 18:10:01 +01:00
if ( ! fliped )
2015-09-22 12:45:27 +02:00
{
( * Ax ) [ NZE ] = u [ index ] ;
( * Ai ) [ NZE ] = eq - lag * Size ;
NZE + + ;
}
else /*if (fliped)*/
{
# ifdef DEBUG
if ( eq - lag * Size < 0 | | eq - lag * Size > = Size * periods )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, index ( "
+ to_string ( eq - lag * Size )
+ " ) out of range for b vector " } ;
2021-02-03 18:10:01 +01:00
if ( var + Size * ( y_kmin + t ) < 0
| | var + Size * ( y_kmin + t ) > = Size * ( periods + y_kmin + y_kmax ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, index ( "
+ to_string ( var + Size * ( y_kmin + t ) )
+ " ) out of range for index_vara vector " } ;
2021-02-03 18:10:01 +01:00
if ( index_vara [ var + Size * ( y_kmin + t ) ] < 0
| | index_vara [ var + Size * ( y_kmin + t ) ] > = y_size * ( periods + y_kmin + y_kmax ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, index ( "
+ to_string ( index_vara [ var + Size * ( y_kmin + t ) ] )
+ " ) out of range for y vector max= "
+ to_string ( y_size * ( periods + y_kmin + y_kmax ) ) } ;
2015-09-22 12:45:27 +02:00
# endif
2021-02-03 18:10:01 +01:00
( * b ) [ eq - lag * Size ] + = u [ index ] * y [ index_vara [ var + Size * ( y_kmin + t ) ] ] ;
2015-09-22 12:45:27 +02:00
}
2017-03-24 23:15:25 +01:00
2013-03-22 15:44:34 +01:00
}
if ( lag > ti_y_kmax | | lag < ti_y_kmin )
{
# ifdef DEBUG
if ( eq < 0 | | eq > = Size * periods )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, index ( "
+ to_string ( eq )
+ " ) out of range for b vector " } ;
2021-02-03 18:10:01 +01:00
if ( var + Size * ( y_kmin + t + lag ) < 0
| | var + Size * ( y_kmin + t + lag ) > = Size * ( periods + y_kmin + y_kmax ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, index ( "
+ to_string ( var + Size * ( y_kmin + t + lag ) )
+ " ) out of range for index_vara vector " } ;
2021-02-03 18:10:01 +01:00
if ( index_vara [ var + Size * ( y_kmin + t + lag ) ] < 0
| | index_vara [ var + Size * ( y_kmin + t + lag ) ] > = y_size * ( periods + y_kmin + y_kmax ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, index ( "
+ to_string ( index_vara [ var + Size * ( y_kmin + t + lag ) ] )
+ " ) out of range for y vector max= "
+ to_string ( y_size * ( periods + y_kmin + y_kmax ) ) } ;
2010-07-23 11:20:24 +02:00
# endif
2019-12-20 14:50:19 +01:00
( * b ) [ eq ] + = u [ index + lag * u_count_init ] * y [ index_vara [ var + Size * ( y_kmin + t + lag ) ] ] ;
2010-07-23 11:20:24 +02:00
}
}
2019-12-20 14:50:19 +01:00
else /* ...and store it in the u vector*/
2010-07-23 11:20:24 +02:00
{
2010-12-31 16:29:39 +01:00
# ifdef DEBUG
2010-07-23 11:20:24 +02:00
if ( index < 0 | | index > = u_count_alloc )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, index ( " + to_string ( index )
+ " ) out of range for u vector " } ;
2010-07-23 11:20:24 +02:00
if ( eq < 0 | | eq > = ( Size * periods ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_UMFPACK_Sparse, index ( " + to_string ( eq )
+ " ) out of range for b vector " } ;
2010-07-23 11:20:24 +02:00
# endif
2019-12-20 14:50:19 +01:00
( * b ) [ eq ] + = u [ index ] ;
2010-07-23 11:20:24 +02:00
}
}
}
2013-03-22 15:44:34 +01:00
( * Ap ) [ Size * periods ] = NZE ;
# ifdef DEBUG
mexPrintf ( " *Ax = [ " ) ;
2020-05-12 23:08:04 +02:00
for ( int i = 0 ; i < static_cast < int > ( NZE ) ; i + + )
2017-05-16 16:30:27 +02:00
mexPrintf ( " %f " , ( * Ax ) [ i ] ) ;
2013-03-22 15:44:34 +01:00
mexPrintf ( " ] \n " ) ;
mexPrintf ( " *Ap = [ " ) ;
for ( int i = 0 ; i < n + 1 ; i + + )
2017-05-16 16:30:27 +02:00
mexPrintf ( " %d " , ( * Ap ) [ i ] ) ;
2013-03-22 15:44:34 +01:00
mexPrintf ( " ] \n " ) ;
mexPrintf ( " *Ai = [ " ) ;
2020-05-12 23:08:04 +02:00
for ( int i = 0 ; i < static_cast < int > ( NZE ) ; i + + )
2017-05-16 16:30:27 +02:00
mexPrintf ( " %d " , ( * Ai ) [ i ] ) ;
2013-03-22 15:44:34 +01:00
mexPrintf ( " ] \n " ) ;
# endif
2010-07-23 11:20:24 +02:00
}
2012-02-17 10:59:39 +01:00
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : PrintM ( int n , const double * Ax , const mwIndex * Ap , const mwIndex * Ai )
2009-01-20 23:04:37 +01:00
{
2013-03-22 15:44:34 +01:00
int nnz = Ap [ n ] ;
2021-02-01 12:39:34 +01:00
auto * A = static_cast < double * > ( mxMalloc ( n * n * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( A , __LINE__ , __FILE__ , __func__ , n * n * sizeof ( double ) ) ;
2021-02-03 18:10:01 +01:00
fill_n ( A , n * n , 0 ) ;
2013-03-22 15:44:34 +01:00
int k = 0 ;
2017-05-16 16:30:27 +02:00
for ( int i = 0 ; i < n ; i + + )
2021-02-03 18:10:01 +01:00
for ( int j = Ap [ i ] ; j < static_cast < int > ( Ap [ i + 1 ] ) ; j + + )
{
int row = Ai [ j ] ;
A [ row * n + i ] = Ax [ j ] ;
k + + ;
}
2013-03-22 15:44:34 +01:00
if ( nnz ! = k )
mexPrintf ( " Problem nnz(%d) != number of elements(%d) \n " , nnz , k ) ;
mexPrintf ( " ---------------------- \n " ) ;
2017-05-16 16:30:27 +02:00
for ( int i = 0 ; i < n ; i + + )
2009-01-20 23:04:37 +01:00
{
2013-03-22 15:44:34 +01:00
for ( int j = 0 ; j < n ; j + + )
2017-05-16 16:30:27 +02:00
mexPrintf ( " %-6.3f " , A [ i * n + j ] ) ;
2013-03-22 15:44:34 +01:00
mexPrintf ( " \n " ) ;
2009-01-20 23:04:37 +01:00
}
2013-03-22 15:44:34 +01:00
mxFree ( A ) ;
2009-01-20 23:04:37 +01:00
}
2010-09-24 12:52:58 +02:00
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Init_Matlab_Sparse ( int periods , int y_kmin , int y_kmax , int Size , const map < tuple < int , int , int > , int > & IM , mxArray * A_m , mxArray * b_m , const mxArray * x0_m ) const
2009-01-20 23:04:37 +01:00
{
2013-03-22 15:44:34 +01:00
double * b = mxGetPr ( b_m ) ;
if ( ! b )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse, can't retrieve b vector " } ;
2013-03-22 15:44:34 +01:00
double * x0 = mxGetPr ( x0_m ) ;
if ( ! x0 )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse_Simple, can't retrieve x0 vector " } ;
2013-03-22 15:44:34 +01:00
mwIndex * Aj = mxGetJc ( A_m ) ;
if ( ! Aj )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse, can't allocate Aj index vector " } ;
2013-03-22 15:44:34 +01:00
mwIndex * Ai = mxGetIr ( A_m ) ;
if ( ! Ai )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse, can't allocate Ai index vector " } ;
2013-03-22 15:44:34 +01:00
double * A = mxGetPr ( A_m ) ;
if ( ! A )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse, can't retrieve A matrix " } ;
2013-03-22 15:44:34 +01:00
for ( int i = 0 ; i < y_size * ( periods + y_kmin ) ; i + + )
ya [ i ] = y [ i ] ;
unsigned int NZE = 0 ;
int last_var = 0 ;
for ( int i = 0 ; i < periods * Size ; i + + )
{
b [ i ] = 0 ;
x0 [ i ] = y [ index_vara [ Size * y_kmin + i ] ] ;
}
Aj [ 0 ] = 0 ;
2021-02-03 18:10:01 +01:00
for ( int t = 0 ; t < periods ; t + + )
2013-03-22 15:44:34 +01:00
{
last_var = 0 ;
2021-02-03 18:10:01 +01:00
for ( auto & [ key , value ] : IM )
2013-03-22 15:44:34 +01:00
{
2021-02-03 18:10:01 +01:00
int var = get < 0 > ( key ) ;
2013-03-22 15:44:34 +01:00
if ( var ! = last_var )
{
Aj [ 1 + last_var + t * Size ] = NZE ;
last_var = var ;
}
2021-02-03 18:10:01 +01:00
int eq = get < 2 > ( key ) + Size * t ;
int lag = - get < 1 > ( key ) ;
int index = value + ( t - lag ) * u_count_init ;
2013-03-22 15:44:34 +01:00
if ( var < ( periods + y_kmax ) * Size )
{
2021-02-03 18:10:01 +01:00
int ti_y_kmin = - min ( t , y_kmin ) ;
int ti_y_kmax = min ( periods - ( t + 1 ) , y_kmax ) ;
2013-03-22 15:44:34 +01:00
int ti_new_y_kmax = min ( t , y_kmax ) ;
int ti_new_y_kmin = - min ( periods - ( t + 1 ) , y_kmin ) ;
2019-12-20 14:50:19 +01:00
if ( lag < = ti_new_y_kmax & & lag > = ti_new_y_kmin ) /*Build the index for sparse matrix containing the jacobian : u*/
2013-03-22 15:44:34 +01:00
{
# ifdef DEBUG
if ( index < 0 | | index > = u_count_alloc | | index > Size + Size * Size )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse, index ( " + to_string ( index )
+ " ) out of range for u vector max = "
+ to_string ( Size + Size * Size ) + " allocated = "
+ to_string ( u_count_alloc ) } ;
2023-04-03 18:30:40 +02:00
if ( NZE > = prior_nz )
throw FatalException { " In Init_Matlab_Sparse, exceeds the capacity of allocated sparse matrix " } ;
2013-03-22 15:44:34 +01:00
# endif
A [ NZE ] = u [ index ] ;
Ai [ NZE ] = eq - lag * Size ;
NZE + + ;
}
if ( lag > ti_y_kmax | | lag < ti_y_kmin )
{
# ifdef DEBUG
if ( eq < 0 | | eq > = Size * periods )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse, index ( " + to_string ( eq )
+ " ) out of range for b vector " } ;
2021-02-03 18:10:01 +01:00
if ( var + Size * ( y_kmin + t + lag ) < 0
| | var + Size * ( y_kmin + t + lag ) > = Size * ( periods + y_kmin + y_kmax ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse, index ( "
+ to_string ( var + Size * ( y_kmin + t + lag ) )
+ " ) out of range for index_vara vector " } ;
2021-02-03 18:10:01 +01:00
if ( index_vara [ var + Size * ( y_kmin + t + lag ) ] < 0
| | index_vara [ var + Size * ( y_kmin + t + lag ) ] > = y_size * ( periods + y_kmin + y_kmax ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse, index ( "
+ to_string ( index_vara [ var + Size * ( y_kmin + t + lag ) ] )
+ " ) out of range for y vector max= "
+ to_string ( y_size * ( periods + y_kmin + y_kmax ) ) } ;
2013-03-22 15:44:34 +01:00
# endif
2019-12-20 14:50:19 +01:00
b [ eq ] + = u [ index + lag * u_count_init ] * y [ index_vara [ var + Size * ( y_kmin + t + lag ) ] ] ;
2013-03-22 15:44:34 +01:00
}
}
2019-12-20 14:50:19 +01:00
else /* ...and store it in the u vector*/
2013-03-22 15:44:34 +01:00
{
# ifdef DEBUG
if ( index < 0 | | index > = u_count_alloc )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse, index ( " + to_string ( index )
+ " ) out of range for u vector " } ;
2013-03-22 15:44:34 +01:00
if ( eq < 0 | | eq > = ( Size * periods ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Init_Matlab_Sparse, index ( " + to_string ( eq )
+ " ) out of range for b vector " } ;
2013-03-22 15:44:34 +01:00
# endif
2019-12-20 14:50:19 +01:00
b [ eq ] + = u [ index ] ;
2013-03-22 15:44:34 +01:00
}
}
}
Aj [ Size * periods ] = NZE ;
}
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Init_GE ( int periods , int y_kmin , int y_kmax , int Size , const map < tuple < int , int , int > , int > & IM )
2013-03-22 15:44:34 +01:00
{
double tmp_b = 0.0 ;
2019-04-23 12:58:38 +02:00
pivot = static_cast < int * > ( mxMalloc ( Size * periods * sizeof ( int ) ) ) ;
2017-05-16 16:30:27 +02:00
test_mxMalloc ( pivot , __LINE__ , __FILE__ , __func__ , Size * periods * sizeof ( int ) ) ;
2019-04-23 12:58:38 +02:00
pivot_save = static_cast < int * > ( mxMalloc ( Size * periods * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivot_save , __LINE__ , __FILE__ , __func__ , Size * periods * sizeof ( int ) ) ;
2019-04-23 12:58:38 +02:00
pivotk = static_cast < int * > ( mxMalloc ( Size * periods * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivotk , __LINE__ , __FILE__ , __func__ , Size * periods * sizeof ( int ) ) ;
2019-04-23 12:58:38 +02:00
pivotv = static_cast < double * > ( mxMalloc ( Size * periods * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivotv , __LINE__ , __FILE__ , __func__ , Size * periods * sizeof ( double ) ) ;
2019-04-23 12:58:38 +02:00
pivotva = static_cast < double * > ( mxMalloc ( Size * periods * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivotva , __LINE__ , __FILE__ , __func__ , Size * periods * sizeof ( double ) ) ;
2019-04-23 12:58:38 +02:00
b = static_cast < int * > ( mxMalloc ( Size * periods * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( b , __LINE__ , __FILE__ , __func__ , Size * periods * sizeof ( int ) ) ;
2019-04-23 12:58:38 +02:00
line_done = static_cast < bool * > ( mxMalloc ( Size * periods * sizeof ( bool ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( line_done , __LINE__ , __FILE__ , __func__ , Size * periods * sizeof ( bool ) ) ;
2013-03-22 15:44:34 +01:00
mem_mngr . init_CHUNK_BLCK_SIZE ( u_count ) ;
2021-02-01 13:49:27 +01:00
g_save_op = nullptr ;
2013-03-22 15:44:34 +01:00
g_nop_all = 0 ;
2021-02-03 18:10:01 +01:00
int i = ( periods + y_kmax + 1 ) * Size * sizeof ( NonZeroElem * ) ;
2019-04-23 12:58:38 +02:00
FNZE_R = static_cast < NonZeroElem * * > ( mxMalloc ( i ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( FNZE_R , __LINE__ , __FILE__ , __func__ , i ) ;
2019-04-23 12:58:38 +02:00
FNZE_C = static_cast < NonZeroElem * * > ( mxMalloc ( i ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( FNZE_C , __LINE__ , __FILE__ , __func__ , i ) ;
2021-02-01 12:39:34 +01:00
auto * * temp_NZE_R = static_cast < NonZeroElem * * > ( mxMalloc ( i ) ) ;
2017-06-05 18:51:43 +02:00
test_mxMalloc ( temp_NZE_R , __LINE__ , __FILE__ , __func__ , i ) ;
2021-02-01 12:39:34 +01:00
auto * * temp_NZE_C = static_cast < NonZeroElem * * > ( mxMalloc ( i ) ) ;
2017-06-05 18:51:43 +02:00
test_mxMalloc ( temp_NZE_C , __LINE__ , __FILE__ , __func__ , i ) ;
2013-03-22 15:44:34 +01:00
i = ( periods + y_kmax + 1 ) * Size * sizeof ( int ) ;
2019-04-23 12:58:38 +02:00
NbNZRow = static_cast < int * > ( mxMalloc ( i ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( NbNZRow , __LINE__ , __FILE__ , __func__ , i ) ;
2019-04-23 12:58:38 +02:00
NbNZCol = static_cast < int * > ( mxMalloc ( i ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( NbNZCol , __LINE__ , __FILE__ , __func__ , i ) ;
2013-03-22 15:44:34 +01:00
for ( int i = 0 ; i < periods * Size ; i + + )
{
b [ i ] = 0 ;
2021-02-01 12:40:35 +01:00
line_done [ i ] = false ;
2013-03-22 15:44:34 +01:00
}
for ( int i = 0 ; i < ( periods + y_kmax + 1 ) * Size ; i + + )
{
2021-02-01 13:49:27 +01:00
FNZE_C [ i ] = nullptr ;
FNZE_R [ i ] = nullptr ;
temp_NZE_C [ i ] = nullptr ;
temp_NZE_R [ i ] = nullptr ;
2013-03-22 15:44:34 +01:00
NbNZRow [ i ] = 0 ;
NbNZCol [ i ] = 0 ;
}
int nnz = 0 ;
2019-06-25 15:42:32 +02:00
//pragma omp parallel for ordered private(it4, ti_y_kmin, ti_y_kmax, eq, var, lag) schedule(dynamic)
2021-02-03 18:10:01 +01:00
for ( int t = 0 ; t < periods ; t + + )
2013-03-22 15:44:34 +01:00
{
2021-02-03 18:10:01 +01:00
int ti_y_kmin = - min ( t , y_kmin ) ;
int ti_y_kmax = min ( periods - ( t + 1 ) , y_kmax ) ;
int eq = - 1 ;
2013-03-22 15:44:34 +01:00
//pragma omp ordered
2021-02-03 18:10:01 +01:00
for ( auto & [ key , value ] : IM )
2013-03-22 15:44:34 +01:00
{
2021-02-03 18:10:01 +01:00
int var = get < 1 > ( key ) ;
if ( eq ! = get < 0 > ( key ) + Size * t )
2013-03-22 15:44:34 +01:00
tmp_b = 0 ;
2021-02-03 18:10:01 +01:00
eq = get < 0 > ( key ) + Size * t ;
int lag = get < 2 > ( key ) ;
2013-03-22 15:44:34 +01:00
if ( var < ( periods + y_kmax ) * Size )
{
2021-02-03 18:10:01 +01:00
lag = get < 2 > ( key ) ;
2019-12-20 14:50:19 +01:00
if ( lag < = ti_y_kmax & & lag > = ti_y_kmin ) /*Build the index for sparse matrix containing the jacobian : u*/
2013-03-22 15:44:34 +01:00
{
nnz + + ;
var + = Size * t ;
NbNZRow [ eq ] + + ;
NbNZCol [ var ] + + ;
2021-02-03 18:10:01 +01:00
NonZeroElem * first = mem_mngr . mxMalloc_NZE ( ) ;
2021-02-01 13:49:27 +01:00
first - > NZE_C_N = nullptr ;
first - > NZE_R_N = nullptr ;
2021-02-03 18:10:01 +01:00
first - > u_index = value + u_count_init * t ;
2013-03-22 15:44:34 +01:00
first - > r_index = eq ;
first - > c_index = var ;
first - > lag_index = lag ;
2021-02-01 13:49:27 +01:00
if ( FNZE_R [ eq ] = = nullptr )
2013-03-22 15:44:34 +01:00
FNZE_R [ eq ] = first ;
2021-02-01 13:49:27 +01:00
if ( FNZE_C [ var ] = = nullptr )
2013-03-22 15:44:34 +01:00
FNZE_C [ var ] = first ;
2021-02-01 13:49:27 +01:00
if ( temp_NZE_R [ eq ] ! = nullptr )
2013-03-22 15:44:34 +01:00
temp_NZE_R [ eq ] - > NZE_R_N = first ;
2021-02-01 13:49:27 +01:00
if ( temp_NZE_C [ var ] ! = nullptr )
2013-03-22 15:44:34 +01:00
temp_NZE_C [ var ] - > NZE_C_N = first ;
temp_NZE_R [ eq ] = first ;
temp_NZE_C [ var ] = first ;
}
2019-12-20 14:50:19 +01:00
else /*Build the additive terms ooutside the simulation periods related to the first lags and the last leads...*/
2013-03-22 15:44:34 +01:00
{
if ( lag < ti_y_kmin )
2021-02-03 18:10:01 +01:00
tmp_b + = u [ value + u_count_init * t ] * y [ index_vara [ var + Size * ( y_kmin + t ) ] ] ;
2013-03-22 15:44:34 +01:00
else
2021-02-03 18:10:01 +01:00
tmp_b + = u [ value + u_count_init * t ] * y [ index_vara [ var + Size * ( y_kmin + t ) ] ] ;
2013-03-22 15:44:34 +01:00
}
}
2019-12-20 14:50:19 +01:00
else /* ...and store it in the u vector*/
2013-03-22 15:44:34 +01:00
{
2021-02-03 18:10:01 +01:00
b [ eq ] = value + u_count_init * t ;
2013-03-22 15:44:34 +01:00
u [ b [ eq ] ] + = tmp_b ;
tmp_b = 0 ;
}
}
}
mxFree ( temp_NZE_R ) ;
mxFree ( temp_NZE_C ) ;
}
int
dynSparseMatrix : : Get_u ( )
{
if ( ! u_liste . empty ( ) )
{
int i = u_liste . back ( ) ;
u_liste . pop_back ( ) ;
return i ;
}
else
{
if ( u_count < u_count_alloc )
{
int i = u_count ;
u_count + + ;
return i ;
}
else
{
u_count_alloc + = 5 * u_count_alloc_save ;
2019-04-23 12:58:38 +02:00
u = static_cast < double * > ( mxRealloc ( u , u_count_alloc * sizeof ( double ) ) ) ;
2013-03-22 15:44:34 +01:00
if ( ! u )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Get_u, memory exhausted (realloc( "
+ to_string ( u_count_alloc * sizeof ( double ) ) + " )) " } ;
2013-03-22 15:44:34 +01:00
int i = u_count ;
u_count + + ;
return i ;
}
}
}
void
dynSparseMatrix : : Delete_u ( int pos )
{
u_liste . push_back ( pos ) ;
}
void
dynSparseMatrix : : Clear_u ( )
{
u_liste . clear ( ) ;
}
void
2022-07-05 12:12:08 +02:00
dynSparseMatrix : : End_GE ( )
2013-03-22 15:44:34 +01:00
{
mem_mngr . Free_All ( ) ;
mxFree ( FNZE_R ) ;
mxFree ( FNZE_C ) ;
mxFree ( NbNZRow ) ;
mxFree ( NbNZCol ) ;
mxFree ( b ) ;
mxFree ( line_done ) ;
mxFree ( pivot ) ;
mxFree ( pivot_save ) ;
mxFree ( pivotk ) ;
mxFree ( pivotv ) ;
mxFree ( pivotva ) ;
}
bool
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : compare ( int * save_op , int * save_opa , int * save_opaa , int beg_t , int periods , long nop4 , int Size )
2013-03-22 15:44:34 +01:00
{
2021-02-03 18:10:01 +01:00
long nop = nop4 / 2 ;
2013-03-22 15:44:34 +01:00
double r = 0.0 ;
bool OK = true ;
2021-02-03 18:10:01 +01:00
int * diff1 = static_cast < int * > ( mxMalloc ( nop * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( diff1 , __LINE__ , __FILE__ , __func__ , nop * sizeof ( int ) ) ;
2021-02-03 18:10:01 +01:00
int * diff2 = static_cast < int * > ( mxMalloc ( nop * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( diff2 , __LINE__ , __FILE__ , __func__ , nop * sizeof ( int ) ) ;
2013-03-22 15:44:34 +01:00
int max_save_ops_first = - 1 ;
2021-02-03 18:10:01 +01:00
long j = 0 , i = 0 ;
2013-03-22 15:44:34 +01:00
while ( i < nop4 & & OK )
{
2021-02-09 15:55:36 +01:00
t_save_op_s * save_op_s = reinterpret_cast < t_save_op_s * > ( & save_op [ i ] ) ;
t_save_op_s * save_opa_s = reinterpret_cast < t_save_op_s * > ( & save_opa [ i ] ) ;
t_save_op_s * save_opaa_s = reinterpret_cast < t_save_op_s * > ( & save_opaa [ i ] ) ;
2013-03-22 15:44:34 +01:00
diff1 [ j ] = save_op_s - > first - save_opa_s - > first ;
2021-02-03 18:10:01 +01:00
max_save_ops_first = max ( max_save_ops_first , save_op_s - > first + diff1 [ j ] * ( periods - beg_t ) ) ;
2013-03-22 15:44:34 +01:00
switch ( save_op_s - > operat )
{
case IFLD :
case IFDIV :
OK = ( save_op_s - > operat = = save_opa_s - > operat & & save_opa_s - > operat = = save_opaa_s - > operat
& & diff1 [ j ] = = ( save_opa_s - > first - save_opaa_s - > first ) ) ;
i + = 2 ;
break ;
case IFLESS :
case IFSUB :
diff2 [ j ] = save_op_s - > second - save_opa_s - > second ;
OK = ( save_op_s - > operat = = save_opa_s - > operat & & save_opa_s - > operat = = save_opaa_s - > operat
& & diff1 [ j ] = = ( save_opa_s - > first - save_opaa_s - > first )
& & diff2 [ j ] = = ( save_opa_s - > second - save_opaa_s - > second ) ) ;
i + = 3 ;
break ;
default :
2022-07-29 12:42:50 +02:00
throw FatalException { " In compare, unknown operator = "
+ to_string ( save_op_s - > operat ) } ;
2013-03-22 15:44:34 +01:00
}
j + + ;
}
// the same pivot for all remaining periods
if ( OK )
{
for ( int i = beg_t ; i < periods ; i + + )
2021-02-03 18:10:01 +01:00
for ( int j = 0 ; j < Size ; j + + )
pivot [ i * Size + j ] = pivot [ ( i - 1 ) * Size + j ] + Size ;
2013-03-22 15:44:34 +01:00
if ( max_save_ops_first > = u_count_alloc )
{
u_count_alloc + = max_save_ops_first ;
2019-04-23 12:58:38 +02:00
u = static_cast < double * > ( mxRealloc ( u , u_count_alloc * sizeof ( double ) ) ) ;
2013-03-22 15:44:34 +01:00
if ( ! u )
2022-07-29 12:42:50 +02:00
throw FatalException { " In compare, memory exhausted (realloc( "
+ to_string ( u_count_alloc * sizeof ( double ) ) + " )) " } ;
2013-03-22 15:44:34 +01:00
}
for ( int t = 1 ; t < periods - beg_t - y_kmax ; t + + )
{
int i = j = 0 ;
while ( i < nop4 )
{
2021-02-09 15:55:36 +01:00
auto * save_op_s = reinterpret_cast < t_save_op_s * > ( & save_op [ i ] ) ;
2021-02-03 18:10:01 +01:00
double * up = & u [ save_op_s - > first + t * diff1 [ j ] ] ;
2013-03-22 15:44:34 +01:00
switch ( save_op_s - > operat )
{
case IFLD :
r = * up ;
i + = 2 ;
break ;
case IFDIV :
* up / = r ;
i + = 2 ;
break ;
case IFSUB :
* up - = u [ save_op_s - > second + t * diff2 [ j ] ] * r ; ;
i + = 3 ;
break ;
case IFLESS :
* up = - u [ save_op_s - > second + t * diff2 [ j ] ] * r ;
i + = 3 ;
break ;
}
j + + ;
}
}
int t1 = max ( 1 , periods - beg_t - y_kmax ) ;
int periods_beg_t = periods - beg_t ;
for ( int t = t1 ; t < periods_beg_t ; t + + )
{
int i = j = 0 ;
int gap = periods_beg_t - t ;
while ( i < nop4 )
{
2021-02-09 15:55:36 +01:00
if ( auto * save_op_s = reinterpret_cast < t_save_op_s * > ( & save_op [ i ] ) ;
2021-02-03 18:10:01 +01:00
save_op_s - > lag < gap )
2013-03-22 15:44:34 +01:00
{
double * up = & u [ save_op_s - > first + t * diff1 [ j ] ] ;
switch ( save_op_s - > operat )
{
case IFLD :
r = * up ;
i + = 2 ;
break ;
case IFDIV :
* up / = r ;
i + = 2 ;
break ;
case IFSUB :
* up - = u [ save_op_s - > second + t * diff2 [ j ] ] * r ;
i + = 3 ;
break ;
case IFLESS :
* up = - u [ save_op_s - > second + t * diff2 [ j ] ] * r ;
i + = 3 ;
break ;
}
}
else
2021-02-03 18:10:01 +01:00
switch ( save_op_s - > operat )
{
case IFLD :
case IFDIV :
i + = 2 ;
break ;
case IFSUB :
case IFLESS :
i + = 3 ;
break ;
}
2013-03-22 15:44:34 +01:00
j + + ;
}
}
}
mxFree ( diff1 ) ;
mxFree ( diff2 ) ;
return OK ;
}
int
dynSparseMatrix : : complete ( int beg_t , int Size , int periods , int * b )
{
2021-02-03 18:10:01 +01:00
double yy = 0.0 ;
2013-03-22 15:44:34 +01:00
int size_of_save_code = ( 1 + y_kmax ) * Size * ( Size + 1 + 4 ) / 2 * 4 ;
2021-02-03 18:10:01 +01:00
int * save_code = static_cast < int * > ( mxMalloc ( size_of_save_code * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( save_code , __LINE__ , __FILE__ , __func__ , size_of_save_code * sizeof ( int ) ) ;
2013-03-22 15:44:34 +01:00
int size_of_diff = ( 1 + y_kmax ) * Size * ( Size + 1 + 4 ) ;
2021-02-03 18:10:01 +01:00
int * diff = static_cast < int * > ( mxMalloc ( size_of_diff * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( diff , __LINE__ , __FILE__ , __func__ , size_of_diff * sizeof ( int ) ) ;
2021-02-03 18:10:01 +01:00
long cal_y = y_size * y_kmin ;
2013-03-22 15:44:34 +01:00
2021-02-03 18:10:01 +01:00
long i = ( beg_t + 1 ) * Size - 1 ;
long nop = 0 ;
for ( long j = i ; j > i - Size ; j - - )
2013-03-22 15:44:34 +01:00
{
2021-02-03 18:10:01 +01:00
long pos = pivot [ j ] ;
NonZeroElem * first ;
long nb_var = At_Row ( pos , & first ) ;
2013-03-22 15:44:34 +01:00
first = first - > NZE_R_N ;
nb_var - - ;
save_code [ nop ] = IFLDZ ;
save_code [ nop + 1 ] = 0 ;
save_code [ nop + 2 ] = 0 ;
save_code [ nop + 3 ] = 0 ;
# ifdef DEBUG
if ( ( nop + 3 ) > = size_of_save_code )
mexPrintf ( " out of save_code[%d] (bound=%d) \n " , nop + 2 , size_of_save_code ) ;
# endif
nop + = 4 ;
2021-02-03 18:10:01 +01:00
for ( long k = 0 ; k < nb_var ; k + + )
2013-03-22 15:44:34 +01:00
{
save_code [ nop ] = IFMUL ;
save_code [ nop + 1 ] = index_vara [ first - > c_index ] + cal_y ;
save_code [ nop + 2 ] = first - > u_index ;
save_code [ nop + 3 ] = first - > lag_index ;
# ifdef DEBUG
if ( ( nop + 3 ) > = size_of_save_code )
mexPrintf ( " out of save_code[%d] (bound=%d) \n " , nop + 2 , size_of_save_code ) ;
# endif
nop + = 4 ;
first = first - > NZE_R_N ;
}
save_code [ nop ] = IFADD ;
save_code [ nop + 1 ] = b [ pos ] ;
save_code [ nop + 2 ] = 0 ;
save_code [ nop + 3 ] = 0 ;
# ifdef DEBUG
if ( ( nop + 3 ) > = size_of_save_code )
mexPrintf ( " out of save_code[%d] (bound=%d) \n " , nop + 2 , size_of_save_code ) ;
# endif
nop + = 4 ;
save_code [ nop ] = IFSTP ;
save_code [ nop + 1 ] = index_vara [ j ] + y_size * y_kmin ;
save_code [ nop + 2 ] = 0 ;
save_code [ nop + 3 ] = 0 ;
# ifdef DEBUG
if ( ( nop + 2 ) > = size_of_save_code )
mexPrintf ( " out of save_code[%d] (bound=%d) \n " , nop + 2 , size_of_save_code ) ;
# endif
nop + = 4 ;
}
i = beg_t * Size - 1 ;
2021-02-03 18:10:01 +01:00
long nop1 = 0 , nopa = 0 ;
for ( long j = i ; j > i - Size ; j - - )
2013-03-22 15:44:34 +01:00
{
2021-02-03 18:10:01 +01:00
long pos = pivot [ j ] ;
NonZeroElem * first ;
long nb_var = At_Row ( pos , & first ) ;
2013-03-22 15:44:34 +01:00
first = first - > NZE_R_N ;
nb_var - - ;
diff [ nopa ] = 0 ;
diff [ nopa + 1 ] = 0 ;
nopa + = 2 ;
nop1 + = 4 ;
2021-02-03 18:10:01 +01:00
for ( long k = 0 ; k < nb_var ; k + + )
2013-03-22 15:44:34 +01:00
{
diff [ nopa ] = save_code [ nop1 + 1 ] - ( index_vara [ first - > c_index ] + cal_y ) ;
diff [ nopa + 1 ] = save_code [ nop1 + 2 ] - ( first - > u_index ) ;
# ifdef DEBUG
if ( ( nop1 + 2 ) > = size_of_save_code )
mexPrintf ( " out of save_code[%d] (bound=%d) \n " , nop1 + 2 , size_of_save_code ) ;
if ( ( nopa + 1 ) > = size_of_diff )
mexPrintf ( " out of diff[%d] (bound=%d) \n " , nopa + 2 , size_of_diff ) ;
# endif
nopa + = 2 ;
nop1 + = 4 ;
first = first - > NZE_R_N ;
}
diff [ nopa ] = save_code [ nop1 + 1 ] - ( b [ pos ] ) ;
diff [ nopa + 1 ] = 0 ;
# ifdef DEBUG
if ( ( nop1 + 3 ) > = size_of_save_code )
mexPrintf ( " out of save_code[%d] (bound=%d) \n " , nop1 + 2 , size_of_save_code ) ;
if ( ( nopa + 1 ) > = size_of_diff )
mexPrintf ( " out of diff[%d] (bound=%d) \n " , nopa + 2 , size_of_diff ) ;
# endif
nopa + = 2 ;
nop1 + = 4 ;
diff [ nopa ] = save_code [ nop1 + 1 ] - ( index_vara [ j ] + y_size * y_kmin ) ;
diff [ nopa + 1 ] = 0 ;
# ifdef DEBUG
if ( ( nop1 + 4 ) > = size_of_save_code )
mexPrintf ( " out of save_code[%d] (bound=%d) \n " , nop1 + 2 , size_of_save_code ) ;
if ( ( nopa + 1 ) > = size_of_diff )
mexPrintf ( " out of diff[%d] (bound=%d) \n " , nopa + 2 , size_of_diff ) ;
# endif
nopa + = 2 ;
nop1 + = 4 ;
}
2021-02-03 18:10:01 +01:00
long max_var = ( periods + y_kmin ) * y_size ;
long min_var = y_kmin * y_size ;
2013-03-22 15:44:34 +01:00
for ( int t = periods + y_kmin - 1 ; t > = beg_t + y_kmin ; t - - )
{
int j = 0 , k ;
int ti = t - y_kmin - beg_t ;
for ( int i = 0 ; i < nop ; i + = 4 )
{
switch ( save_code [ i ] )
{
case IFLDZ :
yy = 0 ;
break ;
case IFMUL :
k = save_code [ i + 1 ] + ti * diff [ j ] ;
if ( k < max_var & & k > min_var )
2021-02-03 18:10:01 +01:00
yy + = y [ k ] * u [ save_code [ i + 2 ] + ti * diff [ j + 1 ] ] ;
2013-03-22 15:44:34 +01:00
break ;
case IFADD :
yy = - ( yy + u [ save_code [ i + 1 ] + ti * diff [ j ] ] ) ;
break ;
case IFSTP :
k = save_code [ i + 1 ] + ti * diff [ j ] ;
2021-02-03 18:10:01 +01:00
double err = yy - y [ k ] ;
2013-03-22 15:44:34 +01:00
y [ k ] + = slowc * ( err ) ;
break ;
}
j + = 2 ;
}
}
mxFree ( save_code ) ;
mxFree ( diff ) ;
return ( beg_t ) ;
}
void
dynSparseMatrix : : bksub ( int tbreak , int last_period , int Size , double slowc_l )
{
for ( int i = 0 ; i < y_size * ( periods + y_kmin ) ; i + + )
y [ i ] = ya [ i ] ;
if ( symbolic & & tbreak )
last_period = complete ( tbreak , Size , periods , b ) ;
else
last_period = periods ;
for ( int t = last_period + y_kmin - 1 ; t > = y_kmin ; t - - )
{
int ti = ( t - y_kmin ) * Size ;
int cal = y_kmin * Size ;
int cal_y = y_size * y_kmin ;
2021-02-03 18:10:01 +01:00
for ( int i = ti - 1 ; i > = ti - Size ; i - - )
2013-03-22 15:44:34 +01:00
{
2021-02-03 18:10:01 +01:00
int j = i + cal ;
2013-03-22 15:44:34 +01:00
int pos = pivot [ i + Size ] ;
2021-02-03 18:10:01 +01:00
NonZeroElem * first ;
2013-03-22 15:44:34 +01:00
int nb_var = At_Row ( pos , & first ) ;
first = first - > NZE_R_N ;
nb_var - - ;
int eq = index_vara [ j ] + y_size ;
2021-02-03 18:10:01 +01:00
double yy = 0 ;
for ( int k = 0 ; k < nb_var ; k + + )
2013-03-22 15:44:34 +01:00
{
yy + = y [ index_vara [ first - > c_index ] + cal_y ] * u [ first - > u_index ] ;
first = first - > NZE_R_N ;
}
yy = - ( yy + y [ eq ] + u [ b [ pos ] ] ) ;
direction [ eq ] = yy ;
y [ eq ] + = slowc_l * yy ;
}
}
}
void
dynSparseMatrix : : simple_bksub ( int it_ , int Size , double slowc_l )
{
for ( int i = 0 ; i < y_size ; i + + )
y [ i + it_ * y_size ] = ya [ i + it_ * y_size ] ;
2021-02-03 18:10:01 +01:00
for ( int i = Size - 1 ; i > = 0 ; i - - )
2013-03-22 15:44:34 +01:00
{
int pos = pivot [ i ] ;
2021-02-03 18:10:01 +01:00
NonZeroElem * first ;
2013-03-22 15:44:34 +01:00
int nb_var = At_Row ( pos , & first ) ;
first = first - > NZE_R_N ;
nb_var - - ;
int eq = index_vara [ i ] ;
2021-02-03 18:10:01 +01:00
double yy = 0 ;
for ( int k = 0 ; k < nb_var ; k + + )
2013-03-22 15:44:34 +01:00
{
yy + = y [ index_vara [ first - > c_index ] + it_ * y_size ] * u [ first - > u_index ] ;
first = first - > NZE_R_N ;
}
yy = - ( yy + y [ eq + it_ * y_size ] + u [ b [ pos ] ] ) ;
direction [ eq + it_ * y_size ] = yy ;
y [ eq + it_ * y_size ] + = slowc_l * yy ;
}
}
mxArray *
2022-02-28 12:25:11 +01:00
dynSparseMatrix : : subtract_A_B ( const mxArray * A_m , const mxArray * B_m )
2013-03-22 15:44:34 +01:00
{
size_t n_A = mxGetN ( A_m ) ;
size_t m_A = mxGetM ( A_m ) ;
double * A_d = mxGetPr ( A_m ) ;
size_t n_B = mxGetN ( B_m ) ;
double * B_d = mxGetPr ( B_m ) ;
mxArray * C_m = mxCreateDoubleMatrix ( m_A , n_B , mxREAL ) ;
double * C_d = mxGetPr ( C_m ) ;
2019-04-23 12:58:38 +02:00
for ( int j = 0 ; j < static_cast < int > ( n_A ) ; j + + )
2013-03-22 15:44:34 +01:00
for ( unsigned int i = 0 ; i < m_A ; i + + )
{
size_t index = j * m_A + i ;
C_d [ index ] = A_d [ index ] - B_d [ index ] ;
}
return C_m ;
}
mxArray *
2022-02-28 12:25:11 +01:00
dynSparseMatrix : : Sparse_subtract_SA_SB ( const mxArray * A_m , const mxArray * B_m )
2013-03-22 15:44:34 +01:00
{
size_t n_A = mxGetN ( A_m ) ;
size_t m_A = mxGetM ( A_m ) ;
mwIndex * A_i = mxGetIr ( A_m ) ;
mwIndex * A_j = mxGetJc ( A_m ) ;
size_t total_nze_A = A_j [ n_A ] ;
double * A_d = mxGetPr ( A_m ) ;
size_t n_B = mxGetN ( B_m ) ;
mwIndex * B_i = mxGetIr ( B_m ) ;
mwIndex * B_j = mxGetJc ( B_m ) ;
size_t total_nze_B = B_j [ n_B ] ;
double * B_d = mxGetPr ( B_m ) ;
mxArray * C_m = mxCreateSparse ( m_A , n_B , m_A * n_B , mxREAL ) ;
mwIndex * C_i = mxGetIr ( C_m ) ;
mwIndex * C_j = mxGetJc ( C_m ) ;
double * C_d = mxGetPr ( C_m ) ;
unsigned int nze_B = 0 , nze_C = 0 , nze_A = 0 ;
unsigned int A_col = 0 , B_col = 0 , C_col = 0 ;
C_j [ C_col ] = 0 ;
while ( nze_A < total_nze_A | | nze_B < total_nze_B )
{
2019-04-23 12:58:38 +02:00
while ( nze_A > = static_cast < unsigned int > ( A_j [ A_col + 1 ] ) & & ( nze_A < total_nze_A ) )
2013-03-22 15:44:34 +01:00
A_col + + ;
size_t A_row = A_i [ nze_A ] ;
2019-04-23 12:58:38 +02:00
while ( nze_B > = static_cast < unsigned int > ( B_j [ B_col + 1 ] ) & & ( nze_B < total_nze_B ) )
2013-03-22 15:44:34 +01:00
B_col + + ;
size_t B_row = B_i [ nze_B ] ;
if ( A_col = = B_col )
{
if ( A_row = = B_row & & ( nze_B < total_nze_B & & nze_A < total_nze_A ) )
{
C_d [ nze_C ] = A_d [ nze_A + + ] - B_d [ nze_B + + ] ;
C_i [ nze_C ] = A_row ;
while ( C_col < A_col )
C_j [ + + C_col ] = nze_C ;
C_j [ A_col + 1 ] = nze_C + + ;
C_col = A_col ;
}
2019-11-27 16:54:01 +01:00
else if ( ( A_row < B_row & & nze_A < total_nze_A ) | | nze_B = = total_nze_B )
2013-03-22 15:44:34 +01:00
{
C_d [ nze_C ] = A_d [ nze_A + + ] ;
C_i [ nze_C ] = A_row ;
while ( C_col < A_col )
C_j [ + + C_col ] = nze_C ;
C_j [ A_col + 1 ] = nze_C + + ;
C_col = A_col ;
}
else
{
C_d [ nze_C ] = - B_d [ nze_B + + ] ;
C_i [ nze_C ] = B_row ;
while ( C_col < B_col )
C_j [ + + C_col ] = nze_C ;
C_j [ B_col + 1 ] = nze_C + + ;
C_col = B_col ;
}
}
2019-11-27 16:54:01 +01:00
else if ( ( A_col < B_col & & nze_A < total_nze_A ) | | nze_B = = total_nze_B )
2013-03-22 15:44:34 +01:00
{
C_d [ nze_C ] = A_d [ nze_A + + ] ;
C_i [ nze_C ] = A_row ;
while ( C_col < A_col )
C_j [ + + C_col ] = nze_C ;
C_j [ A_col + 1 ] = nze_C + + ;
C_col = A_col ;
}
else
{
C_d [ nze_C ] = - B_d [ nze_B + + ] ;
C_i [ nze_C ] = B_row ;
while ( C_col < B_col )
C_j [ + + C_col ] = nze_C ;
C_j [ B_col + 1 ] = nze_C + + ;
C_col = B_col ;
}
}
while ( C_col < n_B )
C_j [ + + C_col ] = nze_C ;
mxSetNzmax ( C_m , nze_C ) ;
return C_m ;
}
mxArray *
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : mult_SAT_B ( const mxArray * A_m , const mxArray * B_m )
2013-03-22 15:44:34 +01:00
{
size_t n_A = mxGetN ( A_m ) ;
mwIndex * A_i = mxGetIr ( A_m ) ;
mwIndex * A_j = mxGetJc ( A_m ) ;
double * A_d = mxGetPr ( A_m ) ;
size_t n_B = mxGetN ( B_m ) ;
double * B_d = mxGetPr ( B_m ) ;
2022-02-28 12:18:58 +01:00
mxArray * C_m = mxCreateDoubleMatrix ( n_A , n_B , mxREAL ) ;
2013-03-22 15:44:34 +01:00
double * C_d = mxGetPr ( C_m ) ;
2019-04-23 12:58:38 +02:00
for ( int j = 0 ; j < static_cast < int > ( n_B ) ; j + + )
2021-02-03 18:10:01 +01:00
for ( unsigned int i = 0 ; i < n_A ; i + + )
{
double sum = 0 ;
size_t nze_A = A_j [ i ] ;
while ( nze_A < static_cast < unsigned int > ( A_j [ i + 1 ] ) )
{
size_t i_A = A_i [ nze_A ] ;
sum + = A_d [ nze_A + + ] * B_d [ i_A ] ;
}
C_d [ j * n_A + i ] = sum ;
}
2013-03-22 15:44:34 +01:00
return C_m ;
}
mxArray *
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Sparse_mult_SAT_B ( const mxArray * A_m , const mxArray * B_m )
2013-03-22 15:44:34 +01:00
{
size_t n_A = mxGetN ( A_m ) ;
mwIndex * A_i = mxGetIr ( A_m ) ;
mwIndex * A_j = mxGetJc ( A_m ) ;
double * A_d = mxGetPr ( A_m ) ;
size_t n_B = mxGetN ( B_m ) ;
size_t m_B = mxGetM ( B_m ) ;
double * B_d = mxGetPr ( B_m ) ;
2022-02-28 12:18:58 +01:00
mxArray * C_m = mxCreateSparse ( n_A , n_B , n_A * n_B , mxREAL ) ;
2013-03-22 15:44:34 +01:00
mwIndex * C_i = mxGetIr ( C_m ) ;
mwIndex * C_j = mxGetJc ( C_m ) ;
double * C_d = mxGetPr ( C_m ) ;
unsigned int nze_C = 0 ;
//unsigned int nze_A = 0;
unsigned int C_col = 0 ;
C_j [ C_col ] = 0 ;
2019-06-25 15:42:32 +02:00
//#pragma omp parallel for
2013-03-22 15:44:34 +01:00
for ( unsigned int j = 0 ; j < n_B ; j + + )
2021-02-03 18:10:01 +01:00
for ( unsigned int i = 0 ; i < n_A ; i + + )
{
double sum = 0 ;
size_t nze_A = A_j [ i ] ;
while ( nze_A < static_cast < unsigned int > ( A_j [ i + 1 ] ) )
{
size_t i_A = A_i [ nze_A ] ;
sum + = A_d [ nze_A + + ] * B_d [ i_A ] ;
}
if ( fabs ( sum ) > 1e-10 )
{
C_d [ nze_C ] = sum ;
C_i [ nze_C ] = i ;
while ( C_col < j )
C_j [ + + C_col ] = nze_C ;
nze_C + + ;
}
}
2013-03-22 15:44:34 +01:00
while ( C_col < m_B )
C_j [ + + C_col ] = nze_C ;
mxSetNzmax ( C_m , nze_C ) ;
return C_m ;
}
mxArray *
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Sparse_mult_SAT_SB ( const mxArray * A_m , const mxArray * B_m )
2013-03-22 15:44:34 +01:00
{
size_t n_A = mxGetN ( A_m ) ;
mwIndex * A_i = mxGetIr ( A_m ) ;
mwIndex * A_j = mxGetJc ( A_m ) ;
double * A_d = mxGetPr ( A_m ) ;
size_t n_B = mxGetN ( B_m ) ;
mwIndex * B_i = mxGetIr ( B_m ) ;
mwIndex * B_j = mxGetJc ( B_m ) ;
double * B_d = mxGetPr ( B_m ) ;
2022-02-28 12:18:58 +01:00
mxArray * C_m = mxCreateSparse ( n_A , n_B , n_A * n_B , mxREAL ) ;
2013-03-22 15:44:34 +01:00
mwIndex * C_i = mxGetIr ( C_m ) ;
mwIndex * C_j = mxGetJc ( C_m ) ;
double * C_d = mxGetPr ( C_m ) ;
size_t nze_B = 0 , nze_C = 0 , nze_A = 0 ;
unsigned int C_col = 0 ;
C_j [ C_col ] = 0 ;
for ( unsigned int j = 0 ; j < n_B ; j + + )
2021-02-03 18:10:01 +01:00
for ( unsigned int i = 0 ; i < n_A ; i + + )
{
double sum = 0 ;
nze_B = B_j [ j ] ;
nze_A = A_j [ i ] ;
while ( nze_A < static_cast < unsigned int > ( A_j [ i + 1 ] ) & & nze_B < static_cast < unsigned int > ( B_j [ j + 1 ] ) )
{
size_t i_A = A_i [ nze_A ] ;
size_t i_B = B_i [ nze_B ] ;
if ( i_A = = i_B )
sum + = A_d [ nze_A + + ] * B_d [ nze_B + + ] ;
else if ( i_A < i_B )
nze_A + + ;
else
nze_B + + ;
}
if ( fabs ( sum ) > 1e-10 )
{
C_d [ nze_C ] = sum ;
C_i [ nze_C ] = i ;
while ( C_col < j )
C_j [ + + C_col ] = nze_C ;
nze_C + + ;
}
}
2013-03-22 15:44:34 +01:00
while ( C_col < n_B )
C_j [ + + C_col ] = nze_C ;
mxSetNzmax ( C_m , nze_C ) ;
return C_m ;
}
mxArray *
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Sparse_transpose ( const mxArray * A_m )
2013-03-22 15:44:34 +01:00
{
size_t n_A = mxGetN ( A_m ) ;
size_t m_A = mxGetM ( A_m ) ;
mwIndex * A_i = mxGetIr ( A_m ) ;
mwIndex * A_j = mxGetJc ( A_m ) ;
size_t total_nze_A = A_j [ n_A ] ;
double * A_d = mxGetPr ( A_m ) ;
mxArray * C_m = mxCreateSparse ( n_A , m_A , total_nze_A , mxREAL ) ;
mwIndex * C_i = mxGetIr ( C_m ) ;
mwIndex * C_j = mxGetJc ( C_m ) ;
double * C_d = mxGetPr ( C_m ) ;
unsigned int nze_C = 0 , nze_A = 0 ;
2021-02-09 16:01:01 +01:00
fill_n ( C_j , m_A + 1 , 0 ) ;
2013-03-22 15:44:34 +01:00
map < pair < mwIndex , unsigned int > , double > B2 ;
for ( unsigned int i = 0 ; i < n_A ; i + + )
2021-02-03 18:10:01 +01:00
while ( nze_A < static_cast < unsigned int > ( A_j [ i + 1 ] ) )
{
C_j [ A_i [ nze_A ] + 1 ] + + ;
B2 [ { A_i [ nze_A ] , i } ] = A_d [ nze_A ] ;
nze_A + + ;
}
2013-03-22 15:44:34 +01:00
for ( unsigned int i = 0 ; i < m_A ; i + + )
C_j [ i + 1 ] + = C_j [ i ] ;
2021-02-03 18:10:01 +01:00
for ( auto & [ key , val ] : B2 )
2013-03-22 15:44:34 +01:00
{
2021-02-03 18:10:01 +01:00
C_d [ nze_C ] = val ;
C_i [ nze_C + + ] = key . second ;
2013-03-22 15:44:34 +01:00
}
return C_m ;
}
2023-04-06 18:44:22 +02:00
void
dynSparseMatrix : : compute_block_time ( int Per_u_ , bool evaluate , bool no_derivatives )
{
2023-04-18 15:49:56 +02:00
# ifdef DEBUG
mexPrintf ( " compute_block_time \n " ) ;
# endif
double * jacob { nullptr } , * jacob_exo { nullptr } , * jacob_exo_det { nullptr } ;
if ( evaluate )
{
jacob = mxGetPr ( jacobian_block [ block_num ] ) ;
if ( ! steady_state )
{
jacob_exo = mxGetPr ( jacobian_exo_block [ block_num ] ) ;
jacob_exo_det = mxGetPr ( jacobian_det_exo_block [ block_num ] ) ;
}
}
2023-04-06 18:44:22 +02:00
try
{
2023-04-18 17:53:27 +02:00
evaluator . evaluateBlock ( it_ , y , ya , y_size , x , nb_row_x , params , steady_y , u , Per_u_ , T , periods + y_kmin + y_kmax , TEF , TEFD , TEFDD , r , g1 , jacob , jacob_exo , jacob_exo_det , evaluate , no_derivatives ) ;
2023-04-06 18:44:22 +02:00
}
catch ( FloatingPointException & e )
{
res1 = numeric_limits < double > : : quiet_NaN ( ) ;
2023-06-13 16:34:22 +02:00
if ( verbosity > = 2 )
2023-04-06 18:44:22 +02:00
mexPrintf ( " %s \n %s \n " , e . message . c_str ( ) , e . location . c_str ( ) ) ;
}
}
2023-02-24 21:12:07 +01:00
bool
dynSparseMatrix : : compute_complete ( bool no_derivatives , double & _res1 , double & _res2 , double & _max_res , int & _max_res_idx )
{
bool result ;
res1 = 0 ;
compute_block_time ( 0 , false , no_derivatives ) ;
if ( ! ( isnan ( res1 ) | | isinf ( res1 ) ) )
{
_res1 = 0 ;
_res2 = 0 ;
_max_res = 0 ;
for ( int i = 0 ; i < size ; i + + )
{
double rr ;
rr = r [ i ] ;
if ( max_res < fabs ( rr ) )
{
_max_res = fabs ( rr ) ;
_max_res_idx = i ;
}
_res2 + = rr * rr ;
_res1 + = fabs ( rr ) ;
}
result = true ;
}
else
result = false ;
return result ;
}
bool
dynSparseMatrix : : compute_complete ( double lambda , double * crit )
{
double res1_ = 0 , res2_ = 0 , max_res_ = 0 ;
int max_res_idx_ = 0 ;
if ( steady_state )
{
it_ = 0 ;
for ( int i = 0 ; i < size ; i + + )
{
int eq = index_vara [ i ] ;
y [ eq ] = ya [ eq ] + lambda * direction [ eq ] ;
}
Per_u_ = 0 ;
Per_y_ = 0 ;
if ( compute_complete ( true , res1 , res2 , max_res , max_res_idx ) )
res2_ = res2 ;
else
return false ;
}
else
{
for ( int it = y_kmin ; it < periods + y_kmin ; it + + )
for ( int i = 0 ; i < size ; i + + )
{
int eq = index_vara [ i ] ;
y [ eq + it * y_size ] = ya [ eq + it * y_size ] + lambda * direction [ eq + it * y_size ] ;
}
for ( it_ = y_kmin ; it_ < periods + y_kmin ; it_ + + )
{
Per_u_ = ( it_ - y_kmin ) * u_count_int ;
Per_y_ = it_ * y_size ;
if ( compute_complete ( true , res1 , res2 , max_res , max_res_idx ) )
{
res2_ + = res2 ;
res1_ + = res1 ;
if ( max_res > max_res_ )
{
max_res = max_res_ ;
max_res_idx = max_res_idx_ ;
}
}
else
return false ;
}
it_ = periods + y_kmin - 1 ; // Do not leave it_ in inconsistent state
}
2023-06-13 16:34:22 +02:00
if ( verbosity > = 2 )
mexPrintf ( " lambda=%e, res2=%e \n " , lambda , res2_ ) ;
2023-02-24 21:12:07 +01:00
* crit = res2_ / 2 ;
return true ;
}
2013-03-22 15:44:34 +01:00
bool
dynSparseMatrix : : mnbrak ( double * ax , double * bx , double * cx , double * fa , double * fb , double * fc )
{
2021-02-03 18:10:01 +01:00
constexpr double GOLD = 1.618034 ;
constexpr double GLIMIT = 100.0 ;
constexpr double TINY = 1.0e-20 ;
auto sign = [ ] ( double a , double b ) { return b > = 0.0 ? fabs ( a ) : - fabs ( a ) ; } ;
2013-03-22 15:44:34 +01:00
2023-06-13 16:34:22 +02:00
if ( verbosity > = 2 )
mexPrintf ( " bracketing *ax=%f, *bx=%f \n " , * ax , * bx ) ;
2013-03-22 15:44:34 +01:00
if ( ! compute_complete ( * ax , fa ) )
return false ;
if ( ! compute_complete ( * bx , fb ) )
return false ;
if ( * fb > * fa )
{
2021-02-03 18:10:01 +01:00
swap ( * ax , * bx ) ;
swap ( * fa , * fb ) ;
2013-03-22 15:44:34 +01:00
}
2017-05-16 16:30:27 +02:00
* cx = ( * bx ) + GOLD * ( * bx - * ax ) ;
2013-03-22 15:44:34 +01:00
if ( ! compute_complete ( * cx , fc ) )
return false ;
while ( * fb > * fc )
{
2021-02-03 18:10:01 +01:00
double r = ( * bx - * ax ) * ( * fb - * fc ) ;
double q = ( * bx - * cx ) * ( * fb - * fa ) ;
double u = ( * bx ) - ( ( * bx - * cx ) * q - ( * bx - * ax ) * r )
2017-05-16 16:30:27 +02:00
/ ( 2.0 * sign ( fmax ( fabs ( q - r ) , TINY ) , q - r ) ) ;
2021-02-03 18:10:01 +01:00
double ulim = ( * bx ) + GLIMIT * ( * cx - * bx ) ;
double fu ;
2013-03-22 15:44:34 +01:00
if ( ( * bx - u ) * ( u - * cx ) > 0.0 )
{
if ( ! compute_complete ( u , & fu ) )
return false ;
if ( fu < * fc )
{
2017-05-16 16:30:27 +02:00
* ax = ( * bx ) ;
* bx = u ;
* fa = ( * fb ) ;
* fb = fu ;
2013-03-22 15:44:34 +01:00
return true ;
}
else if ( fu > * fb )
{
2017-05-16 16:30:27 +02:00
* cx = u ;
* fc = fu ;
2013-03-22 15:44:34 +01:00
return true ;
}
2017-05-16 16:30:27 +02:00
u = ( * cx ) + GOLD * ( * cx - * bx ) ;
2013-03-22 15:44:34 +01:00
if ( ! compute_complete ( u , & fu ) )
return false ;
}
else if ( ( * cx - u ) * ( u - ulim ) > 0.0 )
{
if ( ! compute_complete ( u , & fu ) )
return false ;
if ( fu < * fc )
{
* bx = * cx ;
* cx = u ;
u = * cx + GOLD * ( * cx - * bx ) ;
* fb = * fc ;
* fc = fu ;
if ( ! compute_complete ( u , & fu ) )
return false ;
}
}
else if ( ( u - ulim ) * ( ulim - * cx ) > = 0.0 )
{
2017-05-16 16:30:27 +02:00
u = ulim ;
2013-03-22 15:44:34 +01:00
if ( ! compute_complete ( u , & fu ) )
return false ;
}
else
{
2017-05-16 16:30:27 +02:00
u = ( * cx ) + GOLD * ( * cx - * bx ) ;
2013-03-22 15:44:34 +01:00
if ( ! compute_complete ( u , & fu ) )
return false ;
}
* ax = * bx ;
* bx = * cx ;
* cx = u ;
* fa = * fb ;
* fb = * fc ;
* fc = fu ;
}
return true ;
}
bool
dynSparseMatrix : : golden ( double ax , double bx , double cx , double tol , double solve_tolf , double * xmin )
{
2017-05-16 16:30:27 +02:00
const double R = 0.61803399 ;
const double C = ( 1.0 - R ) ;
2023-06-13 16:34:22 +02:00
if ( verbosity > = 2 )
mexPrintf ( " golden \n " ) ;
2017-05-16 16:30:27 +02:00
int iter = 0 , max_iter = 100 ;
2021-02-03 18:10:01 +01:00
double f1 , f2 , x1 , x2 ;
double x0 = ax ;
double x3 = cx ;
2013-03-22 15:44:34 +01:00
if ( fabs ( cx - bx ) > fabs ( bx - ax ) )
{
2017-05-16 16:30:27 +02:00
x1 = bx ;
x2 = bx + C * ( cx - bx ) ;
2013-03-22 15:44:34 +01:00
}
else
{
2017-05-16 16:30:27 +02:00
x2 = bx ;
x1 = bx - C * ( bx - ax ) ;
2013-03-22 15:44:34 +01:00
}
if ( ! compute_complete ( x1 , & f1 ) )
return false ;
if ( ! compute_complete ( x2 , & f2 ) )
return false ;
2021-02-03 18:10:01 +01:00
while ( fabs ( x3 - x0 ) > tol * ( fabs ( x1 ) + fabs ( x2 ) ) & & f1 > solve_tolf & & f2 > solve_tolf
& & iter < max_iter & & abs ( x1 - x2 ) > 1e-4 )
2013-03-22 15:44:34 +01:00
{
if ( f2 < f1 )
{
x0 = x1 ;
x1 = x2 ;
x2 = R * x1 + C * x3 ;
f1 = f2 ;
if ( ! compute_complete ( x2 , & f2 ) )
return false ;
}
else
{
x3 = x2 ;
x2 = x1 ;
x1 = R * x2 + C * x0 ;
f2 = f1 ;
if ( ! compute_complete ( x1 , & f1 ) )
return false ;
}
iter + + ;
}
if ( f1 < f2 )
{
2017-05-16 16:30:27 +02:00
* xmin = x1 ;
2013-03-22 15:44:34 +01:00
return true ;
}
else
{
2017-05-16 16:30:27 +02:00
* xmin = x2 ;
2013-03-22 15:44:34 +01:00
return true ;
}
}
void
2022-07-05 12:12:08 +02:00
dynSparseMatrix : : Solve_Matlab_Relaxation ( mxArray * A_m , mxArray * b_m , unsigned int Size , double slowc_l )
2013-03-22 15:44:34 +01:00
{
double * b_m_d = mxGetPr ( b_m ) ;
if ( ! b_m_d )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve_Matlab_Relaxation, can't retrieve b_m vector " } ;
2013-03-22 15:44:34 +01:00
mwIndex * A_m_i = mxGetIr ( A_m ) ;
if ( ! A_m_i )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve_Matlab_Relaxation, can't retrieve Ir vector of matrix A " } ;
2013-03-22 15:44:34 +01:00
mwIndex * A_m_j = mxGetJc ( A_m ) ;
if ( ! A_m_j )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve_Matlab_Relaxation, can't retrieve Jc vectior of matrix A " } ;
2013-03-22 15:44:34 +01:00
double * A_m_d = mxGetPr ( A_m ) ;
if ( ! A_m_d )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve_Matlab_Relaxation, can't retrieve double float data of matrix A " } ;
2022-02-28 18:41:39 +01:00
/* Extract submatrices from the upper-left corner of A and subvectors at the
beginning of b , so that the system looks like :
⎛ B1 C1 … ⎞ ⎛ b1 ⎞
⎢ A2 B2 … ⎥ ⎢ b2 ⎥
⎢ A3 … ⎥ = ⎢ … ⎥
⎢ … … ⎥ ⎢ … ⎥
⎝ … ⎠ ⎝ … ⎠
*/
2021-02-03 18:10:01 +01:00
mxArray * B1 = mxCreateSparse ( Size , Size , Size * Size , mxREAL ) ;
2013-03-22 15:44:34 +01:00
mwIndex * B1_i = mxGetIr ( B1 ) ;
mwIndex * B1_j = mxGetJc ( B1 ) ;
double * B1_d = mxGetPr ( B1 ) ;
2021-02-03 18:10:01 +01:00
mxArray * C1 = mxCreateSparse ( Size , Size , Size * Size , mxREAL ) ;
2013-03-22 15:44:34 +01:00
mwIndex * C1_i = mxGetIr ( C1 ) ;
mwIndex * C1_j = mxGetJc ( C1 ) ;
double * C1_d = mxGetPr ( C1 ) ;
2021-02-03 18:10:01 +01:00
mxArray * A2 = mxCreateSparse ( Size , Size , Size * Size , mxREAL ) ;
2013-03-22 15:44:34 +01:00
mwIndex * A2_i = mxGetIr ( A2 ) ;
mwIndex * A2_j = mxGetJc ( A2 ) ;
double * A2_d = mxGetPr ( A2 ) ;
2021-02-03 18:10:01 +01:00
mxArray * B2 = mxCreateSparse ( Size , Size , Size * Size , mxREAL ) ;
2013-03-22 15:44:34 +01:00
mwIndex * B2_i = mxGetIr ( B2 ) ;
mwIndex * B2_j = mxGetJc ( B2 ) ;
double * B2_d = mxGetPr ( B2 ) ;
2021-02-03 18:10:01 +01:00
mxArray * A3 = mxCreateSparse ( Size , Size , Size * Size , mxREAL ) ;
2013-03-22 15:44:34 +01:00
mwIndex * A3_i = mxGetIr ( A3 ) ;
mwIndex * A3_j = mxGetJc ( A3 ) ;
double * A3_d = mxGetPr ( A3 ) ;
2022-02-28 18:41:39 +01:00
2021-02-03 18:10:01 +01:00
mxArray * b1 = mxCreateDoubleMatrix ( Size , 1 , mxREAL ) ;
2013-03-22 15:44:34 +01:00
double * b1_d = mxGetPr ( b1 ) ;
2021-02-03 18:10:01 +01:00
mxArray * b2 = mxCreateDoubleMatrix ( Size , 1 , mxREAL ) ;
2013-03-22 15:44:34 +01:00
double * b2_d = mxGetPr ( b2 ) ;
2022-02-28 18:41:39 +01:00
unsigned int nze = 0 ; // Counter in nonzero elements of A
unsigned int B1_nze = 0 , C1_nze = 0 , A2_nze = 0 , B2_nze = 0 , A3_nze = 0 ; // Same for submatrices
for ( size_t var = 0 ; var < 2 * Size ; var + + ) // Iterate over columns of A
2013-03-22 15:44:34 +01:00
{
2022-02-28 18:41:39 +01:00
if ( var < Size )
2013-03-22 15:44:34 +01:00
{
2022-02-28 18:41:39 +01:00
b1_d [ var ] = b_m_d [ var ] ;
B1_j [ var ] = B1_nze ;
A2_j [ var ] = A2_nze ;
2013-03-22 15:44:34 +01:00
}
2022-02-28 18:41:39 +01:00
else
2013-03-22 15:44:34 +01:00
{
2022-02-28 18:41:39 +01:00
b2_d [ var - Size ] = b_m_d [ var ] ;
C1_j [ var - Size ] = C1_nze ;
B2_j [ var - Size ] = B2_nze ;
A3_j [ var - Size ] = A3_nze ;
2013-03-22 15:44:34 +01:00
}
2022-02-28 18:41:39 +01:00
while ( static_cast < unsigned int > ( A_m_j [ var + 1 ] ) > nze )
2013-03-22 15:44:34 +01:00
{
2022-02-28 18:41:39 +01:00
size_t eq = A_m_i [ nze ] ;
if ( var < Size )
2013-03-22 15:44:34 +01:00
{
2022-02-28 18:41:39 +01:00
if ( eq < Size )
{
B1_i [ B1_nze ] = eq ;
B1_d [ B1_nze ] = A_m_d [ nze ] ;
B1_nze + + ;
}
else // Here we know that eq < 2*Size, because of the structure of A
{
A2_i [ A2_nze ] = eq - Size ;
A2_d [ A2_nze ] = A_m_d [ nze ] ;
A2_nze + + ;
}
2013-03-22 15:44:34 +01:00
}
2022-02-28 18:41:39 +01:00
else if ( var < 2 * Size )
2013-03-22 15:44:34 +01:00
{
2022-02-28 18:41:39 +01:00
if ( eq < Size )
{
C1_i [ C1_nze ] = eq ;
C1_d [ C1_nze ] = A_m_d [ nze ] ;
C1_nze + + ;
}
else if ( eq < 2 * Size )
{
B2_i [ B2_nze ] = eq - Size ;
B2_d [ B2_nze ] = A_m_d [ nze ] ;
B2_nze + + ;
}
else // Here we know that eq < 3*Size, because of the structure of A
{
A3_i [ A3_nze ] = eq - 2 * Size ;
A3_d [ A3_nze ] = A_m_d [ nze ] ;
A3_nze + + ;
}
2010-02-05 18:33:34 +01:00
}
2022-02-28 18:41:39 +01:00
nze + + ;
2010-02-05 18:33:34 +01:00
}
2009-01-20 23:04:37 +01:00
}
2022-02-28 18:41:39 +01:00
B1_j [ Size ] = B1_nze ;
C1_j [ Size ] = C1_nze ;
A2_j [ Size ] = A2_nze ;
B2_j [ Size ] = B2_nze ;
A3_j [ Size ] = A3_nze ;
2019-12-20 14:50:19 +01:00
vector < pair < mxArray * , mxArray * > > triangular_form ;
2022-02-28 18:41:39 +01:00
mxArray * d1 = nullptr ;
2013-03-22 15:44:34 +01:00
for ( int t = 1 ; t < = periods ; t + + )
2009-12-16 18:18:38 +01:00
{
2022-02-28 18:41:39 +01:00
mxArray * B1_inv ;
mexCallMATLAB ( 1 , & B1_inv , 1 , & B1 , " inv " ) ;
2013-03-22 15:44:34 +01:00
2022-02-28 18:41:39 +01:00
// Compute subvector d1 of the triangularized system.
mxArray * B1_inv_t = Sparse_transpose ( B1_inv ) ;
mxDestroyArray ( B1_inv ) ;
2013-03-22 15:44:34 +01:00
d1 = mult_SAT_B ( B1_inv_t , b1 ) ;
2022-02-28 18:41:39 +01:00
/* Compute block S1 of the triangularized system.
Update B1 , C1 , B2 , A2 , A3 , b1 and b2 for the next relaxation iteration .
Save S1 and d1 for the subsequent backward iteration .
E . g . at the end of the first iteration , the system will look like :
⎛ I S1 … … ⎞ ⎛ d1 ⎞
⎢ B1 C1 … ⎥ ⎢ b1 ⎥
⎢ A2 B2 … ⎥ = ⎢ b2 ⎥
⎢ A3 … ⎥ ⎢ … ⎥
⎝ … ⎠ ⎝ … ⎠
*/
2013-03-22 15:44:34 +01:00
if ( t < periods )
{
2022-02-28 18:41:39 +01:00
// Compute S1
mxArray * S1 = Sparse_mult_SAT_SB ( B1_inv_t , C1 ) ;
2013-03-22 15:44:34 +01:00
2022-02-28 18:41:39 +01:00
// Update A2, B1, b1
mxArray * A2_t = Sparse_transpose ( A2 ) ;
2013-03-22 15:44:34 +01:00
mxArray * tmp = Sparse_mult_SAT_SB ( A2_t , S1 ) ;
mxDestroyArray ( B1 ) ;
2022-02-28 12:25:11 +01:00
B1 = Sparse_subtract_SA_SB ( B2 , tmp ) ;
2013-03-22 15:44:34 +01:00
mxDestroyArray ( tmp ) ;
tmp = mult_SAT_B ( A2_t , d1 ) ;
2022-02-28 18:41:39 +01:00
mxDestroyArray ( A2_t ) ;
mxDestroyArray ( b1 ) ;
2022-02-28 12:25:11 +01:00
b1 = subtract_A_B ( b2 , tmp ) ;
2013-03-22 15:44:34 +01:00
mxDestroyArray ( tmp ) ;
2022-02-28 18:41:39 +01:00
mxDestroyArray ( A2 ) ;
A2 = mxDuplicateArray ( A3 ) ;
// Save S1 and d1
2021-02-01 12:46:02 +01:00
triangular_form . emplace_back ( S1 , d1 ) ;
2013-03-22 15:44:34 +01:00
}
2022-02-28 18:41:39 +01:00
mxDestroyArray ( B1_inv_t ) ;
if ( t < periods - 1 )
2013-03-22 15:44:34 +01:00
{
2022-02-28 18:41:39 +01:00
// Update C1, B2, A3, b2
C1_nze = B2_nze = A3_nze = 0 ;
for ( size_t var = ( t + 1 ) * Size ; var < ( t + 2 ) * Size ; var + + )
2013-03-22 15:44:34 +01:00
{
2022-02-28 18:41:39 +01:00
b2_d [ var - ( t + 1 ) * Size ] = b_m_d [ var ] ;
C1_j [ var - ( t + 1 ) * Size ] = C1_nze ;
B2_j [ var - ( t + 1 ) * Size ] = B2_nze ;
A3_j [ var - ( t + 1 ) * Size ] = A3_nze ;
while ( static_cast < unsigned int > ( A_m_j [ var + 1 ] ) > nze )
{
size_t eq = A_m_i [ nze ] ;
if ( eq < ( t + 1 ) * Size )
{
C1_i [ C1_nze ] = eq - t * Size ;
C1_d [ C1_nze ] = A_m_d [ nze ] ;
C1_nze + + ;
}
else if ( eq < ( t + 2 ) * Size )
{
B2_i [ B2_nze ] = eq - ( t + 1 ) * Size ;
B2_d [ B2_nze ] = A_m_d [ nze ] ;
B2_nze + + ;
}
else
{
A3_i [ A3_nze ] = eq - ( t + 2 ) * Size ;
A3_d [ A3_nze ] = A_m_d [ nze ] ;
A3_nze + + ;
}
nze + + ;
}
2013-03-22 15:44:34 +01:00
}
2022-02-28 18:41:39 +01:00
C1_j [ Size ] = C1_nze ;
B2_j [ Size ] = B2_nze ;
A3_j [ Size ] = A3_nze ;
2013-03-22 15:44:34 +01:00
}
2009-08-29 18:04:06 +02:00
}
2022-02-28 18:41:39 +01:00
// At this point, d1 contains the solution for the last period
2013-03-22 15:44:34 +01:00
double * d1_d = mxGetPr ( d1 ) ;
for ( unsigned i = 0 ; i < Size ; i + + )
2010-02-05 18:33:34 +01:00
{
2013-03-22 15:44:34 +01:00
int eq = index_vara [ i + Size * ( y_kmin + periods - 1 ) ] ;
double yy = - ( d1_d [ i ] + y [ eq ] ) ;
direction [ eq ] = yy ;
y [ eq ] + = slowc_l * yy ;
2010-02-05 18:33:34 +01:00
}
2013-03-22 15:44:34 +01:00
2022-02-28 18:41:39 +01:00
// Perform backward iteration to compute the solution for other periods
2013-03-22 15:44:34 +01:00
for ( int t = periods - 2 ; t > = 0 ; t - - )
2010-07-23 11:20:24 +02:00
{
2022-02-28 18:41:39 +01:00
auto [ S1 , d1_next ] = triangular_form . back ( ) ;
2013-03-22 15:44:34 +01:00
triangular_form . pop_back ( ) ;
2022-02-28 18:41:39 +01:00
mxArray * S1_t = Sparse_transpose ( S1 ) ;
mxDestroyArray ( S1 ) ;
mxArray * tmp = mult_SAT_B ( S1_t , d1 ) ;
mxDestroyArray ( S1_t ) ;
mxDestroyArray ( d1 ) ;
2022-02-28 12:25:11 +01:00
d1 = subtract_A_B ( d1_next , tmp ) ;
2013-03-22 15:44:34 +01:00
d1_d = mxGetPr ( d1 ) ;
2022-02-28 18:41:39 +01:00
mxDestroyArray ( d1_next ) ;
2013-03-22 15:44:34 +01:00
mxDestroyArray ( tmp ) ;
for ( unsigned i = 0 ; i < Size ; i + + )
2010-07-23 11:20:24 +02:00
{
2013-03-22 15:44:34 +01:00
int eq = index_vara [ i + Size * ( y_kmin + t ) ] ;
double yy = - ( d1_d [ i ] + y [ eq ] ) ;
direction [ eq ] = yy ;
y [ eq ] + = slowc_l * yy ;
2010-07-23 11:20:24 +02:00
}
}
2022-02-28 18:41:39 +01:00
2013-03-22 15:44:34 +01:00
mxDestroyArray ( B1 ) ;
mxDestroyArray ( C1 ) ;
mxDestroyArray ( A2 ) ;
mxDestroyArray ( B2 ) ;
mxDestroyArray ( A3 ) ;
mxDestroyArray ( b1 ) ;
mxDestroyArray ( b2 ) ;
mxDestroyArray ( A_m ) ;
mxDestroyArray ( b_m ) ;
2022-02-28 18:41:39 +01:00
mxDestroyArray ( d1 ) ;
2010-09-24 12:52:58 +02:00
}
2013-03-22 15:44:34 +01:00
void
dynSparseMatrix : : End_Matlab_LU_UMFPack ( )
2010-10-18 17:28:21 +02:00
{
2013-03-22 15:44:34 +01:00
if ( Symbolic )
2023-03-31 18:36:42 +02:00
{
umfpack_dl_free_symbolic ( & Symbolic ) ;
Symbolic = nullptr ;
}
2013-03-22 15:44:34 +01:00
if ( Numeric )
2023-03-31 18:36:42 +02:00
{
umfpack_dl_free_numeric ( & Numeric ) ;
Numeric = nullptr ;
}
2010-10-18 17:28:21 +02:00
}
2013-03-22 15:44:34 +01:00
void
dynSparseMatrix : : End_Solver ( )
2010-10-18 17:28:21 +02:00
{
2021-02-03 18:10:01 +01:00
if ( ( ( stack_solve_algo = = 0 | | stack_solve_algo = = 4 ) & & ! steady_state )
| | ( solve_algo = = 6 & & steady_state ) )
2013-03-22 15:44:34 +01:00
End_Matlab_LU_UMFPack ( ) ;
}
2015-09-22 12:45:27 +02:00
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Printfull_UMFPack ( const SuiteSparse_long * Ap , const SuiteSparse_long * Ai , const double * Ax , const double * b , int n )
2015-09-22 12:45:27 +02:00
{
double A [ n * n ] ;
2019-12-20 14:50:19 +01:00
for ( int i = 0 ; i < n * n ; i + + )
2015-09-22 12:45:27 +02:00
A [ i ] = 0 ;
int k = 0 ;
for ( int i = 0 ; i < n ; i + + )
2017-05-16 16:30:27 +02:00
for ( int j = Ap [ i ] ; j < Ap [ i + 1 ] ; j + + )
2019-12-20 14:50:19 +01:00
A [ Ai [ j ] * n + i ] = Ax [ k + + ] ;
2015-09-22 12:45:27 +02:00
for ( int i = 0 ; i < n ; i + + )
{
for ( int j = 0 ; j < n ; j + + )
2017-05-16 16:30:27 +02:00
mexPrintf ( " %4.1f " , A [ i * n + j ] ) ;
mexPrintf ( " %6.3f \n " , b [ i ] ) ;
2015-09-22 12:45:27 +02:00
}
}
2013-06-08 17:16:20 +02:00
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Print_UMFPack ( const SuiteSparse_long * Ap , const SuiteSparse_long * Ai , const double * Ax , int n )
2013-06-08 17:16:20 +02:00
{
int k = 0 ;
for ( int i = 0 ; i < n ; i + + )
2017-05-16 16:30:27 +02:00
for ( int j = Ap [ i ] ; j < Ap [ i + 1 ] ; j + + )
mexPrintf ( " (%d, %d) %f \n " , Ai [ j ] + 1 , i + 1 , Ax [ k + + ] ) ;
2013-06-08 17:16:20 +02:00
}
2015-09-22 12:45:27 +02:00
void
2021-02-03 18:10:01 +01:00
dynSparseMatrix : : Solve_LU_UMFPack ( SuiteSparse_long * Ap , SuiteSparse_long * Ai , double * Ax , double * b , int n , int Size , double slowc_l , bool is_two_boundaries , int it_ , const vector_table_conditional_local_type & vector_table_conditional_local )
2015-09-22 12:45:27 +02:00
{
2021-02-03 18:10:01 +01:00
SuiteSparse_long sys = 0 ;
2019-12-20 14:50:19 +01:00
double Control [ UMFPACK_CONTROL ] , Info [ UMFPACK_INFO ] , res [ n ] ;
2015-09-22 12:45:27 +02:00
umfpack_dl_defaults ( Control ) ;
2021-02-03 18:10:01 +01:00
SuiteSparse_long status = 0 ;
2015-09-22 12:45:27 +02:00
if ( iter = = 0 )
{
2023-03-31 18:36:42 +02:00
if ( Symbolic )
umfpack_dl_free_symbolic ( & Symbolic ) ;
2015-09-22 12:45:27 +02:00
status = umfpack_dl_symbolic ( n , n , Ap , Ai , Ax , & Symbolic , Control , Info ) ;
2023-04-03 18:32:32 +02:00
if ( status ! = UMFPACK_OK )
2015-09-22 12:45:27 +02:00
{
umfpack_dl_report_info ( Control , Info ) ;
umfpack_dl_report_status ( Control , status ) ;
2022-07-29 12:42:50 +02:00
throw FatalException { " umfpack_dl_symbolic failed " } ;
2015-09-22 12:45:27 +02:00
}
}
2023-03-31 18:36:42 +02:00
if ( Numeric )
2017-05-16 16:30:27 +02:00
umfpack_dl_free_numeric ( & Numeric ) ;
status = umfpack_dl_numeric ( Ap , Ai , Ax , Symbolic , & Numeric , Control , Info ) ;
2023-04-03 18:32:32 +02:00
if ( status ! = UMFPACK_OK )
2015-09-22 12:45:27 +02:00
{
umfpack_dl_report_info ( Control , Info ) ;
umfpack_dl_report_status ( Control , status ) ;
2022-07-29 12:42:50 +02:00
throw FatalException { " umfpack_dl_numeric failed " } ;
2015-09-22 12:45:27 +02:00
}
status = umfpack_dl_solve ( sys , Ap , Ai , Ax , res , b , Numeric , Control , Info ) ;
if ( status ! = UMFPACK_OK )
{
umfpack_dl_report_info ( Control , Info ) ;
umfpack_dl_report_status ( Control , status ) ;
2022-07-29 12:42:50 +02:00
throw FatalException { " umfpack_dl_solve failed " } ;
2015-09-22 12:45:27 +02:00
}
if ( vector_table_conditional_local . size ( ) )
{
if ( is_two_boundaries )
for ( int t = 0 ; t < n / Size ; t + + )
if ( t = = 0 )
{
for ( int i = 0 ; i < Size ; i + + )
{
bool fliped = vector_table_conditional_local [ i ] . is_cond ;
if ( fliped )
{
int eq = index_vara [ i + Size * ( y_kmin ) ] ;
int flip_exo = vector_table_conditional_local [ i ] . var_exo ;
2019-12-20 14:50:19 +01:00
double yy = - ( res [ i ] + x [ y_kmin + flip_exo * nb_row_x ] ) ;
2017-05-05 14:22:38 +02:00
direction [ eq ] = 0 ;
x [ flip_exo * nb_row_x + y_kmin ] + = slowc_l * yy ;
2015-09-22 12:45:27 +02:00
}
else
{
int eq = index_vara [ i + Size * ( y_kmin ) ] ;
2019-12-20 14:50:19 +01:00
double yy = - ( res [ i ] + y [ eq ] ) ;
2015-09-22 12:45:27 +02:00
direction [ eq ] = yy ;
y [ eq ] + = slowc_l * yy ;
}
}
}
else
{
for ( int i = 0 ; i < Size ; i + + )
{
int eq = index_vara [ i + Size * ( t + y_kmin ) ] ;
double yy = - ( res [ i + Size * t ] + y [ eq ] ) ;
direction [ eq ] = yy ;
y [ eq ] + = slowc_l * yy ;
}
}
else
for ( int i = 0 ; i < n ; i + + )
{
int eq = index_vara [ i ] ;
double yy = - ( res [ i ] + y [ eq + it_ * y_size ] ) ;
direction [ eq ] = yy ;
y [ eq + it_ * y_size ] + = slowc_l * yy ;
}
}
else
{
if ( is_two_boundaries )
for ( int i = 0 ; i < n ; i + + )
{
int eq = index_vara [ i + Size * y_kmin ] ;
double yy = - ( res [ i ] + y [ eq ] ) ;
direction [ eq ] = yy ;
y [ eq ] + = slowc_l * yy ;
}
else
for ( int i = 0 ; i < n ; i + + )
{
int eq = index_vara [ i ] ;
double yy = - ( res [ i ] + y [ eq + it_ * y_size ] ) ;
direction [ eq ] = yy ;
y [ eq + it_ * y_size ] + = slowc_l * yy ;
}
2017-05-16 16:30:27 +02:00
}
2017-03-24 23:15:25 +01:00
2015-09-22 12:45:27 +02:00
mxFree ( Ap ) ;
mxFree ( Ai ) ;
mxFree ( Ax ) ;
mxFree ( b ) ;
}
2013-03-22 15:44:34 +01:00
void
2019-12-20 14:50:19 +01:00
dynSparseMatrix : : Solve_LU_UMFPack ( SuiteSparse_long * Ap , SuiteSparse_long * Ai , double * Ax , double * b , int n , int Size , double slowc_l , bool is_two_boundaries , int it_ )
2013-03-22 15:44:34 +01:00
{
2021-02-03 18:10:01 +01:00
SuiteSparse_long sys = 0 ;
2019-12-20 14:50:19 +01:00
double Control [ UMFPACK_CONTROL ] , Info [ UMFPACK_INFO ] , res [ n ] ;
2013-03-22 15:44:34 +01:00
umfpack_dl_defaults ( Control ) ;
2021-02-03 18:10:01 +01:00
SuiteSparse_long status = 0 ;
2013-03-22 15:44:34 +01:00
if ( iter = = 0 )
2010-10-18 17:28:21 +02:00
{
2023-03-31 18:36:42 +02:00
if ( Symbolic )
umfpack_dl_free_symbolic ( & Symbolic ) ;
2013-03-22 15:44:34 +01:00
status = umfpack_dl_symbolic ( n , n , Ap , Ai , Ax , & Symbolic , Control , Info ) ;
2023-04-03 18:32:32 +02:00
if ( status ! = UMFPACK_OK )
2010-10-18 17:28:21 +02:00
{
2013-03-22 15:44:34 +01:00
umfpack_dl_report_info ( Control , Info ) ;
umfpack_dl_report_status ( Control , status ) ;
2022-07-29 12:42:50 +02:00
throw FatalException { " umfpack_dl_symbolic failed " } ;
2010-10-18 17:28:21 +02:00
}
}
2023-03-31 18:36:42 +02:00
if ( Numeric )
2017-05-16 16:30:27 +02:00
umfpack_dl_free_numeric ( & Numeric ) ;
status = umfpack_dl_numeric ( Ap , Ai , Ax , Symbolic , & Numeric , Control , Info ) ;
2023-04-03 18:32:32 +02:00
if ( status ! = UMFPACK_OK )
2013-03-22 15:44:34 +01:00
{
umfpack_dl_report_info ( Control , Info ) ;
umfpack_dl_report_status ( Control , status ) ;
2022-07-29 12:42:50 +02:00
throw FatalException { " umfpack_dl_numeric failed " } ;
2013-03-22 15:44:34 +01:00
}
status = umfpack_dl_solve ( sys , Ap , Ai , Ax , res , b , Numeric , Control , Info ) ;
if ( status ! = UMFPACK_OK )
{
umfpack_dl_report_info ( Control , Info ) ;
umfpack_dl_report_status ( Control , status ) ;
2022-07-29 12:42:50 +02:00
throw FatalException { " umfpack_dl_solve failed " } ;
2013-03-22 15:44:34 +01:00
}
if ( is_two_boundaries )
for ( int i = 0 ; i < n ; i + + )
{
int eq = index_vara [ i + Size * y_kmin ] ;
double yy = - ( res [ i ] + y [ eq ] ) ;
direction [ eq ] = yy ;
y [ eq ] + = slowc_l * yy ;
}
else
for ( int i = 0 ; i < n ; i + + )
{
int eq = index_vara [ i ] ;
double yy = - ( res [ i ] + y [ eq + it_ * y_size ] ) ;
direction [ eq ] = yy ;
y [ eq + it_ * y_size ] + = slowc_l * yy ;
}
mxFree ( Ap ) ;
mxFree ( Ai ) ;
mxFree ( Ax ) ;
mxFree ( b ) ;
}
2010-07-23 11:20:24 +02:00
void
2013-03-22 15:44:34 +01:00
dynSparseMatrix : : Solve_Matlab_GMRES ( mxArray * A_m , mxArray * b_m , int Size , double slowc , int block , bool is_two_boundaries , int it_ , mxArray * x0_m )
2010-07-23 11:20:24 +02:00
{
2013-03-22 15:44:34 +01:00
size_t n = mxGetM ( A_m ) ;
2013-04-05 14:52:49 +02:00
const char * field_names [ ] = { " droptol " , " type " } ;
2013-03-25 12:03:09 +01:00
mwSize dims [ 1 ] = { 1 } ;
2023-01-24 12:21:08 +01:00
mxArray * Setup = mxCreateStructArray ( 1 , dims , std : : extent_v < decltype ( field_names ) > , field_names ) ;
2013-03-25 12:03:09 +01:00
mxSetFieldByNumber ( Setup , 0 , 0 , mxCreateDoubleScalar ( lu_inc_tol ) ) ;
2013-04-05 14:52:49 +02:00
mxSetFieldByNumber ( Setup , 0 , 1 , mxCreateString ( " ilutp " ) ) ;
2010-07-23 11:20:24 +02:00
mxArray * lhs0 [ 2 ] ;
2023-01-24 12:21:08 +01:00
mxArray * rhs0 [ ] = { A_m , Setup } ;
if ( mexCallMATLAB ( std : : extent_v < decltype ( lhs0 ) > , lhs0 , std : : extent_v < decltype ( rhs0 ) > , rhs0 , " ilu " ) )
2022-07-29 12:42:50 +02:00
throw FatalException ( " In GMRES, the incomplete LU decomposition (ilu) has failed " ) ;
2010-07-23 11:20:24 +02:00
mxArray * L1 = lhs0 [ 0 ] ;
mxArray * U1 = lhs0 [ 1 ] ;
/*[za,flag1] = gmres(g1a,b,Blck_size,1e-6,Blck_size*periods,L1,U1);*/
2023-01-24 12:21:08 +01:00
mxArray * rhs [ ] = { A_m , b_m , mxCreateDoubleScalar ( Size ) , mxCreateDoubleScalar ( 1e-6 ) ,
mxCreateDoubleScalar ( static_cast < double > ( n ) ) , L1 , U1 , x0_m } ;
2010-07-23 11:20:24 +02:00
mxArray * lhs [ 2 ] ;
2023-01-24 12:21:08 +01:00
mexCallMATLAB ( std : : extent_v < decltype ( lhs ) > , lhs , std : : extent_v < decltype ( rhs ) > , rhs , " gmres " ) ;
2010-07-23 11:20:24 +02:00
mxArray * z = lhs [ 0 ] ;
mxArray * flag = lhs [ 1 ] ;
double * flag1 = mxGetPr ( flag ) ;
mxDestroyArray ( rhs0 [ 1 ] ) ;
mxDestroyArray ( rhs [ 2 ] ) ;
mxDestroyArray ( rhs [ 3 ] ) ;
mxDestroyArray ( rhs [ 4 ] ) ;
mxDestroyArray ( rhs [ 5 ] ) ;
mxDestroyArray ( rhs [ 6 ] ) ;
2010-10-18 17:28:21 +02:00
if ( * flag1 > 0 )
2010-07-23 11:20:24 +02:00
{
if ( * flag1 = = 1 )
2021-02-03 18:10:01 +01:00
mexWarnMsgTxt ( ( " Error in bytecode: No convergence inside GMRES, in block "
+ to_string ( block + 1 ) ) . c_str ( ) ) ;
2010-07-23 11:20:24 +02:00
else if ( * flag1 = = 2 )
2021-02-03 18:10:01 +01:00
mexWarnMsgTxt ( ( " Error in bytecode: Preconditioner is ill-conditioned, in block "
+ to_string ( block + 1 ) ) . c_str ( ) ) ;
2010-07-23 11:20:24 +02:00
else if ( * flag1 = = 3 )
2021-02-03 18:10:01 +01:00
mexWarnMsgTxt ( ( " Error in bytecode: GMRES stagnated (Two consecutive iterates were the same.), in block "
+ to_string ( block + 1 ) ) . c_str ( ) ) ;
2010-07-23 11:20:24 +02:00
lu_inc_tol / = 10 ;
}
else
{
double * res = mxGetPr ( z ) ;
2010-08-18 13:51:57 +02:00
if ( is_two_boundaries )
2019-04-23 12:58:38 +02:00
for ( int i = 0 ; i < static_cast < int > ( n ) ; i + + )
2010-08-18 13:51:57 +02:00
{
int eq = index_vara [ i + Size * y_kmin ] ;
2011-02-04 16:53:12 +01:00
double yy = - ( res [ i ] + y [ eq ] ) ;
2010-08-18 13:51:57 +02:00
direction [ eq ] = yy ;
y [ eq ] + = slowc * yy ;
}
else
2019-04-23 12:58:38 +02:00
for ( int i = 0 ; i < static_cast < int > ( n ) ; i + + )
2010-08-18 13:51:57 +02:00
{
int eq = index_vara [ i ] ;
2011-02-04 16:53:12 +01:00
double yy = - ( res [ i ] + y [ eq + it_ * y_size ] ) ;
2010-10-18 17:28:21 +02:00
direction [ eq ] = yy ;
y [ eq + it_ * y_size ] + = slowc * yy ;
2010-08-18 13:51:57 +02:00
}
2010-07-23 11:20:24 +02:00
}
mxDestroyArray ( A_m ) ;
mxDestroyArray ( b_m ) ;
2023-03-31 18:44:24 +02:00
mxDestroyArray ( x0_m ) ;
2010-07-23 11:20:24 +02:00
mxDestroyArray ( z ) ;
mxDestroyArray ( flag ) ;
}
void
2013-03-22 15:44:34 +01:00
dynSparseMatrix : : Solve_Matlab_BiCGStab ( mxArray * A_m , mxArray * b_m , int Size , double slowc , int block , bool is_two_boundaries , int it_ , mxArray * x0_m , int preconditioner )
2010-07-23 11:20:24 +02:00
{
2013-03-22 15:44:34 +01:00
/* precond = 0 => Jacobi
precond = 1 = > Incomplet LU decomposition */
size_t n = mxGetM ( A_m ) ;
2021-02-03 18:10:01 +01:00
mxArray * L1 = nullptr , * U1 = nullptr , * Diag = nullptr ;
2013-03-22 15:44:34 +01:00
if ( preconditioner = = 0 )
{
mxArray * lhs0 [ 1 ] ;
2023-01-24 12:21:08 +01:00
mxArray * rhs0 [ ] = { A_m , mxCreateDoubleScalar ( 0 ) } ;
mexCallMATLAB ( std : : extent_v < decltype ( lhs0 ) > , lhs0 , std : : extent_v < decltype ( rhs0 ) > , rhs0 , " spdiags " ) ;
2017-05-16 16:30:27 +02:00
mxArray * tmp = lhs0 [ 0 ] ;
double * tmp_val = mxGetPr ( tmp ) ;
2013-03-22 15:44:34 +01:00
Diag = mxCreateSparse ( n , n , n , mxREAL ) ;
mwIndex * Diag_i = mxGetIr ( Diag ) ;
mwIndex * Diag_j = mxGetJc ( Diag ) ;
double * Diag_val = mxGetPr ( Diag ) ;
for ( size_t i = 0 ; i < n ; i + + )
{
Diag_val [ i ] = tmp_val [ i ] ;
Diag_j [ i ] = i ;
Diag_i [ i ] = i ;
}
Diag_j [ n ] = n ;
}
else if ( preconditioner = = 1 )
{
/*[L1, U1] = ilu(g1a=;*/
const char * field_names [ ] = { " type " , " droptol " , " milu " , " udiag " , " thresh " } ;
2021-02-03 18:10:01 +01:00
const int type = 0 , droptol = 1 , milu = 2 , udiag = 3 , thresh = 4 ;
mwSize dims [ 1 ] = { static_cast < mwSize > ( 1 ) } ;
2023-01-24 12:21:08 +01:00
mxArray * Setup = mxCreateStructArray ( 1 , dims , std : : extent_v < decltype ( field_names ) > , field_names ) ;
2013-03-22 15:44:34 +01:00
mxSetFieldByNumber ( Setup , 0 , type , mxCreateString ( " ilutp " ) ) ;
mxSetFieldByNumber ( Setup , 0 , droptol , mxCreateDoubleScalar ( lu_inc_tol ) ) ;
mxSetFieldByNumber ( Setup , 0 , milu , mxCreateString ( " off " ) ) ;
mxSetFieldByNumber ( Setup , 0 , udiag , mxCreateDoubleScalar ( 0 ) ) ;
2013-06-08 17:16:20 +02:00
mxSetFieldByNumber ( Setup , 0 , thresh , mxCreateDoubleScalar ( 1 ) ) ;
2013-03-22 15:44:34 +01:00
mxArray * lhs0 [ 2 ] ;
2023-01-24 12:21:08 +01:00
mxArray * rhs0 [ ] = { A_m , Setup } ;
if ( mexCallMATLAB ( std : : extent_v < decltype ( lhs0 ) > , lhs0 , std : : extent_v < decltype ( rhs0 ) > , rhs0 , " ilu " ) )
2022-07-29 12:42:50 +02:00
throw FatalException { " In BiCGStab, the incomplete LU decomposition (ilu) has failed " } ;
2013-03-22 15:44:34 +01:00
L1 = lhs0 [ 0 ] ;
U1 = lhs0 [ 1 ] ;
mxDestroyArray ( Setup ) ;
}
2011-01-03 14:15:12 +01:00
double flags = 2 ;
2021-02-03 18:10:01 +01:00
mxArray * z = nullptr ;
2019-12-20 14:50:19 +01:00
if ( steady_state ) /*Octave BicStab algorihtm involves a 0 division in case of a preconditionner equal to the LU decomposition of A matrix*/
2011-01-03 14:15:12 +01:00
{
2011-02-04 16:53:12 +01:00
mxArray * res = mult_SAT_B ( Sparse_transpose ( A_m ) , x0_m ) ;
2011-01-03 14:15:12 +01:00
double * resid = mxGetPr ( res ) ;
double * b = mxGetPr ( b_m ) ;
2019-04-23 12:58:38 +02:00
for ( int i = 0 ; i < static_cast < int > ( n ) ; i + + )
2011-01-03 14:15:12 +01:00
resid [ i ] = b [ i ] - resid [ i ] ;
mxArray * lhs [ 1 ] ;
2023-01-24 12:21:08 +01:00
mxArray * rhs [ ] = { L1 , res } ;
mexCallMATLAB ( std : : extent_v < decltype ( lhs ) > , lhs , std : : extent_v < decltype ( rhs ) > , rhs , " mldivide " ) ;
mxArray * rhs2 [ ] = { U1 , lhs [ 0 ] } ;
mexCallMATLAB ( std : : extent_v < decltype ( lhs ) > , lhs , std : : extent_v < decltype ( rhs2 ) > , rhs2 , " mldivide " ) ;
2011-01-03 14:15:12 +01:00
z = lhs [ 0 ] ;
double * phat = mxGetPr ( z ) ;
double * x0 = mxGetPr ( x0_m ) ;
2019-04-23 12:58:38 +02:00
for ( int i = 0 ; i < static_cast < int > ( n ) ; i + + )
2011-01-03 14:15:12 +01:00
phat [ i ] = x0 [ i ] + phat [ i ] ;
/*Check the solution*/
res = mult_SAT_B ( Sparse_transpose ( A_m ) , z ) ;
resid = mxGetPr ( res ) ;
double cum_abs = 0 ;
2019-04-23 12:58:38 +02:00
for ( int i = 0 ; i < static_cast < int > ( n ) ; i + + )
2011-01-03 14:15:12 +01:00
{
resid [ i ] = b [ i ] - resid [ i ] ;
cum_abs + = fabs ( resid [ i ] ) ;
}
if ( cum_abs > 1e-7 )
flags = 2 ;
else
flags = 0 ;
mxDestroyArray ( res ) ;
}
2013-03-22 15:44:34 +01:00
2011-01-03 14:15:12 +01:00
if ( flags = = 2 )
{
2013-03-22 15:44:34 +01:00
if ( preconditioner = = 0 )
{
/*[za,flag1] = bicgstab(g1a,b,1e-6,Blck_size*periods,L1,U1);*/
2023-01-24 12:21:08 +01:00
mxArray * rhs [ ] = { A_m , b_m , mxCreateDoubleScalar ( 1e-6 ) ,
mxCreateDoubleScalar ( static_cast < double > ( n ) ) , Diag } ;
2013-03-22 15:44:34 +01:00
mxArray * lhs [ 2 ] ;
2023-01-24 12:21:08 +01:00
mexCallMATLAB ( std : : extent_v < decltype ( lhs ) > , lhs , std : : extent_v < decltype ( rhs ) > , rhs , " bicgstab " ) ;
2013-03-22 15:44:34 +01:00
z = lhs [ 0 ] ;
mxArray * flag = lhs [ 1 ] ;
double * flag1 = mxGetPr ( flag ) ;
flags = flag1 [ 0 ] ;
mxDestroyArray ( flag ) ;
mxDestroyArray ( rhs [ 2 ] ) ;
mxDestroyArray ( rhs [ 3 ] ) ;
mxDestroyArray ( rhs [ 4 ] ) ;
}
else if ( preconditioner = = 1 )
{
/*[za,flag1] = bicgstab(g1a,b,1e-6,Blck_size*periods,L1,U1);*/
2023-01-24 12:21:08 +01:00
mxArray * rhs [ ] = { A_m , b_m , mxCreateDoubleScalar ( 1e-6 ) ,
mxCreateDoubleScalar ( static_cast < double > ( n ) ) , L1 , U1 , x0_m } ;
2013-03-22 15:44:34 +01:00
mxArray * lhs [ 2 ] ;
2023-01-24 12:21:08 +01:00
mexCallMATLAB ( std : : extent_v < decltype ( lhs ) > , lhs , std : : extent_v < decltype ( rhs ) > , rhs , " bicgstab " ) ;
2013-03-22 15:44:34 +01:00
z = lhs [ 0 ] ;
mxArray * flag = lhs [ 1 ] ;
double * flag1 = mxGetPr ( flag ) ;
flags = flag1 [ 0 ] ;
mxDestroyArray ( flag ) ;
mxDestroyArray ( rhs [ 2 ] ) ;
mxDestroyArray ( rhs [ 3 ] ) ;
mxDestroyArray ( rhs [ 4 ] ) ;
mxDestroyArray ( rhs [ 5 ] ) ;
}
}
2011-01-03 14:15:12 +01:00
if ( flags > 0 )
2010-07-23 11:20:24 +02:00
{
2011-01-03 14:15:12 +01:00
if ( flags = = 1 )
2021-02-03 18:10:01 +01:00
mexWarnMsgTxt ( ( " Error in bytecode: No convergence inside BiCGStab, in block "
+ to_string ( block + 1 ) ) . c_str ( ) ) ;
2011-01-03 14:15:12 +01:00
else if ( flags = = 2 )
2021-02-03 18:10:01 +01:00
mexWarnMsgTxt ( ( " Error in bytecode: Preconditioner is ill-conditioned, in block "
+ to_string ( block + 1 ) ) . c_str ( ) ) ;
2011-01-03 14:15:12 +01:00
else if ( flags = = 3 )
2021-02-03 18:10:01 +01:00
mexWarnMsgTxt ( ( " Error in bytecode: BiCGStab stagnated (Two consecutive iterates were the same.), in block "
+ to_string ( block + 1 ) ) . c_str ( ) ) ;
2010-07-23 11:20:24 +02:00
lu_inc_tol / = 10 ;
}
else
{
double * res = mxGetPr ( z ) ;
2010-08-18 13:51:57 +02:00
if ( is_two_boundaries )
2019-04-23 12:58:38 +02:00
for ( int i = 0 ; i < static_cast < int > ( n ) ; i + + )
2010-08-18 13:51:57 +02:00
{
int eq = index_vara [ i + Size * y_kmin ] ;
2011-02-04 16:53:12 +01:00
double yy = - ( res [ i ] + y [ eq ] ) ;
direction [ eq ] = yy ;
2010-08-18 13:51:57 +02:00
y [ eq ] + = slowc * yy ;
}
else
2019-04-23 12:58:38 +02:00
for ( int i = 0 ; i < static_cast < int > ( n ) ; i + + )
2010-08-18 13:51:57 +02:00
{
int eq = index_vara [ i ] ;
2011-02-04 16:53:12 +01:00
double yy = - ( res [ i ] + y [ eq + it_ * y_size ] ) ;
direction [ eq ] = yy ;
2010-10-18 17:28:21 +02:00
y [ eq + it_ * y_size ] + = slowc * yy ;
2010-08-18 13:51:57 +02:00
}
2010-07-23 11:20:24 +02:00
}
mxDestroyArray ( A_m ) ;
mxDestroyArray ( b_m ) ;
2023-03-31 18:44:24 +02:00
mxDestroyArray ( x0_m ) ;
2010-07-23 11:20:24 +02:00
mxDestroyArray ( z ) ;
}
2010-09-24 12:52:58 +02:00
void
2013-03-22 15:44:34 +01:00
dynSparseMatrix : : Singular_display ( int block , int Size )
2012-03-06 11:03:13 +01:00
{
bool zero_solution ;
Simple_Init ( Size , IM_i , zero_solution ) ;
2023-01-24 12:21:08 +01:00
mxArray * rhs [ ] = { mxCreateDoubleMatrix ( Size , Size , mxREAL ) } ;
2021-02-09 15:55:36 +01:00
double * pind = mxGetPr ( rhs [ 0 ] ) ;
2012-03-06 11:03:13 +01:00
for ( int j = 0 ; j < Size * Size ; j + + )
pind [ j ] = 0.0 ;
for ( int ii = 0 ; ii < Size ; ii + + )
{
2021-02-09 15:55:36 +01:00
NonZeroElem * first ;
2012-03-06 11:03:13 +01:00
int nb_eq = At_Col ( ii , & first ) ;
for ( int j = 0 ; j < nb_eq ; j + + )
{
int k = first - > u_index ;
int jj = first - > r_index ;
2019-12-20 14:50:19 +01:00
pind [ ii * Size + jj ] = u [ k ] ;
2012-03-06 11:03:13 +01:00
first = first - > NZE_C_N ;
}
}
mxArray * lhs [ 3 ] ;
2023-01-24 12:21:08 +01:00
mexCallMATLAB ( std : : extent_v < decltype ( lhs ) > , lhs , std : : extent_v < decltype ( rhs ) > , rhs , " svd " ) ;
2017-05-16 16:30:27 +02:00
mxArray * SVD_u = lhs [ 0 ] ;
mxArray * SVD_s = lhs [ 1 ] ;
2012-03-06 11:03:13 +01:00
double * SVD_ps = mxGetPr ( SVD_s ) ;
double * SVD_pu = mxGetPr ( SVD_u ) ;
for ( int i = 0 ; i < Size ; i + + )
2021-02-09 15:55:36 +01:00
if ( abs ( SVD_ps [ i * ( 1 + Size ) ] ) < 1e-12 )
{
mexPrintf ( " The following equations form a linear combination: \n " ) ;
double max_u = 0 ;
for ( int j = 0 ; j < Size ; j + + )
if ( abs ( SVD_pu [ j + i * Size ] ) > abs ( max_u ) )
max_u = SVD_pu [ j + i * Size ] ;
vector < int > equ_list ;
for ( int j = 0 ; j < Size ; j + + )
{
double rr = SVD_pu [ j + i * Size ] / max_u ;
if ( rr < - 1e-10 )
{
equ_list . push_back ( j ) ;
if ( rr ! = - 1 )
mexPrintf ( " - %3.2f*Dequ_%d_dy " , abs ( rr ) , j + 1 ) ;
else
mexPrintf ( " - Dequ_%d_dy " , j + 1 ) ;
}
else if ( rr > 1e-10 )
{
equ_list . push_back ( j ) ;
if ( j > 0 )
if ( rr ! = 1 )
mexPrintf ( " + %3.2f*Dequ_%d_dy " , rr , j + 1 ) ;
2013-03-22 15:44:34 +01:00
else
2021-02-09 15:55:36 +01:00
mexPrintf ( " + Dequ_%d_dy " , j + 1 ) ;
else if ( rr ! = 1 )
mexPrintf ( " %3.2f*Dequ_%d_dy " , rr , j + 1 ) ;
else
mexPrintf ( " Dequ_%d_dy " , j + 1 ) ;
}
}
mexPrintf ( " = 0 \n " ) ;
}
2012-03-06 11:03:13 +01:00
mxDestroyArray ( lhs [ 0 ] ) ;
mxDestroyArray ( lhs [ 1 ] ) ;
mxDestroyArray ( lhs [ 2 ] ) ;
if ( block > 1 )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve_ByteCode_Sparse_GaussianElimination, singular system in block "
+ to_string ( block + 1 ) } ;
2012-03-06 11:03:13 +01:00
else
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve_ByteCode_Sparse_GaussianElimination, singular system " } ;
2012-03-06 11:03:13 +01:00
}
bool
2013-03-22 15:44:34 +01:00
dynSparseMatrix : : Solve_ByteCode_Sparse_GaussianElimination ( int Size , int blck , int it_ )
2007-11-21 00:27:30 +01:00
{
2009-08-25 11:43:01 +02:00
int pivj = 0 , pivk = 0 ;
2021-02-09 15:55:36 +01:00
NonZeroElem * * bc = static_cast < NonZeroElem * * > ( mxMalloc ( Size * sizeof ( * bc ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( bc , __LINE__ , __FILE__ , __func__ , Size * sizeof ( * bc ) ) ;
2021-02-09 15:55:36 +01:00
double * piv_v = static_cast < double * > ( mxMalloc ( Size * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( piv_v , __LINE__ , __FILE__ , __func__ , Size * sizeof ( double ) ) ;
2021-02-09 15:55:36 +01:00
int * pivj_v = static_cast < int * > ( mxMalloc ( Size * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivj_v , __LINE__ , __FILE__ , __func__ , Size * sizeof ( int ) ) ;
2021-02-09 15:55:36 +01:00
int * pivk_v = static_cast < int * > ( mxMalloc ( Size * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivk_v , __LINE__ , __FILE__ , __func__ , Size * sizeof ( int ) ) ;
2021-02-09 15:55:36 +01:00
int * NR = static_cast < int * > ( mxMalloc ( Size * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( NR , __LINE__ , __FILE__ , __func__ , Size * sizeof ( int ) ) ;
2010-09-24 12:52:58 +02:00
for ( int i = 0 ; i < Size ; i + + )
{
/*finding the max-pivot*/
2021-02-09 15:55:36 +01:00
double piv = 0 , piv_abs = 0 ;
NonZeroElem * first ;
2010-09-24 12:52:58 +02:00
int nb_eq = At_Col ( i , & first ) ;
2021-02-09 15:55:36 +01:00
int l = 0 ;
int N_max = 0 ;
bool one = false ;
2010-09-24 12:52:58 +02:00
for ( int j = 0 ; j < nb_eq ; j + + )
{
if ( ! line_done [ first - > r_index ] )
{
int k = first - > u_index ;
int jj = first - > r_index ;
int NRow_jj = NRow ( jj ) ;
piv_v [ l ] = u [ k ] ;
double piv_fabs = fabs ( u [ k ] ) ;
pivj_v [ l ] = jj ;
pivk_v [ l ] = k ;
NR [ l ] = NRow_jj ;
if ( NRow_jj = = 1 & & ! one )
{
one = true ;
piv_abs = piv_fabs ;
N_max = NRow_jj ;
}
if ( ! one )
{
if ( piv_fabs > piv_abs )
piv_abs = piv_fabs ;
if ( NRow_jj > N_max )
N_max = NRow_jj ;
}
2021-02-09 15:55:36 +01:00
else if ( NRow_jj = = 1 )
2010-09-24 12:52:58 +02:00
{
2021-02-09 15:55:36 +01:00
if ( piv_fabs > piv_abs )
piv_abs = piv_fabs ;
if ( NRow_jj > N_max )
N_max = NRow_jj ;
2010-09-24 12:52:58 +02:00
}
l + + ;
}
first = first - > NZE_C_N ;
}
if ( piv_abs < eps )
{
mxFree ( piv_v ) ;
mxFree ( pivj_v ) ;
mxFree ( pivk_v ) ;
mxFree ( NR ) ;
mxFree ( bc ) ;
if ( steady_state )
{
2023-06-13 16:34:22 +02:00
if ( verbosity > = 1 )
{
if ( blck > 1 )
mexPrintf ( " Error: singular system in Simulate_NG in block %d \n " , blck + 1 ) ;
else
mexPrintf ( " Error: singular system in Simulate_NG " ) ;
}
2012-03-06 11:03:13 +01:00
return true ;
2010-09-24 12:52:58 +02:00
}
else
{
if ( blck > 1 )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve_ByteCode_Sparse_GaussianElimination, singular system in block "
+ to_string ( blck + 1 ) } ;
2010-09-24 12:52:58 +02:00
else
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve_ByteCode_Sparse_GaussianElimination, singular system " } ;
2010-09-24 12:52:58 +02:00
}
}
double markovitz = 0 , markovitz_max = - 9e70 ;
if ( ! one )
2021-02-09 15:55:36 +01:00
for ( int j = 0 ; j < l ; j + + )
{
if ( N_max > 0 & & NR [ j ] > 0 )
{
if ( fabs ( piv_v [ j ] ) > 0 )
{
if ( markowitz_c > 0 )
markovitz = exp ( log ( fabs ( piv_v [ j ] ) / piv_abs )
- markowitz_c * log ( static_cast < double > ( NR [ j ] )
/ static_cast < double > ( N_max ) ) ) ;
else
markovitz = fabs ( piv_v [ j ] ) / piv_abs ;
2010-09-24 12:52:58 +02:00
}
else
markovitz = 0 ;
}
else
markovitz = fabs ( piv_v [ j ] ) / piv_abs ;
if ( markovitz > markovitz_max )
{
piv = piv_v [ j ] ;
2019-12-20 14:50:19 +01:00
pivj = pivj_v [ j ] ; //Line number
pivk = pivk_v [ j ] ; //positi
2010-09-24 12:52:58 +02:00
markovitz_max = markovitz ;
}
2021-02-09 15:55:36 +01:00
}
2010-09-24 12:52:58 +02:00
else
2021-02-09 15:55:36 +01:00
for ( int j = 0 ; j < l ; j + + )
{
if ( N_max > 0 & & NR [ j ] > 0 )
{
if ( fabs ( piv_v [ j ] ) > 0 )
{
if ( markowitz_c > 0 )
markovitz = exp ( log ( fabs ( piv_v [ j ] ) / piv_abs )
- markowitz_c * log ( static_cast < double > ( NR [ j ] )
/ static_cast < double > ( N_max ) ) ) ;
else
markovitz = fabs ( piv_v [ j ] ) / piv_abs ;
}
else
markovitz = 0 ;
}
else
markovitz = fabs ( piv_v [ j ] ) / piv_abs ;
if ( NR [ j ] = = 1 )
{
piv = piv_v [ j ] ;
pivj = pivj_v [ j ] ; //Line number
pivk = pivk_v [ j ] ; //positi
markovitz_max = markovitz ;
}
}
2010-09-24 12:52:58 +02:00
pivot [ i ] = pivj ;
pivotk [ i ] = pivk ;
pivotv [ i ] = piv ;
line_done [ pivj ] = true ;
/*divide all the non zeros elements of the line pivj by the max_pivot*/
int nb_var = At_Row ( pivj , & first ) ;
for ( int j = 0 ; j < nb_var ; j + + )
{
u [ first - > u_index ] / = piv ;
first = first - > NZE_R_N ;
}
u [ b [ pivj ] ] / = piv ;
2022-02-28 12:25:11 +01:00
/*subtract the elements on the non treated lines*/
2010-09-24 12:52:58 +02:00
nb_eq = At_Col ( i , & first ) ;
NonZeroElem * first_piva ;
int nb_var_piva = At_Row ( pivj , & first_piva ) ;
int nb_eq_todo = 0 ;
for ( int j = 0 ; j < nb_eq & & first ; j + + )
{
if ( ! line_done [ first - > r_index ] )
bc [ nb_eq_todo + + ] = first ;
first = first - > NZE_C_N ;
}
for ( int j = 0 ; j < nb_eq_todo ; j + + )
{
first = bc [ j ] ;
int row = first - > r_index ;
double first_elem = u [ first - > u_index ] ;
int nb_var_piv = nb_var_piva ;
NonZeroElem * first_piv = first_piva ;
NonZeroElem * first_sub ;
int nb_var_sub = At_Row ( row , & first_sub ) ;
int l_sub = 0 , l_piv = 0 ;
int sub_c_index = first_sub - > c_index , piv_c_index = first_piv - > c_index ;
while ( l_sub < nb_var_sub | | l_piv < nb_var_piv )
2021-02-09 15:55:36 +01:00
if ( l_sub < nb_var_sub & & ( sub_c_index < piv_c_index | | l_piv > = nb_var_piv ) )
{
first_sub = first_sub - > NZE_R_N ;
if ( first_sub )
sub_c_index = first_sub - > c_index ;
else
sub_c_index = Size ;
l_sub + + ;
}
else if ( sub_c_index > piv_c_index | | l_sub > = nb_var_sub )
{
int tmp_u_count = Get_u ( ) ;
Insert ( row , first_piv - > c_index , tmp_u_count , 0 ) ;
u [ tmp_u_count ] = - u [ first_piv - > u_index ] * first_elem ;
first_piv = first_piv - > NZE_R_N ;
if ( first_piv )
piv_c_index = first_piv - > c_index ;
else
piv_c_index = Size ;
l_piv + + ;
}
else
{
if ( i = = sub_c_index )
{
NonZeroElem * firsta = first ;
NonZeroElem * first_suba = first_sub - > NZE_R_N ;
Delete ( first_sub - > r_index , first_sub - > c_index ) ;
first = firsta - > NZE_C_N ;
first_sub = first_suba ;
if ( first_sub )
sub_c_index = first_sub - > c_index ;
else
sub_c_index = Size ;
l_sub + + ;
first_piv = first_piv - > NZE_R_N ;
if ( first_piv )
piv_c_index = first_piv - > c_index ;
else
piv_c_index = Size ;
l_piv + + ;
}
else
{
u [ first_sub - > u_index ] - = u [ first_piv - > u_index ] * first_elem ;
first_sub = first_sub - > NZE_R_N ;
if ( first_sub )
sub_c_index = first_sub - > c_index ;
else
sub_c_index = Size ;
l_sub + + ;
first_piv = first_piv - > NZE_R_N ;
if ( first_piv )
piv_c_index = first_piv - > c_index ;
else
piv_c_index = Size ;
l_piv + + ;
}
}
2010-09-24 12:52:58 +02:00
u [ b [ row ] ] - = u [ b [ pivj ] ] * first_elem ;
}
}
2012-02-17 10:59:39 +01:00
double slowc_lbx = slowc ;
2010-09-24 12:52:58 +02:00
for ( int i = 0 ; i < y_size ; i + + )
ya [ i + it_ * y_size ] = y [ i + it_ * y_size ] ;
2013-03-22 15:44:34 +01:00
2010-09-24 12:52:58 +02:00
slowc_save = slowc ;
2012-02-17 10:59:39 +01:00
simple_bksub ( it_ , Size , slowc_lbx ) ;
2022-07-05 12:12:08 +02:00
End_GE ( ) ;
2010-09-24 12:52:58 +02:00
mxFree ( piv_v ) ;
mxFree ( pivj_v ) ;
mxFree ( pivk_v ) ;
mxFree ( NR ) ;
mxFree ( bc ) ;
2012-03-06 11:03:13 +01:00
return false ;
2010-09-24 12:52:58 +02:00
}
void
2013-03-22 15:44:34 +01:00
dynSparseMatrix : : Solve_ByteCode_Symbolic_Sparse_GaussianElimination ( int Size , bool symbolic , int Block_number )
2010-09-24 12:52:58 +02:00
{
/*Triangularisation at each period of a block using a simple gaussian Elimination*/
2021-02-01 13:49:27 +01:00
int * save_op = nullptr , * save_opa = nullptr , * save_opaa = nullptr ;
2010-09-24 12:52:58 +02:00
long int nop = 0 , nopa = 0 ;
bool record = false ;
2021-02-09 15:55:36 +01:00
2010-09-24 12:52:58 +02:00
int pivj = 0 , pivk = 0 ;
int tbreak = 0 , last_period = periods ;
2021-02-09 15:55:36 +01:00
double * piv_v = static_cast < double * > ( mxMalloc ( Size * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( piv_v , __LINE__ , __FILE__ , __func__ , Size * sizeof ( double ) ) ;
2021-02-09 15:55:36 +01:00
int * pivj_v = static_cast < int * > ( mxMalloc ( Size * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivj_v , __LINE__ , __FILE__ , __func__ , Size * sizeof ( int ) ) ;
2021-02-09 15:55:36 +01:00
int * pivk_v = static_cast < int * > ( mxMalloc ( Size * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( pivk_v , __LINE__ , __FILE__ , __func__ , Size * sizeof ( int ) ) ;
2021-02-09 15:55:36 +01:00
int * NR = static_cast < int * > ( mxMalloc ( Size * sizeof ( int ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( NR , __LINE__ , __FILE__ , __func__ , Size * sizeof ( int ) ) ;
2021-02-09 15:55:36 +01:00
NonZeroElem * * bc = static_cast < NonZeroElem * * > ( mxMalloc ( Size * sizeof ( NonZeroElem * ) ) ) ;
test_mxMalloc ( bc , __LINE__ , __FILE__ , __func__ , Size * sizeof ( NonZeroElem * ) ) ;
2010-09-24 12:52:58 +02:00
for ( int t = 0 ; t < periods ; t + + )
{
2014-01-02 16:17:37 +01:00
# ifdef MATLAB_MEX_FILE
2017-05-16 16:30:27 +02:00
if ( utIsInterruptPending ( ) )
2022-07-29 12:42:50 +02:00
throw UserException { } ;
2013-03-22 15:44:34 +01:00
# endif
2010-09-24 12:52:58 +02:00
if ( record & & symbolic )
{
2019-04-23 12:58:38 +02:00
save_op = static_cast < int * > ( mxMalloc ( nop * sizeof ( int ) ) ) ;
2017-05-16 16:30:27 +02:00
test_mxMalloc ( save_op , __LINE__ , __FILE__ , __func__ , nop * sizeof ( int ) ) ;
2010-09-24 12:52:58 +02:00
nopa = nop ;
}
nop = 0 ;
Clear_u ( ) ;
int ti = t * Size ;
for ( int i = ti ; i < Size + ti ; i + + )
{
/*finding the max-pivot*/
2021-02-09 15:55:36 +01:00
double piv = 0 , piv_abs = 0 ;
NonZeroElem * first ;
2010-09-24 12:52:58 +02:00
int nb_eq = At_Col ( i , 0 , & first ) ;
if ( ( symbolic & & t < = start_compare ) | | ! symbolic )
{
int l = 0 , N_max = 0 ;
bool one = false ;
piv_abs = 0 ;
for ( int j = 0 ; j < nb_eq ; j + + )
{
if ( ! line_done [ first - > r_index ] )
{
int k = first - > u_index ;
int jj = first - > r_index ;
int NRow_jj = NRow ( jj ) ;
piv_v [ l ] = u [ k ] ;
double piv_fabs = fabs ( u [ k ] ) ;
pivj_v [ l ] = jj ;
pivk_v [ l ] = k ;
NR [ l ] = NRow_jj ;
if ( NRow_jj = = 1 & & ! one )
{
one = true ;
piv_abs = piv_fabs ;
N_max = NRow_jj ;
}
if ( ! one )
{
if ( piv_fabs > piv_abs )
piv_abs = piv_fabs ;
if ( NRow_jj > N_max )
N_max = NRow_jj ;
}
2021-02-09 15:55:36 +01:00
else if ( NRow_jj = = 1 )
2010-09-24 12:52:58 +02:00
{
2021-02-09 15:55:36 +01:00
if ( piv_fabs > piv_abs )
piv_abs = piv_fabs ;
if ( NRow_jj > N_max )
N_max = NRow_jj ;
2010-09-24 12:52:58 +02:00
}
l + + ;
}
first = first - > NZE_C_N ;
}
double markovitz = 0 , markovitz_max = - 9e70 ;
int NR_max = 0 ;
if ( ! one )
2021-02-09 15:55:36 +01:00
for ( int j = 0 ; j < l ; j + + )
{
if ( N_max > 0 & & NR [ j ] > 0 )
{
if ( fabs ( piv_v [ j ] ) > 0 )
{
if ( markowitz_c > 0 )
markovitz = exp ( log ( fabs ( piv_v [ j ] ) / piv_abs )
- markowitz_c * log ( static_cast < double > ( NR [ j ] )
/ static_cast < double > ( N_max ) ) ) ;
else
markovitz = fabs ( piv_v [ j ] ) / piv_abs ;
}
else
markovitz = 0 ;
}
else
markovitz = fabs ( piv_v [ j ] ) / piv_abs ;
if ( markovitz > markovitz_max )
{
piv = piv_v [ j ] ;
pivj = pivj_v [ j ] ; //Line number
pivk = pivk_v [ j ] ; //positi
markovitz_max = markovitz ;
NR_max = NR [ j ] ;
}
}
2010-09-24 12:52:58 +02:00
else
2021-02-09 15:55:36 +01:00
for ( int j = 0 ; j < l ; j + + )
{
if ( N_max > 0 & & NR [ j ] > 0 )
{
if ( fabs ( piv_v [ j ] ) > 0 )
{
if ( markowitz_c > 0 )
markovitz = exp ( log ( fabs ( piv_v [ j ] ) / piv_abs )
- markowitz_c * log ( static_cast < double > ( NR [ j ] )
/ static_cast < double > ( N_max ) ) ) ;
else
markovitz = fabs ( piv_v [ j ] ) / piv_abs ;
}
else
markovitz = 0 ;
}
else
markovitz = fabs ( piv_v [ j ] ) / piv_abs ;
if ( NR [ j ] = = 1 )
{
piv = piv_v [ j ] ;
pivj = pivj_v [ j ] ; //Line number
pivk = pivk_v [ j ] ; //positi
markovitz_max = markovitz ;
NR_max = NR [ j ] ;
}
}
2023-06-13 16:34:22 +02:00
if ( fabs ( piv ) < eps & & verbosity > = 1 )
2011-02-04 16:53:12 +01:00
mexPrintf ( " ==> Error NR_max=%d, N_max=%d and piv=%f, piv_abs=%f, markovitz_max=%f \n " , NR_max , N_max , piv , piv_abs , markovitz_max ) ;
2023-06-13 16:34:22 +02:00
if ( NR_max = = 0 & & verbosity > = 1 )
2011-02-04 16:53:12 +01:00
mexPrintf ( " ==> Error NR_max=0 and piv=%f, markovitz_max=%f \n " , piv , markovitz_max ) ;
2010-09-24 12:52:58 +02:00
pivot [ i ] = pivj ;
pivot_save [ i ] = pivj ;
pivotk [ i ] = pivk ;
pivotv [ i ] = piv ;
}
else
{
pivj = pivot [ i - Size ] + Size ;
pivot [ i ] = pivj ;
At_Pos ( pivj , i , & first ) ;
pivk = first - > u_index ;
piv = u [ pivk ] ;
piv_abs = fabs ( piv ) ;
}
line_done [ pivj ] = true ;
2013-03-22 15:44:34 +01:00
if ( record & & symbolic )
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
if ( nop + 1 > = nopa )
2010-09-24 12:52:58 +02:00
{
2021-02-09 15:55:36 +01:00
nopa = static_cast < long > ( mem_increasing_factor * static_cast < double > ( nopa ) ) ;
2019-04-23 12:58:38 +02:00
save_op = static_cast < int * > ( mxRealloc ( save_op , nopa * sizeof ( int ) ) ) ;
2010-09-24 12:52:58 +02:00
}
2021-02-09 15:55:36 +01:00
t_save_op_s * save_op_s = reinterpret_cast < t_save_op_s * > ( & save_op [ nop ] ) ;
2013-03-22 15:44:34 +01:00
save_op_s - > operat = IFLD ;
save_op_s - > first = pivk ;
save_op_s - > lag = 0 ;
2010-09-24 12:52:58 +02:00
nop + = 2 ;
2013-03-22 15:44:34 +01:00
if ( piv_abs < eps )
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
if ( Block_number > 1 )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve_ByteCode_Symbolic_Sparse_GaussianElimination, singular system in block "
+ to_string ( Block_number + 1 ) } ;
2013-03-22 15:44:34 +01:00
else
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve_ByteCode_Symbolic_Sparse_GaussianElimination, singular system " } ;
2010-09-24 12:52:58 +02:00
}
2013-03-22 15:44:34 +01:00
/*divide all the non zeros elements of the line pivj by the max_pivot*/
int nb_var = At_Row ( pivj , & first ) ;
for ( int j = 0 ; j < nb_var ; j + + )
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
u [ first - > u_index ] / = piv ;
if ( nop + j * 2 + 1 > = nopa )
2010-09-24 12:52:58 +02:00
{
2019-04-23 12:58:38 +02:00
nopa = static_cast < long > ( mem_increasing_factor * static_cast < double > ( nopa ) ) ;
save_op = static_cast < int * > ( mxRealloc ( save_op , nopa * sizeof ( int ) ) ) ;
2010-09-24 12:52:58 +02:00
}
2021-02-09 15:55:36 +01:00
save_op_s = reinterpret_cast < t_save_op_s * > ( & save_op [ nop + j * 2 ] ) ;
2010-09-24 12:52:58 +02:00
save_op_s - > operat = IFDIV ;
2013-03-22 15:44:34 +01:00
save_op_s - > first = first - > u_index ;
save_op_s - > lag = first - > lag_index ;
first = first - > NZE_R_N ;
}
nop + = nb_var * 2 ;
u [ b [ pivj ] ] / = piv ;
if ( nop + 1 > = nopa )
{
2019-04-23 12:58:38 +02:00
nopa = static_cast < long > ( mem_increasing_factor * static_cast < double > ( nopa ) ) ;
save_op = static_cast < int * > ( mxRealloc ( save_op , nopa * sizeof ( int ) ) ) ;
2010-09-24 12:52:58 +02:00
}
2021-02-09 15:55:36 +01:00
save_op_s = reinterpret_cast < t_save_op_s * > ( & save_op [ nop ] ) ;
2013-03-22 15:44:34 +01:00
save_op_s - > operat = IFDIV ;
save_op_s - > first = b [ pivj ] ;
save_op_s - > lag = 0 ;
2010-09-24 12:52:58 +02:00
nop + = 2 ;
2022-02-28 12:25:11 +01:00
// Subtract the elements on the non treated lines
2013-03-22 15:44:34 +01:00
nb_eq = At_Col ( i , & first ) ;
NonZeroElem * first_piva ;
int nb_var_piva = At_Row ( pivj , & first_piva ) ;
2010-09-24 12:52:58 +02:00
2013-03-22 15:44:34 +01:00
int nb_eq_todo = 0 ;
for ( int j = 0 ; j < nb_eq & & first ; j + + )
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
if ( ! line_done [ first - > r_index ] )
bc [ nb_eq_todo + + ] = first ;
first = first - > NZE_C_N ;
2010-09-24 12:52:58 +02:00
}
2013-03-22 15:44:34 +01:00
for ( int j = 0 ; j < nb_eq_todo ; j + + )
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
t_save_op_s * save_op_s_l ;
NonZeroElem * first = bc [ j ] ;
int row = first - > r_index ;
double first_elem = u [ first - > u_index ] ;
if ( nop + 1 > = nopa )
2010-09-24 12:52:58 +02:00
{
2019-04-23 12:58:38 +02:00
nopa = static_cast < long > ( mem_increasing_factor * static_cast < double > ( nopa ) ) ;
save_op = static_cast < int * > ( mxRealloc ( save_op , nopa * sizeof ( int ) ) ) ;
2010-09-24 12:52:58 +02:00
}
2021-02-09 15:55:36 +01:00
save_op_s_l = reinterpret_cast < t_save_op_s * > ( & save_op [ nop ] ) ;
2013-03-22 15:44:34 +01:00
save_op_s_l - > operat = IFLD ;
save_op_s_l - > first = first - > u_index ;
save_op_s_l - > lag = abs ( first - > lag_index ) ;
nop + = 2 ;
int nb_var_piv = nb_var_piva ;
NonZeroElem * first_piv = first_piva ;
NonZeroElem * first_sub ;
int nb_var_sub = At_Row ( row , & first_sub ) ;
int l_sub = 0 ;
int l_piv = 0 ;
int sub_c_index = first_sub - > c_index ;
int piv_c_index = first_piv - > c_index ;
int tmp_lag = first_sub - > lag_index ;
2021-02-09 15:55:36 +01:00
while ( l_sub < nb_var_sub /*=NRow(row)*/ | | l_piv < nb_var_piv )
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
if ( l_sub < nb_var_sub & & ( sub_c_index < piv_c_index | | l_piv > = nb_var_piv ) )
2010-09-24 12:52:58 +02:00
{
2021-02-09 15:55:36 +01:00
/* There is no nonzero element at row pivot for this
column ⇒ Nothing to do for the current element got to
next column */
2013-03-22 15:44:34 +01:00
first_sub = first_sub - > NZE_R_N ;
2010-09-24 12:52:58 +02:00
if ( first_sub )
sub_c_index = first_sub - > c_index ;
else
sub_c_index = Size * periods ;
l_sub + + ;
2013-03-22 15:44:34 +01:00
}
else if ( sub_c_index > piv_c_index | | l_sub > = nb_var_sub )
{
// There is an nonzero element at row pivot but not at the current row=> insert a negative element in the current row
2021-02-09 15:55:36 +01:00
int tmp_u_count = Get_u ( ) ;
int lag = first_piv - > c_index / Size - row / Size ;
Insert ( row , first_piv - > c_index , tmp_u_count , lag ) ;
2013-03-22 15:44:34 +01:00
u [ tmp_u_count ] = - u [ first_piv - > u_index ] * first_elem ;
if ( nop + 2 > = nopa )
{
2019-04-23 12:58:38 +02:00
nopa = static_cast < long > ( mem_increasing_factor * static_cast < double > ( nopa ) ) ;
save_op = static_cast < int * > ( mxRealloc ( save_op , nopa * sizeof ( int ) ) ) ;
2013-03-22 15:44:34 +01:00
}
2021-02-09 15:55:36 +01:00
save_op_s_l = reinterpret_cast < t_save_op_s * > ( & save_op [ nop ] ) ;
2013-03-22 15:44:34 +01:00
save_op_s_l - > operat = IFLESS ;
save_op_s_l - > first = tmp_u_count ;
save_op_s_l - > second = first_piv - > u_index ;
save_op_s_l - > lag = max ( first_piv - > lag_index , abs ( tmp_lag ) ) ;
nop + = 3 ;
2010-09-24 12:52:58 +02:00
first_piv = first_piv - > NZE_R_N ;
if ( first_piv )
piv_c_index = first_piv - > c_index ;
else
piv_c_index = Size * periods ;
l_piv + + ;
}
2013-03-22 15:44:34 +01:00
else /*first_sub->c_index==first_piv->c_index*/
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
if ( i = = sub_c_index )
{
NonZeroElem * firsta = first ;
NonZeroElem * first_suba = first_sub - > NZE_R_N ;
2021-02-09 15:55:36 +01:00
Delete ( first_sub - > r_index , first_sub - > c_index ) ;
2013-03-22 15:44:34 +01:00
first = firsta - > NZE_C_N ;
first_sub = first_suba ;
if ( first_sub )
sub_c_index = first_sub - > c_index ;
else
sub_c_index = Size * periods ;
l_sub + + ;
first_piv = first_piv - > NZE_R_N ;
if ( first_piv )
piv_c_index = first_piv - > c_index ;
else
piv_c_index = Size * periods ;
l_piv + + ;
}
else
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
u [ first_sub - > u_index ] - = u [ first_piv - > u_index ] * first_elem ;
if ( nop + 3 > = nopa )
2010-09-24 12:52:58 +02:00
{
2019-04-23 12:58:38 +02:00
nopa = static_cast < long > ( mem_increasing_factor * static_cast < double > ( nopa ) ) ;
save_op = static_cast < int * > ( mxRealloc ( save_op , nopa * sizeof ( int ) ) ) ;
2010-09-24 12:52:58 +02:00
}
2021-02-09 15:55:36 +01:00
save_op_s_l = reinterpret_cast < t_save_op_s * > ( & save_op [ nop ] ) ;
2013-03-22 15:44:34 +01:00
save_op_s_l - > operat = IFSUB ;
save_op_s_l - > first = first_sub - > u_index ;
save_op_s_l - > second = first_piv - > u_index ;
save_op_s_l - > lag = max ( abs ( tmp_lag ) , first_piv - > lag_index ) ;
2010-09-24 12:52:58 +02:00
nop + = 3 ;
2013-03-22 15:44:34 +01:00
first_sub = first_sub - > NZE_R_N ;
if ( first_sub )
sub_c_index = first_sub - > c_index ;
else
sub_c_index = Size * periods ;
l_sub + + ;
first_piv = first_piv - > NZE_R_N ;
if ( first_piv )
piv_c_index = first_piv - > c_index ;
else
piv_c_index = Size * periods ;
l_piv + + ;
2010-09-24 12:52:58 +02:00
}
2013-03-22 15:44:34 +01:00
}
}
u [ b [ row ] ] - = u [ b [ pivj ] ] * first_elem ;
if ( nop + 3 > = nopa )
{
2019-04-23 12:58:38 +02:00
nopa = static_cast < long > ( mem_increasing_factor * static_cast < double > ( nopa ) ) ;
save_op = static_cast < int * > ( mxRealloc ( save_op , nopa * sizeof ( int ) ) ) ;
2013-03-22 15:44:34 +01:00
}
2021-02-09 15:55:36 +01:00
save_op_s_l = reinterpret_cast < t_save_op_s * > ( & save_op [ nop ] ) ;
2013-03-22 15:44:34 +01:00
save_op_s_l - > operat = IFSUB ;
save_op_s_l - > first = b [ row ] ;
save_op_s_l - > second = b [ pivj ] ;
save_op_s_l - > lag = abs ( tmp_lag ) ;
nop + = 3 ;
}
}
2017-05-16 16:30:27 +02:00
else if ( symbolic )
2013-03-22 15:44:34 +01:00
{
nop + = 2 ;
if ( piv_abs < eps )
{
if ( Block_number > 1 )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve_ByteCode_Symbolic_Sparse_GaussianElimination, singular system in block "
+ to_string ( Block_number + 1 ) } ;
2013-03-22 15:44:34 +01:00
else
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve_ByteCode_Symbolic_Sparse_GaussianElimination, singular system " } ;
2013-03-22 15:44:34 +01:00
}
2021-02-09 15:55:36 +01:00
// Divide all the non zeros elements of the line pivj by the max_pivot
2013-03-22 15:44:34 +01:00
int nb_var = At_Row ( pivj , & first ) ;
for ( int j = 0 ; j < nb_var ; j + + )
{
u [ first - > u_index ] / = piv ;
first = first - > NZE_R_N ;
}
nop + = nb_var * 2 ;
u [ b [ pivj ] ] / = piv ;
nop + = 2 ;
2022-02-28 12:25:11 +01:00
// Subtract the elements on the non treated lines
2013-03-22 15:44:34 +01:00
nb_eq = At_Col ( i , & first ) ;
NonZeroElem * first_piva ;
int nb_var_piva = At_Row ( pivj , & first_piva ) ;
int nb_eq_todo = 0 ;
for ( int j = 0 ; j < nb_eq & & first ; j + + )
{
if ( ! line_done [ first - > r_index ] )
bc [ nb_eq_todo + + ] = first ;
first = first - > NZE_C_N ;
}
for ( int j = 0 ; j < nb_eq_todo ; j + + )
{
NonZeroElem * first = bc [ j ] ;
int row = first - > r_index ;
double first_elem = u [ first - > u_index ] ;
nop + = 2 ;
int nb_var_piv = nb_var_piva ;
NonZeroElem * first_piv = first_piva ;
NonZeroElem * first_sub ;
int nb_var_sub = At_Row ( row , & first_sub ) ;
int l_sub = 0 ;
int l_piv = 0 ;
int sub_c_index = first_sub - > c_index ;
int piv_c_index = first_piv - > c_index ;
2021-02-09 15:55:36 +01:00
while ( l_sub < nb_var_sub /*= NRow(row)*/ | | l_piv < nb_var_piv )
2013-03-22 15:44:34 +01:00
{
if ( l_sub < nb_var_sub & & ( sub_c_index < piv_c_index | | l_piv > = nb_var_piv ) )
{
2021-02-09 15:55:36 +01:00
/* There is no nonzero element at row pivot for this
column ⇒ Nothing to do for the current element got to
next column */
2010-09-24 12:52:58 +02:00
first_sub = first_sub - > NZE_R_N ;
if ( first_sub )
sub_c_index = first_sub - > c_index ;
else
sub_c_index = Size * periods ;
l_sub + + ;
2013-03-22 15:44:34 +01:00
}
else if ( sub_c_index > piv_c_index | | l_sub > = nb_var_sub )
{
2021-02-09 15:55:36 +01:00
/* There is an nonzero element at row pivot but not
at the current row ⇒ insert a negative element in the
current row */
int tmp_u_count = Get_u ( ) ;
int lag = first_piv - > c_index / Size - row / Size ;
Insert ( row , first_piv - > c_index , tmp_u_count , lag ) ;
2013-03-22 15:44:34 +01:00
u [ tmp_u_count ] = - u [ first_piv - > u_index ] * first_elem ;
nop + = 3 ;
2010-09-24 12:52:58 +02:00
first_piv = first_piv - > NZE_R_N ;
if ( first_piv )
piv_c_index = first_piv - > c_index ;
else
piv_c_index = Size * periods ;
l_piv + + ;
}
2013-03-22 15:44:34 +01:00
else /*first_sub->c_index==first_piv->c_index*/
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
if ( i = = sub_c_index )
{
NonZeroElem * firsta = first ;
NonZeroElem * first_suba = first_sub - > NZE_R_N ;
2021-02-09 15:55:36 +01:00
Delete ( first_sub - > r_index , first_sub - > c_index ) ;
2013-03-22 15:44:34 +01:00
first = firsta - > NZE_C_N ;
first_sub = first_suba ;
if ( first_sub )
sub_c_index = first_sub - > c_index ;
else
sub_c_index = Size * periods ;
l_sub + + ;
first_piv = first_piv - > NZE_R_N ;
if ( first_piv )
piv_c_index = first_piv - > c_index ;
else
piv_c_index = Size * periods ;
l_piv + + ;
}
else
{
u [ first_sub - > u_index ] - = u [ first_piv - > u_index ] * first_elem ;
nop + = 3 ;
first_sub = first_sub - > NZE_R_N ;
if ( first_sub )
sub_c_index = first_sub - > c_index ;
else
sub_c_index = Size * periods ;
l_sub + + ;
first_piv = first_piv - > NZE_R_N ;
if ( first_piv )
piv_c_index = first_piv - > c_index ;
else
piv_c_index = Size * periods ;
l_piv + + ;
}
2010-09-24 12:52:58 +02:00
}
}
2013-03-22 15:44:34 +01:00
u [ b [ row ] ] - = u [ b [ pivj ] ] * first_elem ;
2010-09-24 12:52:58 +02:00
nop + = 3 ;
}
}
}
if ( symbolic )
{
2021-02-03 18:10:01 +01:00
if ( t > static_cast < int > ( periods * 0.35 ) )
2012-11-06 14:38:51 +01:00
{
symbolic = false ;
2012-11-05 11:29:25 +01:00
mxFree ( save_opaa ) ;
2012-11-06 14:38:51 +01:00
mxFree ( save_opa ) ;
mxFree ( save_op ) ;
}
2021-02-09 15:55:36 +01:00
else if ( record & & nop = = nop1 )
2010-09-24 12:52:58 +02:00
{
2021-02-03 18:10:01 +01:00
if ( t > static_cast < int > ( periods * 0.35 ) )
2013-03-22 15:44:34 +01:00
{
symbolic = false ;
if ( save_opaa )
{
mxFree ( save_opaa ) ;
2021-02-01 13:49:27 +01:00
save_opaa = nullptr ;
2013-03-22 15:44:34 +01:00
}
if ( save_opa )
{
mxFree ( save_opa ) ;
2021-02-01 13:49:27 +01:00
save_opa = nullptr ;
2013-03-22 15:44:34 +01:00
}
if ( save_op )
{
mxFree ( save_op ) ;
2021-02-01 13:49:27 +01:00
save_op = nullptr ;
2013-03-22 15:44:34 +01:00
}
}
else if ( save_opa & & save_opaa )
2010-09-24 12:52:58 +02:00
{
if ( compare ( save_op , save_opa , save_opaa , t , periods , nop , Size ) )
{
tbreak = t ;
tbreak_g = tbreak ;
break ;
}
}
if ( save_opa )
{
if ( save_opaa )
{
mxFree ( save_opaa ) ;
2021-02-01 13:49:27 +01:00
save_opaa = nullptr ;
2010-09-24 12:52:58 +02:00
}
2013-03-22 15:44:34 +01:00
save_opaa = save_opa ;
2010-09-24 12:52:58 +02:00
}
2013-03-22 15:44:34 +01:00
save_opa = save_op ;
2010-09-24 12:52:58 +02:00
}
else
{
if ( nop = = nop1 )
record = true ;
else
{
record = false ;
if ( save_opa )
{
mxFree ( save_opa ) ;
2021-02-01 13:49:27 +01:00
save_opa = nullptr ;
2010-09-24 12:52:58 +02:00
}
if ( save_opaa )
{
mxFree ( save_opaa ) ;
2021-02-01 13:49:27 +01:00
save_opaa = nullptr ;
2010-09-24 12:52:58 +02:00
}
}
}
nop2 = nop1 ;
nop1 = nop ;
}
}
2013-03-22 15:44:34 +01:00
mxFree ( bc ) ;
2010-09-24 12:52:58 +02:00
mxFree ( piv_v ) ;
mxFree ( pivj_v ) ;
mxFree ( pivk_v ) ;
mxFree ( NR ) ;
nop_all + = nop ;
if ( symbolic )
{
if ( save_op )
mxFree ( save_op ) ;
if ( save_opa )
mxFree ( save_opa ) ;
if ( save_opaa )
mxFree ( save_opaa ) ;
}
2021-02-09 15:55:36 +01:00
// The backward substitution
2012-02-17 10:59:39 +01:00
double slowc_lbx = slowc ;
2010-09-24 12:52:58 +02:00
for ( int i = 0 ; i < y_size * ( periods + y_kmin ) ; i + + )
ya [ i ] = y [ i ] ;
slowc_save = slowc ;
2012-02-17 10:59:39 +01:00
bksub ( tbreak , last_period , Size , slowc_lbx ) ;
2022-07-05 12:12:08 +02:00
End_GE ( ) ;
2010-09-24 12:52:58 +02:00
}
2013-03-22 15:44:34 +01:00
void
2022-07-05 12:12:08 +02:00
dynSparseMatrix : : Check_and_Correct_Previous_Iteration ( int y_size , int size )
2013-03-22 15:44:34 +01:00
{
if ( isnan ( res1 ) | | isinf ( res1 ) | | ( res2 > g0 & & iter > 0 ) )
{
2021-02-09 15:55:36 +01:00
while ( isnan ( res1 ) | | isinf ( res1 ) )
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
prev_slowc_save = slowc_save ;
slowc_save / = 1.1 ;
for ( int i = 0 ; i < size ; i + + )
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
int eq = index_vara [ i ] ;
y [ eq + it_ * y_size ] = ya [ eq + it_ * y_size ] + slowc_save * direction [ eq + it_ * y_size ] ;
2010-09-24 12:52:58 +02:00
}
2017-05-16 16:30:27 +02:00
compute_complete ( true , res1 , res2 , max_res , max_res_idx ) ;
2013-03-22 15:44:34 +01:00
}
while ( res2 > g0 & & slowc_save > 1e-1 )
{
prev_slowc_save = slowc_save ;
slowc_save / = 1.5 ;
for ( int i = 0 ; i < size ; i + + )
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
int eq = index_vara [ i ] ;
y [ eq + it_ * y_size ] = ya [ eq + it_ * y_size ] + slowc_save * direction [ eq + it_ * y_size ] ;
2010-09-24 12:52:58 +02:00
}
2013-03-22 15:44:34 +01:00
compute_complete ( true , res1 , res2 , max_res , max_res_idx ) ;
2010-09-24 12:52:58 +02:00
}
2023-06-13 16:34:22 +02:00
if ( verbosity > = 2 )
mexPrintf ( " Error: Simulation diverging, trying to correct it using slowc=%f \n " , slowc_save ) ;
2013-03-22 15:44:34 +01:00
for ( int i = 0 ; i < size ; i + + )
{
int eq = index_vara [ i ] ;
y [ eq + it_ * y_size ] = ya [ eq + it_ * y_size ] + slowc_save * direction [ eq + it_ * y_size ] ;
}
compute_complete ( false , res1 , res2 , max_res , max_res_idx ) ;
2010-09-24 12:52:58 +02:00
}
2013-03-22 15:44:34 +01:00
else
2021-02-09 15:55:36 +01:00
for ( int i = 0 ; i < size ; i + + )
{
int eq = index_vara [ i ] ;
y [ eq + it_ * y_size ] = ya [ eq + it_ * y_size ] + slowc_save * direction [ eq + it_ * y_size ] ;
}
2013-03-22 15:44:34 +01:00
slowc_save = slowc ;
}
bool
2022-07-05 12:12:08 +02:00
dynSparseMatrix : : Simulate_One_Boundary ( int block_num , int y_size , int size )
2013-03-22 15:44:34 +01:00
{
2021-02-01 13:49:27 +01:00
mxArray * b_m = nullptr , * A_m = nullptr , * x0_m = nullptr ;
SuiteSparse_long * Ap = nullptr , * Ai = nullptr ;
double * Ax = nullptr , * b = nullptr ;
2013-06-08 17:16:20 +02:00
int preconditioner = 1 ;
2013-03-22 15:44:34 +01:00
try_at_iteration = 0 ;
Clear_u ( ) ;
bool singular_system = false ;
u_count_alloc_save = u_count_alloc ;
if ( isnan ( res1 ) | | isinf ( res1 ) )
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
# ifdef DEBUG
for ( int j = 0 ; j < y_size ; j + + )
{
bool select = false ;
for ( int i = 0 ; i < size ; i + + )
if ( j = = index_vara [ i ] )
{
select = true ;
break ;
}
if ( select )
2020-05-12 23:08:04 +02:00
mexPrintf ( " -> variable %s (%d) at time %d = %f direction = %f \n " , get_variable ( SymbolType : : endogenous , j ) . c_str ( ) , j + 1 , it_ , y [ j + it_ * y_size ] , direction [ j + it_ * y_size ] ) ;
2013-03-22 15:44:34 +01:00
else
2020-05-12 23:08:04 +02:00
mexPrintf ( " variable %s (%d) at time %d = %f direction = %f \n " , get_variable ( SymbolType : : endogenous , j ) . c_str ( ) , j + 1 , it_ , y [ j + it_ * y_size ] , direction [ j + it_ * y_size ] ) ;
2013-03-22 15:44:34 +01:00
}
# endif
if ( steady_state )
{
2023-06-13 16:34:22 +02:00
if ( verbosity > = 1 )
{
if ( iter = = 0 )
mexPrintf ( " the initial values of endogenous variables are too far from the solution. \n Change them! \n " ) ;
else
mexPrintf ( " dynare cannot improve the simulation in block %d at time %d (variable %d) \n " , block_num + 1 , it_ + 1 , index_vara [ max_res_idx ] + 1 ) ;
mexEvalString ( " drawnow; " ) ;
}
2013-03-22 15:44:34 +01:00
}
else
{
if ( iter = = 0 )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Simulate_One_Boundary, The initial values of endogenous variables are too far from the solution. Change them! " } ;
2013-03-22 15:44:34 +01:00
else
2022-07-29 12:42:50 +02:00
throw FatalException { " In Simulate_One_Boundary, Dynare cannot improve the simulation in block "
+ to_string ( block_num + 1 ) + " at time " + to_string ( it_ + 1 )
+ " (variable " + to_string ( index_vara [ max_res_idx ] + 1 ) } ;
2013-03-22 15:44:34 +01:00
}
2010-09-24 12:52:58 +02:00
}
2022-02-17 17:00:53 +01:00
2023-06-13 16:34:22 +02:00
if ( verbosity > = 1 )
2010-09-24 12:52:58 +02:00
{
2010-10-18 17:28:21 +02:00
if ( steady_state )
{
switch ( solve_algo )
{
2011-02-04 16:53:12 +01:00
case 5 :
2023-06-13 16:55:37 +02:00
mexPrintf ( " MODEL STEADY STATE: (method=Sparse Gaussian Elimination) \n " ) ;
2011-02-04 16:53:12 +01:00
break ;
case 6 :
2023-06-13 16:55:37 +02:00
mexPrintf ( " MODEL STEADY STATE: (method=Sparse LU) \n " ) ;
2011-02-04 16:53:12 +01:00
break ;
case 7 :
2017-05-16 16:30:27 +02:00
mexPrintf ( preconditioner_print_out ( " MODEL STEADY STATE: (method=GMRES) \n " , preconditioner , true ) . c_str ( ) ) ;
2011-02-04 16:53:12 +01:00
break ;
case 8 :
2013-06-08 17:16:20 +02:00
mexPrintf ( preconditioner_print_out ( " MODEL STEADY STATE: (method=BiCGStab) \n " , preconditioner , true ) . c_str ( ) ) ;
2011-02-04 16:53:12 +01:00
break ;
2010-10-18 17:28:21 +02:00
}
}
2023-06-12 15:11:15 +02:00
mexPrintf ( " ------------------------------------ \n " ) ;
2023-06-13 16:55:37 +02:00
mexPrintf ( " Iteration no. %d \n " , iter + 1 ) ;
2023-06-12 15:11:15 +02:00
mexPrintf ( " Inf-norm error = %.3e \n " , static_cast < double > ( max_res ) ) ;
mexPrintf ( " 2-norm error = %.3e \n " , static_cast < double > ( sqrt ( res2 ) ) ) ;
mexPrintf ( " 1-norm error = %.3e \n " , static_cast < double > ( res1 ) ) ;
mexPrintf ( " ------------------------------------ \n " ) ;
2010-09-24 12:52:58 +02:00
}
2010-10-18 17:28:21 +02:00
bool zero_solution ;
2013-03-22 15:44:34 +01:00
2010-10-22 16:49:47 +02:00
if ( ( solve_algo = = 5 & & steady_state ) | | ( stack_solve_algo = = 5 & & ! steady_state ) )
2013-03-22 15:44:34 +01:00
Simple_Init ( size , IM_i , zero_solution ) ;
2010-09-24 12:52:58 +02:00
else
{
2013-03-22 15:44:34 +01:00
x0_m = mxCreateDoubleMatrix ( size , 1 , mxREAL ) ;
2011-01-03 14:15:12 +01:00
if ( ! x0_m )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Simulate_One_Boundary, can't allocate x0_m vector " } ;
2021-02-09 15:55:36 +01:00
if ( ! ( ( solve_algo = = 6 & & steady_state )
2022-06-15 14:46:44 +02:00
| | ( ( stack_solve_algo = = 0 | | stack_solve_algo = = 1 | | stack_solve_algo = = 4
| | stack_solve_algo = = 6 ) & & ! steady_state ) ) )
2013-03-22 15:44:34 +01:00
{
2023-03-31 18:44:24 +02:00
b_m = mxCreateDoubleMatrix ( size , 1 , mxREAL ) ;
if ( ! b_m )
throw FatalException { " In Simulate_One_Boundary, can't allocate b_m vector " } ;
A_m = mxCreateSparse ( size , size , min ( static_cast < int > ( IM_i . size ( ) * 2 ) , size * size ) , mxREAL ) ;
if ( ! A_m )
throw FatalException { " In Simulate_One_Boundary, can't allocate A_m matrix " } ;
2013-03-22 15:44:34 +01:00
Init_Matlab_Sparse_Simple ( size , IM_i , A_m , b_m , zero_solution , x0_m ) ;
A_m_save = mxDuplicateArray ( A_m ) ;
b_m_save = mxDuplicateArray ( b_m ) ;
}
else
{
Init_UMFPACK_Sparse_Simple ( size , IM_i , & Ap , & Ai , & Ax , & b , zero_solution , x0_m ) ;
if ( Ap_save [ size ] ! = Ap [ size ] )
{
mxFree ( Ai_save ) ;
mxFree ( Ax_save ) ;
2019-04-23 12:58:38 +02:00
Ai_save = static_cast < SuiteSparse_long * > ( mxMalloc ( Ap [ size ] * sizeof ( SuiteSparse_long ) ) ) ;
2017-05-16 16:30:27 +02:00
test_mxMalloc ( Ai_save , __LINE__ , __FILE__ , __func__ , Ap [ size ] * sizeof ( SuiteSparse_long ) ) ;
2019-04-23 12:58:38 +02:00
Ax_save = static_cast < double * > ( mxMalloc ( Ap [ size ] * sizeof ( double ) ) ) ;
2017-05-16 16:30:27 +02:00
test_mxMalloc ( Ax_save , __LINE__ , __FILE__ , __func__ , Ap [ size ] * sizeof ( double ) ) ;
2013-03-22 15:44:34 +01:00
}
2021-02-09 15:55:36 +01:00
copy_n ( Ap , size + 1 , Ap_save ) ;
copy_n ( Ai , Ap [ size ] , Ai_save ) ;
copy_n ( Ax , Ap [ size ] , Ax_save ) ;
copy_n ( b , size , b_save ) ;
2013-03-22 15:44:34 +01:00
}
2010-10-18 17:28:21 +02:00
}
if ( zero_solution )
2021-02-09 15:55:36 +01:00
for ( int i = 0 ; i < size ; i + + )
{
int eq = index_vara [ i ] ;
double yy = - ( y [ eq + it_ * y_size ] ) ;
direction [ eq ] = yy ;
y [ eq + it_ * y_size ] + = slowc * yy ;
}
2010-10-18 17:28:21 +02:00
else
{
2010-10-22 16:49:47 +02:00
if ( ( solve_algo = = 5 & & steady_state ) | | ( stack_solve_algo = = 5 & & ! steady_state ) )
2013-03-22 15:44:34 +01:00
singular_system = Solve_ByteCode_Sparse_GaussianElimination ( size , block_num , it_ ) ;
2010-10-22 16:49:47 +02:00
else if ( ( solve_algo = = 7 & & steady_state ) | | ( stack_solve_algo = = 2 & & ! steady_state ) )
2013-03-22 15:44:34 +01:00
Solve_Matlab_GMRES ( A_m , b_m , size , slowc , block_num , false , it_ , x0_m ) ;
2010-10-22 16:49:47 +02:00
else if ( ( solve_algo = = 8 & & steady_state ) | | ( stack_solve_algo = = 3 & & ! steady_state ) )
2013-06-08 17:16:20 +02:00
Solve_Matlab_BiCGStab ( A_m , b_m , size , slowc , block_num , false , it_ , x0_m , preconditioner ) ;
2022-06-15 14:46:44 +02:00
else if ( ( solve_algo = = 6 & & steady_state ) | | ( ( stack_solve_algo = = 0 | | stack_solve_algo = = 1 | | stack_solve_algo = = 4 | | stack_solve_algo = = 6 ) & & ! steady_state ) )
2023-03-31 18:44:24 +02:00
{
Solve_LU_UMFPack ( Ap , Ai , Ax , b , size , size , slowc , false , it_ ) ;
mxDestroyArray ( x0_m ) ;
}
2010-09-24 12:52:58 +02:00
}
2012-03-06 11:03:13 +01:00
return singular_system ;
2010-09-24 12:52:58 +02:00
}
2013-03-22 15:44:34 +01:00
bool
2022-07-05 12:12:08 +02:00
dynSparseMatrix : : solve_linear ( int block_num , int y_size , int size , int iter )
2013-03-22 15:44:34 +01:00
{
bool cvg = false ;
compute_complete ( false , res1 , res2 , max_res , max_res_idx ) ;
cvg = ( max_res < solve_tolf ) ;
if ( ! cvg | | isnan ( res1 ) | | isinf ( res1 ) )
{
if ( iter )
2022-07-05 12:12:08 +02:00
Check_and_Correct_Previous_Iteration ( y_size , size ) ;
bool singular_system = Simulate_One_Boundary ( block_num , y_size , size ) ;
2023-06-13 16:34:22 +02:00
if ( singular_system & & verbosity > = 1 )
2013-03-22 15:44:34 +01:00
Singular_display ( block_num , size ) ;
}
return cvg ;
}
void
2022-07-05 12:12:08 +02:00
dynSparseMatrix : : solve_non_linear ( int block_num , int y_size , int size )
2013-03-22 15:44:34 +01:00
{
max_res_idx = 0 ;
bool cvg = false ;
iter = 0 ;
glambda2 = g0 = very_big ;
2021-02-09 15:55:36 +01:00
while ( ! cvg & & iter < maxit_ )
2013-03-22 15:44:34 +01:00
{
2022-07-05 12:12:08 +02:00
cvg = solve_linear ( block_num , y_size , size , iter ) ;
2013-03-22 15:44:34 +01:00
g0 = res2 ;
iter + + ;
}
if ( ! cvg )
{
if ( steady_state )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve Forward/Backward Complete, convergence not achieved in block "
+ to_string ( block_num + 1 ) + " , after " + to_string ( iter )
+ " iterations " } ;
2013-03-22 15:44:34 +01:00
else
2022-07-29 12:42:50 +02:00
throw FatalException { " In Solve Forward/Backward Complete, convergence not achieved in block "
+ to_string ( block_num + 1 ) + " , at time " + to_string ( it_ )
+ " , after " + to_string ( iter ) + " iterations " } ;
2013-03-22 15:44:34 +01:00
}
}
void
2021-02-09 15:55:36 +01:00
dynSparseMatrix : : Simulate_Newton_One_Boundary ( bool forward )
2013-03-22 15:44:34 +01:00
{
2019-04-23 12:58:38 +02:00
g1 = static_cast < double * > ( mxMalloc ( size * size * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( g1 , __LINE__ , __FILE__ , __func__ , size * size * sizeof ( double ) ) ;
2019-04-23 12:58:38 +02:00
r = static_cast < double * > ( mxMalloc ( size * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( r , __LINE__ , __FILE__ , __func__ , size * sizeof ( double ) ) ;
2013-03-22 15:44:34 +01:00
iter = 0 ;
2021-02-09 15:55:36 +01:00
if ( ( solve_algo = = 6 & & steady_state )
2022-06-15 14:46:44 +02:00
| | ( ( stack_solve_algo = = 0 | | stack_solve_algo = = 1 | | stack_solve_algo = = 4 | | stack_solve_algo = = 6 ) & & ! steady_state ) )
2013-03-22 15:44:34 +01:00
{
2019-04-23 12:58:38 +02:00
Ap_save = static_cast < SuiteSparse_long * > ( mxMalloc ( ( size + 1 ) * sizeof ( SuiteSparse_long ) ) ) ;
2017-05-16 16:30:27 +02:00
test_mxMalloc ( Ap_save , __LINE__ , __FILE__ , __func__ , ( size + 1 ) * sizeof ( SuiteSparse_long ) ) ;
2013-03-22 15:44:34 +01:00
Ap_save [ size ] = 0 ;
2019-04-23 12:58:38 +02:00
Ai_save = static_cast < SuiteSparse_long * > ( mxMalloc ( 1 * sizeof ( SuiteSparse_long ) ) ) ;
2017-05-16 16:30:27 +02:00
test_mxMalloc ( Ai_save , __LINE__ , __FILE__ , __func__ , 1 * sizeof ( SuiteSparse_long ) ) ;
2019-04-23 12:58:38 +02:00
Ax_save = static_cast < double * > ( mxMalloc ( 1 * sizeof ( double ) ) ) ;
2017-05-16 16:30:27 +02:00
test_mxMalloc ( Ax_save , __LINE__ , __FILE__ , __func__ , 1 * sizeof ( double ) ) ;
2019-04-23 12:58:38 +02:00
b_save = static_cast < double * > ( mxMalloc ( ( size ) * sizeof ( SuiteSparse_long ) ) ) ;
2017-05-16 16:30:27 +02:00
test_mxMalloc ( b_save , __LINE__ , __FILE__ , __func__ , ( size ) * sizeof ( SuiteSparse_long ) ) ;
2013-03-22 15:44:34 +01:00
}
if ( steady_state )
{
it_ = 0 ;
if ( ! is_linear )
2022-07-05 12:12:08 +02:00
solve_non_linear ( block_num , y_size , size ) ;
2013-03-22 15:44:34 +01:00
else
2022-07-05 12:12:08 +02:00
solve_linear ( block_num , y_size , size , 0 ) ;
2013-03-22 15:44:34 +01:00
}
else if ( forward )
{
if ( ! is_linear )
2021-02-09 15:55:36 +01:00
for ( it_ = y_kmin ; it_ < periods + y_kmin ; it_ + + )
2022-07-05 12:12:08 +02:00
solve_non_linear ( block_num , y_size , size ) ;
2013-03-22 15:44:34 +01:00
else
2022-02-15 13:06:59 +01:00
for ( it_ = y_kmin ; it_ < periods + y_kmin ; it_ + + )
2022-07-05 12:12:08 +02:00
solve_linear ( block_num , y_size , size , 0 ) ;
2013-03-22 15:44:34 +01:00
}
else
{
if ( ! is_linear )
2021-02-09 15:55:36 +01:00
for ( it_ = periods + y_kmin - 1 ; it_ > = y_kmin ; it_ - - )
2022-07-05 12:12:08 +02:00
solve_non_linear ( block_num , y_size , size ) ;
2013-03-22 15:44:34 +01:00
else
2021-02-09 15:55:36 +01:00
for ( it_ = periods + y_kmin - 1 ; it_ > = y_kmin ; it_ - - )
2022-07-05 12:12:08 +02:00
solve_linear ( block_num , y_size , size , 0 ) ;
2013-03-22 15:44:34 +01:00
}
2021-02-09 15:55:36 +01:00
if ( ( solve_algo = = 6 & & steady_state )
2022-06-15 14:46:44 +02:00
| | ( ( stack_solve_algo = = 0 | | stack_solve_algo = = 1 | | stack_solve_algo = = 4 | | stack_solve_algo = = 6 ) & & ! steady_state ) )
2013-03-22 15:44:34 +01:00
{
mxFree ( Ap_save ) ;
mxFree ( Ai_save ) ;
mxFree ( Ax_save ) ;
mxFree ( b_save ) ;
}
mxFree ( g1 ) ;
mxFree ( r ) ;
}
string
2013-06-08 17:16:20 +02:00
dynSparseMatrix : : preconditioner_print_out ( string s , int preconditioner , bool ss )
2013-03-22 15:44:34 +01:00
{
int n = s . length ( ) ;
string tmp = " , preconditioner= " ;
2017-05-16 16:30:27 +02:00
switch ( preconditioner )
2013-03-22 15:44:34 +01:00
{
case 0 :
2013-06-08 17:16:20 +02:00
if ( ss )
tmp . append ( " Jacobi on static jacobian " ) ;
else
tmp . append ( " Jacobi on dynamic jacobian " ) ;
2013-03-22 15:44:34 +01:00
break ;
case 1 :
2013-06-08 17:16:20 +02:00
if ( ss )
2022-03-16 12:57:42 +01:00
tmp . append ( " incomplete lutp on static jacobian " ) ;
2017-03-24 23:15:25 +01:00
else
2022-03-16 12:57:42 +01:00
tmp . append ( " incomplete lu0 on dynamic jacobian " ) ;
2013-03-22 15:44:34 +01:00
break ;
case 2 :
2022-03-16 12:57:42 +01:00
tmp . append ( " incomplete lutp on dynamic jacobian " ) ;
2013-03-22 15:44:34 +01:00
break ;
case 3 :
tmp . append ( " lu on static jacobian " ) ;
break ;
}
s . insert ( n - 2 , tmp ) ;
return s ;
}
2010-09-24 12:52:58 +02:00
void
2022-07-28 16:56:40 +02:00
dynSparseMatrix : : Simulate_Newton_Two_Boundaries ( int blck , int y_size , int y_kmin , int y_kmax , int Size , int periods , bool cvg , int minimal_solving_periods , int stack_solve_algo , const vector_table_conditional_local_type & vector_table_conditional_local )
2010-09-24 12:52:58 +02:00
{
2013-03-22 15:44:34 +01:00
double top = 0.5 ;
double bottom = 0.1 ;
int preconditioner = 2 ;
2009-08-25 11:43:01 +02:00
if ( start_compare = = 0 )
start_compare = y_kmin ;
u_count_alloc_save = u_count_alloc ;
2023-06-13 16:55:24 +02:00
auto t1 { chrono : : high_resolution_clock : : now ( ) } ;
2009-07-10 17:10:11 +02:00
nop1 = 0 ;
2021-02-01 13:49:27 +01:00
mxArray * b_m = nullptr , * A_m = nullptr , * x0_m = nullptr ;
double * Ax = nullptr , * b ;
SuiteSparse_long * Ap = nullptr , * Ai = nullptr ;
2013-03-22 15:44:34 +01:00
2011-02-04 16:53:12 +01:00
if ( isnan ( res1 ) | | isinf ( res1 ) | | ( res2 > 12 * g0 & & iter > 0 ) )
2010-02-06 15:07:56 +01:00
{
2010-09-24 12:52:58 +02:00
if ( iter = = 0 | | fabs ( slowc_save ) < 1e-8 )
2017-05-16 16:30:27 +02:00
{
2023-06-13 16:34:22 +02:00
if ( verbosity > = 2 )
mexPrintf ( " res1 = %f, res2 = %f g0 = %f iter = %d \n " , res1 , res2 , g0 , iter ) ;
2011-02-04 16:53:12 +01:00
for ( int j = 0 ; j < y_size ; j + + )
2010-02-06 15:07:56 +01:00
{
bool select = false ;
for ( int i = 0 ; i < Size ; i + + )
if ( j = = index_vara [ i ] )
{
select = true ;
break ;
}
2023-06-13 16:34:22 +02:00
if ( verbosity > = 2 )
{
if ( select )
mexPrintf ( " -> variable %s (%d) at time %d = %f direction = %f \n " , symbol_table . getName ( SymbolType : : endogenous , j ) . c_str ( ) , j + 1 , it_ , y [ j + it_ * y_size ] , direction [ j + it_ * y_size ] ) ;
else
mexPrintf ( " variable %s (%d) at time %d = %f direction = %f \n " , symbol_table . getName ( SymbolType : : endogenous , j ) . c_str ( ) , j + 1 , it_ , y [ j + it_ * y_size ] , direction [ j + it_ * y_size ] ) ;
}
2010-02-06 15:07:56 +01:00
}
2011-02-04 16:53:12 +01:00
if ( iter = = 0 )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Simulate_Newton_Two_Boundaries, the initial values of endogenous variables are too far from the solution. Change them! " } ;
2010-09-24 12:52:58 +02:00
else
2022-07-29 12:42:50 +02:00
throw FatalException { " In Simulate_Newton_Two_Boundaries, dynare cannot improve the simulation in block "
+ to_string ( blck + 1 ) + " at time " + to_string ( it_ + 1 )
+ " (variable " + to_string ( index_vara [ max_res_idx ] + 1 )
+ " = " + to_string ( max_res ) + " ) " } ;
2010-02-06 15:07:56 +01:00
}
2021-02-09 15:55:36 +01:00
if ( ! ( isnan ( res1 ) | | isinf ( res1 ) ) & & ! ( isnan ( g0 ) | | isinf ( g0 ) )
& & ( stack_solve_algo = = 4 | | stack_solve_algo = = 5 ) )
2010-02-06 15:07:56 +01:00
{
if ( try_at_iteration = = 0 )
{
prev_slowc_save = slowc_save ;
2013-03-22 15:44:34 +01:00
slowc_save = max ( - gp0 / ( 2 * ( res2 - g0 - gp0 ) ) , bottom ) ;
2010-02-06 15:07:56 +01:00
}
else
{
double t1 = res2 - gp0 * slowc_save - g0 ;
double t2 = glambda2 - gp0 * prev_slowc_save - g0 ;
2021-02-09 15:55:36 +01:00
double a = ( 1 / ( slowc_save * slowc_save ) * t1
- 1 / ( prev_slowc_save * prev_slowc_save ) * t2 )
/ ( slowc_save - prev_slowc_save ) ;
double b = ( - prev_slowc_save / ( slowc_save * slowc_save ) * t1
+ slowc_save / ( prev_slowc_save * prev_slowc_save ) * t2 )
/ ( slowc_save - prev_slowc_save ) ;
2010-02-06 15:07:56 +01:00
prev_slowc_save = slowc_save ;
2021-02-09 15:55:36 +01:00
slowc_save = max ( min ( - b + sqrt ( b * b - 3 * a * gp0 ) / ( 3 * a ) ,
top * slowc_save ) , bottom * slowc_save ) ;
2010-02-06 15:07:56 +01:00
}
glambda2 = res2 ;
2011-02-04 16:53:12 +01:00
try_at_iteration + + ;
2013-03-22 15:44:34 +01:00
if ( slowc_save < = bottom )
2010-07-23 11:20:24 +02:00
{
2010-09-24 12:52:58 +02:00
for ( int i = 0 ; i < y_size * ( periods + y_kmin ) ; i + + )
2010-07-23 11:20:24 +02:00
y [ i ] = ya [ i ] + direction [ i ] ;
g0 = res2 ;
gp0 = - res2 ;
try_at_iteration = 0 ;
iter - - ;
2010-09-24 12:52:58 +02:00
return ;
2010-07-23 11:20:24 +02:00
}
2010-02-06 15:07:56 +01:00
}
else
{
prev_slowc_save = slowc_save ;
2015-09-22 12:45:27 +02:00
slowc_save / = 1.05 ;
2010-02-06 15:07:56 +01:00
}
2023-06-13 16:34:22 +02:00
if ( verbosity > = 2 )
2010-08-18 13:51:57 +02:00
{
if ( isnan ( res1 ) | | isinf ( res1 ) )
2010-09-24 12:52:58 +02:00
mexPrintf ( " The model cannot be evaluated, trying to correct it using slowc=%f \n " , slowc_save ) ;
2010-08-18 13:51:57 +02:00
else
2010-09-24 12:52:58 +02:00
mexPrintf ( " Simulation diverging, trying to correct it using slowc=%f \n " , slowc_save ) ;
2010-08-18 13:51:57 +02:00
}
2010-09-24 12:52:58 +02:00
for ( int i = 0 ; i < y_size * ( periods + y_kmin ) ; i + + )
2009-08-25 11:43:01 +02:00
y [ i ] = ya [ i ] + slowc_save * direction [ i ] ;
2007-11-21 00:27:30 +01:00
iter - - ;
2010-09-24 12:52:58 +02:00
return ;
2007-11-21 00:27:30 +01:00
}
2010-07-23 11:20:24 +02:00
u_count + = u_count_init ;
if ( stack_solve_algo = = 5 )
2007-11-21 00:27:30 +01:00
{
2010-07-23 11:20:24 +02:00
if ( alt_symbolic & & alt_symbolic_count < alt_symbolic_count_max )
{
2023-06-13 16:34:22 +02:00
if ( verbosity > = 2 )
mexPrintf ( " Pivoting method will be applied only to the first periods. \n " ) ;
2010-07-23 11:20:24 +02:00
alt_symbolic = false ;
symbolic = true ;
markowitz_c = markowitz_c_s ;
alt_symbolic_count + + ;
}
2021-02-09 15:55:36 +01:00
if ( res1 / res1a - 1 > - 0.3 & & symbolic & & iter > 0 )
2009-08-25 11:43:01 +02:00
{
2010-07-23 11:20:24 +02:00
if ( restart > 2 )
{
2023-06-13 16:34:22 +02:00
if ( verbosity > = 2 )
mexPrintf ( " Divergence or slowdown occurred during simulation. \n In the next iteration, pivoting method will be applied to all periods. \n " ) ;
2010-07-23 11:20:24 +02:00
symbolic = false ;
alt_symbolic = true ;
markowitz_c_s = markowitz_c ;
markowitz_c = 0 ;
}
else
{
2023-06-13 16:34:22 +02:00
if ( verbosity > = 2 )
mexPrintf ( " Divergence or slowdown occurred during simulation. \n In the next iteration, pivoting method will be applied for a longer period. \n " ) ;
2010-07-23 11:20:24 +02:00
start_compare = min ( tbreak_g , periods ) ;
restart + + ;
}
2009-08-25 11:43:01 +02:00
}
2009-07-21 17:50:12 +02:00
else
2007-11-21 00:27:30 +01:00
{
2010-07-23 11:20:24 +02:00
start_compare = max ( y_kmin , minimal_solving_periods ) ;
restart = 0 ;
2007-11-21 00:27:30 +01:00
}
}
2009-08-25 11:43:01 +02:00
res1a = res1 ;
2023-06-13 16:34:22 +02:00
if ( verbosity > = 1 )
2008-12-19 11:24:31 +01:00
{
2010-07-23 11:20:24 +02:00
if ( iter = = 0 )
{
2011-02-04 16:53:12 +01:00
switch ( stack_solve_algo )
{
case 0 :
mexPrintf ( " MODEL SIMULATION: (method=Sparse LU) \n " ) ;
break ;
case 1 :
2022-06-15 14:46:44 +02:00
case 6 :
mexPrintf ( " MODEL SIMULATION: (method=LBJ) \n " ) ;
2011-02-04 16:53:12 +01:00
break ;
case 2 :
2013-06-08 17:16:20 +02:00
mexPrintf ( preconditioner_print_out ( " MODEL SIMULATION: (method=GMRES) \n " , preconditioner , false ) . c_str ( ) ) ;
2011-02-04 16:53:12 +01:00
break ;
case 3 :
2013-06-08 17:16:20 +02:00
mexPrintf ( preconditioner_print_out ( " MODEL SIMULATION: (method=BiCGStab) \n " , preconditioner , false ) . c_str ( ) ) ;
2011-02-04 16:53:12 +01:00
break ;
case 4 :
mexPrintf ( " MODEL SIMULATION: (method=Sparse LU & optimal path length) \n " ) ;
break ;
case 5 :
2023-06-13 16:55:37 +02:00
mexPrintf ( " MODEL SIMULATION: (method=Sparse Gaussian Elimination) \n " ) ;
2011-02-04 16:53:12 +01:00
break ;
2010-07-23 11:20:24 +02:00
}
}
2023-06-12 15:11:15 +02:00
mexPrintf ( " ------------------------------------ \n " ) ;
2023-06-13 16:55:37 +02:00
mexPrintf ( " Iteration no. %d \n " , iter + 1 ) ;
2023-06-12 15:11:15 +02:00
mexPrintf ( " Inf-norm error = %.3e \n " , static_cast < double > ( max_res ) ) ;
mexPrintf ( " 2-norm error = %.3e \n " , static_cast < double > ( sqrt ( res2 ) ) ) ;
mexPrintf ( " 1-norm error = %.3e \n " , static_cast < double > ( res1 ) ) ;
mexPrintf ( " ------------------------------------ \n " ) ;
2010-07-23 11:20:24 +02:00
mexEvalString ( " drawnow; " ) ;
2008-12-19 11:24:31 +01:00
}
2007-11-21 00:27:30 +01:00
if ( cvg )
2021-02-09 15:55:36 +01:00
return ;
2007-11-21 00:27:30 +01:00
else
2009-08-25 11:43:01 +02:00
{
2010-07-23 11:20:24 +02:00
if ( stack_solve_algo = = 5 )
Init_GE ( periods , y_kmin , y_kmax , Size , IM_i ) ;
else
2009-08-25 11:43:01 +02:00
{
2011-02-04 16:53:12 +01:00
x0_m = mxCreateDoubleMatrix ( periods * Size , 1 , mxREAL ) ;
2011-01-03 14:15:12 +01:00
if ( ! x0_m )
2022-07-29 12:42:50 +02:00
throw FatalException { " In Simulate_Newton_Two_Boundaries, can't allocate x0_m vector " } ;
2013-03-22 15:44:34 +01:00
if ( stack_solve_algo = = 0 | | stack_solve_algo = = 4 )
2015-09-22 12:45:27 +02:00
Init_UMFPACK_Sparse ( periods , y_kmin , y_kmax , Size , IM_i , & Ap , & Ai , & Ax , & b , x0_m , vector_table_conditional_local , blck ) ;
2013-03-22 15:44:34 +01:00
else
2023-03-31 18:44:24 +02:00
{
b_m = mxCreateDoubleMatrix ( periods * Size , 1 , mxREAL ) ;
if ( ! b_m )
throw FatalException { " In Simulate_Newton_Two_Boundaries, can't allocate b_m vector " } ;
if ( stack_solve_algo ! = 0 & & stack_solve_algo ! = 4 )
{
A_m = mxCreateSparse ( periods * Size , periods * Size , IM_i . size ( ) * periods * 2 , mxREAL ) ;
if ( ! A_m )
throw FatalException { " In Simulate_Newton_Two_Boundaries, can't allocate A_m matrix " } ;
}
Init_Matlab_Sparse ( periods , y_kmin , y_kmax , Size , IM_i , A_m , b_m , x0_m ) ;
}
2010-07-23 11:20:24 +02:00
}
2010-09-24 12:52:58 +02:00
if ( stack_solve_algo = = 0 | | stack_solve_algo = = 4 )
2023-03-31 18:44:24 +02:00
{
Solve_LU_UMFPack ( Ap , Ai , Ax , b , Size * periods , Size , slowc , true , 0 , vector_table_conditional_local ) ;
mxDestroyArray ( x0_m ) ;
}
2022-06-15 14:46:44 +02:00
else if ( stack_solve_algo = = 1 | | stack_solve_algo = = 6 )
2023-03-31 18:44:24 +02:00
{
Solve_Matlab_Relaxation ( A_m , b_m , Size , slowc ) ;
mxDestroyArray ( x0_m ) ;
}
2010-07-23 11:20:24 +02:00
else if ( stack_solve_algo = = 2 )
2013-03-22 15:44:34 +01:00
Solve_Matlab_GMRES ( A_m , b_m , Size , slowc , blck , true , 0 , x0_m ) ;
2010-07-23 11:20:24 +02:00
else if ( stack_solve_algo = = 3 )
2013-03-22 15:44:34 +01:00
Solve_Matlab_BiCGStab ( A_m , b_m , Size , slowc , blck , true , 0 , x0_m , 1 ) ;
2010-09-24 12:52:58 +02:00
else if ( stack_solve_algo = = 5 )
Solve_ByteCode_Symbolic_Sparse_GaussianElimination ( Size , symbolic , blck ) ;
2009-08-25 11:43:01 +02:00
}
2023-06-13 16:55:24 +02:00
using FloatSeconds = chrono : : duration < double , chrono : : seconds : : period > ;
auto t2 { chrono : : high_resolution_clock : : now ( ) } ;
2023-06-13 16:34:22 +02:00
if ( verbosity > = 1 )
2007-11-21 00:27:30 +01:00
{
2023-06-13 16:55:24 +02:00
mexPrintf ( " (** %.2f seconds **) \n " , FloatSeconds { t2 - t1 } . count ( ) ) ;
2007-11-21 00:27:30 +01:00
mexEvalString ( " drawnow; " ) ;
}
2021-02-09 15:55:36 +01:00
if ( ! steady_state & & stack_solve_algo = = 4 )
2013-03-22 15:44:34 +01:00
{
double ax = - 0.1 , bx = 1.1 , cx = 0.5 , fa , fb , fc , xmin ;
2007-11-21 00:27:30 +01:00
2013-03-22 15:44:34 +01:00
if ( ! mnbrak ( & ax , & bx , & cx , & fa , & fb , & fc ) )
return ;
if ( ! golden ( ax , bx , cx , 1e-1 , solve_tolf , & xmin ) )
return ;
slowc = xmin ;
2023-06-13 16:34:22 +02:00
if ( verbosity > = 1 )
{
2023-06-13 16:55:24 +02:00
auto t3 { chrono : : high_resolution_clock : : now ( ) } ;
mexPrintf ( " (** %.2f seconds **) \n " , FloatSeconds { t3 - t2 } . count ( ) ) ;
2023-06-13 16:34:22 +02:00
mexEvalString ( " drawnow; " ) ;
}
2013-03-22 15:44:34 +01:00
}
2009-08-25 11:43:01 +02:00
if ( tbreak_g = = 0 )
tbreak_g = periods ;
2007-11-21 00:27:30 +01:00
}
void
2013-03-22 15:44:34 +01:00
dynSparseMatrix : : fixe_u ( double * * u , int u_count_int , int max_lag_plus_max_lead_plus_1 )
2007-11-21 00:27:30 +01:00
{
2009-08-25 11:43:01 +02:00
u_count = u_count_int * periods ;
2007-11-21 00:27:30 +01:00
u_count_alloc = 2 * u_count ;
2010-12-31 16:29:39 +01:00
# ifdef DEBUG
2011-02-04 16:53:12 +01:00
mexPrintf ( " fixe_u : alloc(%d double) \n " , u_count_alloc ) ;
2010-11-20 15:45:15 +01:00
# endif
2021-02-09 15:55:36 +01:00
* u = static_cast < double * > ( mxMalloc ( u_count_alloc * sizeof ( double ) ) ) ;
2017-03-24 23:15:25 +01:00
test_mxMalloc ( * u , __LINE__ , __FILE__ , __func__ , u_count_alloc * sizeof ( double ) ) ;
2010-12-31 16:29:39 +01:00
# ifdef DEBUG
2011-02-04 16:53:12 +01:00
mexPrintf ( " *u=%d \n " , * u ) ;
2010-11-20 15:45:15 +01:00
# endif
2021-02-09 15:55:36 +01:00
fill_n ( * u , u_count_alloc , 0 ) ;
2009-08-25 11:43:01 +02:00
u_count_init = max_lag_plus_max_lead_plus_1 ;
2007-11-21 00:27:30 +01:00
}