Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolving circular imports in physics.vector #26411

Open
tjstienstra opened this issue Mar 27, 2024 · 3 comments
Open

Resolving circular imports in physics.vector #26411

tjstienstra opened this issue Mar 27, 2024 · 3 comments

Comments

@tjstienstra
Copy link
Contributor

tjstienstra commented Mar 27, 2024

There are various circular dependencies in the sympy.physics.vector module. This was also pointed out in #26384, where a new circular import will be added.
The aim of this issue is to see whether it might be possible to reduce the number of circular.
As an overview, I've made a (mostly) complete list of all circular imports.

vector.py:

  • No import from physics.vector at the start of the module.
  • Vector.dot: from .dyadic import Dyadic, _check_dyadic both used for the same type check (Dyadic could be removed)
  • Vector.outer: from .dyadic import Dyadic uses Dyadic(...)
  • Vector._pretty: from sympy.printing.pretty.stringpict import prettyForm
  • Vector.cross: from .dyadic import Dyadic, _check_dyadic both used for the same type check and uses Dyadic(0)
  • Vector.diff: from sympy.physics.vector.frame import _check_frame
  • Vector.express: from .functions import express used as forward call
  • Vector.dt: from .functions import time_derivative used as forward call
  • Vector.free_dynamicsymbols: from sympy.physics.mechanics.functions import find_dynamicsymbols

dyadic.py:

  • No import from physics.vector at the start of the module.
  • Dyadic.dot: from .vector import Vector, _check_vector used for type checking and creation of Vector(0)
  • Dyadic.cross: from .vector import _check_vector used for type checking
  • Dyadic.express: from .functions import express used as forward call
  • Dyadic.dt: from .functions import time_derivative used as forward call

frame.py:

  • from .vector import Vector, _check_vector at the top of the module. Utilized abundantly.
  • ReferenceFrame._w_diff_dcm: from .functions import dynamicsymbols utilized to get the time symbol
  • ReferenceFrame.orient_axis: from .functions import dynamicsymbols utilized to get the time symbol
  • ReferenceFrame.orient_body_fixed: from .functions import dynamicsymbols utilized to get the time symbol
  • ReferenceFrame.orient_space_fixed: from .functions import dynamicsymbols utilized to get the time symbol
  • ReferenceFrame.orient_quaternion: from .functions import dynamicsymbols utilized to get the time symbol
  • _check_frame: from .vector import VectorTypeError to raise an exception (this one could be moved to the top of the module)
  • ReferenceFrame.partial_velocity: from .functions import partial_velocity (will be introduced in physics/vector: Improved speed of Point/Frame partial_velocity methods #26384)

point.py:

functions.py:

  • Imports various at the top of the module:
    • from .vector import Vector, _check_vector
    • from .frame import CoordinateSym, _check_frame
    • from .dyadic import Dyadic
  • No circular imports
  • cross uses Vector and Dyadic for type checking
  • dot uses Vector and Dyadic for type checking
  • express uses _check_frame, CoordinateSym, Dyadic, and Vector for type checking. Vector(...), Vector.simp, and Dyadic(0) are used.
  • time_derivative uses _check_frame, Vector, and Dyadic for type checking. Vector(...) and Dyadic(0) are used.
  • outer uses Vector for type checking
  • kinematic_equations uses none
  • get_motion_params uses _check_vector, _check_frame, and Vector(0)
  • partial_velocity uses Vector(0)
  • dynamicsymbols uses none (even no other functions from functions.py)

Some preliminary conclusions:

  • Vector and Dyadic form the basis of the module on which everything depends. ReferenceFrame is next, followed by Point. functions should be a gathering place of overarching functions.
  • Several of the above could be resolved if we would move _check_... to a separate module without them using any isinstance checks.
  • We could/should move dynamicsymbols and find_dynamicsymbols also to a separate module.
@tjstienstra
Copy link
Contributor Author

tjstienstra commented Mar 28, 2024

  • Vector and Dyadic form the basis of the module on which everything depends. ReferenceFrame is next, followed by Point. functions should be a gathering place of overarching functions.

As function.py should be seen as a gathering place of overarching functions, I would also suggest having the type-specific implementation of express and time_derivative to Vector and Dyadic.

@moorepants
Copy link
Member

Yes, we should just be able to make express and dt methods in Vector and Dyadic and they be the primary implementations. Then the express and time_derivative in functions.py are just wrappers around the methods.

@tjstienstra
Copy link
Contributor Author

I just noticed that printing.py actually also has a several local imports. Multiple from functions.py because it requires dynamicsymbols._t.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants