11# ## Prepares Tests ###
22
33# Fetch packages.
4- using Catalyst, DiffEqBase, Test
4+ using Catalyst, DiffEqBase, OrdinaryDiffEqRosenbrock, Test
55
66# Sets stable rng number.
77using StableRNGs
1919 (3.0 , 1.0 ), ∅ ↔ Y
2020 (5.0 , 2.0 ), X + Y ↔ XY
2121 end
22-
22+
2323 test_jac = jac_eval (jacobian_network_1, [:X => 1.0 , :Y => 1.0 , :XY => 1.0 ], [], 0.0 )
2424 real_jac = [- 6.0 - 5.0 2.0 ; - 5.0 - 6.0 2.0 ; 5.0 5.0 - 2.0 ]
2525 @test test_jac == real_jac
3333 (p3 * X, 1.0 ), X + Y ↔ XY
3434 end
3535 @unpack X, Y, XY, p1, p2, p3 = jacobian_network_2
36-
36+
3737 for factor in [1e-2 , 1e-1 , 1e0 , 1e1 , 1e2 ], repeat in 1 : 10
3838 u = Dict (rnd_u0 (jacobian_network_2, rng; factor))
3939 p = Dict (rnd_ps (jacobian_network_2, rng; factor))
6767 p[k3]* u[B] p[k3]* u[A] - p[k4]- 3 * p[k5] * u[C]^ 2 / 2 ]
6868 @test test_jac ≈ real_jac
6969 end
70- end
70+ end
71+
72+ # Checks that the Jacobians (dense and sparse) are identical for different system types.
73+ let
74+ # Creates model (vaguely messy model without conserved quantities).
75+ rn = @reaction_network begin
76+ (p,d), 0 <--> (X,Y)
77+ (k1,k2), X + Y <--> XY
78+ (k1,k2), X + 2 Y <--> XY2
79+ (k1,k2), XY + XY2 <--> X2Y3
80+ d, (XY2,X2Y3) --> 0
81+ mm (X2Y3,v,K), 0 --> Z
82+ (k3,k4), 3 Z <--> Z3
83+ 1.0 , X3 --> 0
84+ end
85+
86+ # Performs tests for different randomised values (to be thoroughly sure).
87+ for factor in [0.1 , 1.0 , 10.0 ]
88+ # Creates randomised species and parameter values. Generates jacobians (dense/sparse).
89+ u0 = rnd_u0 (rn, rng; factor)
90+ ps = rnd_ps (rn, rng; factor)
91+ oprob_jac = ODEProblem (rn, u0, 1.0 , ps; jac = true , sparse = false )
92+ oprob_sjac = ODEProblem (rn, u0, 1.0 , ps; jac = true , sparse = true )
93+ sprob_jac = SDEProblem (rn, u0, 1.0 , ps; jac = true , sparse = false )
94+ sprob_sjac = SDEProblem (rn, u0, 1.0 , ps; jac = true , sparse = true )
95+ nlprob_jac = NonlinearProblem (rn, u0, ps; jac = true , sparse = false )
96+ nlprob_sjac = NonlinearProblem (rn, u0, ps; jac = true , sparse = true )
97+
98+ # Checks that Jacobians ar identical.
99+ function eval_jac (prob, sparse)
100+ J = sparse ? deepcopy (prob. f. jac_prototype) : zeros (length (prob. u0), length (prob. u0))
101+ ModelingToolkit. is_time_dependent (prob) ? prob. f. jac (J, prob. u0, prob. p, 0.0 ) : prob. f. jac (J, prob. u0, prob. p)
102+ return J
103+ end
104+ @test eval_jac (oprob_jac, false ) == eval_jac (sprob_jac, false ) == eval_jac (nlprob_jac, false )
105+ @test_broken eval_jac (oprob_sjac, true ) == eval_jac (sprob_sjac, true ) == eval_jac (nlprob_sjac, true ) # https://github.com/SciML/ModelingToolkit.jl/issues/3527
106+ end
107+ end
108+
109+ # ## Sparse Jacobian Tests ###
110+
111+ # Checks that generated dense/sparse Jacobians are identical.
112+ let
113+ # Creates model (vaguely messy model without conserved quantities).
114+ # Model includes a time-dependent reaction.
115+ rn = @reaction_network begin
116+ (p,d), 0 <--> (X,Y,Z)
117+ k1, X + Y --> XY
118+ k2, X + 2 Z --> XZ2
119+ k3, Y3 + X2 --> Y3Z2
120+ k4, X + Y + Z --> XYZ
121+ k5, XZ2 + Y3Z2 --> XY3Z4
122+ k6, XYZ + XYZ --> X2Y2Z2
123+ d, (XY3Z4, X2Y2Z2) --> 0
124+ X + Y, V --> 0
125+ k7/ (1 + t), 2 V --> V2
126+ Z, V2 --> 0
127+ end
128+
129+ # Performs tests for different randomised values (to be thoroughly sure).
130+ for factor in [0.1 , 1.0 , 10.0 ]
131+ # Creates randomised species and parameter values. Generates jacobians (dense/sparse).
132+ u0 = rnd_u0 (rn, rng; factor)
133+ t_val = factor* rand ()
134+ ps = rnd_ps (rn, rng; factor)
135+ jac = jac_eval (rn, u0, ps, t_val; sparse = false )
136+ jac_sparse = jac_eval (rn, u0, ps, t_val; sparse = true )
137+
138+ # Check correctness (both by converting to sparse jac to dense, and through multiplication with other matrix).
139+ @test Matrix (jac_sparse) == jac
140+ mat = factor* rand (rng, length (u0), length (u0))
141+ @test jac_sparse * mat ≈ jac * mat
142+ end
143+ end
144+
145+ # Tests that simulations with different Jacobian and sparsity options are identical.
146+ let
147+ # Creates model (vaguely messy model without conserved quantities).
148+ rn = @reaction_network begin
149+ (v0 + mm (X,v,K),d), 0 <--> X + 2 Y
150+ (k1,k2), X + Y <--> XY
151+ (k1,k2), X + Y2 <--> XY2
152+ (k3,k4), XY + XY2 <--> X2Y3
153+ 1.0 , (XY,XY2,X2Y3) --> 0
154+ mm (X2Y3,v,K), 0 --> Z
155+ (k3* X,k4* Y), 3 Z <--> Z3
156+ d, Z --> 0
157+ end
158+
159+ # Generates initial conditions and parameter values. Creates problems with/o (sparse/dense) jacobian.
160+ u0 = rnd_u0 (rn, rng)
161+ ps = rnd_ps (rn, rng)
162+ oprob = ODEProblem (rn, u0, 1.0 , ps; jac = false , sparse = false )
163+ oprob_j = ODEProblem (rn, u0, 1.0 , ps; jac = true , sparse = false )
164+ oprob_s = ODEProblem (rn, u0, 1.0 , ps; jac = false , sparse = true )
165+ oprob_js = ODEProblem (rn, u0, 1.0 , ps; jac = true , sparse = true )
166+
167+ # Simulates system with implicit solver. Checks that all solutions are identical.
168+ sol = solve (oprob, Rosenbrock23 (), saveat = 0.1 , abstol = 1e-8 , reltol = 1e-8 )
169+ sol_j = solve (oprob_j, Rosenbrock23 (), saveat = 0.1 , abstol = 1e-8 , reltol = 1e-8 )
170+ sol_s = solve (oprob_s, Rosenbrock23 (), saveat = 0.1 , abstol = 1e-8 , reltol = 1e-8 )
171+ sol_js = solve (oprob_js, Rosenbrock23 (), saveat = 0.1 , abstol = 1e-8 , reltol = 1e-8 )
172+ @test sol ≈ sol_j ≈ sol_s ≈ sol_js
173+ end
0 commit comments