Skip to content

Commit 1e92135

Browse files
committed
init
1 parent cc2f95f commit 1e92135

File tree

6 files changed

+93
-35
lines changed

6 files changed

+93
-35
lines changed

ext/CatalystBifurcationKitExtension/bifurcation_kit_extension.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ function BK.BifurcationProblem(rs::ReactionSystem, u0_bif, ps, bif_par, args...;
2222

2323
# Creates NonlinearSystem.
2424
Catalyst.conservationlaw_errorcheck(rs, vcat(ps, u0))
25-
nsys = convert(NonlinearSystem, rs; remove_conserved = true, defaults = Dict(u0))
25+
nsys = convert(NonlinearSystem, rs; defaults = Dict(u0),
26+
remove_conserved = true, remove_conserved_warn = false)
2627
nsys = complete(nsys)
2728

2829
# Makes BifurcationProblem (this call goes through the ModelingToolkit-based BifurcationKit extension).

ext/CatalystHomotopyContinuationExtension/homotopy_continuation_extension.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ end
4949
# For a given reaction system, parameter values, and initial conditions, find the polynomial that HC solves to find steady states.
5050
function steady_state_polynomial(rs::ReactionSystem, ps, u0)
5151
rs = Catalyst.expand_registered_functions(rs)
52-
ns = complete(convert(NonlinearSystem, rs; remove_conserved = true))
52+
ns = complete(convert(NonlinearSystem, rs;
53+
remove_conserved = true, remove_conserved_warn = false))
5354
pre_varmap = [symmap_to_varmap(rs, u0)..., symmap_to_varmap(rs, ps)...]
5455
Catalyst.conservationlaw_errorcheck(rs, pre_varmap)
5556
p_vals = ModelingToolkit.varmap_to_vars(pre_varmap, parameters(ns);

ext/CatalystStructuralIdentifiabilityExtension/structural_identifiability_extension.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ function make_osys(rs::ReactionSystem; remove_conserved = true)
167167
error("Identifiability should only be computed for complete systems. A ReactionSystem can be marked as complete using the `complete` function.")
168168
end
169169
rs = complete(Catalyst.expand_registered_functions(flatten(rs)))
170-
osys = complete(convert(ODESystem, rs; remove_conserved))
170+
osys = complete(convert(ODESystem, rs; remove_conserved, remove_conserved_warn = false))
171171
vars = [unknowns(rs); parameters(rs)]
172172

173173
# Computes equations for system conservation laws.

src/reactionsystem_conversions.jl

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,17 @@ diff_2_zero(expr) = (Symbolics.is_derivative(expr) ? 0 : expr)
450450

451451
COMPLETENESS_ERROR = "A ReactionSystem must be complete before it can be converted to other system types. A ReactionSystem can be marked as complete using the `complete` function."
452452

453+
# Used to, when required, display a warning about conservation law removeal and remake.
454+
function check_cons_warning(remove_conserved, remove_conserved_warn)
455+
(remove_conserved && remove_conserved_warn) || return
456+
@warn "You are creating a system while eliminating conserved quantities. While this is possible,
457+
if you use the created system to create a problem (e.g. an `ODEProblem`), you *should not*
458+
modify that problem's species values (e.g. using `remake`). Modification of parameter values
459+
is still possible. You might get this warning when creating a problem directly.
460+
461+
You can remove this warning by setting `remove_conserved_warn = false`."
462+
end
463+
453464
### System Conversions ###
454465

455466
"""
@@ -467,15 +478,20 @@ Keyword args and default values:
467478
- `remove_conserved=false`, if set to `true` will calculate conservation laws of the
468479
underlying set of reactions (ignoring constraint equations), and then apply them to reduce
469480
the number of equations.
481+
- `remove_conserved_warn = true`: If `true`, if also `remove_conserved = true`, there will be
482+
a warning regarding limitations of modifying problems generated from the created system.
470483
"""
471484
function Base.convert(::Type{<:ODESystem}, rs::ReactionSystem; name = nameof(rs),
472485
combinatoric_ratelaws = get_combinatoric_ratelaws(rs),
473-
include_zero_odes = true, remove_conserved = false, checks = false,
474-
default_u0 = Dict(), default_p = Dict(),
486+
include_zero_odes = true, remove_conserved = false, remove_conserved_warn = true,
487+
checks = false, default_u0 = Dict(), default_p = Dict(),
475488
defaults = _merge(Dict(default_u0), Dict(default_p)),
476489
kwargs...)
490+
# Error checks.
477491
iscomplete(rs) || error(COMPLETENESS_ERROR)
478492
spatial_convert_err(rs::ReactionSystem, ODESystem)
493+
check_cons_warning(remove_conserved, remove_conserved_warn)
494+
479495
fullrs = Catalyst.flatten(rs)
480496
remove_conserved && conservationlaws(fullrs)
481497
ists, ispcs = get_indep_sts(fullrs, remove_conserved)
@@ -509,16 +525,19 @@ Keyword args and default values:
509525
- `remove_conserved=false`, if set to `true` will calculate conservation laws of the
510526
underlying set of reactions (ignoring constraint equations), and then apply them to reduce
511527
the number of equations.
528+
- `remove_conserved_warn = true`: If `true`, if also `remove_conserved = true`, there will be
529+
a warning regarding limitations of modifying problems generated from the created system.
512530
"""
513531
function Base.convert(::Type{<:NonlinearSystem}, rs::ReactionSystem; name = nameof(rs),
514532
combinatoric_ratelaws = get_combinatoric_ratelaws(rs),
515533
include_zero_odes = true, remove_conserved = false, checks = false,
516-
default_u0 = Dict(), default_p = Dict(),
534+
remove_conserved_warn = true, default_u0 = Dict(), default_p = Dict(),
517535
defaults = _merge(Dict(default_u0), Dict(default_p)),
518536
all_differentials_permitted = false, kwargs...)
519537
# Error checks.
520538
iscomplete(rs) || error(COMPLETENESS_ERROR)
521539
spatial_convert_err(rs::ReactionSystem, NonlinearSystem)
540+
check_cons_warning(remove_conserved, remove_conserved_warn)
522541
if !isautonomous(rs)
523542
error("Attempting to convert a non-autonomous `ReactionSystem` (e.g. where some rate depend on $(get_iv(rs))) to a `NonlinearSystem`. This is not possible. if you are intending to compute system steady states, consider creating and solving a `SteadyStateProblem.")
524543
end
@@ -589,17 +608,19 @@ Notes:
589608
- `remove_conserved=false`, if set to `true` will calculate conservation laws of the
590609
underlying set of reactions (ignoring constraint equations), and then apply them to reduce
591610
the number of equations.
592-
- Does not currently support `ReactionSystem`s that include coupled algebraic or
593-
differential equations.
611+
- `remove_conserved_warn = true`: If `true`, if also `remove_conserved = true`, there will be
612+
a warning regarding limitations of modifying problems generated from the created system.
594613
"""
595614
function Base.convert(::Type{<:SDESystem}, rs::ReactionSystem;
596615
name = nameof(rs), combinatoric_ratelaws = get_combinatoric_ratelaws(rs),
597616
include_zero_odes = true, checks = false, remove_conserved = false,
598-
default_u0 = Dict(), default_p = Dict(),
617+
remove_conserved_warn = true, default_u0 = Dict(), default_p = Dict(),
599618
defaults = _merge(Dict(default_u0), Dict(default_p)),
600619
kwargs...)
620+
# Error checks.
601621
iscomplete(rs) || error(COMPLETENESS_ERROR)
602622
spatial_convert_err(rs::ReactionSystem, SDESystem)
623+
check_cons_warning(remove_conserved, remove_conserved_warn)
603624

604625
flatrs = Catalyst.flatten(rs)
605626

@@ -651,7 +672,6 @@ function Base.convert(::Type{<:JumpSystem}, rs::ReactionSystem; name = nameof(rs
651672
kwargs...)
652673
iscomplete(rs) || error(COMPLETENESS_ERROR)
653674
spatial_convert_err(rs::ReactionSystem, JumpSystem)
654-
655675
(remove_conserved !== nothing) &&
656676
throw(ArgumentError("Catalyst does not support removing conserved species when converting to JumpSystems."))
657677

@@ -684,12 +704,12 @@ function DiffEqBase.ODEProblem(rs::ReactionSystem, u0, tspan,
684704
p = DiffEqBase.NullParameters(), args...;
685705
check_length = false, name = nameof(rs),
686706
combinatoric_ratelaws = get_combinatoric_ratelaws(rs),
687-
include_zero_odes = true, remove_conserved = false,
707+
include_zero_odes = true, remove_conserved = false, remove_conserved_warn = true,
688708
checks = false, structural_simplify = false, kwargs...)
689709
u0map = symmap_to_varmap(rs, u0)
690710
pmap = symmap_to_varmap(rs, p)
691711
osys = convert(ODESystem, rs; name, combinatoric_ratelaws, include_zero_odes, checks,
692-
remove_conserved)
712+
remove_conserved, remove_conserved_warn)
693713

694714
# Handles potential differential algebraic equations (which requires `structural_simplify`).
695715
if structural_simplify
@@ -708,12 +728,12 @@ function DiffEqBase.NonlinearProblem(rs::ReactionSystem, u0,
708728
p = DiffEqBase.NullParameters(), args...;
709729
name = nameof(rs), include_zero_odes = true,
710730
combinatoric_ratelaws = get_combinatoric_ratelaws(rs),
711-
remove_conserved = false, checks = false,
731+
remove_conserved = false, remove_conserved_warn = true, checks = false,
712732
check_length = false, all_differentials_permitted = false, kwargs...)
713733
u0map = symmap_to_varmap(rs, u0)
714734
pmap = symmap_to_varmap(rs, p)
715735
nlsys = convert(NonlinearSystem, rs; name, combinatoric_ratelaws, include_zero_odes,
716-
checks, all_differentials_permitted, remove_conserved)
736+
checks, all_differentials_permitted, remove_conserved, remove_conserved_warn)
717737
nlsys = complete(nlsys)
718738
return NonlinearProblem(nlsys, u0map, pmap, args...; check_length,
719739
kwargs...)
@@ -723,12 +743,12 @@ end
723743
function DiffEqBase.SDEProblem(rs::ReactionSystem, u0, tspan,
724744
p = DiffEqBase.NullParameters(), args...;
725745
name = nameof(rs), combinatoric_ratelaws = get_combinatoric_ratelaws(rs),
726-
include_zero_odes = true, checks = false, check_length = false,
727-
remove_conserved = false, structural_simplify = false, kwargs...)
746+
include_zero_odes = true, checks = false, check_length = false, remove_conserved = false,
747+
remove_conserved_warn = true, structural_simplify = false, kwargs...)
728748
u0map = symmap_to_varmap(rs, u0)
729749
pmap = symmap_to_varmap(rs, p)
730750
sde_sys = convert(SDESystem, rs; name, combinatoric_ratelaws,
731-
include_zero_odes, checks, remove_conserved)
751+
include_zero_odes, checks, remove_conserved, remove_conserved_warn)
732752

733753
# Handles potential differential algebraic equations (which requires `structural_simplify`).
734754
if structural_simplify
@@ -772,12 +792,12 @@ function DiffEqBase.SteadyStateProblem(rs::ReactionSystem, u0,
772792
p = DiffEqBase.NullParameters(), args...;
773793
check_length = false, name = nameof(rs),
774794
combinatoric_ratelaws = get_combinatoric_ratelaws(rs),
775-
remove_conserved = false, include_zero_odes = true,
795+
remove_conserved = false, remove_conserved_warn = true, include_zero_odes = true,
776796
checks = false, structural_simplify = false, kwargs...)
777797
u0map = symmap_to_varmap(rs, u0)
778798
pmap = symmap_to_varmap(rs, p)
779799
osys = convert(ODESystem, rs; name, combinatoric_ratelaws, include_zero_odes, checks,
780-
remove_conserved)
800+
remove_conserved, remove_conserved_warn)
781801

782802
# Handles potential differential algebraic equations (which requires `structural_simplify`).
783803
if structural_simplify

src/steady_state_stability.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ function steady_state_jac(rs::ReactionSystem; u0 = [sp => 0.0 for sp in unknowns
117117

118118
# Creates an `ODEProblem` with a Jacobian. Dummy values for `u0` and `ps` must be provided.
119119
ps = [p => 0.0 for p in parameters(rs)]
120-
return ODEProblem(rs, u0, 0, ps; jac = true, remove_conserved = true,
121-
combinatoric_ratelaws = combinatoric_ratelaws)
120+
return ODEProblem(rs, u0, 0, ps; jac = true, combinatoric_ratelaws,
121+
remove_conserved = true, remove_conserved_warn = false)
122122
end
123123

124124
# Converts a `u` vector from a vector of values to a map.

test/network_analysis/conservation_laws.jl

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ seed = rand(rng, 1:100)
1111
# Fetch test networks.
1212
include("../test_networks.jl")
1313

14+
# Except where we test the warnings, we do not want to print this warning.
15+
remove_conserved_warn = false
16+
1417
### Basic Tests ###
1518

1619
# Tests basic functionality on system with known conservation laws.
@@ -114,23 +117,23 @@ let
114117
tspan = (0.0, 20.0)
115118

116119
# Simulates model using ODEs and checks that simulations are identical.
117-
osys = complete(convert(ODESystem, rn; remove_conserved = true))
120+
osys = complete(convert(ODESystem, rn; remove_conserved = true, remove_conserved_warn))
118121
oprob1 = ODEProblem(osys, u0, tspan, p)
119122
oprob2 = ODEProblem(rn, u0, tspan, p)
120-
oprob3 = ODEProblem(rn, u0, tspan, p; remove_conserved = true)
123+
oprob3 = ODEProblem(rn, u0, tspan, p; remove_conserved = true, remove_conserved_warn)
121124
osol1 = solve(oprob1, Tsit5(); abstol = 1e-8, reltol = 1e-8, saveat= 0.2)
122125
osol2 = solve(oprob2, Tsit5(); abstol = 1e-8, reltol = 1e-8, saveat= 0.2)
123126
osol3 = solve(oprob3, Tsit5(); abstol = 1e-8, reltol = 1e-8, saveat= 0.2)
124127
@test osol1[sps] osol2[sps] osol3[sps]
125128

126129
# Checks that steady states found using nonlinear solving and steady state simulations are identical.
127-
nsys = complete(convert(NonlinearSystem, rn; remove_conserved = true))
130+
nsys = complete(convert(NonlinearSystem, rn; remove_conserved = true, remove_conserved_warn))
128131
nprob1 = NonlinearProblem{true}(nsys, u0, p)
129132
nprob2 = NonlinearProblem(rn, u0, p)
130-
nprob3 = NonlinearProblem(rn, u0, p; remove_conserved = true)
133+
nprob3 = NonlinearProblem(rn, u0, p; remove_conserved = true, remove_conserved_warn)
131134
ssprob1 = SteadyStateProblem{true}(osys, u0, p)
132135
ssprob2 = SteadyStateProblem(rn, u0, p)
133-
ssprob3 = SteadyStateProblem(rn, u0, p; remove_conserved = true)
136+
ssprob3 = SteadyStateProblem(rn, u0, p; remove_conserved = true, remove_conserved_warn)
134137
nsol1 = solve(nprob1, NewtonRaphson(); abstol = 1e-8)
135138
# Nonlinear problems cannot find steady states properly without removing conserved species.
136139
nsol3 = solve(nprob3, NewtonRaphson(); abstol = 1e-8)
@@ -142,10 +145,10 @@ let
142145
# Creates SDEProblems using various approaches.
143146
u0_sde = [A => 100.0, B => 20.0, C => 5.0, D => 10.0, E => 3.0, F1 => 8.0, F2 => 2.0,
144147
F3 => 20.0]
145-
ssys = complete(convert(SDESystem, rn; remove_conserved = true))
148+
ssys = complete(convert(SDESystem, rn; remove_conserved = true, remove_conserved_warn))
146149
sprob1 = SDEProblem(ssys, u0_sde, tspan, p)
147150
sprob2 = SDEProblem(rn, u0_sde, tspan, p)
148-
sprob3 = SDEProblem(rn, u0_sde, tspan, p; remove_conserved = true)
151+
sprob3 = SDEProblem(rn, u0_sde, tspan, p; remove_conserved = true, remove_conserved_warn)
149152

150153
# Checks that the SDEs f and g function evaluates to the same thing.
151154
ind_us = ModelingToolkit.get_unknowns(ssys)
@@ -186,9 +189,9 @@ let
186189
u0_2 = [rn.X => 2.0, rn.Y => 3.0, rn.XY => 4.0]
187190
u0_3 = [:X => 2.0, :Y => 3.0, :XY => 4.0]
188191
ps = (kB => 2, kD => 1.5)
189-
oprob1 = ODEProblem(rn, u0_1, 10.0, ps; remove_conserved = true)
190-
oprob2 = ODEProblem(rn, u0_2, 10.0, ps; remove_conserved = true)
191-
oprob3 = ODEProblem(rn, u0_3, 10.0, ps; remove_conserved = true)
192+
oprob1 = ODEProblem(rn, u0_1, 10.0, ps; remove_conserved = true, remove_conserved_warn)
193+
oprob2 = ODEProblem(rn, u0_2, 10.0, ps; remove_conserved = true, remove_conserved_warn)
194+
oprob3 = ODEProblem(rn, u0_3, 10.0, ps; remove_conserved = true, remove_conserved_warn)
192195
@test solve(oprob1)[sps] solve(oprob2)[sps] solve(oprob3)[sps]
193196
end
194197

@@ -200,7 +203,7 @@ let
200203
end
201204
u0 = Dict([:X1 => 100.0, :X2 => 120.0])
202205
ps = [:k1 => 0.2, :k2 => 0.15]
203-
sprob = SDEProblem(rn, u0, 10.0, ps; remove_conserved = true)
206+
sprob = SDEProblem(rn, u0, 10.0, ps; remove_conserved = true, remove_conserved_warn)
204207

205208
# Checks that conservation laws hold in all simulations.
206209
sol = solve(sprob, ImplicitEM(); seed)
@@ -213,7 +216,7 @@ let
213216
rn = @reaction_network begin
214217
(k1,k2), X1 <--> X2
215218
end
216-
osys = complete(convert(ODESystem, rn; remove_conserved = true))
219+
osys = complete(convert(ODESystem, rn; remove_conserved = true, remove_conserved_warn))
217220
u0 = [osys.X1 => 1.0, osys.X2 => 1.0]
218221
ps_1 = [osys.k1 => 2.0, osys.k2 => 3.0]
219222
ps_2 = [osys.k1 => 2.0, osys.k2 => 3.0, osys.Γ[1] => 4.0]
@@ -234,7 +237,7 @@ let
234237
rn = @reaction_network begin
235238
(k1,k2), X1 <--> X2
236239
end
237-
@test_throws ArgumentError convert(JumpSystem, rn; remove_conserved = true)
240+
@test_throws ArgumentError convert(JumpSystem, rn; remove_conserved = true, remove_conserved_warn)
238241
end
239242

240243
# Checks that `conserved` metadata is added correctly to parameters.
@@ -245,11 +248,44 @@ let
245248
(k1,k2), X1 <--> X2
246249
(k1,k2), Y1 <--> Y2
247250
end
248-
osys = convert(ODESystem, rs; remove_conserved = true)
251+
osys = convert(ODESystem, rs; remove_conserved = true, remove_conserved_warn)
249252

250253
# Checks that the correct parameters have the `conserved` metadata.
251254
@test Catalyst.isconserved(osys.Γ[1])
252255
@test Catalyst.isconserved(osys.Γ[2])
253256
@test !Catalyst.isconserved(osys.k1)
254257
@test !Catalyst.isconserved(osys.k2)
255258
end
259+
260+
# Checks that conservation law elimination warnings are generated in the correct cases.
261+
let
262+
# Prepare model.
263+
rn = @reaction_network begin
264+
(k1,k2), X1 <--> X2
265+
end
266+
u0 = [:X1 => 1.0, :X2 => 2.0]
267+
tspan = (0.0, 1.0)
268+
ps = [:k1 => 3.0, :k2 => 4.0]
269+
270+
# Check warnings in system conversion.
271+
for XSystem in [ODESystem, SDESystem, NonlinearSystem]
272+
@test_nowarn convert(XSystem, rn)
273+
@test_logs (:warn, r"You are creating a system while eliminating conserved quantities. While *") convert(XSystem, rn; remove_conserved = true)
274+
@test_nowarn convert(XSystem, rn; remove_conserved_warn = false)
275+
@test_nowarn convert(XSystem, rn; remove_conserved = true, remove_conserved_warn = false)
276+
end
277+
278+
# Checks during problem creation (separate depending on whether they have a time span or not).
279+
for XProblem in [ODEProblem, SDEProblem]
280+
@test_nowarn XProblem(rn, u0, tspan, ps)
281+
@test_logs (:warn, r"You are creating a system while eliminating conserved quantities. While *") XProblem(rn, u0, tspan, ps; remove_conserved = true)
282+
@test_nowarn XProblem(rn, u0, tspan, ps; remove_conserved_warn = false)
283+
@test_nowarn XProblem(rn, u0, tspan, ps; remove_conserved = true, remove_conserved_warn = false)
284+
end
285+
for XProblem in [NonlinearProblem, SteadyStateProblem]
286+
@test_nowarn XProblem(rn, u0, ps)
287+
@test_logs (:warn, r"You are creating a system while eliminating conserved quantities. While *") XProblem(rn, u0, ps; remove_conserved = true)
288+
@test_nowarn XProblem(rn, u0, ps; remove_conserved_warn = false)
289+
@test_nowarn XProblem(rn, u0, ps; remove_conserved = true, remove_conserved_warn = false)
290+
end
291+
end

0 commit comments

Comments
 (0)