Skip to content

Commit a649acc

Browse files
authored
Merge pull request #853 from SciML/new_conserved_quantities_metadata
Add `conservedquantity` metadata
2 parents 1808a3a + 334ccb2 commit a649acc

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

src/network_analysis.jl

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,23 @@ end
542542

543543
### Conservation Laws ###
544544

545+
# Implements the `conserved` parameter metadata.
546+
struct ConservedParameter end
547+
Symbolics.option_to_metadata_type(::Val{:conserved}) = ConservedParameter
548+
549+
"""
550+
isconserved(p)
551+
552+
Checks if the input parameter (`p`) is a conserved quantity (i.e. have the `conserved`)
553+
metadata.
554+
"""
555+
isconserved(x::Num, args...) = isconserved(Symbolics.unwrap(x), args...)
556+
function isconserved(x, default = false)
557+
p = Symbolics.getparent(x, nothing)
558+
p === nothing || (x = p)
559+
Symbolics.getmetadata(x, ConservedParameter, default)
560+
end
561+
545562
"""
546563
conservedequations(rn::ReactionSystem)
547564
@@ -635,7 +652,8 @@ function cache_conservationlaw_eqs!(rn::ReactionSystem, N::AbstractMatrix, col_o
635652
indepspecs = sts[indepidxs]
636653
depidxs = col_order[(r + 1):end]
637654
depspecs = sts[depidxs]
638-
constants = MT.unwrap.(MT.scalarize((@parameters Γ[1:nullity])[1]))
655+
constants = MT.unwrap.(MT.scalarize(only(
656+
@parameters $(CONSERVED_CONSTANT_SYMBOL)[1:nullity] [conserved=true])))
639657

640658
conservedeqs = Equation[]
641659
constantdefs = Equation[]

test/network_analysis/conservation_laws.jl

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,23 @@ let
142142
sprob3.g(g3, u3, sprob3.p, 1.0)
143143
@test isapprox(g1, g2[istsidxs, :])
144144
@test isapprox(g2[istsidxs, :], g3)
145-
end
145+
end
146+
147+
### ConservedParameter Metadata Tests ###
148+
149+
# Checks that `conserved` metadata is added correctly to parameters.
150+
# Checks that the `isconserved` getter function works correctly.
151+
let
152+
# Creates ODESystem with conserved quantities.
153+
rs = @reaction_network begin
154+
(k1,k2), X1 <--> X2
155+
(k1,k2), Y1 <--> Y2
156+
end
157+
osys = convert(ODESystem, rs; remove_conserved = true)
158+
159+
# Checks that the correct parameters have the `conserved` metadata.
160+
@test Catalyst.isconserved(osys.Γ[1])
161+
@test Catalyst.isconserved(osys.Γ[2])
162+
@test !Catalyst.isconserved(osys.k1)
163+
@test !Catalyst.isconserved(osys.k2)
164+
end

0 commit comments

Comments
 (0)