Skip to content

Commit 38a6df7

Browse files
feat: separate parameter-only equations to parameter_dependencies in complete
1 parent 317c2f7 commit 38a6df7

File tree

1 file changed

+45
-43
lines changed

1 file changed

+45
-43
lines changed

src/systems/abstractsystem.jl

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,7 @@ function complete(
632632
@set! newsys.parent = complete(sys; split = false, flatten = false)
633633
end
634634
sys = newsys
635+
sys = process_parameter_equations(sys)
635636
if add_initial_parameters
636637
sys = add_initialization_parameters(sys; split)
637638
end
@@ -2760,52 +2761,53 @@ function Symbolics.substitute(sys::AbstractSystem, rules::Union{Vector{<:Pair},
27602761
end
27612762
end
27622763

2763-
struct InvalidParameterDependenciesType
2764-
got::Any
2765-
end
2764+
"""
2765+
$(TYPEDSIGNATURES)
27662766
2767-
function Base.showerror(io::IO, err::InvalidParameterDependenciesType)
2768-
print(
2769-
io, "Parameter dependencies must be a `Dict`, or an array of `Pair` or `Equation`.")
2770-
if err.got !== nothing
2771-
print(io, " Got ", err.got)
2767+
Find equations of `sys` involving only parameters and separate them out into the
2768+
`parameter_dependencies` field. Relative ordering of equations is maintained.
2769+
Parameter-only equations are validated to be explicit and sorted topologically. All such
2770+
explicitly determined parameters are removed from the parameters of `sys`. Return the new
2771+
system.
2772+
"""
2773+
function process_parameter_equations(sys::AbstractSystem)
2774+
if !isempty(get_systems(sys))
2775+
throw(ArgumentError("Expected flattened system"))
27722776
end
2773-
end
2774-
2775-
function process_parameter_dependencies(pdeps, ps)
2776-
if pdeps === nothing || isempty(pdeps)
2777-
return Equation[], ps
2777+
varsbuf = Set()
2778+
pareq_idxs = Int[]
2779+
eqs = equations(sys)
2780+
for (i, eq) in enumerate(eqs)
2781+
empty!(varsbuf)
2782+
vars!(varsbuf, eq; op = Union{Differential, Initial, Pre})
2783+
# singular equations
2784+
isempty(varsbuf) && continue
2785+
if all(varsbuf) do sym
2786+
is_parameter(sys, sym) ||
2787+
symbolic_type(sym) == ArraySymbolic() &&
2788+
is_sized_array_symbolic(sym) &&
2789+
all(Base.Fix1(is_parameter, sys), collect(sym))
2790+
end
2791+
if !isparameter(eq.lhs)
2792+
throw(ArgumentError("""
2793+
LHS of parameter dependency equation must be a single parameter. Found \
2794+
$(eq.lhs).
2795+
"""))
2796+
end
2797+
push!(pareq_idxs, i)
2798+
end
27782799
end
2779-
if pdeps isa Dict
2780-
pdeps = [k ~ v for (k, v) in pdeps]
2781-
else
2782-
pdeps isa AbstractArray || throw(InvalidParameterDependenciesType(pdeps))
2783-
pdeps = [if p isa Pair
2784-
p[1] ~ p[2]
2785-
elseif p isa Equation
2786-
p
2787-
else
2788-
error("Parameter dependencies must be a `Dict`, `Vector{Pair}` or `Vector{Equation}`")
2789-
end
2790-
for p in pdeps]
2791-
end
2792-
lhss = []
2793-
for p in pdeps
2794-
if !isparameter(p.lhs)
2795-
error("LHS of parameter dependency must be a single parameter. Found $(p.lhs).")
2796-
end
2797-
syms = vars(p.rhs)
2798-
if !all(isparameter, syms)
2799-
error("RHS of parameter dependency must only include parameters. Found $(p.rhs)")
2800-
end
2801-
push!(lhss, p.lhs)
2802-
end
2803-
lhss = map(identity, lhss)
2804-
pdeps = topsort_equations(pdeps, union(ps, lhss))
2805-
ps = filter(ps) do p
2806-
!any(isequal(p), lhss)
2807-
end
2808-
return pdeps, ps
2800+
2801+
pareqs = [get_parameter_dependencies(sys); eqs[pareq_idxs]]
2802+
explicitpars = [eq.lhs for eq in pareqs]
2803+
pareqs = topsort_equations(pareqs, explicitpars)
2804+
2805+
eqs = eqs[setdiff(eachindex(eqs), pareq_idxs)]
2806+
2807+
@set! sys.eqs = eqs
2808+
@set! sys.parameter_dependencies = pareqs
2809+
@set! sys.ps = setdiff(get_ps(sys), explicitpars)
2810+
return sys
28092811
end
28102812

28112813
"""

0 commit comments

Comments
 (0)