2011-03-13 17:06:57 +01:00
function [ y , info ] = solve_one_boundary ( fname , y , x , params , steady_state , ...
2011-11-25 12:57:42 +01:00
y_index_eq , nze , periods , is_linear , Block_Num , y_kmin , maxit_ , solve_tolf , lambda , cutoff , stack_solve_algo , forward_backward , is_dynamic , verbose , M , options , oo )
2009-12-16 18:17:34 +01:00
% Computes the deterministic simulation of a block of equation containing
2017-05-16 15:10:20 +02:00
% lead or lag variables
2009-12-16 18:17:34 +01:00
%
% INPUTS
% fname [string] name of the file containing the block
% to simulate
% y [matrix] All the endogenous variables of the model
% x [matrix] All the exogenous variables of the model
% params [vector] All the parameters of the model
2011-03-13 17:06:57 +01:00
% steady_state [vector] steady state of the model
2009-12-16 18:17:34 +01:00
% y_index_eq [vector of int] The index of the endogenous variables of
% the block
% nze [integer] number of non-zero elements in the
% jacobian matrix
% periods [integer] number of simulation periods
% is_linear [integer] if is_linear=1 the block is linear
% if is_linear=0 the block is not linear
% Block_Num [integer] block number
% y_kmin [integer] maximum number of lag in the model
% maxit_ [integer] maximum number of iteration in Newton
% solve_tolf [double] convergence criteria
% lambda [double] initial value of step size in
% Newton
% cutoff [double] cutoff to correct the direction in Newton in case
% of singular jacobian matrix
% stack_solve_algo [integer] linear solver method used in the
2017-05-16 15:10:20 +02:00
% Newton algorithm :
2009-12-16 18:17:34 +01:00
% - 1 sparse LU
% - 2 GMRES
% - 3 BicGStab
% - 4 Optimal path length
% forward_backward [integer] The block has to be solve forward
% (1) or backward (0)
% is_dynamic [integer] (1) The block belong to the dynamic
% file and the oo_.deterministic_simulation field has to be uptated
% (0) The block belong to the static
% file and th oo_.deteerminstic
% field remains unchanged
% verbose [integer] (0) iterations are not printed
% (1) iterations are printed
2010-10-18 17:28:21 +02:00
% indirect_call [integer] (0) direct call to the fname
% (1) indirect call via the
% local_fname wrapper
2017-05-16 15:10:20 +02:00
% OUTPUTS
% y [matrix] All endogenous variables of the model
2010-10-18 17:28:21 +02:00
% info [integer] >=0 no error
% <0 error
2017-05-16 15:10:20 +02:00
%
2009-12-16 18:17:34 +01:00
% ALGORITHM
% Newton with LU or GMRES or BicGstab for dynamic block
2017-05-16 15:10:20 +02:00
%
2009-12-16 18:17:34 +01:00
% SPECIAL REQUIREMENTS
% none.
2017-05-16 15:10:20 +02:00
%
2009-12-16 18:17:34 +01:00
2017-10-10 10:05:59 +02:00
% Copyright (C) 1996-2018 Dynare Team
2009-12-16 18:17:34 +01:00
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
Blck_size = size ( y_index_eq , 2 ) ;
g2 = [ ] ;
g3 = [ ] ;
correcting_factor = 0.01 ;
2013-03-25 12:03:09 +01:00
ilu_setup . droptol = 1e-10 ;
2009-12-16 18:17:34 +01:00
max_resa = 1e100 ;
reduced = 0 ;
2015-02-20 14:44:45 +01:00
if forward_backward
2009-12-16 18:17:34 +01:00
incr = 1 ;
start = y_kmin + 1 ;
finish = periods + y_kmin ;
else
incr = - 1 ;
start = periods + y_kmin ;
finish = y_kmin + 1 ;
end
2015-02-20 14:44:45 +01:00
2009-12-16 18:17:34 +01:00
for it_ = start : incr : finish
cvg = 0 ;
iter = 0 ;
g1 = spalloc ( Blck_size , Blck_size , nze ) ;
2015-02-20 14:44:45 +01:00
while ~ ( cvg == 1 || iter > maxit_ )
if is_dynamic
[ r , y , g1 , g2 , g3 ] = feval ( fname , y , x , params , steady_state , it_ , 0 ) ;
2009-12-16 18:17:34 +01:00
else
2011-03-18 14:11:00 +01:00
[ r , y , g1 ] = feval ( fname , y , x , params ) ;
2015-02-20 14:44:45 +01:00
end
if ~ isreal ( r )
2009-12-16 18:17:34 +01:00
max_res = ( - ( max ( max ( abs ( r ) ) ) ) ^2 ) ^0.5 ;
else
max_res = max ( max ( abs ( r ) ) ) ;
2015-02-20 14:44:45 +01:00
end
if verbose == 1
disp ( [ ' iteration : ' int2str ( iter + 1 ) ' => ' num2str ( max_res ) ' time = ' int2str ( it_ ) ] )
if is_dynamic
2017-10-10 10:05:59 +02:00
disp ( [ M . endo_names { y_index_eq } num2str ( [ y ( it_ , y_index_eq ) ' r g1 ] ) ] )
2009-12-16 18:17:34 +01:00
else
2017-10-10 10:05:59 +02:00
disp ( [ M . endo_names { y_index_eq } num2str ( [ y ( y_index_eq ) r g1 ] ) ] )
2015-02-20 14:44:45 +01:00
end
end
if ~ isreal ( max_res ) || isnan ( max_res )
2009-12-16 18:17:34 +01:00
cvg = 0 ;
2015-02-20 14:44:45 +01:00
elseif is_linear && iter > 0
2009-12-16 18:17:34 +01:00
cvg = 1 ;
else
cvg = ( max_res < solve_tolf ) ;
2015-02-20 14:44:45 +01:00
end
if ~ cvg
if iter > 0
if ~ isreal ( max_res ) || isnan ( max_res ) || ( max_resa < max_res && iter > 1 )
if isnan ( max_res ) || ( max_resa < max_res && iter > 0 )
2009-12-16 18:17:34 +01:00
detJ = det ( g1a ) ;
if ( abs ( detJ ) < 1e-7 )
max_factor = max ( max ( abs ( g1a ) ) ) ;
ze_elem = sum ( diag ( g1a ) < cutoff ) ;
2015-02-20 14:44:45 +01:00
if verbose
disp ( [ num2str ( full ( ze_elem ) , ' %d' ) ' elements on the Jacobian diagonal are below the cutoff (' num2str ( cutoff , ' %f' ) ' )' ] )
end
if correcting_factor < max_factor
2009-12-16 18:17:34 +01:00
correcting_factor = correcting_factor * 4 ;
2015-02-20 14:44:45 +01:00
if verbose
disp ( [ ' The Jacobain matrix is singular, det(Jacobian)=' num2str ( detJ , ' %f' ) ' .' ] )
disp ( [ ' trying to correct the Jacobian matrix:' ] )
disp ( [ ' correcting_factor=' num2str ( correcting_factor , ' %f' ) ' max(Jacobian)=' num2str ( full ( max_factor ) , ' %f' ) ] )
end
2009-12-16 18:17:34 +01:00
dx = - r / ( g1 + correcting_factor * speye ( Blck_size ) ) ;
y ( it_ , y_index_eq ) = ya_save + lambda * dx ;
2015-02-20 14:44:45 +01:00
continue
2009-12-16 18:17:34 +01:00
else
2015-02-20 14:44:45 +01:00
if verbose
disp ( ' The singularity of the jacobian matrix could not be corrected' )
end
2009-12-16 18:17:34 +01:00
info = - Block_Num * 10 ;
2015-02-20 14:44:45 +01:00
return
end
end
elseif lambda > 1e-8
2009-12-16 18:17:34 +01:00
lambda = lambda / 2 ;
reduced = 1 ;
2015-02-20 14:44:45 +01:00
if verbose
disp ( [ ' reducing the path length: lambda=' num2str ( lambda , ' %f' ) ] )
end
if is_dynamic
2009-12-16 18:17:34 +01:00
y ( it_ , y_index_eq ) = ya_save - lambda * dx ;
else
y ( y_index_eq ) = ya_save - lambda * dx ;
2015-02-20 14:44:45 +01:00
end
continue
2009-12-16 18:17:34 +01:00
else
2015-02-20 14:44:45 +01:00
if verbose
if cutoff == 0
fprintf ( ' Error in simul: Convergence not achieved in block %d, at time %d, after %d iterations.\n Increase "options_.simul.maxit".\n' , Block_Num , it_ , iter ) ;
else
fprintf ( ' Error in simul: Convergence not achieved in block %d, at time %d, after %d iterations.\n Increase "options_.simul.maxit" or set "cutoff=0" in model options.\n' , Block_Num , it_ , iter ) ;
end
end
if is_dynamic
2009-12-16 18:17:34 +01:00
oo_ . deterministic_simulation . status = 0 ;
oo_ . deterministic_simulation . error = max_res ;
oo_ . deterministic_simulation . iterations = iter ;
oo_ . deterministic_simulation . block ( Block_Num ) . status = 0 ; % Convergency failed.
oo_ . deterministic_simulation . block ( Block_Num ) . error = max_res ;
oo_ . deterministic_simulation . block ( Block_Num ) . iterations = iter ;
2015-02-20 14:44:45 +01:00
end
2009-12-16 18:17:34 +01:00
info = - Block_Num * 10 ;
2015-02-20 14:44:45 +01:00
return
end
2009-12-16 18:17:34 +01:00
else
2015-02-20 14:44:45 +01:00
if lambda < 1
2009-12-16 18:17:34 +01:00
lambda = max ( lambda * 2 , 1 ) ;
2015-02-20 14:44:45 +01:00
end
end
end
if is_dynamic
2009-12-16 18:17:34 +01:00
ya = y ( it_ , y_index_eq ) ' ;
else
ya = y ( y_index_eq ) ;
2015-02-20 14:44:45 +01:00
end
2009-12-16 18:17:34 +01:00
ya_save = ya ;
g1a = g1 ;
2015-02-20 14:44:45 +01:00
if ~ is_dynamic && options . solve_algo == 0
if verbose
disp ( ' steady: fsolve' )
2011-02-04 17:17:48 +01:00
end
2013-11-04 10:54:45 +01:00
if ~ isoctave
2012-01-09 11:06:26 +01:00
if ~ user_has_matlab_license ( ' optimization_toolbox' )
2011-12-19 12:36:35 +01:00
error ( ' SOLVE_ONE_BOUNDARY: you can' ' t use solve_algo=0 since you don' ' t have MATLAB' ' s Optimization Toolbox' )
end
2009-12-16 18:17:34 +01:00
end
options = optimset ( ' fsolve' ) ;
options . MaxFunEvals = 50000 ;
options . MaxIter = 2000 ;
options . TolFun = 1e-8 ;
options . Display = ' iter' ;
options . Jacobian = ' on' ;
2013-11-04 10:54:45 +01:00
if ~ isoctave
2011-09-19 12:37:17 +02:00
[ yn , fval , exitval , output ] = fsolve ( @ local_fname , y ( y_index_eq ) , ...
options , x , params , steady_state , y , y_index_eq , fname , 0 ) ;
else
% Under Octave, use a wrapper, since fsolve() does not have a 4th arg
func = @ ( z ) local_fname ( z , x , params , steady_state , y , y_index_eq , fname , 0 ) ;
% The Octave version of fsolve does not converge when it starts from the solution
fvec = feval ( func , y ( y_index_eq ) ) ;
2011-11-25 12:57:42 +01:00
if max ( abs ( fvec ) ) > = options . solve_tolf
2011-09-19 12:37:17 +02:00
[ yn , fval , exitval , output ] = fsolve ( func , y ( y_index_eq ) , options ) ;
else
yn = y ( y_index_eq ) ;
exitval = 3 ;
2015-02-20 14:44:45 +01:00
end
2011-09-19 12:37:17 +02:00
end
2009-12-16 18:17:34 +01:00
y ( y_index_eq ) = yn ;
if exitval > 0
info = 0 ;
else
info = - Block_Num * 10 ;
end
2015-02-20 14:44:45 +01:00
elseif ( ~ is_dynamic && options . solve_algo == 2 ) || ( is_dynamic && stack_solve_algo == 4 )
if verbose == 1 && ~ is_dynamic
disp ( ' steady: LU + lnsrch1' )
2011-02-04 17:17:48 +01:00
end
2009-12-16 18:17:34 +01:00
lambda = 1 ;
stpmx = 100 ;
2015-02-20 14:44:45 +01:00
if is_dynamic
2009-12-21 11:29:21 +01:00
stpmax = stpmx * max ( [ sqrt ( ya ' * ya ) ; size ( y_index_eq , 2 ) ] ) ;
2009-12-16 18:17:34 +01:00
else
2009-12-21 11:29:21 +01:00
stpmax = stpmx * max ( [ sqrt ( ya ' * ya ) ; size ( y_index_eq , 2 ) ] ) ;
2015-02-20 14:44:45 +01:00
end
2009-12-16 18:17:34 +01:00
nn = 1 : size ( y_index_eq , 2 ) ;
g = ( r ' * g1 ) ' ;
f = 0.5 * r ' * r ;
p = - g1 \ r ;
2015-02-20 14:44:45 +01:00
if is_dynamic
2011-03-13 17:06:57 +01:00
[ ya , f , r , check ] = lnsrch1 ( y ( it_ , : ) ' , f , g , p , stpmax , ...
' lnsrch1_wrapper_one_boundary' , nn , ...
2016-02-26 22:06:49 +01:00
y_index_eq , options . solve_tolx , y_index_eq , fname , y , x , params , steady_state , it_ ) ;
2010-12-31 16:20:35 +01:00
dx = ya ' - y ( it_ , : ) ;
2009-12-16 18:17:34 +01:00
else
2016-02-26 22:06:49 +01:00
[ ya , f , r , check ] = lnsrch1 ( y , f , g , p , stpmax , fname , nn , y_index_eq , options . solve_tolx , x , ...
2011-03-13 17:06:57 +01:00
params , steady_state , 0 ) ;
2010-12-31 16:20:35 +01:00
dx = ya - y ( y_index_eq ) ;
2015-02-20 14:44:45 +01:00
end
if is_dynamic
2009-12-21 11:29:21 +01:00
y ( it_ , : ) = ya ' ;
else
y = ya ' ;
2015-02-20 14:44:45 +01:00
end
elseif ~ is_dynamic && options . solve_algo == 3
if verbose == 1
disp ( ' steady: csolve' )
2011-02-04 17:17:48 +01:00
end
2011-03-13 17:06:57 +01:00
[ yn , info ] = csolve ( @ local_fname , y ( y_index_eq ) , @ ...
local_fname , 1e-6 , 500 , x , params , steady_state , y , y_index_eq , fname , 1 ) ;
2009-12-16 18:17:34 +01:00
dx = ya - yn ;
y ( y_index_eq ) = yn ;
2015-02-20 14:44:45 +01:00
elseif ( stack_solve_algo == 1 && is_dynamic ) || ( stack_solve_algo == 0 && is_dynamic ) || ( ~ is_dynamic && ( options . solve_algo == 1 || options . solve_algo == 6 ) )
if verbose == 1 && ~ is_dynamic
disp ( ' steady: Sparse LU ' )
2011-02-04 17:17:48 +01:00
end
2009-12-16 18:17:34 +01:00
dx = g1 \ r ;
ya = ya - lambda * dx ;
2015-02-20 14:44:45 +01:00
if is_dynamic
2009-12-16 18:17:34 +01:00
y ( it_ , y_index_eq ) = ya ' ;
else
y ( y_index_eq ) = ya ;
2015-02-20 14:44:45 +01:00
end
elseif ( stack_solve_algo == 2 && is_dynamic ) || ( options . solve_algo == 7 && ~ is_dynamic )
2009-12-16 18:17:34 +01:00
flag1 = 1 ;
2015-02-20 14:44:45 +01:00
if verbose == 1 && ~ is_dynamic
disp ( ' steady: GMRES ' )
2011-02-04 17:17:48 +01:00
end
2015-02-20 14:44:45 +01:00
while flag1 > 0
2013-03-25 12:03:09 +01:00
[ L1 , U1 ] = ilu ( g1 , ilu_setup ) ;
2009-12-21 11:29:21 +01:00
[ dx , flag1 ] = gmres ( g1 , - r , Blck_size , 1e-6 , Blck_size , L1 , U1 ) ;
2015-02-20 14:44:45 +01:00
if flag1 > 0 || reduced
if verbose
if flag1 == 1
disp ( [ ' Error in simul: No convergence inside GMRES after ' num2str ( iter , ' %6d' ) ' iterations, in block' num2str ( Block_Num , ' %3d' ) ] )
elseif ( flag1 == 2 )
disp ( [ ' Error in simul: Preconditioner is ill-conditioned, in block' num2str ( Block_Num , ' %3d' ) ] )
elseif ( flag1 == 3 )
disp ( [ ' Error in simul: GMRES stagnated (Two consecutive iterates were the same.), in block' num2str ( Block_Num , ' %3d' ) ] )
end
end
2013-03-25 12:03:09 +01:00
ilu_setup . droptol = ilu_setup . droptol / 10 ;
2009-12-16 18:17:34 +01:00
reduced = 0 ;
else
ya = ya + lambda * dx ;
2015-02-20 14:44:45 +01:00
if is_dynamic
2009-12-16 18:17:34 +01:00
y ( it_ , y_index_eq ) = ya ' ;
else
y ( y_index_eq ) = ya ' ;
2015-02-20 14:44:45 +01:00
end
end
end
elseif ( stack_solve_algo == 3 && is_dynamic ) || ( options . solve_algo == 8 && ~ is_dynamic )
2009-12-16 18:17:34 +01:00
flag1 = 1 ;
2015-02-20 14:44:45 +01:00
if verbose == 1 && ~ is_dynamic
disp ( ' steady: BiCGStab' )
2011-02-04 17:17:48 +01:00
end
2015-02-20 14:44:45 +01:00
while flag1 > 0
2013-03-25 12:03:09 +01:00
[ L1 , U1 ] = ilu ( g1 , ilu_setup ) ;
2011-02-04 17:17:48 +01:00
phat = ya - U1 \ ( L1 \ r ) ;
2015-02-20 14:44:45 +01:00
if is_dynamic
2011-01-14 19:22:29 +01:00
y ( it_ , y_index_eq ) = phat ;
else
y ( y_index_eq ) = phat ;
2015-02-20 14:44:45 +01:00
end
if is_dynamic
2011-03-13 17:06:57 +01:00
[ r , y , g1 , g2 , g3 ] = feval ( fname , y , x , params , ...
steady_state , it_ , 0 ) ;
2011-01-14 19:22:29 +01:00
else
2011-09-16 17:44:59 +02:00
[ r , y , g1 ] = feval ( fname , y , x , params ) ;
2015-02-20 14:44:45 +01:00
end
if max ( abs ( r ) ) > = options . solve_tolf
2011-01-14 14:45:48 +01:00
[ dx , flag1 ] = bicgstab ( g1 , - r , 1e-7 , Blck_size , L1 , U1 ) ;
2011-01-14 19:22:29 +01:00
else
2011-02-04 17:17:48 +01:00
flag1 = 0 ;
dx = phat - ya ;
2015-02-20 14:44:45 +01:00
end
if flag1 > 0 || reduced
if verbose
if ( flag1 == 1 )
disp ( [ ' Error in simul: No convergence inside BICGSTAB after ' num2str ( iter , ' %6d' ) ' iterations, in block' num2str ( Block_Num , ' %3d' ) ] )
elseif ( flag1 == 2 )
disp ( [ ' Error in simul: Preconditioner is ill-conditioned, in block' num2str ( Block_Num , ' %3d' ) ] )
elseif ( flag1 == 3 )
disp ( [ ' Error in simul: GMRES stagnated (Two consecutive iterates were the same.), in block' num2str ( Block_Num , ' %3d' ) ] )
end
end
2013-03-25 12:03:09 +01:00
ilu_setup . droptol = ilu_setup . droptol / 10 ;
2009-12-16 18:17:34 +01:00
reduced = 0 ;
else
ya = ya + lambda * dx ;
2015-02-20 14:44:45 +01:00
if is_dynamic
2009-12-16 18:17:34 +01:00
y ( it_ , y_index_eq ) = ya ' ;
else
y ( y_index_eq ) = ya ' ;
2015-02-20 14:44:45 +01:00
end
end
end
2009-12-16 18:17:34 +01:00
else
2015-02-20 14:44:45 +01:00
if verbose
disp ( ' unknown option : ' )
if is_dynamic
disp ( [ ' options_.stack_solve_algo = ' num2str ( stack_solve_algo ) ' not implemented' ] )
else
disp ( [ ' options_.solve_algo = ' num2str ( options . solve_algo ) ' not implemented' ] )
end
end
2009-12-16 18:17:34 +01:00
info = - Block_Num * 10 ;
2015-02-20 14:44:45 +01:00
return
end
2009-12-16 18:17:34 +01:00
iter = iter + 1 ;
max_resa = max_res ;
end
end
if cvg == 0
2015-02-20 14:44:45 +01:00
if verbose
if cutoff == 0
fprintf ( ' Error in simul: Convergence not achieved in block %d, at time %d, after %d iterations.\n Increase "options_.simul.maxit\".\n' , Block_Num , it_ , iter ) ;
else
fprintf ( ' Error in simul: Convergence not achieved in block %d, at time %d, after %d iterations.\n Increase "options_.simul.maxit" or set "cutoff=0" in model options.\n' , Block_Num , it_ , iter ) ;
end
end
2009-12-16 18:17:34 +01:00
if ( is_dynamic )
oo_ . deterministic_simulation . status = 0 ;
oo_ . deterministic_simulation . error = max_res ;
oo_ . deterministic_simulation . iterations = iter ;
oo_ . deterministic_simulation . block ( Block_Num ) . status = 0 ; % Convergency failed.
oo_ . deterministic_simulation . block ( Block_Num ) . error = max_res ;
oo_ . deterministic_simulation . block ( Block_Num ) . iterations = iter ;
2017-05-16 12:42:01 +02:00
end
2009-12-16 18:17:34 +01:00
info = - Block_Num * 10 ;
2015-02-20 14:44:45 +01:00
return
2009-12-16 18:17:34 +01:00
end
end
2015-02-20 14:44:45 +01:00
if is_dynamic
2010-10-22 16:49:47 +02:00
info = 1 ;
2009-12-16 18:17:34 +01:00
oo_ . deterministic_simulation . status = 1 ;
oo_ . deterministic_simulation . error = max_res ;
oo_ . deterministic_simulation . iterations = iter ;
oo_ . deterministic_simulation . block ( Block_Num ) . status = 1 ;
oo_ . deterministic_simulation . block ( Block_Num ) . error = max_res ;
oo_ . deterministic_simulation . block ( Block_Num ) . iterations = iter ;
2010-10-22 16:49:47 +02:00
else
2011-02-04 17:17:48 +01:00
info = 0 ;
2015-02-20 14:44:45 +01:00
end
2009-12-16 18:17:34 +01:00
2011-03-13 17:06:57 +01:00
function [err, G]= local_fname ( yl, x, params, steady_state, y, y_index_eq, fname, is_csolve)
2009-12-16 18:17:34 +01:00
y ( y_index_eq ) = yl ;
2011-03-13 17:06:57 +01:00
[ err , y , G ] = feval ( fname , y , x , params , steady_state , 0 ) ;
2009-12-16 18:17:34 +01:00
if ( is_csolve )
G = full ( G ) ;
2015-02-20 14:44:45 +01:00
end