Skip to content
Snippets Groups Projects
Verified Commit d2065889 authored by Sébastien Villemot's avatar Sébastien Villemot
Browse files

sim1_linear.m: use sparse representation for the model

Incidentally:
– fix a bug where path for endogenous after failure to converge was not centered
– ensure that sim1_linear.m is actually tested, by adding a test for
  linear_approximation + stack_solve_algo=0

Ref. #1859
parent 916b5479
No related branches found
No related tags found
No related merge requests found
...@@ -39,7 +39,7 @@ function [endogenousvariables, success, ERR] = sim1_linear(endogenousvariables, ...@@ -39,7 +39,7 @@ function [endogenousvariables, success, ERR] = sim1_linear(endogenousvariables,
% to center the variables around the deterministic steady state to solve the % to center the variables around the deterministic steady state to solve the
% perfect foresight model. % perfect foresight model.
% Copyright © 2015-2023 Dynare Team % Copyright © 2015-2024 Dynare Team
% %
% This file is part of Dynare. % This file is part of Dynare.
% %
...@@ -58,49 +58,15 @@ function [endogenousvariables, success, ERR] = sim1_linear(endogenousvariables, ...@@ -58,49 +58,15 @@ function [endogenousvariables, success, ERR] = sim1_linear(endogenousvariables,
verbose = options_.verbosity; verbose = options_.verbosity;
lead_lag_incidence = M_.lead_lag_incidence;
ny = M_.endo_nbr; ny = M_.endo_nbr;
nx = M_.exo_nbr; nx = M_.exo_nbr;
maximum_lag = M_.maximum_lag; maximum_lag = M_.maximum_lag;
max_lag = M_.maximum_endo_lag;
nyp = nnz(lead_lag_incidence(1,:));
ny0 = nnz(lead_lag_incidence(2,:));
nyf = nnz(lead_lag_incidence(3,:));
nd = nyp+ny0+nyf; % size of y (first argument passed to the dynamic file).
periods = options_.periods; periods = options_.periods;
params = M_.params; params = M_.params;
% Indices in A.
ip = find(lead_lag_incidence(1,:)');
ic = find(lead_lag_incidence(2,:)');
in = find(lead_lag_incidence(3,:)');
icn = find(lead_lag_incidence(2:3,:)');
ipcn = find(lead_lag_incidence');
% Indices in y.
jp = nonzeros(lead_lag_incidence(1,:)');
jc = nonzeros(lead_lag_incidence(2,:)');
jn = nonzeros(lead_lag_incidence(3,:)');
jpc = [jp; jc];
jcn = [jc; jn];
jexog = transpose(nd+(1:nx));
jendo = transpose(1:nd);
i_upd = maximum_lag*ny+(1:periods*ny);
% Center the endogenous and exogenous variables around the deterministic steady state.
endogenousvariables = bsxfun(@minus, endogenousvariables, steadystate_y);
exogenousvariables = bsxfun(@minus, exogenousvariables, transpose(steadystate_x));
Y = endogenousvariables(:);
if verbose if verbose
skipline() skipline()
printline(80) printline(80)
...@@ -108,24 +74,26 @@ if verbose ...@@ -108,24 +74,26 @@ if verbose
skipline() skipline()
end end
dynamicmodel = str2func([M_.fname,'.dynamic']);
z = steadystate_y([ip; ic; in]);
x = repmat(transpose(steadystate_x), 1+M_.maximum_exo_lag+M_.maximum_exo_lead, 1);
% Evaluate the Jacobian of the dynamic model at the deterministic steady state. % Evaluate the Jacobian of the dynamic model at the deterministic steady state.
[d1, jacobian] = dynamicmodel(z, x, params, steadystate_y, M_.maximum_exo_lag+1); y3n = repmat(steadystate_y, 3, 1);
[d1, TT_order, TT] = feval([M_.fname,'.sparse.dynamic_resid'], y3n, steadystate_x', params, ...
steadystate_y);
jacobian = feval([M_.fname,'.sparse.dynamic_g1'], y3n, steadystate_x', params, steadystate_y, ...
M_.dynamic_g1_sparse_rowval, M_.dynamic_g1_sparse_colval, ...
M_.dynamic_g1_sparse_colptr, TT_order, TT);
if options_.debug if options_.debug
column=find(all(jacobian==0,1)); column=find(all(jacobian(:, 1:3*ny)==0,1));
if ~isempty(column) if ~isempty(column)
fprintf('The dynamic Jacobian is singular. The problem derives from:\n') fprintf('The dynamic Jacobian is singular. The problem derives from:\n')
for iter=1:length(column) for iter=1:length(column)
[var_row,var_index]=find(M_.lead_lag_incidence==column(iter)); var_index = mod(column(iter)-1, ny)+1;
if var_row==2 lead_lag = floor((column(iter)-1)/ny)-1;
if lead_lag == 0
fprintf('The derivative with respect to %s being 0 for all equations.\n',M_.endo_names{var_index}) fprintf('The derivative with respect to %s being 0 for all equations.\n',M_.endo_names{var_index})
elseif var_row==1 elseif lead_lag == -1
fprintf('The derivative with respect to the lag of %s being 0 for all equations.\n',M_.endo_names{var_index}) fprintf('The derivative with respect to the lag of %s being 0 for all equations.\n',M_.endo_names{var_index})
elseif var_row==3 elseif lead_lag == 1
fprintf('The derivative with respect to the lead of %s being 0 for all equations.\n',M_.endo_names{var_index}) fprintf('The derivative with respect to the lead of %s being 0 for all equations.\n',M_.endo_names{var_index})
end end
end end
...@@ -137,55 +105,25 @@ if ~options_.steadystate.nocheck && max(abs(d1))>options_.solve_tolf ...@@ -137,55 +105,25 @@ if ~options_.steadystate.nocheck && max(abs(d1))>options_.solve_tolf
error('Jacobian is not evaluated at the steady state!') error('Jacobian is not evaluated at the steady state!')
end end
% current variables % Center the endogenous and exogenous variables around the deterministic steady state.
[r0,c0,v0] = find(jacobian(:,jc)); endogenousvariables = bsxfun(@minus, endogenousvariables, steadystate_y);
% current and predetermined exogenousvariables = bsxfun(@minus, exogenousvariables, transpose(steadystate_x));
[rT,cT,vT] = find(jacobian(:,jpc));
% current and jump variables
[r1,c1,v1] = find(jacobian(:,jcn));
% all endogenous variables
[rr,cc,vv] = find(jacobian(:,jendo));
iv0 = 1:length(v0);
ivT = 1:length(vT);
iv1 = 1:length(v1);
iv = 1:length(vv);
% Initialize the vector of residuals.
res = zeros(periods*ny, 1);
% Initialize the sparse Jacobian. if M_.maximum_lag > 0
iA = zeros(periods*M_.NNZDerivatives(1), 3); y0 = endogenousvariables(:, maximum_lag);
else
y0 = NaN(M_.endo_nbr, 1);
end
if M_.maximum_lead > 0
yT = endogenousvariables(:, maximum_lag+periods+1);
else
yT = NaN(M_.endo_nbr, 1);
end
Y = vec(endogenousvariables(:,maximum_lag+(1:periods)));
h2 = clock; h2 = clock;
i_rows = (1:ny)';
i_cols_A = ipcn; [res, A] = linear_perfect_foresight_problem(Y, jacobian, y0, yT, exogenousvariables, params, steadystate_y, maximum_lag, periods, ny);
i_cols = ipcn+(maximum_lag-1)*ny;
m = 0;
for it = (maximum_lag+1):(maximum_lag+periods)
if periods==1 && isequal(it, maximum_lag+1)
nv = length(v0);
iA(iv0+m,:) = [i_rows(r0),ic(c0),v0];
elseif isequal(it, maximum_lag+periods)
nv = length(vT);
iA(ivT+m,:) = [i_rows(rT), i_cols_A(jpc(cT)), vT];
elseif isequal(it, maximum_lag+1)
nv = length(v1);
iA(iv1+m,:) = [i_rows(r1), icn(c1), v1];
else
nv = length(vv);
iA(iv+m,:) = [i_rows(rr),i_cols_A(cc),vv];
end
z(jendo) = Y(i_cols);
z(jexog) = transpose(exogenousvariables(it,:));
res(i_rows) = jacobian*z;
m = m + nv;
i_rows = i_rows + ny;
i_cols = i_cols + ny;
if it > maximum_lag+1
i_cols_A = i_cols_A + ny;
end
end
% Evaluation of the maximum residual at the initial guess (steady state for the endogenous variables). % Evaluation of the maximum residual at the initial guess (steady state for the endogenous variables).
err = max(abs(res)); err = max(abs(res));
...@@ -201,12 +139,9 @@ if options_.debug ...@@ -201,12 +139,9 @@ if options_.debug
skipline() skipline()
end end
iA = iA(1:m,:);
A = sparse(iA(:,1), iA(:,2), iA(:,3), periods*ny, periods*ny);
% Try to update the vector of endogenous variables. % Try to update the vector of endogenous variables.
try try
Y(i_upd) = Y(i_upd) - A\res; Y = Y - A\res;
catch catch
% Normally, because the model is linear, the solution of the perfect foresight model should % Normally, because the model is linear, the solution of the perfect foresight model should
% be obtained in one Newton step. This is not the case if the model is singular. % be obtained in one Newton step. This is not the case if the model is singular.
...@@ -219,15 +154,13 @@ catch ...@@ -219,15 +154,13 @@ catch
return return
end end
i_cols = ipcn+(maximum_lag-1)*ny; YY = reshape([y0; Y; yT], ny, periods+2);
i_rows = (1:ny)'; i_rows = (1:ny)';
for it = (maximum_lag+1):(maximum_lag+periods) for t = 1:periods
z(jendo) = Y(i_cols); z = [ vec(YY(:,t+(0:2))); transpose(exogenousvariables(t+maximum_lag, :))];
z(jexog) = transpose(exogenousvariables(it,:));
m = m + nv;
res(i_rows) = jacobian*z; res(i_rows) = jacobian*z;
i_rows = i_rows + ny; i_rows = i_rows + ny;
i_cols = i_cols + ny;
end end
ERR = max(abs(res)); ERR = max(abs(res));
...@@ -239,7 +172,6 @@ end ...@@ -239,7 +172,6 @@ end
if any(isnan(res)) || any(isinf(res)) || any(isnan(Y)) || any(isinf(Y)) || ~isreal(res) || ~isreal(Y) if any(isnan(res)) || any(isinf(res)) || any(isnan(Y)) || any(isinf(Y)) || ~isreal(res) || ~isreal(Y)
success = false; % NaN or Inf occurred success = false; % NaN or Inf occurred
endogenousvariables = reshape(Y, ny, periods+maximum_lag+M_.maximum_lead);
if verbose if verbose
skipline() skipline()
if ~isreal(res) || ~isreal(Y) if ~isreal(res) || ~isreal(Y)
...@@ -251,9 +183,11 @@ if any(isnan(res)) || any(isinf(res)) || any(isnan(Y)) || any(isinf(Y)) || ~isre ...@@ -251,9 +183,11 @@ if any(isnan(res)) || any(isinf(res)) || any(isnan(Y)) || any(isinf(Y)) || ~isre
end end
else else
success = true; % Convergency obtained. success = true; % Convergency obtained.
endogenousvariables = bsxfun(@plus, reshape(Y, ny, periods+maximum_lag+M_.maximum_lead), steadystate_y);
end end
endogenousvariables(:,maximum_lag+(1:periods)) = reshape(Y, ny, periods);
endogenousvariables = bsxfun(@plus, endogenousvariables, steadystate_y);
if verbose if verbose
skipline(); skipline();
end end
...@@ -133,3 +133,15 @@ end ...@@ -133,3 +133,15 @@ end
if max(abs(endo_simul_0(:)-endo_simul_1(:)))>.01*options_.dynatol.f if max(abs(endo_simul_0(:)-endo_simul_1(:)))>.01*options_.dynatol.f
error('Something is wrong!') error('Something is wrong!')
end end
// Test stack_solve_algo=0+linear_approximation, which uses a different codepath than stack_solve_algo=7
perfect_foresight_setup(periods=300);
perfect_foresight_solver(linear_approximation, stack_solve_algo=0);
endo_simul_2 = oo_.endo_simul;
if ~oo_.deterministic_simulation.status
error('Perfect foresight simulation failed')
end
if max(abs(endo_simul_0(:)-endo_simul_2(:)))>.01*options_.dynatol.f
error('Something is wrong!')
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment