Skip to content

Commit 836521e

Browse files
committed
add warning for acausal analysis point connections
1 parent 0f85ae3 commit 836521e

File tree

2 files changed

+17
-5
lines changed

2 files changed

+17
-5
lines changed

src/Blocks/analysis_points.jl

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,13 @@ function Base.show(io::IO, ::MIME"text/plain", ap::AnalysisPoint)
8484
end
8585
end
8686

87+
_isinput(x) = x isa ODESystem && endswith(string(nameof(x)), "input")
88+
_isoutput(x) = x isa ODESystem && endswith(string(nameof(x)), "output")
89+
ap_warning(n) = @warn "The $(n == 1 ? "first" : "third") argument to a connection with an analysis point was a $(n == 1 ? "RealInput" : "RealOutput"). This is supported in order to handle inverse models, but may not be what you intended. If you are building a forward model (causal), you may want to swap the first and the third arguments to connect. Learn more about the causality of analysis points in the docstring for AnalysisPoint. Silence this message by connect(out, :name, in; verbose = false)"
90+
8791
"""
88-
connect(output_connector, ap_name::Symbol, input_connector)
89-
connect(output_connector, ap::AnalysisPoint, input_connector)
92+
connect(output_connector, ap_name::Symbol, input_connector; verbose = true)
93+
connect(output_connector, ap::AnalysisPoint, input_connector; verbose = true)
9094
9195
Connect `output_connector` and `input_connector` with an [`AnalysisPoint`](@ref) inbetween.
9296
The incoming connection `output_connector` is expected to be of type [`RealOutput`](@ref), and vice versa.
@@ -105,19 +109,25 @@ typically is not (unless the model is an inverse model).
105109
- `input_connector`: A connector of type [`RealInput`](@ref)
106110
- `ap`: An explicitly created [`AnalysisPoint`](@ref)
107111
- `ap_name`: If a name is given, an [`AnalysisPoint`](@ref) with the given name will be created automatically.
112+
- `verbose`: Causes a warning to be displayed if an input is connected to an output (reverse causality). Silence this warning if you are analysing an inverse model.
108113
"""
109-
function ModelingToolkit.connect(in, ap::AnalysisPoint, out)
114+
function ModelingToolkit.connect(in, ap::AnalysisPoint, out; verbose = true)
115+
verbose && _isinput(in) && ap_warning(1)
116+
verbose && _isoutput(out) && ap_warning(2)
110117
ap.in = in
111118
ap.out = out
112119
return AnalysisPoint() ~ ap
113120
end
114121

115-
ModelingToolkit.get_systems(ap::AnalysisPoint) = (ap.in, ap.out)
116-
function ModelingToolkit.connect(in, ap_name::Symbol, out)
122+
function ModelingToolkit.connect(in, ap_name::Symbol, out; verbose = true)
123+
verbose && _isinput(in) && ap_warning(1)
124+
verbose && _isoutput(out) && ap_warning(2)
117125
ap = AnalysisPoint(in, out, ap_name)
118126
return AnalysisPoint() ~ ap
119127
end
120128

129+
ModelingToolkit.get_systems(ap::AnalysisPoint) = (ap.in, ap.out)
130+
121131
function ModelingToolkit.vars(ap::AnalysisPoint; op = Differential)
122132
vars(connect(ap.in, ap.out); op)
123133
end

test/Blocks/test_analysis_points.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ using ModelingToolkit: get_eqs, vars, @set!, get_iv
88
@named C = Gain(-1)
99
t = ModelingToolkit.get_iv(P)
1010

11+
@test_logs (:warn,) (:warn,) connect(P.input, :bad_connection, C.output)
12+
1113
# Test with explicitly created AnalysisPoint
1214
ap = AnalysisPoint(:plant_input)
1315
eqs = [connect(P.output, C.input)

0 commit comments

Comments
 (0)