Skip to content

Commit d70e7c7

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

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

src/Blocks/analysis_points.jl

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,15 @@ 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+
function ap_warning(n)
90+
@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)"
91+
end
92+
8793
"""
88-
connect(output_connector, ap_name::Symbol, input_connector)
89-
connect(output_connector, ap::AnalysisPoint, input_connector)
94+
connect(output_connector, ap_name::Symbol, input_connector; verbose = true)
95+
connect(output_connector, ap::AnalysisPoint, input_connector; verbose = true)
9096
9197
Connect `output_connector` and `input_connector` with an [`AnalysisPoint`](@ref) inbetween.
9298
The incoming connection `output_connector` is expected to be of type [`RealOutput`](@ref), and vice versa.
@@ -105,19 +111,25 @@ typically is not (unless the model is an inverse model).
105111
- `input_connector`: A connector of type [`RealInput`](@ref)
106112
- `ap`: An explicitly created [`AnalysisPoint`](@ref)
107113
- `ap_name`: If a name is given, an [`AnalysisPoint`](@ref) with the given name will be created automatically.
114+
- `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.
108115
"""
109-
function ModelingToolkit.connect(in, ap::AnalysisPoint, out)
116+
function ModelingToolkit.connect(in, ap::AnalysisPoint, out; verbose = true)
117+
verbose && _isinput(in) && ap_warning(1)
118+
verbose && _isoutput(out) && ap_warning(2)
110119
ap.in = in
111120
ap.out = out
112121
return AnalysisPoint() ~ ap
113122
end
114123

115-
ModelingToolkit.get_systems(ap::AnalysisPoint) = (ap.in, ap.out)
116-
function ModelingToolkit.connect(in, ap_name::Symbol, out)
124+
function ModelingToolkit.connect(in, ap_name::Symbol, out; verbose = true)
125+
verbose && _isinput(in) && ap_warning(1)
126+
verbose && _isoutput(out) && ap_warning(2)
117127
ap = AnalysisPoint(in, out, ap_name)
118128
return AnalysisPoint() ~ ap
119129
end
120130

131+
ModelingToolkit.get_systems(ap::AnalysisPoint) = (ap.in, ap.out)
132+
121133
function ModelingToolkit.vars(ap::AnalysisPoint; op = Differential)
122134
vars(connect(ap.in, ap.out); op)
123135
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)