You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Concatenate the operating points of the systems in `systems` into a single operating point. If any system has an operating point, the resulting system will have an operating point with the concatenated state and input vectors.
168
+
"""
169
+
functionmerge_ops(systems...)
170
+
ifany(has_operating_point, systems)
171
+
opx =reduce(vcat, operating_point(sys).x for sys in systems)
172
+
opu =reduce(vcat, operating_point(sys).u for sys in systems)
173
+
op = (; x = opx, u = opu)
174
+
extra =Dict(:operating_point=> op)
175
+
else
176
+
extra =Dict{Symbol, Any}()
177
+
end
178
+
end
179
+
180
+
"""
181
+
merge_ops_x(systems...)
182
+
183
+
Concatenate the operating points of the systems in `systems` into a single operating point, but only for the state vector `x`. The input vector `u` is taken from the first system's operating point, and all other systems are verified to have the same `u` operating point. If any system has an operating point, the resulting system will have an operating point with the concatenated state vector and the input vector from the first system.
184
+
"""
185
+
functionmerge_ops_x(systems...)
186
+
ifany(has_operating_point, systems)
187
+
allequal(operating_point(sys).u for sys in systems) ||
188
+
throw(ArgumentError("All systems must have the same input operating point u to be concatenated."))
189
+
opx =reduce(vcat, operating_point(sys).x for sys in systems)
190
+
opu =operating_point(systems[1]).u
191
+
op = (; x = opx, u = opu)
192
+
extra =Dict(:operating_point=> op)
193
+
else
194
+
extra =Dict{Symbol, Any}()
195
+
end
196
+
end
197
+
164
198
165
199
"""
166
200
infer_operating_point(P1, P2, method = :obsv)
@@ -308,7 +342,7 @@ function Base.getindex(sys::NamedStateSpace{T,S}, i::NamedIndex, j::NamedIndex)
308
342
sys.u[jj],
309
343
sys.y[ii],
310
344
sys.name,
311
-
sys.extra,
345
+
copy(sys.extra),
312
346
) # |> sminreal
313
347
ifhas_operating_point(sys)
314
348
op =operating_point(sys)
@@ -329,7 +363,7 @@ function Base.getindex(sys::NamedStateSpace{T,S}, inds...) where {T,S}
329
363
sys.u[cols],
330
364
sys.y[rows],
331
365
sys.name,
332
-
sys.extra,
366
+
copy(sys.extra),
333
367
) # |> sminreal
334
368
ifhas_operating_point(sys)
335
369
op =operating_point(sys)
@@ -362,18 +396,19 @@ function Base.:-(s1::NamedStateSpace{T,S}) where {T <: CS.TimeEvolution, S}
362
396
s1.u,
363
397
s1.y,
364
398
s1.name,
365
-
s1.extra,
399
+
copy(s1.extra),
366
400
)
367
401
end
368
402
369
403
function Base.:+(s1::NamedStateSpace{T,S}, s2::NamedStateSpace{T,S}) where {T <:CS.TimeEvolution, S}
404
+
extra =merge_ops_x(s1, s2)
370
405
returnNamedStateSpace{T,S}(
371
406
s1.sys+s2.sys,
372
407
[s1.x; s2.x],
373
408
s1.u,
374
409
s1.y,
375
410
"",
376
-
s1.extra,
411
+
extra,
377
412
)
378
413
end
379
414
@@ -385,13 +420,14 @@ function Base.:*(s1::NamedStateSpace{T}, s2::NamedStateSpace{T}) where {T <: CS.
385
420
end
386
421
sys = s1.sys*s2.sys
387
422
S =typeof(sys)
423
+
extra =merge_ops_x(s1, s2)
388
424
returnNamedStateSpace{T,S}(
389
425
sys,
390
426
x_names,
391
427
s2.u,
392
428
s1.y,
393
429
"",
394
-
s1.extra,
430
+
extra,
395
431
)
396
432
end
397
433
@@ -402,7 +438,7 @@ function Base.:*(s1::Number, s2::NamedStateSpace{T, S}) where {T <: CS.TimeEvolu
402
438
s2.u,
403
439
[Symbol(string(y)*"_scaled") for y in s2.y],
404
440
isempty(s2.name) ?"": s2.name*"_scaled",
405
-
s2.extra,
441
+
copy(s2.extra),
406
442
)
407
443
end
408
444
@@ -413,7 +449,7 @@ function Base.:*(s1::NamedStateSpace{T, S}, s2::Number) where {T <: CS.TimeEvolu
413
449
[Symbol(string(u)*"_scaled") for u in s1.u],
414
450
s1.y,
415
451
isempty(s1.name) ?"": s1.name*"_scaled",
416
-
s1.extra,
452
+
copy(s1.extra),
417
453
)
418
454
end
419
455
@@ -425,7 +461,7 @@ function Base.:*(s1::AbstractMatrix, s2::NamedStateSpace{T, S}) where {T <: CS.T
425
461
s2.u,
426
462
[Symbol(string(y)*"_scaled") for y in s2.y],
427
463
isempty(s2.name) ?"": s2.name*"_scaled",
428
-
s2.extra,
464
+
copy(s2.extra),
429
465
)
430
466
else
431
467
return*(promote(s1, s2)...)
@@ -440,7 +476,7 @@ function Base.:*(s1::NamedStateSpace{T, S}, s2::AbstractMatrix) where {T <: CS.T
440
476
[Symbol(string(u)*"_scaled") for u in s1.u],
441
477
s1.y,
442
478
isempty(s1.name) ?"": s1.name*"_scaled",
443
-
s1.extra,
479
+
copy(s1.extra),
444
480
)
445
481
else
446
482
return*(promote(s1, s2)...)
@@ -465,14 +501,7 @@ function Base.hcat(systems::NamedStateSpace{T,S}...) where {T,S}
465
501
x =generate_unique_x_names(systems...)
466
502
u =reduce(vcat, getproperty.(systems, :u))
467
503
check_unique(u, "u")
468
-
ifany(has_operating_point, systems)
469
-
opx =reduce(vcat, operating_point(sys).x for sys in systems)
470
-
opu =reduce(vcat, operating_point(sys).u for sys in systems)
471
-
op = (; x = opx, u = opu)
472
-
extra =Dict(:operating_point=> op)
473
-
else
474
-
extra =Dict{Symbol, Any}()
475
-
end
504
+
extra =merge_ops(systems...)
476
505
returnNamedStateSpace{T,S}(
477
506
hcat(getproperty.(systems, :sys)...),
478
507
x,
@@ -487,16 +516,7 @@ function Base.vcat(systems::NamedStateSpace{T,S}...) where {T,S}
487
516
x =generate_unique_x_names(systems...)
488
517
y =reduce(vcat, getproperty.(systems, :y))
489
518
check_unique(y, "y")
490
-
ifany(has_operating_point, systems)
491
-
allequal(operating_point(sys).u for sys in systems) ||
492
-
throw(ArgumentError("All systems must have the same input operating point u to be concatenated."))
493
-
opx =reduce(vcat, operating_point(sys).x for sys in systems)
494
-
opu =operating_point(systems[1]).u
495
-
op = (; x = opx, u = opu)
496
-
extra =Dict(:operating_point=> op)
497
-
else
498
-
extra =Dict{Symbol, Any}()
499
-
end
519
+
extra =merge_ops_x(systems...)
500
520
returnNamedStateSpace{T,S}(
501
521
vcat(getproperty.(systems, :sys)...),
502
522
x,
@@ -523,7 +543,7 @@ function measure(s::NamedStateSpace, names)
@@ -831,7 +851,7 @@ function ControlSystemsBase.sminreal(s::NamedStateSpace)
831
851
_, _, _, inds = CS.struct_ctrb_obsv(s.sys) # we do this one more time to get the inds. This implies repeated calculations, but will allow inner systems of exotic types that have a special method for sminreal to keep their type.
0 commit comments