Skip to content

Commit 8ee6187

Browse files
Merge pull request #4431 from SciML/as/irstructure
refactor: use `IRStructure` for codegen
2 parents 915dbf6 + 3e44c9b commit 8ee6187

17 files changed

Lines changed: 246 additions & 192 deletions

lib/ModelingToolkitBase/Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ StaticArrays = "1.9.14"
167167
StochasticDelayDiffEq = "1.11"
168168
StochasticDiffEq = "6.82.0"
169169
SymbolicIndexingInterface = "0.3.39"
170-
SymbolicUtils = "4.20.1"
171-
Symbolics = "7.12"
170+
SymbolicUtils = "4.23.1"
171+
Symbolics = "7.18.1"
172172
UnPack = "0.1, 1.0"
173173
julia = "1.9"
174174

lib/ModelingToolkitBase/src/ModelingToolkitBase.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ include("systems/imperative_affect.jl")
190190
include("systems/callbacks.jl")
191191
include("systems/system.jl")
192192
include("systems/analysis_points.jl")
193+
include("systems/ir_info.jl")
193194
include("systems/codegen_utils.jl")
194195
include("problems/docs.jl")
195196
include("systems/codegen.jl")
@@ -382,6 +383,8 @@ function __init__()
382383
SU.hashcons(BVP_SOLUTION, true)
383384
SU.hashcons(unwrap(W_GAMMA), true)
384385
SU.hashcons(unwrap(ASSERTION_LOG_VARIABLE), true)
386+
SU.hashcons(DDE_AT_IDX_SYM, true)
387+
SU.hashcons(DDE_DELAY_SYM, true)
385388
return nothing
386389
end
387390

lib/ModelingToolkitBase/src/systems/abstractsystem.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ function generate_custom_function(
5555
if expression == Val{true}
5656
return fnexpr
5757
end
58-
if fnexpr isa Tuple
58+
if SU.is_array_shape(SU.shape(unwrap(exprs)))
5959
return eval_or_rgf.(fnexpr; eval_expression, eval_module)
6060
else
61-
return eval_or_rgf(fnexpr; eval_expression, eval_module)
61+
return eval_or_rgf(fnexpr[1]; eval_expression, eval_module)
6262
end
6363
end
6464

@@ -941,6 +941,7 @@ const SYS_PROPS = [
941941
:state_priorities
942942
:irreducibles
943943
:maybe_zeros
944+
:irstructure
944945
:assertions
945946
:ignored_connections
946947
:parent

lib/ModelingToolkitBase/src/systems/callbacks.jl

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,11 @@ function AffectSystem(
171171
p in pre_params && continue
172172
push!(sys_params, p)
173173
end
174-
discretes = map(tovar, discrete_parameters)
174+
discretes = discrete_parameters
175175
dvs = collect(dvs)
176176
_dvs = map(default_toterm, dvs)
177177

178-
rev_map = Dict{SymbolicT, SymbolicT}(zip(discrete_parameters, discretes))
179-
subs = merge(rev_map, Dict{SymbolicT, SymbolicT}(zip(dvs, _dvs)))
178+
subs = Dict{SymbolicT, SymbolicT}(zip(dvs, _dvs))
180179
affect = substitute(affect, subs)
181180

182181
ps = collect(gather_array_params(union(pre_params, sys_params)))
@@ -985,9 +984,6 @@ Base.@nospecializeinfer function compile_condition(
985984
fs = build_function_wrapper(
986985
sys, condit, u, p..., t; kwargs..., cse = false
987986
)
988-
if is_discrete(cbs)
989-
fs = (fs, nothing)
990-
end
991987
fs = GeneratedFunctionWrapper{(2, 3, is_split(sys))}(
992988
Val{false}, fs...; eval_expression, eval_module
993989
)
@@ -1384,7 +1380,13 @@ Base.@nospecializeinfer function compile_explicit_affect(
13841380
dvs_to_update = setdiff(unknowns(aff), getfield.(observed(sys), :lhs))
13851381

13861382
_affsys = unhack_system(affsys)
1387-
obseqs = observed(_affsys)
1383+
aff_ir_info = get_ir_info(affsys)
1384+
aff_ir = get_irstructure(affsys)
1385+
obseqs = Equation[]
1386+
sizehint!(obseqs, length(observed(_affsys)))
1387+
for (i, eq) in enumerate(observed(_affsys))
1388+
push!(obseqs, eq.lhs ~ aff_ir_info.obs_subber(eq.rhs))
1389+
end
13881390

13891391
update_eqs = substitute(
13901392
obseqs, Dict([p => unPre(p) for p in parameters(affsys)])
@@ -1416,18 +1418,19 @@ Base.@nospecializeinfer function compile_explicit_affect(
14161418
u_up,
14171419
u_up! = build_function_wrapper(
14181420
sys, (@view rhss[is_u]), dvs, _ps..., t;
1419-
wrap_code = add_integrator_header(sys, integ, :u), expression = Val{false},
1420-
outputidxs = u_idxs, wrap_mtkparameters, cse = false, eval_expression,
1421-
eval_module
1421+
wrap_code = add_integrator_header(sys, integ, :u),
1422+
outputidxs = u_idxs, wrap_mtkparameters, iip_config = (false, true)
14221423
)
14231424
p_up,
14241425
p_up! = build_function_wrapper(
14251426
sys, (@view rhss[is_p]), dvs, _ps..., t;
1426-
wrap_code = add_integrator_header(sys, integ, :p), expression = Val{false},
1427-
outputidxs = p_idxs, wrap_mtkparameters, cse = false, eval_expression,
1428-
eval_module
1427+
wrap_code = add_integrator_header(sys, integ, :p),
1428+
outputidxs = p_idxs, wrap_mtkparameters, iip_config = (false, true)
14291429
)
14301430

1431+
u_up! = eval_or_rgf(u_up!; eval_expression, eval_module)
1432+
p_up! = eval_or_rgf(p_up!; eval_expression, eval_module)
1433+
14311434
return ExplicitAffect(dvs_to_update, ps_to_update, reset_jumps, u_up!, p_up!)
14321435
end
14331436

lib/ModelingToolkitBase/src/systems/codegen.jl

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -698,11 +698,10 @@ function generate_cost(
698698
res = build_function_wrapper(
699699
sys, obj, args...; expression = Val{true}, p_start, p_end, wrap_delays,
700700
histfn = (p, t) -> BVP_SOLUTION(t), histfn_symbolic = BVP_SOLUTION, kwargs...
701-
)
701+
)[1]
702702
if expression == Val{true}
703703
return res
704704
end
705-
f_oop = eval_or_rgf(res; eval_expression, eval_module)
706705
return maybe_compile_function(
707706
expression, wrap_gfw, (2, nargs, is_split(sys)), res; eval_expression, eval_module
708707
)
@@ -750,7 +749,7 @@ function generate_bvp_cost(
750749
histfn = (p, t) -> BVP_SOLUTION(t),
751750
histfn_symbolic = BVP_SOLUTION,
752751
cse, checkbounds, kwargs...
753-
)
752+
)[1]
754753

755754
# (2, 2, is_split) means: 2 args out-of-place, 2 original args, split status
756755
return maybe_compile_function(
@@ -1061,8 +1060,9 @@ function generate_rate_function(js::System, rate)
10611060
return build_function_wrapper(
10621061
js, rate, unknowns(js), p...,
10631062
get_iv(js),
1064-
expression = Val{true}
1065-
)
1063+
expression = Val{true},
1064+
iip_config = (true, false),
1065+
)[1]
10661066
end
10671067

10681068
function generate_affect_function(js::System, affect; kwargs...)
@@ -1178,7 +1178,7 @@ Generates a function that computes the observed value(s) `ts` in the system `sys
11781178
- `ts`: The symbolic observed values whose value should be computed
11791179
11801180
## Keywords
1181-
- `return_inplace = false`: If true and the observed value is a vector, then return both the in place and out of place methods.
1181+
- `return_inplace = Val(false)`: If true and the observed value is a vector, then return both the in place and out of place methods. Can take boolean `true` or `false` values, but `Val(true)` or `Val(false)` is preferred.
11821182
- `expression = false`: Generates a Julia `Expr`` computing the observed value if `expression` is true
11831183
- `eval_expression = false`: If true and `expression = false`, evaluates the returned function in the module `eval_module`
11841184
- `output_type = Array` the type of the array generated by a out-of-place vector-valued function
@@ -1228,7 +1228,7 @@ function build_explicit_observed_function(
12281228
output_type = Array,
12291229
checkbounds = true,
12301230
ps = parameters(sys; initial_parameters = true),
1231-
return_inplace = false,
1231+
return_inplace = Val(false),
12321232
param_only = false,
12331233
throw = true,
12341234
cse = true,
@@ -1320,10 +1320,6 @@ function build_explicit_observed_function(
13201320
SU.query(pred, x)
13211321
end
13221322
end
1323-
extra_assignments = Assignment[]
1324-
for var in pred.present_dervars
1325-
push!(extra_assignments, var dervals[var])
1326-
end
13271323
ts = substitute(ts, namespace_subs)
13281324

13291325
dvs = if param_only
@@ -1371,35 +1367,22 @@ function build_explicit_observed_function(
13711367
fns = build_function_wrapper(
13721368
sys, ts, args...; p_start, p_end,
13731369
output_type, mkarray, try_namespaced = true, expression = Val{true}, cse,
1374-
wrap_delays, extra_assignments, kwargs...
1375-
)
1376-
if fns isa Tuple
1377-
if expression == true || expression === Val{true}
1378-
return return_inplace ? fns : fns[1]
1379-
end
1380-
oop, iip = eval_or_rgf.(fns; eval_expression, eval_module)
1381-
f = GeneratedFunctionWrapper{
1382-
(
1383-
p_start + wrap_delays, length(args) - length(rps) + 1 + wrap_delays, is_split(sys),
1384-
),
1385-
}(
1370+
wrap_delays, kwargs...
1371+
)::NTuple{2, Expr}
1372+
if expression === true || expression === Val{true}
1373+
return (return_inplace isa Val{true} || return_inplace isa Bool && return_inplace) ? fns : fns[1]
1374+
end
1375+
1376+
oop = eval_or_rgf(fns[1]; eval_expression, eval_module)
1377+
iip = eval_or_rgf(fns[2]; eval_expression, eval_module)
1378+
f = GeneratedFunctionWrapper{
1379+
(
1380+
p_start + wrap_delays, length(args) - length(rps) + 1 + wrap_delays, is_split(sys),
1381+
),
1382+
}(
13861383
oop, iip
13871384
)
1388-
return return_inplace ? (f, f) : f
1389-
else
1390-
if expression == true || expression === Val{true}
1391-
return fns
1392-
end
1393-
f = eval_or_rgf(fns; eval_expression, eval_module)
1394-
f = GeneratedFunctionWrapper{
1395-
(
1396-
p_start + wrap_delays, length(args) - length(rps) + 1 + wrap_delays, is_split(sys),
1397-
),
1398-
}(
1399-
f, nothing
1400-
)
1401-
return f
1402-
end
1385+
return (return_inplace isa Val{true} || return_inplace isa Bool && return_inplace) ? (f, f) : f
14031386
end
14041387

14051388
struct CachedLinearAb

0 commit comments

Comments
 (0)