From 4d1c6771cabc66ce3d5f9318aaaea2916d037478 Mon Sep 17 00:00:00 2001 From: Torkel Loman Date: Mon, 17 Mar 2025 23:48:40 +0000 Subject: [PATCH 1/4] init --- test/simulation_and_solving/simulate_ODEs.jl | 28 ++++++++++++++ test/simulation_and_solving/simulate_SDEs.jl | 28 ++++++++++++++ test/simulation_and_solving/simulate_jumps.jl | 37 +++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/test/simulation_and_solving/simulate_ODEs.jl b/test/simulation_and_solving/simulate_ODEs.jl index 3bff83eae5..d59ebf1f6e 100644 --- a/test/simulation_and_solving/simulate_ODEs.jl +++ b/test/simulation_and_solving/simulate_ODEs.jl @@ -164,6 +164,34 @@ end ### Other Tests ### +# Checks that simulations values consistently have Float64 type. +let + # Create model and check simulation value type (FLoat64 values). + # Generally, the tend type should not matter. + rn = @reaction_network begin + (k1,k2), X1 <--> X2 + end + u0 = [:X1 => 1.0, :X2 => 3.0] + ps = [:k1 => 2.0, :k2 => 3.0] + oprob = ODEProblem(rn, u0, 1.0, ps) + osol = solve(oprob) + @test eltype(osol[:X1]) == eltype(osol[:X2]) == typeof(oprob[:X1]) == typeof(oprob[:X2]) == Float64 + + # Check type when input values are Int64. + u0 = [:X1 => 1, :X2 => 3] + ps = [:k1 => 2, :k2 => 3] + oprob = ODEProblem(rn, u0, 1, ps) + osol = solve(oprob) + @test eltype(osol[:X1]) == eltype(osol[:X2]) == typeof(oprob[:X1]) == typeof(oprob[:X2]) == Float64 + + # Check type when input values are Float32. + u0 = [:X1 => 1.0f0, :X2 => 3.0f0] + ps = [:k1 => 2.0f0, :k2 => 3.0f0] + oprob = ODEProblem(rn, u0, 1.0f0, ps) + osol = solve(oprob) + @test eltype(osol[:X1]) == eltype(osol[:X2]) == typeof(oprob[:X1]) == typeof(oprob[:X2]) == Float32 +end + # Tests simulating a network without parameters. let no_param_network = @reaction_network begin diff --git a/test/simulation_and_solving/simulate_SDEs.jl b/test/simulation_and_solving/simulate_SDEs.jl index 16f662e7a4..200454bbe8 100644 --- a/test/simulation_and_solving/simulate_SDEs.jl +++ b/test/simulation_and_solving/simulate_SDEs.jl @@ -383,6 +383,34 @@ end ### Other Tests ### +# Checks that simulations values consistently have Float64 type. +let + # Create model and check simulation value type (FLoat64 values). + # Generally, the tend type should not matter. + rn = @reaction_network begin + (k1,k2), X1 <--> X2 + end + u0 = [:X1 => 100.0, :X2 => 300.0] + ps = [:k1 => 2.0, :k2 => 3.0] + sprob = SDEProblem(rn, u0, 1.0, ps) + ssol = solve(sprob, ISSEM()) + @test eltype(ssol[:X1]) == eltype(ssol[:X2]) == typeof(sprob[:X1]) == typeof(sprob[:X2]) == Float64 + + # Check type when input values are Int64. + u0 = [:X1 => 100, :X2 => 300] + ps = [:k1 => 2, :k2 => 3] + sprob = SDEProblem(rn, u0, 1, ps) + ssol = solve(sprob, ISSEM()) + @test eltype(ssol[:X1]) == eltype(ssol[:X2]) == typeof(sprob[:X1]) == typeof(sprob[:X2]) == Float64 + + # Check type when input values are Float32. + u0 = [:X1 => 100.0f0, :X2 => 300.0f0] + ps = [:k1 => 2.0f0, :k2 => 3.0f0] + sprob = SDEProblem(rn, u0, 1.0f0, ps) + ssol = solve(sprob, ISSEM()) + @test eltype(ssol[:X1]) == eltype(ssol[:X2]) == typeof(sprob[:X1]) == typeof(sprob[:X2]) == Float32 +end + # Tests simulating a network without parameters. let no_param_network = @reaction_network begin diff --git a/test/simulation_and_solving/simulate_jumps.jl b/test/simulation_and_solving/simulate_jumps.jl index c0b19a81da..ee9742aef6 100644 --- a/test/simulation_and_solving/simulate_jumps.jl +++ b/test/simulation_and_solving/simulate_jumps.jl @@ -220,3 +220,40 @@ let @test (means1[1] - means1[2]) < .1 * means1[1] @test (means2[1] - means2[2]) < .1 * means2[1] end + +### Other Tests ### + +# Checks that simulations values have the correct type (Float64/Int64 depending on input). +let + # Create model and check simulation value type (FLoat64 values). + # Generally, the tend type should not matter. + rn = @reaction_network begin + (k1,k2), X1 <--> X2 + end + u0 = [:X1 => 1.0, :X2 => 3.0] + ps = [:k1 => 2.0, :k2 => 3.0] + jprob = JumpProblem(JumpInputs(rn, u0, (0.0, 1.0), ps)) + jsol = solve(jprob) + @test eltype(jsol[:X1]) == eltype(jsol[:X2]) == typeof(jprob[:X1]) == typeof(jprob[:X2]) == Float64 + + # Check type when input values are Int64. + u0 = [:X1 => 1 :X2 => 3] + ps = [:k1 => 2, :k2 => 3] + jprob = JumpProblem(JumpInputs(rn, u0, (0, 1), ps)) + jsol = solve(jprob) + @test eltype(jsol[:X1]) == eltype(jsol[:X2]) == typeof(jprob[:X1]) == typeof(jprob[:X2]) == Int64 + + # Check type when input values are Float32 (should yield types that are ). + u0 = [:X1 => 1.0f0, :X2 => 3.0f0] + ps = [:k1 => 2.0f0, :k2 => 3.0f0] + jprob = JumpProblem(JumpInputs(rn, u0, (0.0f0, 1.0f0), ps)) + jsol = solve(jprob) + @test eltype(jsol[:X1]) == eltype(jsol[:X2]) == typeof(jprob[:X1]) == typeof(jprob[:X2]) == Float32 + + # Check type when input values are Int32 (should yield types that are ). + u0 = [:X1 => Int32(1), :X2 => Int32(3)] + ps = [:k1 => Int32(2), :k2 => Int32(3)] + jprob = JumpProblem(JumpInputs(rn, u0, (Int32(0), Int32(1)), ps)) + jsol = solve(jprob) + @test eltype(jsol[:X1]) == eltype(jsol[:X2]) == typeof(jprob[:X1]) == typeof(jprob[:X2]) == Int32 +end From 88374e9b71e27afe7378a52a0569d1d2a4809a30 Mon Sep 17 00:00:00 2001 From: Torkel Loman Date: Wed, 19 Mar 2025 22:18:20 +0000 Subject: [PATCH 2/4] init --- test/simulation_and_solving/simulate_ODEs.jl | 17 +++++++--- test/simulation_and_solving/simulate_SDEs.jl | 23 +++++++++----- test/simulation_and_solving/simulate_jumps.jl | 23 +++++++++----- .../simulation_and_solving/solve_nonlinear.jl | 31 +++++++++++++++++++ 4 files changed, 73 insertions(+), 21 deletions(-) diff --git a/test/simulation_and_solving/simulate_ODEs.jl b/test/simulation_and_solving/simulate_ODEs.jl index d59ebf1f6e..0d725e5a10 100644 --- a/test/simulation_and_solving/simulate_ODEs.jl +++ b/test/simulation_and_solving/simulate_ODEs.jl @@ -164,10 +164,13 @@ end ### Other Tests ### -# Checks that simulations values consistently have Float64 type. +# Checks that solution values have types consistent with their input types. +# Check that both float types are preserved in the solution (and problems), while integers are +# promoted to floats. +# Checks that the time types are correct (`Float64` by default or possibly `Float32`), however, +# type conversion only occurs in the solution, and integer types are preserved in problems. let - # Create model and check simulation value type (FLoat64 values). - # Generally, the tend type should not matter. + # Create model. Checks when input type is `Float64` the produced values are also `Float64`. rn = @reaction_network begin (k1,k2), X1 <--> X2 end @@ -176,20 +179,24 @@ let oprob = ODEProblem(rn, u0, 1.0, ps) osol = solve(oprob) @test eltype(osol[:X1]) == eltype(osol[:X2]) == typeof(oprob[:X1]) == typeof(oprob[:X2]) == Float64 + @test eltype(osol.t) == typeof(oprob.tspan[1]) == typeof(oprob.tspan[2]) == Float64 - # Check type when input values are Int64. + # Checks that `Int64` values are promoted to `Float64`. u0 = [:X1 => 1, :X2 => 3] ps = [:k1 => 2, :k2 => 3] oprob = ODEProblem(rn, u0, 1, ps) osol = solve(oprob) @test eltype(osol[:X1]) == eltype(osol[:X2]) == typeof(oprob[:X1]) == typeof(oprob[:X2]) == Float64 + @test eltype(osol.t) == Float64 + @test typeof(oprob.tspan[1]) == typeof(oprob.tspan[2]) == Int64 - # Check type when input values are Float32. + # Checks when values are `Float32` (a valid type and should be preserved). u0 = [:X1 => 1.0f0, :X2 => 3.0f0] ps = [:k1 => 2.0f0, :k2 => 3.0f0] oprob = ODEProblem(rn, u0, 1.0f0, ps) osol = solve(oprob) @test eltype(osol[:X1]) == eltype(osol[:X2]) == typeof(oprob[:X1]) == typeof(oprob[:X2]) == Float32 + @test eltype(osol.t) == typeof(oprob.tspan[1]) == typeof(oprob.tspan[2]) == Float32 end # Tests simulating a network without parameters. diff --git a/test/simulation_and_solving/simulate_SDEs.jl b/test/simulation_and_solving/simulate_SDEs.jl index 200454bbe8..d2f8707d76 100644 --- a/test/simulation_and_solving/simulate_SDEs.jl +++ b/test/simulation_and_solving/simulate_SDEs.jl @@ -383,32 +383,39 @@ end ### Other Tests ### -# Checks that simulations values consistently have Float64 type. +# Checks that solution values have types consistent with their input types. +# Check that both float types are preserved in the solution (and problems), while integers are +# promoted to floats. +# Checks that the time types are correct (`Float64` by default or possibly `Float32`), however, +# type conversion only occurs in the solution, and integer types are preserved in problems. let - # Create model and check simulation value type (FLoat64 values). - # Generally, the tend type should not matter. + # Create model. Checks when input type is `Float64` the produced values are also `Float64`. rn = @reaction_network begin (k1,k2), X1 <--> X2 end - u0 = [:X1 => 100.0, :X2 => 300.0] + u0 = [:X1 => 1.0, :X2 => 3.0] ps = [:k1 => 2.0, :k2 => 3.0] sprob = SDEProblem(rn, u0, 1.0, ps) ssol = solve(sprob, ISSEM()) @test eltype(ssol[:X1]) == eltype(ssol[:X2]) == typeof(sprob[:X1]) == typeof(sprob[:X2]) == Float64 + @test eltype(ssol.t) == typeof(sprob.tspan[1]) == typeof(sprob.tspan[2]) == Float64 - # Check type when input values are Int64. - u0 = [:X1 => 100, :X2 => 300] + # Checks that `Int64` values are promoted to `Float64`. + u0 = [:X1 => 1, :X2 => 3] ps = [:k1 => 2, :k2 => 3] sprob = SDEProblem(rn, u0, 1, ps) ssol = solve(sprob, ISSEM()) @test eltype(ssol[:X1]) == eltype(ssol[:X2]) == typeof(sprob[:X1]) == typeof(sprob[:X2]) == Float64 + @test eltype(ssol.t) == Float64 + @test typeof(sprob.tspan[1]) == typeof(sprob.tspan[2]) == Int64 - # Check type when input values are Float32. - u0 = [:X1 => 100.0f0, :X2 => 300.0f0] + # Checks when values are `Float32` (a valid type and should be preserved). + u0 = [:X1 => 1.0f0, :X2 => 3.0f0] ps = [:k1 => 2.0f0, :k2 => 3.0f0] sprob = SDEProblem(rn, u0, 1.0f0, ps) ssol = solve(sprob, ISSEM()) @test eltype(ssol[:X1]) == eltype(ssol[:X2]) == typeof(sprob[:X1]) == typeof(sprob[:X2]) == Float32 + @test eltype(ssol.t) == typeof(sprob.tspan[1]) == typeof(sprob.tspan[2]) == Float32 end # Tests simulating a network without parameters. diff --git a/test/simulation_and_solving/simulate_jumps.jl b/test/simulation_and_solving/simulate_jumps.jl index ee9742aef6..6e26deef44 100644 --- a/test/simulation_and_solving/simulate_jumps.jl +++ b/test/simulation_and_solving/simulate_jumps.jl @@ -223,10 +223,13 @@ end ### Other Tests ### -# Checks that simulations values have the correct type (Float64/Int64 depending on input). +# Checks that solution values have types consistent with their input types. +# Check that both float and integer values are preserved in the solution (and problems). +# Checks that the time values are correct (`Float64` by default or possibly `Float32`). +# `JumpInputs` currently does not support integer time spans. When it does, we will check that +# these produce `Float64` time values. let - # Create model and check simulation value type (FLoat64 values). - # Generally, the tend type should not matter. + # Create model. Checks when input type is `Float64` the produced values are also `Float64`. rn = @reaction_network begin (k1,k2), X1 <--> X2 end @@ -235,25 +238,29 @@ let jprob = JumpProblem(JumpInputs(rn, u0, (0.0, 1.0), ps)) jsol = solve(jprob) @test eltype(jsol[:X1]) == eltype(jsol[:X2]) == typeof(jprob[:X1]) == typeof(jprob[:X2]) == Float64 + @test eltype(jsol.t) == typeof(jprob.prob.tspan[1]) == typeof(jprob.prob.tspan[2]) == Float64 - # Check type when input values are Int64. + # Checks that `Int64` gives `Int64` species values. u0 = [:X1 => 1 :X2 => 3] ps = [:k1 => 2, :k2 => 3] - jprob = JumpProblem(JumpInputs(rn, u0, (0, 1), ps)) + jprob = JumpProblem(JumpInputs(rn, u0, (0.0, 1.0), ps)) jsol = solve(jprob) @test eltype(jsol[:X1]) == eltype(jsol[:X2]) == typeof(jprob[:X1]) == typeof(jprob[:X2]) == Int64 + @test eltype(jsol.t) == typeof(jprob.prob.tspan[1]) == typeof(jprob.prob.tspan[2]) == Float64 - # Check type when input values are Float32 (should yield types that are ). + # Checks when values are `Float32` (a valid type and should be preserved). u0 = [:X1 => 1.0f0, :X2 => 3.0f0] ps = [:k1 => 2.0f0, :k2 => 3.0f0] jprob = JumpProblem(JumpInputs(rn, u0, (0.0f0, 1.0f0), ps)) jsol = solve(jprob) @test eltype(jsol[:X1]) == eltype(jsol[:X2]) == typeof(jprob[:X1]) == typeof(jprob[:X2]) == Float32 + @test eltype(jsol.t) == typeof(jprob.prob.tspan[1]) == typeof(jprob.prob.tspan[2]) == Float32 - # Check type when input values are Int32 (should yield types that are ). + # Checks when values are `Int32` (a valid species type and should be preserved). u0 = [:X1 => Int32(1), :X2 => Int32(3)] ps = [:k1 => Int32(2), :k2 => Int32(3)] - jprob = JumpProblem(JumpInputs(rn, u0, (Int32(0), Int32(1)), ps)) + jprob = JumpProblem(JumpInputs(rn, u0, (0.0, 1.0), ps)) jsol = solve(jprob) @test eltype(jsol[:X1]) == eltype(jsol[:X2]) == typeof(jprob[:X1]) == typeof(jprob[:X2]) == Int32 + @test eltype(jsol.t) == typeof(jprob.prob.tspan[1]) == typeof(jprob.prob.tspan[2]) == Float64 end diff --git a/test/simulation_and_solving/solve_nonlinear.jl b/test/simulation_and_solving/solve_nonlinear.jl index 4f5b19a8a6..dc44a25434 100644 --- a/test/simulation_and_solving/solve_nonlinear.jl +++ b/test/simulation_and_solving/solve_nonlinear.jl @@ -101,3 +101,34 @@ let @test f_eval(steady_state_network_3, [:X => sol1[X], :Y => sol1[Y], :Y2 => sol1[Y2], :XY2 => sol1[XY2]], p, 0.0) ≈ [0.0, 0.0, 0.0, 0.0] atol=1e-10 @test f_eval(steady_state_network_3, [:X => sol2[X], :Y => sol2[Y], :Y2 => sol2[Y2], :XY2 => sol2[XY2]], p, 0.0) ≈ [0.0, 0.0, 0.0, 0.0] atol=1e-10 end + +### Other Tests ### + +# Checks that solution values have types consistent with their input types. +# Check for values that types that should be preserved (`Float64` and `Float32`) and types +# that should be converted to the default (conversion of `Int64 to `Float64`). +let + # Create model. Checks when input type is `Float64` that the problem and solution types are `Float64`. + rn = @reaction_network begin + (k1,k2), X1 <--> X2 + end + u0 = [:X1 => 1.0, :X2 => 3.0] + ps = [:k1 => 2.0, :k2 => 3.0] + nlprob = NonlinearProblem(rn, u0, ps) + nlsol = solve(nlprob) + @test eltype(nlsol[:X1]) == eltype(nlsol[:X2]) == typeof(nlprob[:X1]) == typeof(nlprob[:X2]) == Float64 + + # Checks that input type `Int64` is converted to `Float64`. + u0 = [:X1 => 1, :X2 => 3] + ps = [:k1 => 2, :k2 => 3] + nlprob = NonlinearProblem(rn, u0, ps) + nlsol = solve(nlprob) + @test eltype(nlsol[:X1]) == eltype(nlsol[:X2]) == typeof(nlprob[:X1]) == typeof(nlprob[:X2]) == Float64 + + # Checks that input type `Float32` is preserved + u0 = [:X1 => 1.0f0, :X2 => 3.0f0] + ps = [:k1 => 2.0f0, :k2 => 3.0f0] + nlprob = NonlinearProblem(rn, u0, ps) + nlsol = solve(nlprob) + @test eltype(nlsol[:X1]) == eltype(nlsol[:X2]) == typeof(nlprob[:X1]) == typeof(nlprob[:X2]) == Float32 +end \ No newline at end of file From 295c1e7679d64f0c95efa4fc1c8bda060af7ff30 Mon Sep 17 00:00:00 2001 From: Torkel Loman Date: Thu, 20 Mar 2025 09:12:07 +0000 Subject: [PATCH 3/4] comment clarification --- test/simulation_and_solving/simulate_jumps.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/simulation_and_solving/simulate_jumps.jl b/test/simulation_and_solving/simulate_jumps.jl index 6e26deef44..cad8b5bdfd 100644 --- a/test/simulation_and_solving/simulate_jumps.jl +++ b/test/simulation_and_solving/simulate_jumps.jl @@ -224,8 +224,8 @@ end ### Other Tests ### # Checks that solution values have types consistent with their input types. -# Check that both float and integer values are preserved in the solution (and problems). -# Checks that the time values are correct (`Float64` by default or possibly `Float32`). +# Check that both float and integer types are preserved in the solution (and problems). +# Checks that the time types are correct (`Float64` by default or possibly `Float32`). # `JumpInputs` currently does not support integer time spans. When it does, we will check that # these produce `Float64` time values. let From a54094ccdb15ea2704a99a630a5cccdc09de8e5e Mon Sep 17 00:00:00 2001 From: Torkel Loman Date: Sun, 30 Mar 2025 21:22:13 +0100 Subject: [PATCH 4/4] up --- test/simulation_and_solving/simulate_ODEs.jl | 4 +--- test/simulation_and_solving/simulate_SDEs.jl | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/test/simulation_and_solving/simulate_ODEs.jl b/test/simulation_and_solving/simulate_ODEs.jl index 0d725e5a10..491c45c953 100644 --- a/test/simulation_and_solving/simulate_ODEs.jl +++ b/test/simulation_and_solving/simulate_ODEs.jl @@ -167,8 +167,7 @@ end # Checks that solution values have types consistent with their input types. # Check that both float types are preserved in the solution (and problems), while integers are # promoted to floats. -# Checks that the time types are correct (`Float64` by default or possibly `Float32`), however, -# type conversion only occurs in the solution, and integer types are preserved in problems. +# Checks that the time types are correct (`Float64` by default or possibly `Float32`). let # Create model. Checks when input type is `Float64` the produced values are also `Float64`. rn = @reaction_network begin @@ -188,7 +187,6 @@ let osol = solve(oprob) @test eltype(osol[:X1]) == eltype(osol[:X2]) == typeof(oprob[:X1]) == typeof(oprob[:X2]) == Float64 @test eltype(osol.t) == Float64 - @test typeof(oprob.tspan[1]) == typeof(oprob.tspan[2]) == Int64 # Checks when values are `Float32` (a valid type and should be preserved). u0 = [:X1 => 1.0f0, :X2 => 3.0f0] diff --git a/test/simulation_and_solving/simulate_SDEs.jl b/test/simulation_and_solving/simulate_SDEs.jl index d2f8707d76..72c104b11b 100644 --- a/test/simulation_and_solving/simulate_SDEs.jl +++ b/test/simulation_and_solving/simulate_SDEs.jl @@ -407,7 +407,6 @@ let ssol = solve(sprob, ISSEM()) @test eltype(ssol[:X1]) == eltype(ssol[:X2]) == typeof(sprob[:X1]) == typeof(sprob[:X2]) == Float64 @test eltype(ssol.t) == Float64 - @test typeof(sprob.tspan[1]) == typeof(sprob.tspan[2]) == Int64 # Checks when values are `Float32` (a valid type and should be preserved). u0 = [:X1 => 1.0f0, :X2 => 3.0f0]