Skip to content

Commit a62cb14

Browse files
Merge pull request #3886 from DhairyaLGandhi/dg/change_tunables
chore: add `change_tunables`
2 parents 094f810 + e12213b commit a62cb14

File tree

4 files changed

+69
-1
lines changed

4 files changed

+69
-1
lines changed

docs/src/API/model_building.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ change_independent_variable
226226
add_accumulations
227227
noise_to_brownians
228228
convert_system_indepvar
229+
subset_tunables
229230
```
230231

231232
## Hybrid systems

src/ModelingToolkit.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,8 @@ export isinput, isoutput, getbounds, hasbounds, getguess, hasguess, isdisturbanc
265265
istunable, getdist, hasdist,
266266
tunable_parameters, isirreducible, getdescription, hasdescription,
267267
hasunit, getunit, hasconnect, getconnect,
268-
hasmisc, getmisc, state_priority
268+
hasmisc, getmisc, state_priority,
269+
subset_tunables
269270
export liouville_transform, change_independent_variable, substitute_component,
270271
add_accumulations, noise_to_brownians, Girsanov_transform, change_of_variables
271272
export PDESystem

src/parameters.jl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,42 @@ function split_parameters_by_type(ps)
147147
end
148148
end
149149
end
150+
151+
"""
152+
$(TYPEDSIGNATURES)
153+
154+
Change the tunable parameters of a system to a new set of tunables.
155+
156+
The new tunable parameters must be a subset of the current tunables as discovered by [`tunable_parameters`](@ref).
157+
The remaining parameters will be set as constants in the system.
158+
"""
159+
function subset_tunables(sys, new_tunables)
160+
if !iscomplete(sys)
161+
throw(ArgumentError("System must be `complete` before changing tunables."))
162+
end
163+
if !is_split(sys)
164+
throw(ArgumentError("Tunable parameters can only be changed for split systems."))
165+
end
166+
167+
cur_tunables = tunable_parameters(sys, parameters(sys))
168+
diff_params = setdiff(cur_tunables, new_tunables)
169+
170+
if !isempty(setdiff(new_tunables, cur_tunables))
171+
throw(ArgumentError("""New tunable parameters must be a subset of the current tunable parameters. Found tunable parameters not in the system: $(setdiff(new_tunables, cur_tunables)).
172+
Note that array parameters can only be set as tunable or non-tunable, not partially tunable. They should be specified in the un-scalarized form.
173+
"""))
174+
end
175+
cur_ps = get_ps(sys)
176+
const_ps = toconstant.(diff_params)
177+
178+
for (idx, p) in enumerate(cur_ps)
179+
for (d, c) in zip(diff_params, const_ps)
180+
if isequal(p, d)
181+
setindex!(cur_ps, c, idx)
182+
break
183+
end
184+
end
185+
end
186+
@set! sys.ps = cur_ps
187+
complete(sys)
188+
end

test/parameter_dependencies.jl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,33 @@ end
173173
@test SciMLBase.successful_retcode(sol)
174174
end
175175

176+
@testset "Change Tunables" begin
177+
@variables θ(t)=π/6 ω(t)=0.
178+
@parameters g=9.81 L=1.0 b=0.1 errp=1
179+
eqs = [
180+
D(θ) ~ ω,
181+
D(ω) ~ -(g/L)*sin(θ) - b*ω
182+
]
183+
@named pendulum_sys = System(eqs, t, [θ, ω], [g, L, b])
184+
sys = mtkcompile(pendulum_sys)
185+
186+
new_tunables = [L, b]
187+
sys2 = ModelingToolkit.subset_tunables(sys, new_tunables)
188+
sys2_tunables = ModelingToolkit.tunable_parameters(sys2, ModelingToolkit.parameters(sys2))
189+
@test length(sys2_tunables) == 2
190+
@test isempty(setdiff(sys2_tunables, new_tunables))
191+
@test_throws ArgumentError ModelingToolkit.subset_tunables(sys, [errp])
192+
@test_throws ArgumentError ModelingToolkit.subset_tunables(sys, [θ, L])
193+
sys3 = ModelingToolkit.subset_tunables(sys, [])
194+
sys3_tunables = ModelingToolkit.tunable_parameters(sys3, ModelingToolkit.parameters(sys3))
195+
@test length(sys3_tunables) == 0
196+
197+
sys_incomplete = pendulum_sys
198+
@test_throws ArgumentError ModelingToolkit.subset_tunables(sys_incomplete, new_tunables)
199+
sys_nonsplit = mtkcompile(pendulum_sys; split = false)
200+
@test_throws ArgumentError ModelingToolkit.subset_tunables(sys_nonsplit, new_tunables)
201+
end
202+
176203
struct CallableFoo
177204
p::Any
178205
end

0 commit comments

Comments
 (0)