Description
mtkcompile / structural_simplify fails with
ArgumentError: The equations have at least one cycle.
from ModelingToolkitBase.topsort_equations when a multibody model chains two or more rotation-matrix orientation states in series — concretely, two Euler-angle Spherical joints (from MultibodyComponents.jl, a Dyad port of Multibody.jl) connected by a rigid link, with a Body at the end.
A single such joint compiles fine (e.g. a spherical pendulum), and a quaternion-state version of the same chain compiles fine — only chaining the Euler/rotation-matrix orientation representation triggers the cycle. It looks like the structural simplification produces an equation set whose dependency graph cannot be topologically ordered (an algebraic loop that tearing didn't resolve), rather than a modeling error: Multibody.jl builds the identical topology successfully (it uses dedicated Orientation/cut-orientation machinery).
Reproducer
multibody(model) is a thin wrapper around mtkcompile.
using ModelingToolkit, MultibodyComponents
using ModelingToolkit: t_nounits as t
@named world = MultibodyComponents.World()
@named j1 = MultibodyComponents.Spherical(orientation_state = MultibodyComponents.OrientationState.Euler())
@named bar = MultibodyComponents.FixedTranslation(r = [0.0, -0.5, 0.0])
@named j2 = MultibodyComponents.Spherical(orientation_state = MultibodyComponents.OrientationState.Euler())
@named body = MultibodyComponents.Body(m = 1.0)
eqs = [
connect(world.frame_b, j1.frame_a)
connect(j1.frame_b, bar.frame_a)
connect(bar.frame_b, j2.frame_a)
connect(j2.frame_b, body.frame_a)
]
@named model = System(eqs, t; systems = [world, j1, bar, j2, body])
multibody(model) # ArgumentError: The equations have at least one cycle.
Observations that localize it:
- 1 Euler joint (
world → Spherical(Euler) → bar → body, a spherical pendulum): compiles & solves.
- ≥2 Euler joints chained (above):
topsort_equations cycle.
- Quaternion orientation state (
OrientationState.Quaternion()) for the same chain: compiles & solves.
- Euler joints used only as internal joints (rigid bodies at both chain ends) also compile; the failure is specific to chaining the rotation-matrix orientation representation.
Stacktrace
ArgumentError: The equations have at least one cycle.
[1] topsort_equations(sys::System, eqs::Vector{Equation}, unknowns::Vector{...}; check::Bool)
@ ModelingToolkitBase .../ModelingToolkitBase/src/systems/systems.jl:1003
[4] _mtkcompile!(state::TearingState; ...)
@ ModelingToolkit .../ModelingToolkit/src/systems/systemstructure.jl:229
[11] mtkcompile(sys::System; ...)
@ ModelingToolkitBase .../ModelingToolkitBase/src/systems/systems.jl:95
Versions
- Julia 1.12.6
- ModelingToolkit v11.26.8
- ModelingToolkitBase v1.42.2
- ModelingToolkitTearing v1.14.1
- SymbolicUtils v4.34.3
Description
mtkcompile/structural_simplifyfails withfrom
ModelingToolkitBase.topsort_equationswhen a multibody model chains two or more rotation-matrix orientation states in series — concretely, two Euler-angleSphericaljoints (from MultibodyComponents.jl, a Dyad port of Multibody.jl) connected by a rigid link, with aBodyat the end.A single such joint compiles fine (e.g. a spherical pendulum), and a quaternion-state version of the same chain compiles fine — only chaining the Euler/rotation-matrix orientation representation triggers the cycle. It looks like the structural simplification produces an equation set whose dependency graph cannot be topologically ordered (an algebraic loop that tearing didn't resolve), rather than a modeling error: Multibody.jl builds the identical topology successfully (it uses dedicated
Orientation/cut-orientation machinery).Reproducer
multibody(model)is a thin wrapper aroundmtkcompile.Observations that localize it:
world → Spherical(Euler) → bar → body, a spherical pendulum): compiles & solves.topsort_equationscycle.OrientationState.Quaternion()) for the same chain: compiles & solves.Stacktrace
Versions