diff --git a/matlab/+occbin/DSGE_smoother.m b/matlab/+occbin/DSGE_smoother.m
index 6fa4a27fe13d33781d1da1a7d268e41f5a47d6d9..364b328862aaf3b86735f10fcbe5c26117419457 100644
--- a/matlab/+occbin/DSGE_smoother.m
+++ b/matlab/+occbin/DSGE_smoother.m
@@ -124,6 +124,8 @@ occbin_options.opts_regime.binding_indicator = options_.occbin.smoother.init_bin
 occbin_options.opts_regime.regime_history=options_.occbin.smoother.init_regime_history;
 
 error_indicator=false;
+options_.noprint = true;
+
 try
     %blanket try-catch should be replaced be proper error handling, see https://git.dynare.org/Dynare/dynare/-/merge_requests/2226#note_20318
     [alphahat,etahat,epsilonhat,ahat,SteadyState,trend_coeff,aK,T0,R0,P,PK,decomp,Trend,state_uncertainty,oo_,bayestopt_,alphahat0,state_uncertainty0] = DsgeSmoother(xparam1,gend,Y,data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_,occbin_options);%     T1=TT;
@@ -178,7 +180,6 @@ opts_simul.endo_init = alphahat0(oo_.dr.inv_order_var,1);
 opts_simul.init_regime=regime_history; % use realtime regime for guess, to avoid multiple solution issues!
 opts_simul.periods = size(opts_simul.SHOCKS,1);
 options_.occbin.simul=opts_simul;
-options_.noprint = true;
 [~, out, ss] = occbin.solver(M_,options_,oo_.dr,oo_.steady_state,oo_.exo_steady_state,oo_.exo_det_steady_state);
 if out.error_flag
     fprintf('Occbin smoother:: simulation within smoother did not converge.\n')
diff --git a/matlab/+occbin/IVF_core.m b/matlab/+occbin/IVF_core.m
index 30666cd3220ee8bcd99793c54a9f9442514e4f45..f3d4c4650798a14d2e9dcc542b158fec5f60401d 100644
--- a/matlab/+occbin/IVF_core.m
+++ b/matlab/+occbin/IVF_core.m
@@ -1,4 +1,4 @@
-function [filtered_errs, resids, Emat, stateval, error_code] = IVF_core(M_,dr, endo_steady_state, exo_steady_state, exo_det_steady_state,options_,err_index,filtered_errs_init,my_obs_list,obs,init_val)
+function [filtered_errs, resids, Emat, stateval, error_code, regime_history] = IVF_core(M_,dr, endo_steady_state, exo_steady_state, exo_det_steady_state,options_,err_index,filtered_errs_init,my_obs_list,obs,init_val)
 % [filtered_errs, resids, Emat, stateval, error_code] = IVF_core(M_,dr, endo_steady_state, exo_steady_state, exo_det_steady_state,options_,err_index,filtered_errs_init,my_obs_list,obs,init_val)
 % Calls the solver to get the shocks explaining the data for the inversion filter
 %
@@ -92,6 +92,9 @@ for this_period=1:sample_length
         filtered_errs=NaN;
         error_code(1) = 304;
         error_code(4) = 1000;
+        if this_period == 1
+            regime_history(this_period) = [];
+        end
         if options_.occbin.likelihood.waitbar; dyn_waitbar_close(hh_fig); end
         return
     end
@@ -99,9 +102,10 @@ for this_period=1:sample_length
 
     opts_simul.SHOCKS = err_vals_out;
 
-    [ resids(this_period,inan), ~, stateval(this_period,:), Emat(:,inan,this_period), M_] = occbin.match_function(...
+    [ resids(this_period,inan), ~, stateval(this_period,:), Emat(:,inan,this_period), M_, out] = occbin.match_function(...
         err_vals_out,obs_list,current_obs,opts_simul, M_,dr, endo_steady_state, exo_steady_state, exo_det_steady_state,options_);
     init_val = stateval(this_period,:); %update
+    regime_history(this_period) = out.regime_history(1);
     if max(abs(err_vals_out))>1e8
         error_code(1) = 306;
         error_code(4) = max(abs(err_vals_out))/1000;
diff --git a/matlab/+occbin/IVF_posterior.m b/matlab/+occbin/IVF_posterior.m
index 69c6c110ddb34815d31c8df8701ae1e24c5fe29a..dbfcaa9c8eac2c42f8f8f96918f59228017e1780 100644
--- a/matlab/+occbin/IVF_posterior.m
+++ b/matlab/+occbin/IVF_posterior.m
@@ -1,4 +1,4 @@
-function [fval,info,exit_flag,DLIK,Hess,SteadyState,trend_coeff,M_,options_,bayestopt_,dr, atT, innov] = IVF_posterior(xparam1,...
+function [fval,info,exit_flag,DLIK,Hess,SteadyState,trend_coeff,M_,options_,bayestopt_,dr, atT, innov, regime_history] = IVF_posterior(xparam1,...
     dataset_,dataset_info,options_,M_,estim_params_,bayestopt_,BoundsInfo,dr, endo_steady_state, exo_steady_state, exo_det_steady_state)
 % [fval,info,exit_flag,DLIK,Hess,SteadyState,trend_coeff,M_,options_,bayestopt_,dr, atT, innov] = IVF_posterior(xparam1,...
 %     dataset_,dataset_info,options_,M_,estim_params_,bayestopt_,BoundsInfo,dr, endo_steady_state, exo_steady_state, exo_det_steady_state)
@@ -58,6 +58,8 @@ trend_coeff = [];
 obs = dataset_.data;
 obs_list = options_.varobs(:);
 exit_flag   = 1;
+% initialize output argument in case of early return
+regime_history = [];
 
 
 if size(xparam1,1)<size(xparam1,2)
@@ -107,7 +109,7 @@ end
 sample_length = size(obs,1);
 filtered_errs_init = zeros(sample_length,sum(err_index));
 
-[filtered_errs, resids, Emat, stateval, info] = occbin.IVF_core(M_,dr,endo_steady_state,exo_steady_state,exo_det_steady_state,options_,err_index,filtered_errs_init,obs_list,obs);
+[filtered_errs, resids, Emat, stateval, info, regime_history] = occbin.IVF_core(M_,dr,endo_steady_state,exo_steady_state,exo_det_steady_state,options_,err_index,filtered_errs_init,obs_list,obs);
 if info(1)
     fval = Inf;
     exit_flag = 0;
diff --git a/matlab/+occbin/kalman_update_algo_1.m b/matlab/+occbin/kalman_update_algo_1.m
index 11205e63e0c80159a2af1994e51d4ca4a5a5acd6..83cbd587ba8f3ae9e440bd46ce7e1743d54a5f1e 100644
--- a/matlab/+occbin/kalman_update_algo_1.m
+++ b/matlab/+occbin/kalman_update_algo_1.m
@@ -213,7 +213,12 @@ if any(myregime) || ~isequal(regimes_(1),regimes0(1))
         if M_.occbin.constraint_nbr==1
             regime_end(niter) = regimes_(1).regimestart(end);
         end
-        [a, a1, P, P1, v, alphahat, etahat, lik, V] = occbin_kalman_update0(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,iF,L,mm, options_.rescale_prediction_error_covariance, options_.occbin.likelihood.IF_likelihood, options_.occbin.filter.state_covariance);
+        [a, a1, P, P1, v, alphahat, etahat, lik, V, error_flag] = occbin_kalman_update0(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,iF,L,mm, options_.rescale_prediction_error_covariance, options_.occbin.likelihood.IF_likelihood, options_.occbin.filter.state_covariance);
+        if error_flag
+            etahat=NaN(size(QQQ,1),1);
+            warning(orig_warning_state);
+            return;
+        end
         etahat_hist(niter) = {etahat};
         lik_hist(niter) = lik;
         opts_simul.SHOCKS(1,:) = etahat(:,2)';
@@ -278,7 +283,12 @@ if any(myregime) || ~isequal(regimes_(1),regimes0(1))
                         TT(:,:,2)=ss.T(my_order_var,my_order_var,1);
                         RR(:,:,2)=ss.R(my_order_var,:,1);
                         CC(:,2)=ss.C(my_order_var,1);
-                        [a, a1, P, P1, v, alphahat, etahat, lik, V] = occbin_kalman_update0(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,iF,L,mm, options_.rescale_prediction_error_covariance, options_.occbin.likelihood.IF_likelihood, options_.occbin.filter.state_covariance);
+                        [a, a1, P, P1, v, alphahat, etahat, lik, V, error_flag] = occbin_kalman_update0(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,iF,L,mm, options_.rescale_prediction_error_covariance, options_.occbin.likelihood.IF_likelihood, options_.occbin.filter.state_covariance);
+                        if error_flag
+                            etahat=NaN(size(QQQ,1),1);
+                            warning(orig_warning_state);
+                            return;
+                        end
                     end
                 else
                     error_flag = 330;
@@ -294,7 +304,7 @@ end
 
 error_flag = out.error_flag;
 if ~error_flag && niter>options_.occbin.likelihood.max_number_of_iterations && ~isequal(regimes_(1),regimes0(1))
-    error_flag = 1;
+    error_flag = 331;
 end
 
 if ~error_flag
@@ -357,7 +367,7 @@ else
     F = ZZ*P(:,:,t)*ZZ' + H(di,di);
     sig=sqrt(diag(F));
     if any(any(isnan(F)))
-        error_flag=1;
+        error_flag=325;
         warning(orig_warning_state);
         return;
     end
diff --git a/matlab/+occbin/kalman_update_algo_3.m b/matlab/+occbin/kalman_update_algo_3.m
index 457c47480666f57757ceeca79d35c83fe6883b5e..efffc9badbb50593472ba8681a4f0d2133733efc 100644
--- a/matlab/+occbin/kalman_update_algo_3.m
+++ b/matlab/+occbin/kalman_update_algo_3.m
@@ -282,7 +282,7 @@ end
 
 error_flag = out.error_flag;
 if ~error_flag && niter>options_.occbin.likelihood.max_number_of_iterations && ~isequal(regimes_(1),regimes0(1)) %fixed point algorithm did not converge
-  error_flag = 1;
+  error_flag = 331;
 end
 
 if ~error_flag
diff --git a/matlab/+occbin/kalman_update_engine.m b/matlab/+occbin/kalman_update_engine.m
index fe2346436ad94fa82febe265bb9bbd70ac83fcad..3459a26712cdb504bbc9852ee227ee886914a9fd 100644
--- a/matlab/+occbin/kalman_update_engine.m
+++ b/matlab/+occbin/kalman_update_engine.m
@@ -1,6 +1,6 @@
 function [ax, a1x, Px, P1x, vx, Tx, Rx, Cx, regx, info, M_, likx, etahat, alphahat, V, Fix, Kix, TTx,RRx,CCx] = ...
-                    kalman_update_engine(a0,a1,P0,P1,t,data_index,Z,vv,Y,H,Qt,T0,R0,TT,RR,CC,regimes_,base_regime,d_index,M_,...
-                    dr,endo_steady_state,exo_steady_state,exo_det_steady_state,options_,occbin_options, Fi,Ki,kalman_tol,nk)
+    kalman_update_engine(a0,a1,P0,P1,t,data_index,Z,vv,Y,H,Qt,T0,R0,TT,RR,CC,regimes_,base_regime,d_index,M_,...
+    dr,endo_steady_state,exo_steady_state,exo_det_steady_state,options_,occbin_options, Fi,Ki,kalman_tol,nk)
 % [ax, a1x, Px, P1x, vx, Tx, Rx, Cx, regx, info, M_, likx, etahat, alphahat, V, Fix, Kix, TTx,RRx,CCx] = kalman_update_engine(
 %                                       a0,a1,P0,P1,t,data_index,Z,vv,Y,H,Qt,T0,R0,TT,RR,CC,regimes_,base_regime,d_index,M_,
 %                                       dr,endo_steady_state,exo_steady_state,exo_det_steady_state,options_,occbin_options, Fi,Ki,kalman_tol,nk)
@@ -32,13 +32,14 @@ if nargin>26
     is_multivariate = false;
 end
 
-use_relaxation = false;
 
 if is_multivariate
     [ax, a1x, Px, P1x, vx, Tx, Rx, Cx, regx, info, M_, likx, etahat, alphahat, V] = occbin.kalman_update_algo_1(a0,a1,P0,P1,data_index,Z,vv,Y,H,Qt,T0,R0,TT,RR,CC,struct(),M_,dr,endo_steady_state,exo_steady_state,exo_det_steady_state,options_,occbin_options);
 else
     [ax, a1x, Px, P1x, vx, Fix, Kix, Tx, Rx, Cx, regx, info, M_, likx, alphahat, etahat,TTx,RRx,CCx] = occbin.kalman_update_algo_3(a0,a1,P0,P1,data_index,Z,vv,Fi,Ki,Y,H,Qt,T0,R0,TT,RR,CC,struct(),M_,dr,endo_steady_state,exo_steady_state,exo_det_steady_state,options_,occbin_options,kalman_tol,nk);
 end
+likvec = likx;
+regvec = regx(1);
 info0=info;
 if info
     if ~isequal(regimes_(1:2),[base_regime base_regime])
@@ -48,6 +49,8 @@ if info
             [ax, a1x, Px, P1x, vx, Fix, Kix, Tx, Rx, Cx, regx, info, M_, likx, alphahat, etahat,TTx,RRx,CCx] = occbin.kalman_update_algo_3(a0,a1,P0,P1,data_index,Z,vv,Fi,Ki,Y,H,Qt,T0,R0,TT,RR,CC,regimes_(1:2),M_,dr,endo_steady_state,exo_steady_state,exo_det_steady_state,options_,occbin_options,kalman_tol,nk);
         end
     end
+    likvec = likx;
+    regvec = regx(1);
     info1=info;
 else
     if ~isequal(regimes_(1:2),[base_regime base_regime])
@@ -56,6 +59,10 @@ else
         else
             [ax1, a1x1, Px1, P1x1, vx1, Fix1, Kix1, Tx1, Rx1, Cx1, regx1, info1, M_1, likx1, alphahat1, etahat1,TTx1,RRx1,CCx1] = occbin.kalman_update_algo_3(a0,a1,P0,P1,data_index,Z,vv,Fi,Ki,Y,H,Qt,T0,R0,TT,RR,CC,regimes_(1:2),M_,dr,endo_steady_state,exo_steady_state,exo_det_steady_state,options_,occbin_options,kalman_tol,nk);
         end
+        if info1==0 && not(isequal(regx1,regx))
+            likvec = [likvec likx1];
+            regvec = [regvec; regx1(1)];
+        end
         if info1==0 && likx1<likx
             ax=ax1;
             a1x=a1x1;
@@ -72,7 +79,7 @@ else
             etahat=etahat1;
             alphahat=alphahat1;
             if is_multivariate
-            V=V1;
+                V=V1;
             else
                 Fix = Fix1;
                 Kix = Kix1;
@@ -85,8 +92,8 @@ else
         if t>options_.occbin.likelihood.number_of_initial_periods_with_extra_regime_guess
             info1=0;
         else
-        % may help in first 2 periods to try some other guess regime, due to
-        % larger state uncertainty
+            % may help in first 2 periods to try some other guess regime, due to
+            % larger state uncertainty
             info1=1;
             options_.occbin.likelihood.brute_force_regime_guess   = true;
             options_.occbin.likelihood.loss_function_regime_guess = true;
@@ -97,27 +104,83 @@ end
 
 diffstart=0;
 if info==0
-if M_.occbin.constraint_nbr==1
-    oldstart = regimes_(1).regimestart(end);
-    newstart = regx(1).regimestart(end);
-    diffstart = newstart-oldstart;
-else
-    newstart1 = regx(1).regimestart1(end);
-    newstart2 = regx(1).regimestart2(end);
-    oldstart1 = regimes_(1).regimestart1(end);
-    oldstart2 = regimes_(1).regimestart2(end);
-    diffstart = max(newstart1-oldstart1,newstart2-oldstart2);
+    if M_.occbin.constraint_nbr==1
+        oldstart = regimes_(1).regimestart(end);
+        newstart = regx(1).regimestart(end);
+        diffstart = newstart-oldstart;
+        regname = 'regimestart';
+    else
+        newstart1 = regx(1).regimestart1(end);
+        newstart2 = regx(1).regimestart2(end);
+        oldstart1 = regimes_(1).regimestart1(end);
+        oldstart2 = regimes_(1).regimestart2(end);
+        [diffstart, diffregime] = max([newstart1-oldstart1,newstart2-oldstart2]);
+        switch diffregime
+            case 1
+                regname = 'regimestart1';
+            case 2
+                regname = 'regimestart2';
+    end
 end
 end
+if options_.occbin.filter.use_relaxation && diffstart>options_.occbin.filter.use_relaxation
+    guess_regime = [base_regime base_regime];
+    options_.occbin.filter.guess_regime = true;
+    guess_regime(1) = regx(1);
+    regx2= regx;
+    while isequal(guess_regime(1),regx2(1))
+        % we reduce length until the converged regime does not change
 
-if options_.occbin.filter.use_relaxation && diffstart>2
-    if info0==0
-        % make sure we match criteria to enter further solution attempts
-        info1=1;
+        guess_regime(1).(regname)(end) = regx2(1).(regname)(end)-1;
+        if guess_regime(1).(regname)(end-1)==guess_regime(1).(regname)(end)
+            guess_regime(1).(regname)(end-1) = guess_regime(1).(regname)(end-1)-1;
+        end
+        if is_multivariate
+            [ax2, a1x2, Px2, P1x2, vx2, Tx2, Rx2, Cx2, regx2, info2, M_2, likx2, etahat2, alphahat2, V2] = occbin.kalman_update_algo_1(a0,a1,P0,P1,data_index,Z,vv,Y,H,Qt,T0,R0,TT,RR,CC,guess_regime,M_,dr,endo_steady_state,exo_steady_state,exo_det_steady_state,options_,occbin_options);
+        else
+            [ax2, a1x2, Px2, P1x2, vx2, Fix2, Kix2, Tx2, Rx2, Cx2, regx2, info2, M_2, likx2, alphahat2, etahat2,TTx2,RRx2,CCx2] = occbin.kalman_update_algo_3(a0,a1,P0,P1,data_index,Z,vv,Fi,Ki,Y,H,Qt,T0,R0,TT,RR,CC,guess_regime,M_,dr,endo_steady_state,exo_steady_state,exo_det_steady_state,options_,occbin_options,kalman_tol,nk);
+        end
+        isnew=true;
+        for kr=1:length(likvec)
+            % make sure likelihood does not differ by rounding issue
+            % but due to different regimes
+            if isequal(regx2(1),regvec(kr))
+                isnew = false;
+            end
+        end
+        if isnew
+            likvec = [likvec likx2];
+            regvec = [regvec; regx2(1)];
+        end
+        if info2==0 && likx2<likx
+            ax=ax2;
+            a1x=a1x2;
+            Px=Px2;
+            P1x=P1x2;
+            vx=vx2;
+            Tx=Tx2;
+            Rx=Rx2;
+            Cx=Cx2;
+            regx=regx2;
+            info=info2;
+            likx=likx2;
+            M_= M_2;
+            etahat=etahat2;
+            alphahat=alphahat2;
+            if is_multivariate
+                V=V2;
+            else
+                Fix = Fix2;
+                Kix = Kix2;
+                TTx = TTx2;
+                RRx = RRx2;
+                CCx = CCx2;
+            end
+        end
     end
-    options_.occbin.likelihood.brute_force_regime_guess   = true;
-    options_.occbin.likelihood.loss_function_regime_guess = true;
-    use_relaxation = true;
+    options_.occbin.filter.guess_regime = false;
+    options_.occbin.likelihood.brute_force_regime_guess   = false;
+    options_.occbin.likelihood.loss_function_regime_guess = false;
 end
 
 if options_.occbin.likelihood.brute_force_regime_guess && (info0 || info1) %|| (info==0 &&  ~isequal(regx(1),base_regime))
@@ -137,9 +200,8 @@ if options_.occbin.likelihood.brute_force_regime_guess && (info0 || info1) %|| (
             end
             if info2==0
                 use_index= 1;
-                if not(info==0 && isequal(regx2{1},regx)) && not(use_relaxation && likx2{1}>=likx)
-                    % found a solution, different from previous or
-                    % use_relaxation and likelihood is better
+                if not(info==0 && isequal(regx2{1},regx)) 
+                    % found a solution, different from previous 
                     break
                 end
             end
@@ -153,8 +215,6 @@ if options_.occbin.likelihood.brute_force_regime_guess && (info0 || info1) %|| (
             end
             if info2==0
                 use_index = 2;
-                % if use_relaxation and we are here, previous guess did not
-                % improve solution, so we test for this one
             end
 
             if use_index
@@ -216,18 +276,16 @@ if options_.occbin.likelihood.brute_force_regime_guess && (info0 || info1) %|| (
                             end
                             if info2==0
                                 use_index= gindex;
-                                if not(info==0 && isequal(regx2{gindex},regx)) && not(use_relaxation && likx2{gindex}>=likx)
+                                if not(info==0 && isequal(regx2{gindex},regx)) 
                                     % found a solution, different from previous one
-                                    % use_relaxation and likelihood improves
-                                    break
+                                     break
                                 end
                             end
                         end % loop over other regime slack, binding in expectation or binding in current period
 
                         if info2==0
-                            if not(info==0 && isequal(regx2{gindex},regx)) && not(use_relaxation && likx2{gindex}>=likx)
+                            if not(info==0 && isequal(regx2{gindex},regx)) 
                                 % found a solution, different from previous one
-                                % use_relaxation and likelihood improves
                                 break
                             end
                         end
@@ -235,9 +293,8 @@ if options_.occbin.likelihood.brute_force_regime_guess && (info0 || info1) %|| (
                     end % loop over current regime binding in expectation vs binding in current period
 
                     if info2==0
-                        if not(info==0 && isequal(regx2{gindex},regx)) && not(use_relaxation && likx2{gindex}>=likx)
+                        if not(info==0 && isequal(regx2{gindex},regx)) 
                             % found a solution, different from previous one
-                            % use_relaxation and likelihood improves
                             break
                         end
                     end
@@ -261,6 +318,18 @@ if options_.occbin.likelihood.brute_force_regime_guess && (info0 || info1) %|| (
         % so that we DO NOT enter IVF step
         info0=0;
         info1=0;
+        isnew=true;
+        for kr=1:length(likvec)
+            % make sure likelihood does not differ by rounding issue
+            % but truly for different regimes
+            if isequal(regx2{use_index}(1),regvec(kr))
+                isnew = false;
+            end
+        end
+        if isnew
+            likvec = [likvec likx2{use_index}];
+            regvec = [regvec; regx2{use_index}(1)];
+        end
     end
     if info2==0 && likx2{use_index}<likx
         ax=ax2{use_index};
@@ -301,6 +370,18 @@ if options_.occbin.likelihood.loss_function_regime_guess && (info0 || info1) %||
             [ax2, a1x2, Px2, P1x2, vx2, Fix2, Kix2, Tx2, Rx2, Cx2, regx2, info2, M_2, likx2, alphahat2, etahat2,TTx2,RRx2,CCx2] = occbin.kalman_update_algo_3(a0,a1,P0,P1,data_index,Z,vv,Fi,Ki,Y,H,Qt,T0,R0,TT,RR,CC,guess_regime,M_,dr,endo_steady_state,exo_steady_state,exo_det_steady_state,options_,occbin_options,kalman_tol,nk);
         end
         options_.occbin.filter.guess_regime = false;
+        isnew=true;
+        for kr=1:length(likvec)
+            % make sure likelihood does not differ by rounding issue
+            % but due to different regimes
+            if isequal(regx2(1),regvec(kr))
+                isnew = false;
+            end
+        end
+        if isnew
+            likvec = [likvec likx2];
+            regvec = [regvec; regx2(1)];
+        end
         if info2==0 && likx2<likx
             ax=ax2;
             a1x=a1x2;
@@ -328,4 +409,17 @@ if options_.occbin.likelihood.loss_function_regime_guess && (info0 || info1) %||
         end
     end
 end
+if length(likvec)>1
+    % sum the likelihood of multiple solutions
+    likx = -2*log(sum(exp(-likvec./2)));
+end
+
+if info(1)==0
+    if isnan(likx)
+        info = 323;
+    elseif any(any(isnan(ax)))
+        info = 324;
+    end
+end
+
 end
diff --git a/matlab/+occbin/set_default_options.m b/matlab/+occbin/set_default_options.m
index b720160c5392e6bcbba83ba096921b5141cf4d5d..04e13d54df14d98f8a7b783848481936f19cddeb 100644
--- a/matlab/+occbin/set_default_options.m
+++ b/matlab/+occbin/set_default_options.m
@@ -46,6 +46,7 @@ if ismember(flag,{'filter','all'})
     options_occbin_.filter.guess_regime = false;
     options_occbin_.filter.periodic_solution = true;
     options_occbin_.filter.use_relaxation = false;
+    options_occbin_.filter.use_relaxation_tol_period = 1;
 end
 
 if ismember(flag,{'forecast','all'})
diff --git a/matlab/estimation/dynare_estimation_1.m b/matlab/estimation/dynare_estimation_1.m
index 52a51a4cf5862903152be09b763afef77b5c07d7..a1a01039280d585d8009bea5f34d4244804ef580 100644
--- a/matlab/estimation/dynare_estimation_1.m
+++ b/matlab/estimation/dynare_estimation_1.m
@@ -189,7 +189,7 @@ if isequal(options_.mode_compute,0) && isempty(options_.mode_file) && ~options_.
     if options_.order==1 && ~options_.particle.status
         if options_.smoother
             if options_.occbin.smoother.status && options_.occbin.smoother.inversion_filter
-                [~, info, ~, ~, ~, ~, ~, ~, ~, ~, oo_.dr, atT, innov] = occbin.IVF_posterior(xparam1,dataset_,dataset_info,options_,M_,estim_params_,bayestopt_,prior_bounds(bayestopt_,options_.prior_trunc),oo_.dr, oo_.steady_state,oo_.exo_steady_state,oo_.exo_det_steady_state);
+                [~, info, ~, ~, ~, ~, ~, ~, ~, ~, oo_.dr, atT, innov, oo_.occbin.smoother.regime_history] = occbin.IVF_posterior(xparam1,dataset_,dataset_info,options_,M_,estim_params_,bayestopt_,prior_bounds(bayestopt_,options_.prior_trunc),oo_.dr, oo_.steady_state,oo_.exo_steady_state,oo_.exo_det_steady_state);
                 if ismember(info(1),[303,304,306])
                     fprintf('\nIVF: smoother did not succeed. No results will be written to oo_.\n')
                 else
diff --git a/matlab/get_error_message.m b/matlab/get_error_message.m
index 9680a675737846095a2609abd8d036494dc67189..7156e3c253c4e7d2dc1b60b35d92491e4d016227 100644
--- a/matlab/get_error_message.m
+++ b/matlab/get_error_message.m
@@ -197,6 +197,16 @@ switch info(1)
         message = 'Occbin: there was a problem in running the smoother. Simulation within smoother failed.';
     case 322
         message = 'Occbin: smoother did not converge.';
+    case 323
+        message = 'Piecewise linear Kalman filter: the likelihood is NaN.';
+    case 324
+        message = 'Piecewise linear Kalman filter: updated state vector is NaN.';
+    case 325
+        message = 'Piecewise linear Kalman filter: filter covariance NaN.';
+    case 330
+        message = 'Piecewise linear Kalman filter: update step did not reach a fixed point (periodic loop).';
+    case 331
+        message = 'Piecewise linear Kalman filter: update step did not reach a fixed point (max number of iterations reached).';
     case 401
         message = 'Cycle reduction reached the iteration limit. Try increasing maxit.';
     case 402
diff --git a/matlab/kalman/DsgeSmoother.m b/matlab/kalman/DsgeSmoother.m
index f4fb1f801f1a922b92b86e9e25cfbf3b934c3cf4..c84b800286e301ff5a65c02db894c4c4c5f723e9 100644
--- a/matlab/kalman/DsgeSmoother.m
+++ b/matlab/kalman/DsgeSmoother.m
@@ -506,6 +506,13 @@ else
         aaa = zeros(nk,M_.endo_nbr,gend+nk);
         aaa(:,oo_.dr.restrict_var_list,:)=aK;
         
+        if isoccbin
+            tstart = 1;
+        else
+            % we enter here in the first occbin smoother iteration
+            % occbin kalman update is not yet able to accommodate diffuse steps!
+            tstart=d+2; 
+        end
         for k=2:gend+1
             opts_simul.curb_retrench = options_.occbin.smoother.curb_retrench;
             opts_simul.waitbar = options_.occbin.smoother.waitbar;
@@ -526,8 +533,24 @@ else
             % period ahead (so if regimestart was [1 5] it should be [1 4]
             % in out
             %         end
-            for jnk=1:nk
-                aaa(jnk,oo_.dr.inv_order_var,k+jnk-1) = out.piecewise(jnk,:) - out.ys';
+            if out.error_flag==0
+                for jnk=1:nk
+                    aaa(jnk,oo_.dr.inv_order_var,k+jnk-1) = out.piecewise(jnk,:) - out.ys';
+                end
+            elseif k>tstart
+                % the issue only matters non-stationary models, with
+                % diffuse filter, and for the first occbin smoother iteration,
+                % where tstart>1
+                %
+                % if k>tstart, the same simulation should have been done
+                % already in occbin.kalman_update, so it should never give
+                % an error
+                %
+                % if k<=tstart, the simulation may crash, since we ignore OBC in the first (diffuse) steps
+                % and it may happen that, given the linear updated states,
+                % the occbin simulation does not converge
+                error('this error should not occur, please contact the developers!')
+
             end
         end
         aK=aaa;
diff --git a/matlab/kalman/missing_DiffuseKalmanSmootherH3_Z.m b/matlab/kalman/missing_DiffuseKalmanSmootherH3_Z.m
index 2b6f9046681e1916fd64a62465cf26df5539391c..366e415f4a8a51b728427a1d363dfde2abaa0cf7 100644
--- a/matlab/kalman/missing_DiffuseKalmanSmootherH3_Z.m
+++ b/matlab/kalman/missing_DiffuseKalmanSmootherH3_Z.m
@@ -544,7 +544,7 @@ while notsteady && t<smpl
             opts_simul.init_regime = []; %regimes_(t);
             opts_simul.waitbar=0;
             options_.occbin.simul=opts_simul;
-            [~, out] = occbin.solver(M_,options_,dr,steady_state,exo_steady_state,exo_det_steady_state);
+            [~, out] = occbin.solver(M_,options_,dr,endo_steady_state,exo_steady_state,exo_det_steady_state);
         end
         for jnk=1:nk
             if filter_covariance_flag
diff --git a/matlab/kalman/save_display_classical_smoother_results.m b/matlab/kalman/save_display_classical_smoother_results.m
index 48dcad0b5b31a0e7eae91bbe043acf70331dac18..f7f2f981e710722c51b9f8ff466d92773f743cac 100644
--- a/matlab/kalman/save_display_classical_smoother_results.m
+++ b/matlab/kalman/save_display_classical_smoother_results.m
@@ -36,7 +36,7 @@ gend= dataset_.nobs;
 n_varobs = length(options_.varobs);
 
 if options_.occbin.smoother.status && options_.occbin.smoother.inversion_filter
-    [~, info, ~, ~, ~, ~, ~, ~, ~, ~, oo_.dr, atT, innov] = occbin.IVF_posterior(xparam1,dataset_,dataset_info,options_,M_,estim_params_,bayestopt_,prior_bounds(bayestopt_,options_.prior_trunc),oo_.dr, oo_.steady_state,oo_.exo_steady_state,oo_.exo_det_steady_state);
+    [~, info, ~, ~, ~, ~, ~, ~, ~, ~, oo_.dr, atT, innov, oo_.occbin.smoother.regime_history] = occbin.IVF_posterior(xparam1,dataset_,dataset_info,options_,M_,estim_params_,bayestopt_,prior_bounds(bayestopt_,options_.prior_trunc),oo_.dr, oo_.steady_state,oo_.exo_steady_state,oo_.exo_det_steady_state);
     if ismember(info(1),[303,304,306])
         fprintf('\nIVF: smoother did not succeed. No results will be written to oo_.\n')
     else
diff --git a/matlab/shock_decomposition/annualized_shock_decomposition.m b/matlab/shock_decomposition/annualized_shock_decomposition.m
index 962a0910c13b6c261da19af17dc824114a6f0588..834e37c9f3acc964661d8ca0a1dca11e8008239e 100644
--- a/matlab/shock_decomposition/annualized_shock_decomposition.m
+++ b/matlab/shock_decomposition/annualized_shock_decomposition.m
@@ -200,6 +200,7 @@ if realtime_ && isstruct(oo_) && isfield(oo_, 'realtime_shock_decomposition')
 
                 % make annualized shock decomp
                 z = annualiz(z,t0,q2a,aux,steady_state);
+                oo_.annualized_realtime_shock_decomposition.(['yr_' int2str(yr)]) = z;
 
             end
             oo_.annualized_realtime_forecast_shock_decomposition.(['yr_' int2str(yr)]) = z(:,:,end-nfrcst:end);
diff --git a/tests/occbin/filter/NKM.mod b/tests/occbin/filter/NKM.mod
index 1b552290f4dce06214ae6430c3b87fdea665d224..a54142f94ad7f1c928af1183ac1c8b716bd12ba1 100644
--- a/tests/occbin/filter/NKM.mod
+++ b/tests/occbin/filter/NKM.mod
@@ -309,7 +309,7 @@ varobs yg inom pi;
             datafile=dataobsfile2, mode_file=NKM_mh_mode_saved,
             mode_compute=0, nobs=120, first_obs=1,
             mh_replic=0, plot_priors=0, smoother,
-            consider_all_endogenous,heteroskedastic_filter,filter_step_ahead=[1],smoothed_state_uncertainty);
+            consider_all_endogenous,heteroskedastic_filter,filter_step_ahead=[1:8],smoothed_state_uncertainty);
     
     // plot regimes
     occbin.plot_regimes(oo_.occbin.smoother.regime_history,M_,options_)
@@ -350,7 +350,7 @@ varobs yg inom pi;
             datafile=dataobsfile2, mode_file=NKM_mh_mode_saved,
             mode_compute=0, nobs=120, first_obs=1,
             mh_replic=0, plot_priors=0, smoother, smoother_redux,
-            consider_all_endogenous,heteroskedastic_filter,filter_step_ahead=[1],smoothed_state_uncertainty);
+            consider_all_endogenous,heteroskedastic_filter,filter_step_ahead=[1:8],smoothed_state_uncertainty);
 
     // check consistency of smoother_redux
     for k=1:M_.endo_nbr, 
@@ -362,6 +362,33 @@ varobs yg inom pi;
         disp('smoother redux successfully recovers full smoother results!')
     end
 
+    for k=1:M_.endo_nbr, 
+    mer(k)=max(abs(oo_.UpdatedVariables.(M_.endo_names{k})-oo0.UpdatedVariables.(M_.endo_names{k}))); 
+    end
+    if max(mer)>1.e-10
+    error('smoother redux does not recover full updated variables results!')
+    else
+    disp('smoother redux successfully recovers full updated variables results!')
+    end
+    
+    
+    for k=1:M_.endo_nbr, 
+    mer(k)=max(abs(oo_.FilteredVariables.(M_.endo_names{k})-oo0.FilteredVariables.(M_.endo_names{k}))); 
+    end
+    if max(mer)>1.e-10
+    error('smoother redux does not recover full filtered variables results!')
+    else
+    disp('smoother redux successfully recovers full filtered variables results!')
+    end
+    
+    for k=1:M_.endo_nbr, 
+        mer(k)=max(max(max(abs(oo_.FilteredVariablesKStepAhead(:,k,:)-oo0.FilteredVariablesKStepAhead(:,k,:))))); 
+    end
+    if max(mer)>1.e-10
+    error('smoother redux does not recover full k-step ahead variables results!')
+    else
+    disp('smoother redux successfully recovers full k-step ahead variables results!')
+    end
     // use inversion filter (note that IF provides smoother together with likelihood)
     occbin_setup(likelihood_inversion_filter,smoother_inversion_filter);
             
@@ -369,7 +396,7 @@ varobs yg inom pi;
             datafile=dataobsfile2, mode_file=NKM_mh_mode_saved,
             mode_compute=0, nobs=120, first_obs=1,
             mh_replic=0, plot_priors=0, smoother,
-            consider_all_endogenous,heteroskedastic_filter,filter_step_ahead=[1],smoothed_state_uncertainty);
+            consider_all_endogenous,heteroskedastic_filter,filter_step_ahead=[1:8],smoothed_state_uncertainty);
             
     // show initial condition effect of IF
     figure('Name','OccBin: Smoothed shocks')