diff --git a/core/MarkovProcesses.jl b/core/MarkovProcesses.jl
index 9a17dd2f80af7538a4cd538fc943830815167080..975cb6727200eae29eff6b0f29bb8e3ee89421d5 100644
--- a/core/MarkovProcesses.jl
+++ b/core/MarkovProcesses.jl
@@ -38,7 +38,7 @@ export init_state, next_state!, read_trajectory
 export get_index, get_value, length_var, isaccepted
 
 # Model related methods
-export simulate, volatile_simulate
+export simulate, volatile_simulate, change_simulation_stop_criteria
 export distribute_mean_value_lha, mean_value_lha, distribute_prob_accept_lha, probability_var_value_lha 
 export number_simulations_smc_chernoff, smc_chernoff
 export set_param!, set_x0!, set_time_bound!, set_observed_var!, observe_all!
diff --git a/core/model.jl b/core/model.jl
index 9f6199f4b483075afd90818ddb963afe1f2f21ce..7b8c9153810f8539bfc95930142284ce166bc7f9 100644
--- a/core/model.jl
+++ b/core/model.jl
@@ -271,12 +271,12 @@ function generate_code_synchronized_simulation(model_name::Symbol, lha_name::Sym
                 n += i
             end
             values = full_values[getfield(m, :_g_idx)]
-            if isbounded(m) && !isaccepted(ptr_loc_state[1], A)
+            if isbounded(m) && !isacceptedLHA
                 # Add last value: the convention is that if the last transition is nothing,
                 # the trajectory is bounded
                 MarkovProcesses._finish_bounded_trajectory!(values, times, transitions, time_bound)
             end
-            if isabsorbing && !isacceptedLHA
+            if (isabsorbing || tn > time_bound) && !isacceptedLHA
                 next_state!(A, ptr_loc_state, values_state, ptr_time_state, 
                             xn, time_bound, nothing, xn, p_sim, edge_candidates; verbose = verbose)
             end
@@ -398,6 +398,7 @@ function simulate(pm::ParametricModel, p_prior::AbstractVector{Float64})
     
     return simulate(pm.m; p = full_p) 
 end
+
 """
     `volatile_simulate(pm::ParametricModel, p_prior::AbstractVector{Float64})
 
@@ -413,6 +414,25 @@ function volatile_simulate(pm::ParametricModel, p_prior::AbstractVector{Float64}
     
     return volatile_simulate(pm.m; p = full_p, epsilon = epsilon)
 end
+
+"""
+    `change_simulation_stop_criteria(m::ContinuousTimeModel, isabsorbing_func::Symbol)`
+
+    Change the simulation of the model `m` by adding a stop criteria based on the function named `isabsorbing_func::Symbol`.
+    isabsorbing_func must have the type signature `isabsorbing_func(p::Vector{Float64}, x::Vector{Int})` where `p` is the parameter vector of the model and `x` a state (not an observed state) of the model.
+"""
+function change_simulation_stop_criteria(m::ContinuousTimeModel, isabsorbing_func::Symbol)
+    model_name = Symbol(typeof(m))
+    isabs = getfield(Main, isabsorbing_func)
+    try 
+        isabs(m.p, m.x0) 
+    catch err 
+        error("Something went wrong when trying to apply the criteria function")
+    end
+    @everywhere @eval $(generate_code_simulation(model_name, m.f!, isabsorbing_func; run_isabsorbing = true))
+end
+
+
 """
     `distribute_mean_value_lha(sm::SynchronizedModel, sym_var::Symbol, nbr_stim::Int)`
 
diff --git a/tests/automata/euclidean_distance_on_bound.jl b/tests/automata/euclidean_distance_on_bound.jl
index dae30d13a66552c755f6798266f58eb683c67450..51ad64dd65dc2e4ace752b664c7151b658954698 100644
--- a/tests/automata/euclidean_distance_on_bound.jl
+++ b/tests/automata/euclidean_distance_on_bound.jl
@@ -6,36 +6,86 @@ import Distributions: Uniform
 MAKE_SECOND_AUTOMATON_TESTS = false
 
 load_model("SIR")
+load_automaton("euclidean_distance_automaton")
+if MAKE_SECOND_AUTOMATON_TESTS
+    load_automaton("euclidean_distance_automaton_2")
+end
+
 tml_obs = 0:0.5:200
 set_time_bound!(SIR, 200.0)
 y_obs = vectorize(simulate(SIR), :I, tml_obs)
-
-load_automaton("euclidean_distance_automaton")
 aut1 = create_euclidean_distance_automaton(SIR, tml_obs, y_obs, :I)
 sync_SIR = SIR * aut1
-σ = simulate(sync_SIR)
-test = euclidean_distance(σ, :I, tml_obs, y_obs) == σ.state_lha_end[:d]
 
-if !test
-    @show euclidean_distance(σ, :I, tml_obs, y_obs), σ.state_lha_end[:d]
-    @show σ
+test_all = true
+nbr_sim = 100
+
+for i = 1:nbr_sim
+    let σ, test
+        σ = simulate(sync_SIR)
+        test = euclidean_distance(σ, :I, tml_obs, y_obs) == σ.state_lha_end[:d]
+        if !test
+            @show tml_obs
+            @show euclidean_distance(σ, :I, tml_obs, y_obs), σ.state_lha_end[:d]
+            @show σ
+        end
+        global test_all = test_all && test
+    end
 end
 
 if MAKE_SECOND_AUTOMATON_TESTS
-    load_automaton("euclidean_distance_automaton_2")
     aut2 = create_euclidean_distance_automaton_2(SIR, tml_obs, y_obs, :I)
     sync_SIR = SIR * aut2
-    σ = simulate(sync_SIR)
-    test2 = euclidean_distance(σ, :I, tml_obs, y_obs) == σ.state_lha_end[:d]
-    if !test2
-        @show euclidean_distance(σ, :I, tml_obs, y_obs), σ.state_lha_end[:d]
-        @show σ
+    for i = 1:nbr_sim
+        let σ, test2
+            σ = simulate(sync_SIR)
+            test2 = euclidean_distance(σ, :I, tml_obs, y_obs) == σ.state_lha_end[:d]
+            if !test2
+                @show euclidean_distance(σ, :I, tml_obs, y_obs), σ.state_lha_end[:d]
+                @show σ
+            end
+            global test_all = test_all && test2
+        end
+    end
+end
+
+tml_obs = 0:20.0:200
+set_time_bound!(SIR, 200.0)
+y_obs = vectorize(simulate(SIR), :I, tml_obs)
+aut1 = create_euclidean_distance_automaton(SIR, tml_obs, y_obs, :I)
+sync_SIR = SIR * aut1
+
+test_all = true
+nbr_sim = 100
+
+for i = 1:nbr_sim
+    let σ, test
+        σ = simulate(sync_SIR)
+        test = euclidean_distance(σ, :I, tml_obs, y_obs) == σ.state_lha_end[:d]
+        if !test
+            @show tml_obs
+            @show euclidean_distance(σ, :I, tml_obs, y_obs), σ.state_lha_end[:d]
+            @show σ
+        end
+        global test_all = test_all && test
     end
-else
-    test2 = true
 end
 
-test_all = test && test2
+if MAKE_SECOND_AUTOMATON_TESTS
+    aut2 = create_euclidean_distance_automaton_2(SIR, tml_obs, y_obs, :I)
+    sync_SIR = SIR * aut2
+    for i = 1:nbr_sim
+        let σ, test2
+            σ = simulate(sync_SIR)
+            test2 = euclidean_distance(σ, :I, tml_obs, y_obs) == σ.state_lha_end[:d]
+            if !test2
+                @show euclidean_distance(σ, :I, tml_obs, y_obs), σ.state_lha_end[:d]
+                @show σ
+            end
+            global test_all = test_all && test2
+        end
+    end
+end
 
 return test_all
 
diff --git a/tests/run_unit.jl b/tests/run_unit.jl
index deb8bb1bc1834dc9edc6820efbf8a2c1f118c685..21861b5ed7e81ef734c9b5b83ef2315850f29304 100644
--- a/tests/run_unit.jl
+++ b/tests/run_unit.jl
@@ -41,6 +41,7 @@ using Test
     @test include("unit/simulate_sir.jl")
     @test include("unit/simulate_sir_bounded.jl")
     @test include("unit/simulate_er.jl")
+    @test include("unit/simulation_stop_criteria.jl")
     @test include("unit/square_wave_oscillator.jl")
     
     @test include("unit/vectorize.jl")
diff --git a/tests/unit/simulation_stop_criteria.jl b/tests/unit/simulation_stop_criteria.jl
new file mode 100644
index 0000000000000000000000000000000000000000..f20fb8fdedabb31ca6d2accb39c320dd03422b7f
--- /dev/null
+++ b/tests/unit/simulation_stop_criteria.jl
@@ -0,0 +1,62 @@
+
+using MarkovProcesses
+
+# Settings with two SIR models
+load_model("SIR")
+SIR2 = @network_model begin
+    R1: (S+I => 2I, ki*S*I)
+    R2: (I => R, kr*I)
+end "SIR2"
+set_x0!(SIR, [:S, :I, :R], [95, 5, 0])
+set_x0!(SIR2, [:S, :I, :R], [95, 5, 0])
+set_param!(SIR, [:ki, :kr], [0.012, 0.05])
+set_param!(SIR2, [:ki, :kr], [0.012, 0.05])
+# Settings ER model
+load_model("ER")
+set_x0!(ER, [:E, :S, :ES, :P], [100, 100, 0, 0])
+set_param!(ER, [:k1, :k2, :k3], [1.0, 1.0, 1.0])
+# Settings repressilator model
+load_model("repressilator")
+set_observed_var!(repressilator, [:mRNA1, :mRNA2, :mRNA3, :P1, :P2, :P3])
+set_x0!(repressilator, [:mRNA1, :mRNA2, :mRNA3], fill(0, 3))
+set_x0!(repressilator, [:P1, :P2, :P3], [5, 0, 15])
+set_param!(repressilator, :n, 2.0)
+set_param!(repressilator, [:α, :α0, :β, :n], [400.0, 0.0, 2.0, 2.0])
+set_time_bound!(repressilator, 200.0)
+
+test_all = true
+
+# First test : infinite simulation
+set_time_bound!(ER, Inf)
+set_time_bound!(SIR, Inf)
+set_time_bound!(SIR2, Inf)
+for i = 1:10
+    global test_all = test_all && simulate(ER).P[end] == 100
+    global test_all = test_all && simulate(SIR).I[end] == 0
+    global test_all = test_all && simulate(SIR2).I[end] == 0
+end
+
+# Second test: change the simulation stop criteria
+get_idx(m::ContinuousTimeModel, var::Symbol) = m.map_var_idx[var]
+idx_I_SIR, idx_I_SIR2, idx_P_ER, idx_P1_repressilator = 
+get_idx(SIR, :I), get_idx(SIR2, :I), get_idx(ER, :P), get_idx(repressilator, :P1)
+
+@eval new_isabsorbing_SIR(p::Vector{Float64}, x::Vector{Int}) = x[$(idx_I_SIR)] == 2
+@eval new_isabsorbing_SIR2(p::Vector{Float64}, x::Vector{Int}) = x[$(idx_I_SIR2)] == 3
+@eval new_isabsorbing_ER(p::Vector{Float64}, x::Vector{Int}) = x[$(idx_P_ER)] == 50
+@eval new_isabsorbing_repressilator(p::Vector{Float64}, x::Vector{Int}) = x[$(idx_P1_repressilator)] == 100
+
+change_simulation_stop_criteria(SIR, :new_isabsorbing_SIR)
+change_simulation_stop_criteria(SIR2, :new_isabsorbing_SIR2)
+change_simulation_stop_criteria(ER, :new_isabsorbing_ER)
+change_simulation_stop_criteria(repressilator, :new_isabsorbing_repressilator)
+
+for i = 1:10
+    global test_all = test_all && simulate(SIR).I[end] == 2
+    global test_all = test_all && simulate(SIR2).I[end] == 3
+    global test_all = test_all && simulate(ER).P[end] == 50
+    global test_all = test_all && simulate(repressilator).P1[end] == 100
+end
+
+return test_all
+