Skip to content

Unifies the shared attributes and methods on all mechanics _Methods subclasses and makes ABC class MethodBase public#29815

Open
moorepants wants to merge 38 commits into
sympy:masterfrom
moorepants:unify-methods
Open

Unifies the shared attributes and methods on all mechanics _Methods subclasses and makes ABC class MethodBase public#29815
moorepants wants to merge 38 commits into
sympy:masterfrom
moorepants:unify-methods

Conversation

@moorepants

@moorepants moorepants commented May 31, 2026

Copy link
Copy Markdown
Member

References to other Issues or PRs

Fixes #21772

Brief description of what is fixed or changed

We introduced the _Methods abstract base class some time ago and it unified some attributes among the subclasses (KanesMethod, LagrangesMethod, JointsMethod, System) but there were more common attributes that are helpful for downstream consumers of the *Method classes. This PR makes the renamed _Methods -> MethodBase class public and adds more useful attributes and methods:

  • frame: most common use (LagrangesMethod uses .inertial also)
  • holonomic_constraints: only was defined on System, configuration_constraints is used as initialization parameter
  • nonholonomic_constraints: was only defined on System, all classes need this to given strictly the nonholonomic constraints, had to add new initialization parameter to KanesMethod to unify.
  • velocity_constraints: was defined on System as this and on Lagranges as coneqs, went with velocity_constraints
  • acceleration_constraints: had to add to all classes, was only stored internally in parts
  • bodies: on all classes, but deprecating bodylist
  • loads: on all classes, but deprecating bodylist
  • constraints_jacobian: not necessarily used in all class (e.g. KanesMethod) but a very common matrix to want, made it a method with a default behavior, may need to reconsider and make it an attribute because it is computed internally in some pieces in all classes, Lagranges was the only class to have it already, but it returned the negation for some reason.

It also deprecates attributes (but not parameters) for forcelist and bodylist in favor of loads and bodies.

Other comments

TODO:

  • Decide if constraints_jcaobian should be a method or an attribute. If the underlying EoM method does not calculate this internally already, it could have a high computation cost. I try to avoid attributes doing any significant calculation. KanesMethod calculates the coefficients of the independent and dependent speeds in the velocity constraint equations separately, so maybe just assembling those into the constraint jacobian is minimal computation. So maybe I should make it an attribute.

AI Generation Disclosure

No AI was used.

Release Notes

  • physics.mechanics
    • Introduced a new MethodBase abstract base class (moved from private).
    • Added common attributes to all subclasses of MethodBase: frame, holonomic_constraints, nonholomic_constraints, velocity_constraints, acceleration_constraints, bodies, loads, constraints_jacobian
    • Deprecated forcelist and bodylist attributes from KanesMethod and LagrangesMethod.
    • Improved docstring attributes sections of all Methods classes.

@sympy-bot

sympy-bot commented May 31, 2026

Copy link
Copy Markdown

Hi, I am the SymPy bot. I'm here to help you write a release notes entry. Please read the guide on how to write release notes.

Your release notes are in good order.

Here is what the release notes will look like:

  • physics.mechanics
    • Introduced a new MethodBase abstract base class (moved from private). (#29815 by @moorepants)

    • Added common attributes to all subclasses of MethodBase: frame, holonomic_constraints, nonholomic_constraints, velocity_constraints, acceleration_constraints, bodies, loads, constraints_jacobian (#29815 by @moorepants)

    • Deprecated forcelist and bodylist attributes from KanesMethod and LagrangesMethod. (#29815 by @moorepants)

    • Improved docstring attributes sections of all Methods classes. (#29815 by @moorepants)

This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.15.

Click here to see the pull request description that was parsed.
<!-- DO NOT DELETE OR REPLACE THIS TEMPLATE or the PR will be closed.

Read our Policy on AI Generated Code and Communication at
https://docs.sympy.org/dev/contributing/ai-generated-code-policy.html.

As required in the policy do not use AI-generated text to complete the PR
description below or the PR will be closed. Follow the instructions in the
template below and keep all section headings or the PR will be closed.

The PR title above should be a short description of what was changed. Do not
include the issue number in the title. -->

#### References to other Issues or PRs

<!-- If there is an issue related to this PR, include a link to the issue here.
It is important not to waste reviewer's time by skipping this section.

If this pull request fixes an issue, write "Fixes #NNNN" in that exact format,
e.g. "Fixes #1234" (see https://tinyurl.com/auto-closing for more information).

If this does not completely fix the issue, then write "See #NNNN" or "partially
fixes #NNNN", e.g. "See #1234" or "partially fixes #1234". -->

Fixes #21772

#### Brief description of what is fixed or changed

We introduced the `_Methods` abstract base class some time ago and it unified some attributes among the subclasses (KanesMethod, LagrangesMethod, JointsMethod, System) but there were more common attributes that are helpful for downstream consumers of the *Method classes. This PR makes the renamed `_Methods` -> `MethodBase` class public and adds more useful attributes and methods:

- frame: most common use (LagrangesMethod uses .inertial also)
- holonomic_constraints: only was defined on System, configuration_constraints is used as initialization parameter
- nonholonomic_constraints: was only defined on System, all classes need this to given strictly the nonholonomic constraints, had to add new initialization parameter to KanesMethod to unify.
- velocity_constraints: was defined on System as this and on Lagranges as coneqs, went with velocity_constraints
- acceleration_constraints: had to add to all classes, was only stored internally in parts
- bodies: on all classes, but deprecating bodylist
- loads: on all classes, but deprecating bodylist
- constraints_jacobian: not necessarily used in all class (e.g. KanesMethod) but a very common matrix to want, made it a method with a default behavior, may need to reconsider and make it an attribute because it is computed internally in some pieces in all classes, Lagranges was the only class to have it already, but it returned the negation for some reason.

It also deprecates attributes (but not parameters) for `forcelist` and `bodylist` in favor of `loads` and `bodies`.

#### Other comments

TODO:

- [x] Decide if constraints_jcaobian should be a method or an attribute. If the underlying EoM method does not calculate this internally already, it could have a high computation cost. I try to avoid attributes doing any significant calculation. KanesMethod calculates the coefficients of the independent and dependent speeds in the velocity constraint equations separately, so maybe just assembling those into the constraint jacobian is minimal computation. So maybe I should make it an attribute.

#### AI Generation Disclosure

<!-- If this pull request includes AI-generated code or text, please disclose
the tool used and specify which lines were generated. Disclosure is not
required for minor assistive tasks, such as spell-checking or code reviewing,
in primarily human-authored work. Otherwise, write "NO AI USE" in the text area
below.

DO NOT just delete this AI section of the PR template and do not leave this
blank, or the PR will be closed. If you write "NO AI USE" and the code looks
like it was generated by AI then the PR will be closed. -->

No AI was used.

#### Release Notes

<!-- Write the release notes for this release below between the BEGIN and END
statements. The basic format is a bulleted list with the name of the subpackage
and the release note for this PR. For example:

* solvers
  * Added a new solver for logarithmic equations.

* functions
  * Fixed a bug with log of integers. Formerly, `log(-x)` incorrectly gave `-log(x)`.

* physics.units
  * Corrected a semantical error in the conversion between volt and statvolt which
    reported the volt as being larger than the statvolt.

or if no release note(s) should be included use:

NO ENTRY

See https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more
information on how to write release notes. The bot will check your release
notes automatically to see if they are formatted correctly. -->

<!-- BEGIN RELEASE NOTES -->

* physics.mechanics
  * Introduced a new `MethodBase` abstract base class (moved from private).
  * Added common attributes to all subclasses of `MethodBase`:  frame, holonomic_constraints, nonholomic_constraints, velocity_constraints, acceleration_constraints, bodies, loads, constraints_jacobian
  * Deprecated `forcelist` and `bodylist` attributes from `KanesMethod` and `LagrangesMethod`.
  * Improved docstring attributes sections of all `Methods` classes.

<!-- END RELEASE NOTES -->

@moorepants

Copy link
Copy Markdown
Member Author

Code quality is failing on some unrelated files:

ERROR: 'sympy.polys.domains.mpelements:ComplexElement' defines slots but superclass does not.
ERROR: 'sympy.polys.domains.mpelements:RealElement' defines slots but superclass does not.

@moorepants

Copy link
Copy Markdown
Member Author

@sympy/mechanics @Peter230655 this PR is ready enough for review. I am prepping it to better work with new updates in PyDy so we can support all Method classes and I have a PR coming with the TMTMethod which will also use this ABC class.

P.potential_energy = m * g * P.point.pos_from(O).dot(N.y)
L = Lagrangian(N, P)
raises(ValueError, lambda: LagrangesMethod(L, [q], bodies=P))
raises(ValueError, lambda: LagrangesMethod(L, [q], bodies=[P]))

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this because my internal adjustments caused it to fail on P not being an iterable before catching the incorrect q type.

@sympy-bot

sympy-bot commented May 31, 2026

Copy link
Copy Markdown

🟠

Hi, I am the SymPy bot. I've noticed that some of your commits add or delete files. Since this is sometimes done unintentionally, I wanted to alert you about it.

This is an experimental feature of SymPy Bot. If you have any feedback on it, please comment at sympy/sympy-bot#75.

The following commits add new files:

  • bcc9113:
    • doc/src/modules/physics/mechanics/api/method.rst

If these files were added/deleted on purpose, you can ignore this message.

@moorepants moorepants marked this pull request as ready for review May 31, 2026 09:07
# LagrangesMethod: (attr) -lam_coeffs
# JointsMethod: NA
# System: NA
def constraints_jacobian(self):

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a method or attribute?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am going to change this to an attribute. For all methods, if there are constraints, you have to generate the coefficients of the speeds one way or the other. So, all pieces of this matrix will have been computed and made available when the equations are formed. So I think an attribute is suitable in that case.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, now a property attribute.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One minor argument for method would be the options to add keyword arguments in the future. I don't have a good example, but if you can immediately think of one for which you wouldn't create a separate method then it might be worth keeping it a method.
In general though, I agree that a property is nicer.

@moorepants moorepants Jun 4, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is similar to mass_matrix in that it is just the linear coefficients of a specific set of equations.

We have multiple mass_matrix attributes and I plan to add a mass_matrix_augmented or something like that soon. You could of course imagine having extract_mass_matrix(full=True, aug=True) instead. For this Jacobian an analogy would be extract_constraint_jacobian(all=True, holonomic=True, nonholonomic=True) or something like that. But having these as methods don't quite align with the existing design which is:

  • __init__: provide all necessary input and organize the info
  • _form_eoms(): do the heavy lifting to compute the equations of motion and extract the pieces
  • .mass_matrix: available after _form_eoms() as a (mostly) precomputed attribute

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just added the correct extraction of this matrix from precomputed matrices in KanesMethod.

Comment thread sympy/physics/mechanics/kane.py Outdated

@tjstienstra tjstienstra left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice to see the work to make it more generic and available. As I'm just reading it from my phone I've only left some minor comments/suggestions.

Comment thread sympy/physics/mechanics/method.py Outdated
Comment thread sympy/physics/mechanics/method.py Outdated
@moorepants moorepants changed the title Unifies the shared attributes and methods on all mechanics _Methods subclasses Unifies the shared attributes and methods on all mechanics _Methods subclasses and makes ABC class MethodBase public Jun 3, 2026
@moorepants

Copy link
Copy Markdown
Member Author

This is new to me:

image

We have never had to have "all comments resolved". Some comments aren't resolved in PRs but can still be merged. This is an odd/annoying new requirement.

@oscarbenjamin

Copy link
Copy Markdown
Collaborator

This is an odd/annoying new requirement.

I've removed it in the settings. I think it was something I added when changing a bunch of settings to make the repo more secure but I don't think this particular setting really helps with that.

@moorepants

Copy link
Copy Markdown
Member Author

Thanks @oscarbenjamin, I agree.

@moorepants

Copy link
Copy Markdown
Member Author

@tjstienstra I think I'm satisfied with this. I mostly copy the well designed System attributes and replicate them in the other methods classes. Maybe the only significant changes otherwise are the new .constraints_jacobian method, the new parameter nonholonomic_constraints for KanesMethod, and deprecating .forcelist and .bodylist attributes. If you have no objections and approval, then maybe we can merge it. Thanks for the review.

@moorepants

Copy link
Copy Markdown
Member Author

This test has timed out for me about 3 or 4 times in this PR:

FAILED sympy/functions/special/tests/test_zeta_functions.py::test_issue_8404 - Failed: Timeout (>10.0s) from pytest-timeout.

@moorepants

Copy link
Copy Markdown
Member Author

I marked the test as slow.

Comment thread sympy/physics/mechanics/lagrange.py Outdated
@moorepants

Copy link
Copy Markdown
Member Author

@tjstienstra have I addressed your comments sufficiently? Do you expect more review or possibly think this is good to go in?

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create an abstract base class for the mechanics *Method classes and create a commit set of attributes & methods

5 participants