@@ -198,19 +198,23 @@ function modify_nested_subsystem(
198
198
199
199
# recursive helper function which does the searching and modification
200
200
function _helper (sys:: AbstractSystem , i:: Int )
201
- # we reached past the end, so everything matched and
202
- # `sys` is the system to modify.
203
201
if i > length (hierarchy)
202
+ # we reached past the end, so everything matched and
203
+ # `sys` is the system to modify.
204
204
sys, vars = fn (sys)
205
205
else
206
+ # find the subsystem with the given name and error otherwise
206
207
cur = hierarchy[i]
207
208
idx = findfirst (subsys -> nameof (subsys) == cur, get_systems (sys))
208
209
idx === nothing &&
209
210
error (" System $(join ([nameof (root); hierarchy[1 : i- 1 ]], ' .' )) does not have a subsystem named $cur ." )
210
211
212
+ # recurse into new subsystem
211
213
newsys, vars = _helper (get_systems (sys)[idx], i + 1 )
214
+ # update this system with modified subsystem
212
215
@set! sys. systems[idx] = newsys
213
216
end
217
+ # only namespace variables from inner systems
214
218
if i != 1
215
219
vars = ntuple (Val (length (vars))) do i
216
220
renamespace (sys, vars[i])
270
274
271
275
# ### PRIMITIVE TRANSFORMATIONS
272
276
277
+ const DOC_WILL_REMOVE_AP = """
278
+ Note that this transformation will remove `ap`, causing any subsequent transformations \
279
+ referring to it to fail.\
280
+ """
281
+
282
+ const DOC_ADDED_VARIABLE = """
283
+ The added variable(s) will have a default of zero, of the appropriate type and size.\
284
+ """
285
+
273
286
"""
274
287
$(TYPEDEF)
275
288
@@ -278,11 +291,9 @@ it will add a new input variable which connects to the outputs of the analysis p
278
291
`apply_transformation` returns the new input variable (if added) as the auxiliary
279
292
information. The new input variable will have the name `Symbol(:d_, nameof(ap))`.
280
293
281
- Note that this transformation will remove `ap`, causing any subsequent transformations
282
- referring to it to fail.
294
+ $DOC_WILL_REMOVE_AP
283
295
284
- The added variable, if present, will have a default of zero, of the appropriate type and
285
- size.
296
+ $DOC_ADDED_VARIABLE
286
297
287
298
## Fields
288
299
@@ -340,17 +351,15 @@ end
340
351
$(TYPEDEF)
341
352
342
353
A transformation which returns the variable corresponding to the input of the analysis
343
- point.
344
-
345
- `apply_transformation` returns the variable as auxiliary information.
354
+ point. Does not modify the system.
346
355
347
356
## Fields
348
357
349
358
$(TYPEDFIELDS)
350
359
"""
351
360
struct GetInput <: AnalysisPointTransformation
352
361
"""
353
- The analysis point to add the output to .
362
+ The analysis point to get the input of .
354
363
"""
355
364
ap:: AnalysisPoint
356
365
end
@@ -380,15 +389,12 @@ the analysis point before connecting to the outputs. The new variable will have
380
389
381
390
If `with_output == true`, also creates an additional new variable which has the value
382
391
provided to the outputs after the above modification. This new variable has the same name
383
- as the analysis point.
384
-
385
- `apply_transformation` returns a 1-tuple of the perturbation variable if
386
- `with_output == false` and a 2-tuple of the perturbation variable and output variable if
387
- `with_output == true`.
392
+ as the analysis point and will be the second variable in the tuple of new variables returned
393
+ from `apply_transformation`.
388
394
389
- Removes the analysis point `ap`, so any subsequent transformations requiring it will fail.
395
+ $DOC_WILL_REMOVE_AP
390
396
391
- The added variable(s) will have a default of zero, of the appropriate type and size.
397
+ $DOC_ADDED_VARIABLE
392
398
393
399
## Fields
394
400
@@ -454,17 +460,33 @@ function apply_transformation(tf::PerturbOutput, sys::AbstractSystem)
454
460
end
455
461
456
462
"""
457
- $(TYPEDSIGNATURES )
463
+ $(TYPEDEF )
458
464
459
465
A transformation which adds a variable named `name` to the system containing the analysis
460
- point `ap`. The added variable has the same type and size as the input of the analysis
461
- point.
466
+ point `ap`. $DOC_ADDED_VARIABLE
467
+
468
+ # Fields
469
+
470
+ $(TYPEDFIELDS)
462
471
"""
463
472
struct AddVariable <: AnalysisPointTransformation
473
+ """
474
+ The analysis point in the system to modify, and whose input should be used as the
475
+ template for the new variable.
476
+ """
464
477
ap:: AnalysisPoint
478
+ """
479
+ The name of the added variable.
480
+ """
465
481
name:: Symbol
466
482
end
467
483
484
+ """
485
+ $(TYPEDSIGNATURES)
486
+
487
+ Add a new variable to the system containing analysis point `ap` with the same name as the
488
+ analysis point.
489
+ """
468
490
AddVariable (ap:: AnalysisPoint ) = AddVariable (ap, nameof (ap))
469
491
470
492
function apply_transformation (tf:: AddVariable , sys:: AbstractSystem )
@@ -494,26 +516,34 @@ end
494
516
$(TYPEDSIGNATURES)
495
517
496
518
A transformation enable calculating the sensitivity function about the analysis point `ap`.
497
- `apply_transformation` returns a 2-tuple `du, u` as auxiliary information.
519
+ The returned added variables are `(du, u)` where `du` is the perturbation added to the
520
+ input, and `u` is the output after perturbation.
498
521
499
- Removes the analysis point `ap`, so any subsequent transformations requiring it will fail.
522
+ $DOC_WILL_REMOVE_AP
500
523
501
- The added variables will have a default of zero, of the appropriate type and size.
524
+ $DOC_ADDED_VARIABLE
502
525
"""
503
526
SensitivityTransform (ap:: AnalysisPoint ) = PerturbOutput (ap, true )
504
527
505
528
"""
506
529
$(TYPEDEF)
507
530
508
531
A transformation to enable calculating the complementary sensitivity function about the
509
- analysis point `ap`. `apply_transformation` returns a 2-tuple ` du, u` as auxiliary
510
- information .
532
+ analysis point `ap`. The returned added variables are `( du, u)` where `du` is the
533
+ perturbation added to the outputs and `u` is the input to the analysis point .
511
534
512
- Removes the analysis point `ap`, so any subsequent transformations requiring it will fail.
535
+ $DOC_WILL_REMOVE_AP
513
536
514
- The added variables will have a default of zero, of the appropriate type and size.
537
+ $DOC_ADDED_VARIABLE
538
+
539
+ # Fields
540
+
541
+ $(TYPEDFIELDS)
515
542
"""
516
543
struct ComplementarySensitivityTransform <: AnalysisPointTransformation
544
+ """
545
+ The analysis point to modify.
546
+ """
517
547
ap:: AnalysisPoint
518
548
end
519
549
@@ -537,7 +567,25 @@ function apply_transformation(cst::ComplementarySensitivityTransform, sys::Abstr
537
567
return sys, (du, u)
538
568
end
539
569
570
+ """
571
+ $(TYPEDEF)
572
+
573
+ A transformation to enable calculating the loop transfer function about the analysis point
574
+ `ap`. The returned added variables are `(du, u)` where `du` feeds into the outputs of `ap`
575
+ and `u` is the input of `ap`.
576
+
577
+ $DOC_WILL_REMOVE_AP
578
+
579
+ $DOC_ADDED_VARIABLE
580
+
581
+ # Fields
582
+
583
+ $(TYPEDFIELDS)
584
+ """
540
585
struct LoopTransferTransform <: AnalysisPointTransformation
586
+ """
587
+ The analysis point to modify.
588
+ """
541
589
ap:: AnalysisPoint
542
590
end
543
591
@@ -547,15 +595,25 @@ function apply_transformation(tf::LoopTransferTransform, sys::AbstractSystem)
547
595
return sys, (du, u)
548
596
end
549
597
550
- # ## TODO : Move these
598
+ """
599
+ $(TYPEDSIGNATURES)
551
600
601
+ A utility function to get the "canonical" form of a list of analysis points. Always returns
602
+ a list of values. Any value that cannot be turned into an `AnalysisPoint` (i.e. isn't
603
+ already an `AnalysisPoint` or `Symbol`) is simply wrapped in an array.
604
+ """
552
605
canonicalize_ap (ap:: Symbol ) = [AnalysisPoint (ap)]
553
606
canonicalize_ap (ap:: AnalysisPoint ) = [ap]
554
607
canonicalize_ap (ap) = [ap]
555
608
function canonicalize_ap (aps:: Vector )
556
609
mapreduce (canonicalize_ap, vcat, aps; init = [])
557
610
end
558
611
612
+ """
613
+ $(TYPEDSIGNATURES)
614
+
615
+ Given a list of analysis points, break the connection for each and set the output to zero.
616
+ """
559
617
function handle_loop_openings (sys:: AbstractSystem , aps)
560
618
for ap in canonicalize_ap (aps)
561
619
sys, (outvar,) = apply_transformation (Break (ap, true ), sys)
@@ -568,63 +626,130 @@ function handle_loop_openings(sys::AbstractSystem, aps)
568
626
return sys
569
627
end
570
628
571
- function get_sensitivity_function (
572
- sys:: AbstractSystem , aps; system_modifier = identity, loop_openings = [], kwargs... )
629
+ const DOC_LOOP_OPENINGS = """
630
+ - `loop_openings`: A list of analysis points whose connections should be removed and
631
+ the outputs set to zero as a part of the linear analysis.
632
+ """
633
+
634
+ const DOC_SYS_MODIFIER = """
635
+ - `system_modifier`: A function taking the transformed system and applying any
636
+ additional transformations, returning the modified system. The modified system
637
+ is passed to `linearization_function`.
638
+ """
639
+ """
640
+ $(TYPEDSIGNATURES)
641
+
642
+ Utility function for linear analyses that apply a transformation `transform`, which
643
+ returns the added variables `(du, u)`, to each of the analysis points in `aps` and then
644
+ calls `linearization_function` with all the `du`s as inputs and `u`s as outputs. Returns
645
+ the linearization function and modified, simplified system.
646
+
647
+ # Keyword arguments
648
+
649
+ $DOC_LOOP_OPENINGS
650
+ $DOC_SYS_MODIFIER
651
+
652
+ All other keyword arguments are forwarded to `linearization_function`.
653
+ """
654
+ function get_linear_analysis_function (
655
+ sys:: AbstractSystem , transform, aps; system_modifier = identity, loop_openings = [], kwargs... )
573
656
sys = handle_loop_openings (sys, loop_openings)
574
657
aps = canonicalize_ap (aps)
575
658
dus = []
576
659
us = []
577
660
for ap in aps
578
- sys, (du, u) = apply_transformation (SensitivityTransform (ap), sys)
661
+ sys, (du, u) = apply_transformation (transform (ap), sys)
579
662
push! (dus, du)
580
663
push! (us, u)
581
664
end
582
665
linearization_function (system_modifier (sys), dus, us; kwargs... )
583
666
end
584
667
585
- function get_comp_sensitivity_function (
586
- sys:: AbstractSystem , aps; system_modifier = identity, loop_openings = [], kwargs... )
587
- sys = handle_loop_openings (sys, loop_openings)
588
- aps = canonicalize_ap (aps)
589
- dus = []
590
- us = []
591
- for ap in aps
592
- sys, (du, u) = apply_transformation (ComplementarySensitivityTransform (ap), sys)
593
- push! (dus, du)
594
- push! (us, u)
595
- end
596
- linearization_function (system_modifier (sys), dus, us; kwargs... )
668
+ """
669
+ $(TYPEDSIGNATURES)
670
+
671
+ Return the sensitivity function for the analysis point(s) `aps`, and the modified system
672
+ simplified with the appropriate inputs and outputs.
673
+
674
+ # Keyword Arguments
675
+
676
+ $DOC_LOOP_OPENINGS
677
+ $DOC_SYS_MODIFIER
678
+
679
+ All other keyword arguments are forwarded to `linearization_function`.
680
+ """
681
+ function get_sensitivity_function (sys:: AbstractSystem , aps; kwargs... )
682
+ get_linear_analysis_function (sys, SensitivityTransform, aps; kwargs... )
597
683
end
598
684
599
- function get_looptransfer_function (
600
- sys, aps; system_modifier = identity, loop_openings = [], kwargs... )
601
- sys = handle_loop_openings (sys, loop_openings)
602
- aps = canonicalize_ap (aps)
603
- dus = []
604
- us = []
605
- for ap in aps
606
- sys, (du, u) = apply_transformation (LoopTransferTransform (ap), sys)
607
- push! (dus, du)
608
- push! (us, u)
609
- end
610
- linearization_function (system_modifier (sys), dus, us; kwargs... )
685
+ """
686
+ $(TYPEDSIGNATURES)
687
+
688
+ Return the complementary sensitivity function for the analysis point(s) `aps`, and the
689
+ modified system simplified with the appropriate inputs and outputs.
690
+
691
+ # Keyword Arguments
692
+
693
+ $DOC_LOOP_OPENINGS
694
+ $DOC_SYS_MODIFIER
695
+
696
+ All other keyword arguments are forwarded to `linearization_function`.
697
+ """
698
+ function get_comp_sensitivity_function (sys:: AbstractSystem , aps; kwargs... )
699
+ get_linear_analysis_function (sys, ComplementarySensitivityTransform, aps; kwargs... )
700
+ end
701
+
702
+ """
703
+ $(TYPEDSIGNATURES)
704
+
705
+ Return the loop-transfer function for the analysis point(s) `aps`, and the modified
706
+ system simplified with the appropriate inputs and outputs.
707
+
708
+ # Keyword Arguments
709
+
710
+ $DOC_LOOP_OPENINGS
711
+ $DOC_SYS_MODIFIER
712
+
713
+ All other keyword arguments are forwarded to `linearization_function`.
714
+ """
715
+ function get_looptransfer_function (sys:: AbstractSystem , aps; kwargs... )
716
+ get_linear_analysis_function (sys, LoopTransferTransform, aps; kwargs... )
611
717
end
612
718
613
719
for f in [:get_sensitivity , :get_comp_sensitivity , :get_looptransfer ]
720
+ utility_fun = Symbol (f, :_function )
614
721
@eval function $f (
615
722
sys, ap, args... ; loop_openings = [], system_modifier = identity, kwargs... )
616
- lin_fun, ssys = $ (Symbol (f, :_function ) )(
723
+ lin_fun, ssys = $ (utility_fun )(
617
724
sys, ap, args... ; loop_openings, system_modifier, kwargs... )
618
725
ModelingToolkit. linearize (ssys, lin_fun; kwargs... ), ssys
619
726
end
727
+ @eval @doc """
728
+ $(TYPEDSIGNATURES)
729
+
730
+ Call `$($ utility_fun) ` and perform the linearization. All keyword arguments are
731
+ forwarded to `$($ utility_fun) ` and subsequently `linearize`.
732
+ """ $ f
620
733
end
621
734
622
- function open_loop (sys, ap:: Union{Symbol, AnalysisPoint} ; kwargs... )
735
+ """
736
+ $(TYPEDSIGNATURES)
737
+
738
+ Apply `LoopTransferTransform` to the analysis point `ap` and return the
739
+ result of `apply_transformation`.
740
+
741
+ # Keyword Arguments
742
+
743
+ - `system_modifier`: a function which takes the modified system and returns a new system
744
+ with any required further modifications peformed.
745
+ """
746
+ function open_loop (sys, ap:: Union{Symbol, AnalysisPoint} ; system_modifier = identity)
623
747
if ap isa Symbol
624
748
ap = AnalysisPoint (ap)
625
749
end
626
750
tf = LoopTransferTransform (ap)
627
- return apply_transformation (tf, sys)
751
+ sys, vars = apply_transformation (tf, sys)
752
+ return system_modifier (sys), vars
628
753
end
629
754
630
755
function linearization_function (sys:: AbstractSystem ,
0 commit comments