diff --git a/contrib/ms-sbvar/switch_dw b/contrib/ms-sbvar/switch_dw index ed0942d17..29c446f7f 160000 --- a/contrib/ms-sbvar/switch_dw +++ b/contrib/ms-sbvar/switch_dw @@ -1 +1 @@ -Subproject commit ed0942d17510fcc561e45d16c0e7a59f5646e597 +Subproject commit 29c446f7fe8a773860ebee347662c4ae2494c5e9 diff --git a/doc/dynare.texi b/doc/dynare.texi index 3ce0fb5f8..6ebe67ba0 100644 --- a/doc/dynare.texi +++ b/doc/dynare.texi @@ -8240,7 +8240,7 @@ command. Default: @code{`!'} @end table @end defmethod -@defmethod Report addGraph data, figname, showGrid, showLegend, showLegendBox, legendLocation, legendOrientation, legendFontSize, seriesToUse, shade, shadeColor, shadeOpacity, title, xlabel, ylabel, xrange, yrange, showZeroline +@defmethod Report addGraph data, figname, graphSize, showGrid, showLegend, showLegendBox, legendLocation, legendOrientation, legendFontSize, seriesToUse, shade, shadeColor, shadeOpacity, title, xlabel, ylabel, xrange, xTickLabels, yrange, showZeroline Adds a @code{Graph} to a @code{Section}. @optionshead @table @code @@ -8253,6 +8253,12 @@ The @code{dynSeries} that provides the data for the graph. Default: The name to use when saving this figure. Default: @code{[tempname `.tex']} +@item graphSize, @code{NUMERICAL_VECTOR} +The width and height to be passed to the third and fourth elements of +the array passed to the @code{`Position'} option of Matlab's +@code{figure} command, passed as a vector of size @math{2}. Default: +Matlab sets width and height + @item showGrid, @code{BOOLEAN} Whether or not to display the minor grid on the graph. Default: @code{true} @@ -8303,6 +8309,10 @@ The y-axis label. Default: @code{none} @item xrange, @code{dynDates} The boundary on the x-axis to display in the graph. Default: all +@item xTickLabels, @code{CELL_ARRAY_STRINGS} +The labels to use for the xticks in the graph. Default: the dates of +the @code{dynSeries} + @item yrange, @code{NUMERICAL_VECTOR} The boundary on the y-axis to display in the graph, represented as a @code{NUMERICAL_VECTOR} of size @math{2}, with the first entry less @@ -8349,7 +8359,7 @@ Whether or not to show vertical lines separating the columns. Default: @code{fal @end defmethod @anchor{addSeries} -@defmethod Report addSeries data, graphLineColor, graphLineStyle, graphLineWidth, graphMarker, graphMarkerEdgeColor, graphMarkerFaceColor, graphMarkerSize, tableShowMarkers, tableAlignRight, tableNegColor, tablePosColor +@defmethod Report addSeries data, graphLineColor, graphLineStyle, graphLineWidth, graphMarker, graphMarkerEdgeColor, graphMarkerFaceColor, graphMarkerSize, tableShowMarkers, tableAlignRight, tableNegColor, tablePosColor, zerotol Adds a @code{Series} to a @code{Graph} or a @code{Table}. @optionshead @table @code @@ -8403,6 +8413,11 @@ zero. Default: @code{`red'} The color to use when marking Table data that is greater than zero. Default: @code{`blue'} +@item zerotol, @code{DOUBLE} +The zero tolerance. Anything smaller than @code{zerotol} and larger +than @code{-zerotol} will be set to zero before being +graphed. Default: @math{1e-6} + @end table @end defmethod diff --git a/matlab/@dynDates/subsref.m b/matlab/@dynDates/subsref.m index b1ac3a4b0..65cc3c354 100644 --- a/matlab/@dynDates/subsref.m +++ b/matlab/@dynDates/subsref.m @@ -72,7 +72,7 @@ switch S(1).type if isint(S(1).subs{1}) && S(1).subs{1}>0 && S(1).subs{1}<=A.ndat B = dynDate(A.time(S(1).subs{1},:),A.freq); else - error(['dynDates::subsref: the index have to be a positive integer less than or equal to ' int2str(A.ndat) '!']) + error(['dynDates::subsref: the index has to be a positive integer less than or equal to ' int2str(A.ndat) '!']) end else if isvector(S(1).subs{1}) && all(isint(S(1).subs{1})) && all(S(1).subs{1}>0) && all(S(1).subs{1}<=A.ndat) @@ -81,7 +81,7 @@ switch S(1).type B.time = A.time(S(1).subs{1},:); B.ndat = length(S(1).subs{1}); else - error(['dynDates::subsref: indices have to be a vector of positive integers less than or equal to ' int2str(A.ndat) '!']) + error(['dynDates::subsref: indices has to be a vector of positive integers less than or equal to ' int2str(A.ndat) '!']) end end otherwise diff --git a/matlab/@dynSeries/minus.m b/matlab/@dynSeries/minus.m index 3154a9f32..52bb647a8 100644 --- a/matlab/@dynSeries/minus.m +++ b/matlab/@dynSeries/minus.m @@ -40,6 +40,41 @@ function A = minus(B,C) % You should have received a copy of the GNU General Public License % along with Dynare. If not, see . +if isnumeric(B) && isreal(B) && isequal(length(B),1) && isa(C,'dynSeries') + keyboard + A = dynSeries(); + A.freq = C.freq; + A.init = C.init; + A.time = C.time; + A.nobs = C.nobs; + A.vobs = C.vobs; + A.name = cell(A.vobs,1); + A.tex = cell(A.vobs,1); + for i=1:A.vobs + A.name(i) = {['minus(' num2str(B) ',' C.name{i} ')']}; + A.tex(i) = {['(' num2str(B) '-' C.tex{i} ')']}; + end + A.data = bsxfun(@minus, B, C.data); + return; +end + +if isnumeric(C) && isreal(C) && isequal(length(C),1) && isa(B,'dynSeries') + A = dynSeries(); + A.freq = B.freq; + A.init = B.init; + A.time = B.time; + A.nobs = B.nobs; + A.vobs = B.vobs; + A.name = cell(A.vobs,1); + A.tex = cell(A.vobs,1); + for i=1:A.vobs + A.name(i) = {['minus(' B.name{i} ',' num2str(C) ')']}; + A.tex(i) = {['(' B.tex{i} '-' num2str(C) ')']}; + end + A.data = bsxfun(@minus, B.data, C); + return; +end + if ~isequal(B.vobs,C.vobs) && ~(isequal(B.vobs,1) || isequal(C.vobs,1)) error(['dynSeries::minus: Cannot substract ' inputname(1) ' and ' inputname(2) ' (wrong number of variables)!']) else diff --git a/matlab/@dynSeries/plus.m b/matlab/@dynSeries/plus.m index 165039fc0..9ab3e58e7 100644 --- a/matlab/@dynSeries/plus.m +++ b/matlab/@dynSeries/plus.m @@ -40,6 +40,36 @@ function A = plus(B,C) % You should have received a copy of the GNU General Public License % along with Dynare. If not, see . +if isscalar(B) + assert(isa(C, 'dynSeries')); + b(1:size(C)) = B; + BB = dynSeries(b, C.time(1)); + BB.freq = C.freq; + BB.time = C.time; + BB.nobs = C.nobs; + BB.vobs = C.vobs; + BB.name = cell(BB.vobs,1); + BB.tex = cell(BB.vobs,1); + BB.name(1) = {num2str(B)}; + A = BB + C; + return; +end + +if isscalar(C) + assert(isa(B, 'dynSeries')); + c(1:size(C)) = C; + CC = dynSeries(C, B.time(1)); + CC.freq = B.freq; + CC.time = B.time; + CC.nobs = B.nobs; + CC.vobs = B.vobs; + CC.name = cell(CC.vobs,1); + CC.tex = cell(CC.vobs,1); + CC.name(1) = {num2str(C)}; + A = B + CC; + return; +end + if ~isequal(B.vobs,C.vobs) && ~(isequal(B.vobs,1) || isequal(C.vobs,1)) error(['dynSeries::plus: Cannot add ' inputname(1) ' and ' inputname(2) ' (wrong number of variables)!']) else diff --git a/matlab/dynare_solve.m b/matlab/dynare_solve.m index 613b01112..744a4734e 100644 --- a/matlab/dynare_solve.m +++ b/matlab/dynare_solve.m @@ -48,10 +48,10 @@ if jacobian_flag fprintf('\nSTEADY: The Jacobian contains Inf or NaN. The problem arises from: \n\n') for ii=1:length(infrow) if infcol(ii)<=M.orig_endo_nbr - fprintf('STEADY: Derivative of Equation %d with respect to Variable %s (initial value of %s: %g) \n',infrow(ii),M.endo_names(infcol(ii),:),M.endo_names(infcol(ii),:),x(infcol(ii))) + fprintf('STEADY: Derivative of Equation %d with respect to Variable %s (initial value of %s: %g) \n',infrow(ii),deblank(M.endo_names(infcol(ii),:)),deblank(M.endo_names(infcol(ii),:)),x(infcol(ii))) else %auxiliary vars orig_var_index=M.aux_vars(1,infcol(ii)-M.orig_endo_nbr).orig_index; - fprintf('STEADY: Derivative of Equation %d with respect to Variable %s (initial value of %s: %g) \n',infrow(ii),M.endo_names(orig_var_index,:),M.endo_names(orig_var_index,:),x(infcol(ii))) + fprintf('STEADY: Derivative of Equation %d with respect to Variable %s (initial value of %s: %g) \n',infrow(ii),deblank(M.endo_names(orig_var_index,:)),deblank(M.endo_names(orig_var_index,:)),x(infcol(ii))) end end fprintf('\nSTEADY: The problem most often occurs, because a variable with\n') diff --git a/matlab/lnsrch1.m b/matlab/lnsrch1.m index ef63f44d5..80af34462 100644 --- a/matlab/lnsrch1.m +++ b/matlab/lnsrch1.m @@ -50,6 +50,24 @@ x = xold; nn = length(j2); summ = sqrt(sum(p.*p)) ; if ~isfinite(summ) + eq_number_string=[]; + for ii=1:length(j1)-1 + eq_number_string=[eq_number_string, num2str(j1(ii)), ', ']; + end + eq_number_string=[eq_number_string, num2str(j1(end))]; + var_string=[]; + Model=evalin('base','M_'); + for ii=1:length(j2)-1 + var_string=[var_string, deblank(Model.endo_names(j2(ii),:)), ', ']; + end + var_string=[var_string, deblank(Model.endo_names(j2(end),:))]; + fprintf('\nAn infinite element was encountered when trying to solve equation(s) %s \n',eq_number_string) + fprintf('with respect to the variable(s): %s.\n',var_string) + fprintf('The values of the endogenous variables when the problem was encountered were:\n') + for ii=1:length(xold) + fprintf('%-s % 8.4g \n',Model.endo_names(ii,:),xold(ii)); + end + skipline(); error(['Some element of Newton direction isn''t finite. Jacobian maybe' ... ' singular or there is a problem with initial values']) end diff --git a/matlab/reports/@graph/createGraph.m b/matlab/reports/@graph/createGraph.m index 69e73c4f1..48f1c3771 100755 --- a/matlab/reports/@graph/createGraph.m +++ b/matlab/reports/@graph/createGraph.m @@ -38,7 +38,11 @@ if ~o.seriesElements.numSeriesElements() return; end -h = figure('visible','off'); +if isempty(o.graphSize) + h = figure('visible','off'); +else + h = figure('visible','off','position',[1, 1, o.graphSize(1), o.graphSize(2)]); +end hold on; box on; if o.showGrid @@ -94,15 +98,19 @@ if ~isempty(o.shade) set(gca, 'children', children); end -xticks = get(gca, 'XTick'); -xTickLabels = cell(1, length(xticks)); -for i=1:length(xticks) - if xticks(i) >= x(1) && ... - xticks(i) <= x(end) - xTickLabels{i} = xlabels{xticks(i)}; - else - xTickLabels{i} = ''; +if isempty(o.xTickLabels) + xticks = get(gca, 'XTick'); + xTickLabels = cell(1, length(xticks)); + for i=1:length(xticks) + if xticks(i) >= x(1) && ... + xticks(i) <= x(end) + xTickLabels{i} = xlabels{xticks(i)}; + else + xTickLabels{i} = ''; + end end +else + xTickLabels = o.xTickLabels; end set(gca, 'XTickLabel', xTickLabels); diff --git a/matlab/reports/@graph/graph.m b/matlab/reports/@graph/graph.m index a92003b12..72273c7f9 100644 --- a/matlab/reports/@graph/graph.m +++ b/matlab/reports/@graph/graph.m @@ -59,6 +59,9 @@ o.legendFontSize = 8; o.showZeroline = false; +o.graphSize = []; +o.xTickLabels = {}; + if nargin == 1 assert(isa(varargin{1}, 'graph'),['@graph.graph: with one arg you ' ... 'must pass a graph object']); @@ -127,6 +130,11 @@ assert(isempty(o.data) || isa(o.data, 'dynSeries'), ['@graph.graph: data must ' assert(isempty(o.seriesToUse) || iscellstr(o.seriesToUse), ['@graph.graph: ' ... 'series to use must be a cell array of string(s)']); +assert(isempty(o.graphSize) || ((isfloat(o.graphSize) && length(o.graphSize) == 2)),... + ['@graph.graph: graphSize is specified as an array with two float ' ... + 'entries, [width height]']); +assert(iscellstr(o.xTickLabels), ... + '@graph.graph: xTickLabels must be a cell array of strings'); % using o.seriesToUse, create series objects and put them in o.seriesElements if ~isempty(o.data) if isempty(o.seriesToUse) diff --git a/matlab/reports/@series/getLine.m b/matlab/reports/@series/getLine.m index c1f61c61c..829bf8222 100644 --- a/matlab/reports/@series/getLine.m +++ b/matlab/reports/@series/getLine.m @@ -60,6 +60,9 @@ assert(~(strcmp(o.graphLineStyle, 'none') && isempty(o.graphMarker)), ['@series. % Validate xrange assert(isempty(xrange) || isa(xrange, 'dynDates')); +% Zero tolerance +assert(isfloat(o.zerotol), '@series.write: zerotol must be a float'); + %% if isempty(xrange) || xrange == o.data.time ds = o.data; @@ -67,8 +70,18 @@ else ds = o.data(xrange); end -opt = {'XData', 1:length(ds.data)}; -opt = {opt{:}, 'YData', ds.data}; +% if graphing data that is within zerotol, set to zero, create series and +% get line: +thedata = ds.data; +stz = bsxfun(@and, ... + bsxfun(@lt, thedata, o.zerotol), ... + bsxfun(@gt, thedata, -o.zerotol)); +if any(stz) + thedata(stz) = 0; +end + +opt = {'XData', 1:length(thedata)}; +opt = {opt{:}, 'YData', thedata}; opt = {opt{:}, 'Color', o.graphLineColor}; opt = {opt{:}, 'LineStyle', o.graphLineStyle}; diff --git a/matlab/reports/@series/series.m b/matlab/reports/@series/series.m index cf6f2db9a..6493dced7 100644 --- a/matlab/reports/@series/series.m +++ b/matlab/reports/@series/series.m @@ -51,6 +51,8 @@ o.tableMarkerLimit = 1e-4; o.tableAlignRight = false; +o.zerotol = 1e-6; + if nargin == 1 assert(isa(varargin{1}, 'series'),['@series.series: with one arg you ' ... 'must pass a series object']); diff --git a/matlab/simul.m b/matlab/simul.m index 007a0d77b..c9fb8f896 100644 --- a/matlab/simul.m +++ b/matlab/simul.m @@ -79,6 +79,22 @@ end options_.scalv= 1 ; +if options_.debug + model_static = str2func([M_.fname,'_static']); + for ii=1:size(oo_.exo_simul,1) + [residual(:,ii)] = model_static(oo_.steady_state, oo_.exo_simul(ii,:),M_.params); + end + problematic_periods=find(any(isinf(residual)) | any(isnan(residual)))-M_.maximum_endo_lag; + if ~isempty(problematic_periods) + period_string=num2str(problematic_periods(1)); + for ii=2:length(problematic_periods) + period_string=[period_string, ', ', num2str(problematic_periods(ii))]; + end + fprintf('\n\nWARNING: Value for the exogenous variable(s) in period(s) %s inconsistent with the static model.\n',period_string); + fprintf('WARNING: Check for division by 0.\n') + end +end + if(options_.block) if(options_.bytecode) [info, oo_.endo_simul] = bytecode('dynamic');