@@ -315,7 +315,34 @@ function ori(sys)
315315 end
316316end
317317
318- function connection2set! (connectionsets, namespace, ss, isouter)
318+ """
319+ $(TYPEDSIGNATURES)
320+
321+ Populate `connectionsets` with connections between the connectors `ss`, all of which are
322+ namespaced by `namespace`.
323+
324+ # Keyword Arguments
325+ - `ignored_connects`: A tuple of the systems and variables for which connections should be
326+ ignored. Of the format returned from `as_hierarchy`.
327+ - `namespaced_ignored_systems`: The `from_hierarchy` versions of entries in
328+ `ignored_connects[1]`, purely to avoid unnecessary recomputation.
329+ """
330+ function connection2set! (connectionsets, namespace, ss, isouter;
331+ ignored_connects = (HierarchySystemT[], HierarchyVariableT[]),
332+ namespaced_ignored_systems = ODESystem[])
333+ ignored_systems, ignored_variables = ignored_connects
334+ # ignore specified systems
335+ ss = filter (ss) do s
336+ all (namespaced_ignored_systems) do igsys
337+ nameof (igsys) != nameof (s)
338+ end
339+ end
340+ # `ignored_variables` for each `s` in `ss`
341+ corresponding_ignored_variables = map (
342+ Base. Fix2 (ignored_systems_for_subsystem, ignored_variables), ss)
343+ corresponding_namespaced_ignored_variables = map (
344+ Broadcast. BroadcastFunction (from_hierarchy), corresponding_ignored_variables)
345+
319346 regular_ss = []
320347 domain_ss = nothing
321348 for s in ss
@@ -340,9 +367,12 @@ function connection2set!(connectionsets, namespace, ss, isouter)
340367 for (i, s) in enumerate (ss)
341368 sts = unknowns (s)
342369 io = isouter (s)
343- for (j, v) in enumerate (sts)
370+ _ignored_variables = corresponding_ignored_variables[i]
371+ _namespaced_ignored_variables = corresponding_namespaced_ignored_variables[i]
372+ for v in sts
344373 vtype = get_connection_type (v)
345374 (vtype === Flow && isequal (v, dv)) || continue
375+ any (isequal (v), _namespaced_ignored_variables) && continue
346376 push! (cset, T (LazyNamespace (namespace, domain_ss), dv, false ))
347377 push! (cset, T (LazyNamespace (namespace, s), v, io))
348378 end
@@ -360,6 +390,12 @@ function connection2set!(connectionsets, namespace, ss, isouter)
360390 end
361391 sts1 = Set (sts1v)
362392 num_unknowns = length (sts1)
393+
394+ # we don't filter here because `csets` should include the full set of unknowns.
395+ # not all of `ss` will have the same (or any) variables filtered so the ones
396+ # that aren't should still go in the right cset. Since `sts1` is only used for
397+ # validating that all systems being connected are of the same type, it has
398+ # unfiltered entries.
363399 csets = [T[] for _ in 1 : num_unknowns] # Add 9 orientation variables if connection is between multibody frames
364400 for (i, s) in enumerate (ss)
365401 unknown_vars = unknowns (s)
@@ -372,7 +408,10 @@ function connection2set!(connectionsets, namespace, ss, isouter)
372408 all (Base. Fix2 (in, sts1), unknown_vars)) ||
373409 connection_error (ss))
374410 io = isouter (s)
411+ # don't `filter!` here so that `j` points to the correct cset regardless of
412+ # which variables are filtered.
375413 for (j, v) in enumerate (unknown_vars)
414+ any (isequal (v), corresponding_namespaced_ignored_variables[i]) && continue
376415 push! (csets[j], T (LazyNamespace (namespace, s), v, io))
377416 end
378417 end
@@ -397,7 +436,7 @@ function generate_connection_set(
397436 sys = generate_connection_set! (
398437 connectionsets, domain_csets, sys, find, replace, scalarize, nothing ,
399438 # include systems to be ignored
400- ignored_connections (sys)[ 1 ] )
439+ ignored_connections (sys))
401440 csets = merge (connectionsets)
402441 domain_csets = merge ([csets; domain_csets], true )
403442
@@ -417,18 +456,23 @@ Generate connection sets from `connect` equations.
417456- `sys` is the system whose equations are to be searched.
418457- `namespace` is a system representing the namespace in which `sys` exists, or `nothing`
419458 for no namespace (if `sys` is top-level).
420- - `ignored_systems` is a list of systems (in the format returned by `as_hierarchy`) to
421- be ignored when generating connections. This is typically because the connections
422- they are used in were removed by analysis point transformations.
459+ - `ignored_connects` is a tuple. The first (second) element is a list of systems
460+ (variables) in the format returned by `as_hierarchy` to be ignored when generating
461+ connections. This is typically because the connections they are used in were removed by
462+ analysis point transformations.
423463"""
424464function generate_connection_set! (connectionsets, domain_csets,
425- sys:: AbstractSystem , find, replace, scalarize, namespace = nothing , ignored_systems = [])
465+ sys:: AbstractSystem , find, replace, scalarize, namespace = nothing ,
466+ ignored_connects = (HierarchySystemT[], HierarchyVariableT[]))
426467 subsys = get_systems (sys)
468+ ignored_systems, ignored_variables = ignored_connects
427469 # turn hierarchies into namespaced systems
428- namespaced_ignored = from_hierarchy .(ignored_systems)
470+ namespaced_ignored_systems = from_hierarchy .(ignored_systems)
471+ namespaced_ignored_variables = from_hierarchy .(ignored_variables)
472+ namespaced_ignored = (namespaced_ignored_systems, namespaced_ignored_variables)
429473 # filter the subsystems of `sys` to exclude ignored ones
430474 filtered_subsys = filter (subsys) do ss
431- all (namespaced_ignored ) do igsys
475+ all (namespaced_ignored_systems ) do igsys
432476 nameof (igsys) != nameof (ss)
433477 end
434478 end
@@ -457,21 +501,10 @@ function generate_connection_set!(connectionsets, domain_csets,
457501 neweq isa AbstractArray ? append! (eqs, neweq) : push! (eqs, neweq)
458502 else
459503 if lhs isa Connection && get_systems (lhs) === :domain
460- # don't consider systems that should be ignored
461- systems_to_connect = filter (get_systems (rhs)) do ss
462- all (namespaced_ignored) do igsys
463- nameof (igsys) != nameof (ss)
464- end
465- end
466- connection2set! (domain_csets, namespace, systems_to_connect, isouter)
504+ connection2set! (domain_csets, namespace, get_systems (rhs), isouter;
505+ ignored_connects, namespaced_ignored_systems)
467506 elseif isconnection (rhs)
468- # ignore required systems
469- systems_to_connect = filter (get_systems (rhs)) do ss
470- all (namespaced_ignored) do igsys
471- nameof (igsys) != nameof (ss)
472- end
473- end
474- push! (cts, systems_to_connect)
507+ push! (cts, get_systems (rhs))
475508 else
476509 # split connections and equations
477510 if eq. lhs isa AbstractArray || eq. rhs isa AbstractArray
@@ -489,14 +522,19 @@ function generate_connection_set!(connectionsets, domain_csets,
489522 for s in filtered_subsys
490523 isconnector (s) || continue
491524 is_domain_connector (s) && continue
525+ _ignored_variables = ignored_systems_for_subsystem (s, ignored_variables)
526+ _namespaced_ignored_variables = from_hierarchy .(_ignored_variables)
492527 for v in unknowns (s)
493528 Flow === get_connection_type (v) || continue
529+ # ignore specified variables
530+ any (isequal (v), _namespaced_ignored_variables) && continue
494531 push! (connectionsets, ConnectionSet ([T (LazyNamespace (namespace, s), v, false )]))
495532 end
496533 end
497534
498535 for ct in cts
499- connection2set! (connectionsets, namespace, ct, isouter)
536+ connection2set! (connectionsets, namespace, ct, isouter;
537+ ignored_connects, namespaced_ignored_systems)
500538 end
501539
502540 # pre order traversal
@@ -506,7 +544,7 @@ function generate_connection_set!(connectionsets, domain_csets,
506544 @set! sys. systems = map (
507545 s -> generate_connection_set! (connectionsets, domain_csets, s,
508546 find, replace, scalarize, renamespace (namespace, s),
509- ignored_systems_for_subsystem (s, ignored_systems )),
547+ ignored_systems_for_subsystem .((s,), ignored_connects )),
510548 subsys)
511549 @set! sys. eqs = eqs
512550end
@@ -522,10 +560,16 @@ their hierarchy to not include `subsys`.
522560function ignored_systems_for_subsystem (
523561 subsys:: AbstractSystem , ignored_systems:: Vector{<:HierarchyT} )
524562 result = eltype (ignored_systems)[]
563+ # in case `subsys` is namespaced, get its hierarchy and compare suffixes
564+ # instead of the just the last element
565+ suffix = reverse! (namespace_hierarchy (nameof (subsys)))
566+ N = length (suffix)
525567 for igsys in ignored_systems
526- if igsys[end ] == nameof (subsys)
568+ if igsys[( end - N + 1 ) : end ] == suffix
527569 push! (result, copy (igsys))
528- pop! (result[end ])
570+ for i in 1 : N
571+ pop! (result[end ])
572+ end
529573 end
530574 end
531575 return result
0 commit comments