Skip to content

structural_simplify: "The equations have at least one cycle" (topsort_equations) when chaining rotation-matrix orientation states #4608

@baggepinnen

Description

@baggepinnen

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions