function [dr, info] = dyn_first_order_solver(jacobia, DynareModel, dr, DynareOptions, task) % Computes the first order reduced form of a DSGE model. % % INPUTS % - jacobia [double] matrix, the jacobian of the dynamic model. % - DynareModel [struct] Matlab's structre describing the model, M_ global. % - dr [struct] Matlab's structure describing the reduced form model. % - DynareOptions [struct] Matlab's structure containing the current state of the options, oo_ global. % - task [integer] scalar, if task = 0 then decision rules are computed and if task = 1 then only eigenvales are computed. % % OUTPUTS % - dr [struct] Matlab's structure describing the reduced form model. % - info [integer] scalar, error code. Possible values are: % % info=0 -> no error, % info=1 -> the model doesn't determine the current variables uniquely, % info=2 -> mjdgges dll returned an error, % info=3 -> Blanchard and Kahn conditions are not satisfied: no stable equilibrium, % info=4 -> Blanchard and Kahn conditions are not satisfied: indeterminacy, % info=5 -> Blanchard and Kahn conditions are not satisfied: indeterminacy due to rank failure, % info=7 -> One of the eigenvalues is close to 0/0 (infinity of complex solutions) % Copyright (C) 2001-2020 Dynare Team % % 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 . persistent reorder_jacobian_columns innovations_idx index_s index_m index_c persistent index_p row_indx index_0m index_0p k1 k2 state_var persistent ndynamic nstatic nfwrd npred nboth nd nsfwrd n_current index_d persistent index_e index_d1 index_d2 index_e1 index_e2 row_indx_de_1 persistent row_indx_de_2 cols_b if ~nargin if nargout error('dyn_first_order_solver:: Initialization mode returns zero argument!') end reorder_jacobian_columns = []; return end exo_nbr = DynareModel.exo_nbr; if isempty(reorder_jacobian_columns) maximum_lag = DynareModel.maximum_endo_lag; kstate = dr.kstate; nfwrd = DynareModel.nfwrd; nboth = DynareModel.nboth; npred = DynareModel.npred; nstatic = DynareModel.nstatic; ndynamic = DynareModel.ndynamic; nsfwrd = DynareModel.nsfwrd; n = DynareModel.endo_nbr; k1 = 1:(npred+nboth); k2 = 1:(nfwrd+nboth); order_var = dr.order_var; nd = size(kstate,1); lead_lag_incidence = DynareModel.lead_lag_incidence; nz = nnz(lead_lag_incidence); lead_id = find(lead_lag_incidence(maximum_lag+2,:)); lead_idx = lead_lag_incidence(maximum_lag+2,lead_id); if maximum_lag lag_id = find(lead_lag_incidence(1,:)); lag_idx = lead_lag_incidence(1,lag_id); static_id = find((lead_lag_incidence(1,:) == 0) & ... (lead_lag_incidence(3,:) == 0)); else lag_id = []; lag_idx = []; static_id = find(lead_lag_incidence(2,:)==0); end both_id = intersect(lead_id,lag_id); if maximum_lag no_both_lag_id = setdiff(lag_id,both_id); else no_both_lag_id = lag_id; end innovations_idx = nz+(1:exo_nbr); state_var = [no_both_lag_id, both_id]; index_c = nonzeros(lead_lag_incidence(maximum_lag+1,:)); % Index of all endogenous variables present at time=t n_current = length(index_c); index_s = npred+nboth+(1:nstatic); % Index of all static % endogenous variables % present at time=t indexi_0 = npred+nboth; npred0 = nnz(lead_lag_incidence(maximum_lag+1,no_both_lag_id)); index_0m = indexi_0+nstatic+(1:npred0); nfwrd0 = nnz(lead_lag_incidence(maximum_lag+1,lead_id)); index_0p = indexi_0+nstatic+npred0+(1:nfwrd0); index_m = 1:(npred+nboth); index_p = npred+nboth+n_current+(1:nfwrd+nboth); row_indx_de_1 = 1:ndynamic; row_indx_de_2 = ndynamic+(1:nboth); row_indx = nstatic+row_indx_de_1; index_d = [index_0m index_p]; llx = lead_lag_incidence(:,order_var); index_d1 = [find(llx(maximum_lag+1,nstatic+(1:npred))), npred+nboth+(1:nsfwrd) ]; index_d2 = npred+(1:nboth); index_e = [index_m index_0p]; index_e1 = [1:npred+nboth, npred+nboth+find(llx(maximum_lag+1,nstatic+npred+(1: ... nsfwrd)))]; index_e2 = npred+nboth+(1:nboth); [~,cols_b] = find(lead_lag_incidence(maximum_lag+1, order_var)); reorder_jacobian_columns = [nonzeros(lead_lag_incidence(:,order_var)'); ... nz+(1:exo_nbr)']; end dr.ghx = []; dr.ghu = []; dr.state_var = state_var; jacobia = jacobia(:,reorder_jacobian_columns); if nstatic > 0 [Q, ~] = qr(jacobia(:,index_s)); aa = Q'*jacobia; else aa = jacobia; end A = aa(:,index_m); % Jacobain matrix for lagged endogeneous variables B(:,cols_b) = aa(:,index_c); % Jacobian matrix for contemporaneous endogeneous variables C = aa(:,index_p); % Jacobain matrix for led endogeneous variables info = 0; if task ~= 1 && (DynareOptions.dr_cycle_reduction || DynareOptions.dr_logarithmic_reduction) if n_current < DynareModel.endo_nbr if DynareOptions.dr_cycle_reduction error(['The cycle reduction algorithme can''t be used when the ' ... 'coefficient matrix for current variables isn''t invertible']) elseif DynareOptions.dr_logarithmic_reduction error(['The logarithmic reduction algorithme can''t be used when the ' ... 'coefficient matrix for current variables isn''t invertible']) end end if DynareOptions.gpu gpuArray(A1); gpuArray(B1); gpuArray(C1); end A1 = [aa(row_indx,index_m ) zeros(ndynamic,nfwrd)]; B1 = [aa(row_indx,index_0m) aa(row_indx,index_0p) ]; C1 = [zeros(ndynamic,npred) aa(row_indx,index_p)]; if DynareOptions.dr_cycle_reduction [ghx, info] = cycle_reduction(A1, B1, C1, DynareOptions.dr_cycle_reduction_tol); else [ghx, info] = logarithmic_reduction(C1, B1, A1, DynareOptions.dr_logarithmic_reduction_tol, DynareOptions.dr_logarithmic_reduction_maxiter); end if info % cycle_reduction or logarithmic redution failed and set info return end ghx = ghx(:,index_m); hx = ghx(1:npred+nboth,:); gx = ghx(1+npred:end,:); else D = zeros(ndynamic+nboth); E = zeros(ndynamic+nboth); D(row_indx_de_1,index_d1) = aa(row_indx,index_d); D(row_indx_de_2,index_d2) = eye(nboth); E(row_indx_de_1,index_e1) = -aa(row_indx,index_e); E(row_indx_de_2,index_e2) = eye(nboth); [ss, tt, w, sdim, dr.eigval, info1] = mjdgges(E, D, DynareOptions.qz_criterium, DynareOptions.qz_zero_threshold); if info1 if info1 == -30 % one eigenvalue is close to 0/0 info(1) = 7; else info(1) = 2; info(2) = info1; info(3) = size(E,2); end return end dr.sdim = sdim; % Number of stable eigenvalues. dr.edim = length(dr.eigval)-sdim; % Number of exposive eigenvalues. nba = nd-sdim; if task==1 if rcond(w(npred+nboth+1:end,npred+nboth+1:end)) < 1e-9 dr.full_rank = 0; else dr.full_rank = 1; end end if nba ~= nsfwrd temp = sort(abs(dr.eigval)); if nba > nsfwrd temp = temp(nd-nba+1:nd-nsfwrd)-1-DynareOptions.qz_criterium; info(1) = 3; elseif nba < nsfwrd temp = temp(nd-nsfwrd+1:nd-nba)-1-DynareOptions.qz_criterium; info(1) = 4; end info(2) = temp'*temp; return end if task==1, return, end %First order approximation indx_stable_root = 1: (nd - nsfwrd); %=> index of stable roots indx_explosive_root = npred + nboth + 1:nd; %=> index of explosive roots % derivatives with respect to dynamic state variables % forward variables Z = w'; Z11 = Z(indx_stable_root, indx_stable_root); Z21 = Z(indx_explosive_root, indx_stable_root); Z22 = Z(indx_explosive_root, indx_explosive_root); opts.TRANSA = false; % needed by Octave 4.0.0 [minus_gx,rc] = linsolve(Z22,Z21,opts); if rc < 1e-9 % Z22 is near singular info(1) = 5; info(2) = -log(rc); return end gx = -minus_gx; % predetermined variables opts.UT = true; opts.TRANSA = true; hx1 = linsolve(tt(indx_stable_root, indx_stable_root),Z11,opts)'; opts.UT = false; % needed by Octave 4.0.0 opts.TRANSA = false; % needed by Octave 4.0.0 hx2 = linsolve(Z11,ss(indx_stable_root, indx_stable_root)',opts)'; hx = hx1*hx2; ghx = [hx(k1,:); gx(k2(nboth+1:end),:)]; end if nstatic > 0 B_static = B(:,1:nstatic); % submatrix containing the derivatives w.r. to static variables else B_static = []; end %static variables, backward variable, mixed variables and forward variables B_pred = B(:,nstatic+1:nstatic+npred+nboth); B_fyd = B(:,nstatic+npred+nboth+1:end); % static variables if nstatic > 0 temp = - C(1:nstatic,:)*gx*hx; b(:,cols_b) = aa(:,index_c); b10 = b(1:nstatic, 1:nstatic); b11 = b(1:nstatic, nstatic+1:end); temp(:,index_m) = temp(:,index_m)-A(1:nstatic,:); temp = b10\(temp-b11*ghx); ghx = [temp; ghx]; temp = []; end A_ = real([B_static C*gx+B_pred B_fyd]); % The state_variable of the block are located at [B_pred B_both] if exo_nbr if nstatic > 0 fu = Q' * jacobia(:,innovations_idx); else fu = jacobia(:,innovations_idx); end ghu = - A_ \ fu; else ghu = []; end dr.ghx = ghx; dr.ghu = ghu; if DynareOptions.aim_solver ~= 1 % Necessary when using Sims' routines for QZ dr.ghx = real(ghx); dr.ghu = real(ghu); hx = real(hx); end % non-predetermined variables dr.gx = gx; %predetermined (endogenous state) variables, square transition matrix dr.Gy = hx;