Skip to content

Commit fe2f492

Browse files
committed
handle weird reactions
1 parent 7e2a441 commit fe2f492

File tree

3 files changed

+79
-19
lines changed

3 files changed

+79
-19
lines changed

src/Catalyst.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ export Graph, savegraph, complexgraph
147147
include("chemistry_functionality.jl")
148148
export @compound, @compounds
149149
export iscompound, components, coefficients, component_coefficients
150-
export balance_reaction
150+
export balance_reaction, balance_system
151151

152152
### Extensions ###
153153

src/chemistry_functionality.jl

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,9 +353,38 @@ end
353353
From a system, creates a new system where each reaction is a balanced version of the corresponding
354354
reaction of the original system. For more information, consider the `balance_reaction` function
355355
(which is internally applied to each system reaction).
356+
357+
Arguments
358+
- `rs`: The reaction system that should be balanced.
359+
360+
Notes:
361+
- If any reaction in the system cannot be balanced, throws an error.
362+
- If any reaction in the system have an infinite number of potential reactions, throws an error.
363+
Here, it would be possible to generate a valid reaction, however, no such routine is currently
364+
implemented in `balance_system`.
365+
- `balance_system` will not modify reactions of subsystems to the input system. It is recommended
366+
not to apply `balance_system` to non-flattened systems.
356367
"""
357368
function balance_system(rs::ReactionSystem)
358-
@set! rs.eqs = [(eq isa Reaction) ? balance_reaction(eq) : eq for eq in get_eqs(rs)]
359-
@set! rs.rxs = [balance_reaction(rx) for rx in get_rxs(rs)]
369+
@set! rs.eqs = CatalystEqType[get_balanced_reaction(eq) for eq in get_eqs(rs)]
370+
@set! rs.rxs = [get_balanced_reaction(rx) for rx in get_rxs(rs)]
360371
return rs
361-
end
372+
end
373+
374+
# Selects a balanced version of an input reaction. Handles potential problems when there are no,
375+
# or several, balanced alternatives.
376+
function get_balanced_reaction(rx::Reaction)
377+
brxs = balance_reaction(rx)
378+
379+
# In case there are no, or multiple, solutions to the balancing problem.
380+
if isempty(brxs)
381+
error("Could not balance reaction `$rx`, unable to create a balanced `ReactionSystem`.")
382+
end
383+
if length(brxs) > 1
384+
error("Infinite number of balanced reactions possible for reaction ($rx) are possible. No method for automatically generating a valid reaction is currently implemented in `balance_system`.")
385+
end
386+
387+
return only(brxs)
388+
end
389+
# For non-`Reaction` equations, returns the original equation.
390+
get_balanced_reaction(eq::Equation) = eq

test/miscellaneous_tests/reaction_balancing.jl

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -433,15 +433,15 @@ end
433433

434434
# Simple example with multiple reactions.
435435
let
436-
# Creates a reaction system and tis balanced version.
436+
# Creates an unbalanced `ReactionSystem`.
437437
rs = @reaction_network begin
438438
@species C(t) O(t) H(t)
439439
@compounds begin
440-
H2(t) = 2H
441-
CH4(t) = C + 4H
442-
O2(t) = 2O
443-
CO2(t) = C + 2O
444-
H2O(t) = 2H + O
440+
H2(t) ~ 2H
441+
CH4(t) ~ C + 4H
442+
O2(t) ~ 2O
443+
CO2(t) ~ C + 2O
444+
H2O(t) ~ 2H + O
445445
end
446446
1.0, C + H2 --> CH4
447447
2.0, CH4 + O2 --> CO2 + H2O
@@ -452,23 +452,23 @@ let
452452
# substrates/products for granted).
453453
rx1 = filter(rx -> isequal(rx.rate, 1.0), reactions(rs_balanced))[1]
454454
rx2 = filter(rx -> isequal(rx.rate, 2.0), reactions(rs_balanced))[1]
455-
@test issetequal(rx1.substoich, [1,2])
455+
@test issetequal(rx1.substoich, [1, 2])
456456
@test issetequal(rx1.prodstoich, [1])
457-
@test issetequal(rx2.substoich, [1,2])
458-
@test issetequal(rx2.prodstoich, [1,2])
457+
@test issetequal(rx2.substoich, [1, 2])
458+
@test issetequal(rx2.prodstoich, [1, 2])
459459
end
460460

461461
# Checks for system with non-reaction equations.
462462
let
463-
# Creates a reaction system and tis balanced version.
463+
# Creates an unbalanced `ReactionSystem`.
464464
rs = @reaction_network begin
465465
@species O(t) H(t)
466466
@compounds begin
467-
H2(t) = 2H
468-
O2(t) = 2O
469-
H2O(t) = 2H + O
467+
H2(t) ~ 2H
468+
O2(t) ~ 2O
469+
H2O(t) ~ 2H + O
470470
end
471-
@equation begin
471+
@equations begin
472472
D(V) ~ 1 - V
473473
end
474474
1.0, H2 + O2 --> H2O
@@ -477,6 +477,37 @@ let
477477

478478
# Checks that the system is correctly balanced (while not taking order of reactions or of
479479
# substrates/products for granted).
480-
@test issetequal(reactions(rs_balanced)[1].substoich, [2,1])
480+
@test issetequal(reactions(rs_balanced)[1].substoich, [2, 1])
481481
@test issetequal(reactions(rs_balanced)[1].prodstoich, [2])
482+
end
483+
484+
# Checks that systems problematic reactions yield errors.
485+
let
486+
# Check system with reaction with an infinite number of balanced versions.
487+
rs1 = @reaction_network begin
488+
@species C(t) H(t) O(t)
489+
@compounds begin
490+
CO ~ C + O
491+
CO2 ~ C + 2O
492+
H2 ~ 2H
493+
CH4 ~ C + 4H
494+
H2O ~ 2H + O
495+
end
496+
k, CO + CO2 + H2 --> CH4 + H20
497+
end
498+
@test_throws Exception balance_system(rs1)
499+
500+
# Check system with reaction without any balanced versions.
501+
rs2 = @reaction_network begin
502+
@species Fe(t) S(t) O(t) H(t) N(t)
503+
@compounds begin
504+
FeS2 ~ Fe + 2S
505+
HNO3 ~ H + N + 3O
506+
Fe2S3O12 ~ 2Fe + 3S + 12O
507+
NO ~ N + O
508+
H2SO4 ~ 2H + S + 4O
509+
end
510+
k, FeS2 + HNO3 --> Fe2S3O12 + NO + H2SO4
511+
end
512+
@test_throws Exception balance_system(rs2)
482513
end

0 commit comments

Comments
 (0)