diff --git a/Project.toml b/Project.toml index c00c881..e83b1d2 100644 --- a/Project.toml +++ b/Project.toml @@ -16,7 +16,7 @@ Aqua = "0.8" EzXML = "1.1" MathML = "0.1.14" Memoize = "0.4.2" -ModelingToolkit = "9" +ModelingToolkit = "10" OrdinaryDiffEq = "6.56" SafeTestsets = "0.1" Setfield = "1" diff --git a/README.md b/README.md index 3347f51..10f093e 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ The models directory contains a few CellML model examples. Let's start with a si ml = CellModel("models/lorenz.cellml.xml") ``` -Now, `ml` is a `CellModel` structure that contains both a list of the loaded XML files and their components (accessible as `ml.doc`) and a ModelingToolkit `ODESystem` that defines variables and dynamics and can be accessed as `getsys(ml)`. +Now, `ml` is a `CellModel` structure that contains both a list of the loaded XML files and their components (accessible as `ml.doc`) and a ModelingToolkit `System` that defines variables and dynamics and can be accessed as `getsys(ml)`. The next step is to convert `ml` into an `ODEProblem`, ready to be solved. diff --git a/src/CellMLToolkit.jl b/src/CellMLToolkit.jl index be3f483..ceee5fb 100644 --- a/src/CellMLToolkit.jl +++ b/src/CellMLToolkit.jl @@ -5,8 +5,8 @@ using MathML: extract_mathml, parse_node using Memoize: @memoize using SymbolicUtils: operation using ModelingToolkit: ModelingToolkit, @parameters, @variables, Differential, - Equation, ODEProblem, ODESystem, - Symbolics, equations, parameters, structural_simplify, + Equation, ODEProblem, System, + Symbolics, equations, parameters, mtkcompile, substitute, unknowns using Setfield: @set! @@ -50,7 +50,7 @@ import ModelingToolkit.ODEProblem function ODEProblem(ml::CellModel, tspan; jac = false, level = 1, p = last.(list_params(ml)), u0 = last.(list_states(ml))) - ODEProblem(ml.sys, u0, tspan, p; jac = jac) + ODEProblem(ml.sys, Pair[unknowns(ml.sys) .=> u0; parameters(ml.sys) .=> p], tspan; jac = jac) end function update_list!(l, sym, val) diff --git a/src/analysis.jl b/src/analysis.jl index c825222..e54890e 100644 --- a/src/analysis.jl +++ b/src/analysis.jl @@ -7,7 +7,7 @@ function simplify_systems(systems) sys = last(x) print("simplifying $(nameof(sys))") try - sys = structural_simplify(sys) + sys = mtkcompile(sys) k = max(1, 50 - length(string(nameof(sys)))) printstyled(repeat(" ", k) * "OK!"; color = :green) println() diff --git a/src/components.jl b/src/components.jl index f54a00f..d05bc37 100644 --- a/src/components.jl +++ b/src/components.jl @@ -168,7 +168,7 @@ end """ pre_substitution generates the substitution rules to be applied to - individual systems before structural_simplify merges them together + individual systems before mtkcompile merges them together it morphes variables and parameters to their correct form for ModelingToolkit based on the global CellML doc information @@ -193,7 +193,7 @@ end """ post_substitution generates the substitution rules to be applied to - the merged system after structural_simplify is applied + the merged system after mtkcompile is applied if changes the names of the independent variable (iv) in each system to the global iv name @@ -212,7 +212,7 @@ substitute_eqs(eqs, s) = [substitute(eq.lhs, s) ~ substitute(eq.rhs, s) for eq i """ process_components is the main entry point - it processes an doc document and returns a merged ODESystem + it processes an doc document and returns a merged System use simplify=false only for debugging purposes! """ @@ -224,13 +224,13 @@ function process_components(doc::Document; simplify = true) systems = subsystems(doc, class) post_sub = post_substitution(doc, systems) - sys = ODESystem(translate_connections(doc, systems, class), + sys = System(Vector{Equation}(translate_connections(doc, systems, class)), get_ivₚ(doc), systems = collect(values(systems)), name = gensym(:cellml)) if simplify - sys = structural_simplify(sys) + sys = mtkcompile(sys) @set! sys.eqs = substitute_eqs(equations(sys), post_sub) # Defaults need to be set after simplifying as otherwise parameters and @@ -250,12 +250,12 @@ end class is the output of classify_variables """ function subsystems(doc::Document, class) - Dict{Symbol, ODESystem}(to_symbol(comp) => process_component(doc, comp, class) + Dict{Symbol, System}(to_symbol(comp) => process_component(doc, comp, class) for comp in components(doc)) end """ - process_component converts a single CellML component to an ODESystem + process_component converts a single CellML component to an System comp in the name of the component class is the output of classify_variables @@ -270,7 +270,7 @@ function process_component(doc::Document, comp, class) eqs = vcat(parse_node.(math)...) eqs = substitute_eqs(eqs, pre_sub) sub_rhs = remove_rhs_diff(eqs) - eqs = [eq.lhs ~ substitute(eq.rhs, sub_rhs) for eq in eqs] + eqs = Equation[eq.lhs ~ substitute(eq.rhs, sub_rhs) for eq in eqs] end ivₚ = get_ivₚ(doc) @@ -280,7 +280,7 @@ function process_component(doc::Document, comp, class) states = [last(x) for x in values(pre_sub) if !ModelingToolkit.isparameter(last(x)) && !isequal(last(x), ivₚ)] - ODESystem(eqs, ivₚ, states, ps; name = to_symbol(comp)) + System(eqs, ivₚ, states, ps; name = to_symbol(comp)) end ############################################################################### diff --git a/src/structures.jl b/src/structures.jl index fe0fce1..5b5c49f 100644 --- a/src/structures.jl +++ b/src/structures.jl @@ -32,5 +32,5 @@ connections(doc::Document) = doc.conns struct CellModel doc::Document - sys::ODESystem + sys::System end diff --git a/test/beeler.jl b/test/beeler.jl index e3af958..be83546 100644 --- a/test/beeler.jl +++ b/test/beeler.jl @@ -24,7 +24,7 @@ err = sum(abs.(V1 .- V2)) / length(V1) # Ensure defaults are set and that generating an `ODEProblem` directly from the # `ODESystem` is equivalent to doing so from a `CellModel` @test length(ModelingToolkit.defaults(ml.sys)) > 0 -sys_prob = ODEProblem(ml.sys; tspan = (0, 10000.0)) +sys_prob = ODEProblem(ml.sys, nothing, (0, 10000.0)) sol3 = solve(prob, Euler(), dt = 0.01, saveat = 1.0) V3 = map(x -> x[1], sol3.u) err2 = sum(abs.(V1 .- V3)) / length(V1) diff --git a/test/noble_1962.jl b/test/noble_1962.jl index bc84f0e..6a90393 100644 --- a/test/noble_1962.jl +++ b/test/noble_1962.jl @@ -15,7 +15,7 @@ err1 = sum(abs.(V1 .- V2)) / length(V1) # Ensure defaults are set and that generating an `ODEProblem` directly from the # `ODESystem` is equivalent to doing so from a `CellModel` @test length(ModelingToolkit.defaults(ml.sys)) > 0 -sys_prob = ODEProblem(ml.sys; tspan = (0, 10000.0)) +sys_prob = ODEProblem(ml.sys, nothing, (0, 10000.0)) sol3 = solve(prob, Euler(), dt = 0.01, saveat = 1.0) V3 = map(x -> x[2], sol3.u) err2 = sum(abs.(V1 .- V3)) / length(V1)