function [y, info] = solve_one_boundary(fname, y, x, params, steady_state, ... 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) % Computes the deterministic simulation of a block of equation containing % lead or lag variables % % 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 % steady_state [vector] steady state of the model % 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 % Newton algorithm : % - 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 % indirect_call [integer] (0) direct call to the fname % (1) indirect call via the % local_fname wrapper % OUTPUTS % y [matrix] All endogenous variables of the model % info [integer] >=0 no error % <0 error % % ALGORITHM % Newton with LU or GMRES or BicGstab for dynamic block % % SPECIAL REQUIREMENTS % none. % % Copyright (C) 1996-2018 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 . Blck_size=size(y_index_eq,2); g2 = []; g3 = []; correcting_factor=0.01; ilu_setup.droptol=1e-10; max_resa=1e100; reduced = 0; if forward_backward incr = 1; start = y_kmin+1; finish = periods+y_kmin; else incr = -1; start = periods+y_kmin; finish = y_kmin+1; end for it_=start:incr:finish cvg=0; iter=0; g1=spalloc( Blck_size, Blck_size, nze); while ~(cvg==1 || iter>maxit_) if is_dynamic [r, y, g1, g2, g3] = feval(fname, y, x, params, steady_state, it_, 0); else [r, y, g1] = feval(fname, y, x, params); end if ~isreal(r) max_res=(-(max(max(abs(r))))^2)^0.5; else max_res=max(max(abs(r))); end if verbose==1 disp(['iteration : ' int2str(iter+1) ' => ' num2str(max_res) ' time = ' int2str(it_)]) if is_dynamic disp([M.endo_names{y_index_eq} num2str([y(it_,y_index_eq)' r g1])]) else disp([M.endo_names{y_index_eq} num2str([y(y_index_eq) r g1])]) end end if ~isreal(max_res) || isnan(max_res) cvg = 0; elseif is_linear && iter>0 cvg = 1; else cvg=(max_res0 if ~isreal(max_res) || isnan(max_res) || (max_resa1) if isnan(max_res) || (max_resa0) detJ=det(g1a); if(abs(detJ)<1e-7) max_factor=max(max(abs(g1a))); ze_elem=sum(diag(g1a)1e-8 lambda=lambda/2; reduced = 1; if verbose disp(['reducing the path length: lambda=' num2str(lambda,'%f')]) end if is_dynamic y(it_,y_index_eq)=ya_save-lambda*dx; else y(y_index_eq)=ya_save-lambda*dx; end continue else 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 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; end info = -Block_Num*10; return end else if lambda<1 lambda=max(lambda*2, 1); end end end if is_dynamic ya = y(it_,y_index_eq)'; else ya = y(y_index_eq); end ya_save=ya; g1a=g1; if ~is_dynamic && options.solve_algo==0 if verbose disp('steady: fsolve') end if ~isoctave if ~user_has_matlab_license('optimization_toolbox') error('SOLVE_ONE_BOUNDARY: you can''t use solve_algo=0 since you don''t have MATLAB''s Optimization Toolbox') end end options=optimset('fsolve'); options.MaxFunEvals = 50000; options.MaxIter = 2000; options.TolFun=1e-8; options.Display = 'iter'; options.Jacobian = 'on'; if ~isoctave [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)); if max(abs(fvec)) >= options.solve_tolf [yn,fval,exitval,output] = fsolve(func,y(y_index_eq),options); else yn = y(y_index_eq); exitval = 3; end end y(y_index_eq) = yn; if exitval > 0 info = 0; else info = -Block_Num*10; end elseif (~is_dynamic && options.solve_algo==2) || (is_dynamic && stack_solve_algo==4) if verbose==1 && ~is_dynamic disp('steady: LU + lnsrch1') end lambda=1; stpmx = 100 ; if is_dynamic stpmax = stpmx*max([sqrt(ya'*ya);size(y_index_eq,2)]); else stpmax = stpmx*max([sqrt(ya'*ya);size(y_index_eq,2)]); end nn=1:size(y_index_eq,2); g = (r'*g1)'; f = 0.5*r'*r; p = -g1\r ; if is_dynamic [ya,f,r,check]=lnsrch1(y(it_,:)',f,g,p,stpmax, ... 'lnsrch1_wrapper_one_boundary',nn, ... y_index_eq, options.solve_tolx, y_index_eq, fname, y, x, params, steady_state, it_); dx = ya' - y(it_, :); else [ya,f,r,check]=lnsrch1(y,f,g,p,stpmax,fname,nn,y_index_eq, options.solve_tolx, x, ... params, steady_state,0); dx = ya - y(y_index_eq); end if is_dynamic y(it_,:) = ya'; else y = ya'; end elseif ~is_dynamic && options.solve_algo==3 if verbose==1 disp('steady: csolve') end [yn,info] = csolve(@local_fname, y(y_index_eq),@ ... local_fname,1e-6,500, x, params, steady_state, y, y_index_eq, fname, 1); dx = ya - yn; y(y_index_eq) = yn; 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 ') end dx = g1\r; ya = ya - lambda*dx; if is_dynamic y(it_,y_index_eq) = ya'; else y(y_index_eq) = ya; end elseif (stack_solve_algo==2 && is_dynamic) || (options.solve_algo==7 && ~is_dynamic) flag1=1; if verbose == 1 && ~is_dynamic disp('steady: GMRES ') end while flag1>0 [L1, U1]=ilu(g1,ilu_setup); [dx,flag1] = gmres(g1,-r,Blck_size,1e-6,Blck_size,L1,U1); 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 ilu_setup.droptol = ilu_setup.droptol/10; reduced = 0; else ya = ya + lambda*dx; if is_dynamic y(it_,y_index_eq) = ya'; else y(y_index_eq) = ya'; end end end elseif (stack_solve_algo==3 && is_dynamic) || (options.solve_algo==8 && ~is_dynamic) flag1=1; if verbose == 1 && ~is_dynamic disp('steady: BiCGStab') end while flag1>0 [L1, U1]=ilu(g1,ilu_setup); phat = ya - U1 \ (L1 \ r); if is_dynamic y(it_,y_index_eq) = phat; else y(y_index_eq) = phat; end if is_dynamic [r, y, g1, g2, g3] = feval(fname, y, x, params, ... steady_state, it_, 0); else [r, y, g1] = feval(fname, y, x, params); end if max(abs(r))>=options.solve_tolf [dx,flag1] = bicgstab(g1,-r,1e-7,Blck_size,L1,U1); else flag1 = 0; dx = phat - ya; 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 ilu_setup.droptol = ilu_setup.droptol/10; reduced = 0; else ya = ya + lambda*dx; if is_dynamic y(it_,y_index_eq) = ya'; else y(y_index_eq) = ya'; end end end else 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 info = -Block_Num*10; return end iter=iter+1; max_resa = max_res; end end if cvg==0 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) 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; end info = -Block_Num*10; return end end if is_dynamic info = 1; 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; else info = 0; end function [err, G]=local_fname(yl, x, params, steady_state, y, y_index_eq, fname, is_csolve) y(y_index_eq) = yl; [err, y, G] = feval(fname, y, x, params, steady_state, 0); if(is_csolve) G = full(G); end