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

Implement Inertia object #24588

Merged
merged 9 commits into from Jan 31, 2023

Conversation

tjstienstra
Copy link
Contributor

@tjstienstra tjstienstra commented Jan 25, 2023

References to other Issues or PRs

This PR is part of the mechanics experimental development (#24234) implementing the changes suggested in #24257.

Brief description of what is fixed or changed

This PR implements an Inertia object that stores the quantity (Dyadic) and the reference (Point) of an inertia. This is a replacement of the tuple, which is currently being used. Besides that the functions associated with inertia are moved to a separate inertia.py file removing some circular import issues.

Other comments

Release Notes

NO ENTRY

@sympy-bot
Copy link

sympy-bot commented Jan 25, 2023

Hi, I am the SymPy bot (v169). 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:

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

Click here to see the pull request description that was parsed.
<!-- Your 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 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). Also, please
write a comment on that issue linking back to this pull request once it is
open. -->
This PR is part of the mechanics experimental development (#24234) implementing the changes suggested in #24257.

#### Brief description of what is fixed or changed
This PR implements an `Inertia` object that stores the quantity (Dyadic) and the reference (Point) of an inertia. This is a replacement of the tuple, which is currently being used. Besides that the functions associated with inertia are moved to a separate inertia.py file removing some circular import issues.

#### Other comments


#### 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.

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
  * Added an more intuitive Inertia object.
<!-- END RELEASE NOTES -->

Update

The release notes on the wiki have been updated.

@sympy-bot
Copy link

sympy-bot commented Jan 25, 2023

🟠

Hi, I am the SymPy bot (v169). 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:

  • fb867cf:
    • sympy/physics/mechanics/inertia.py
    • sympy/physics/mechanics/tests/test_inertia.py

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

Copy link
Contributor

@brocksam brocksam left a comment

Choose a reason for hiding this comment

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

I'm a big fan, well done. Few minor comments to discuss before approval.

sympy/physics/mechanics/inertia.py Outdated Show resolved Hide resolved
sympy/physics/mechanics/inertia.py Outdated Show resolved Hide resolved
(pos_vec | pos_vec))


class Inertia:
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we be subclassing tuple or typing.NamedTuple here in order to achieve correct typing behaviour for backwards compatibility? Inertias were previously tuples, if a user is using an isinstance check then this could fail with Inertia.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I personally don't like inheriting from tuple, because we'll also get methods which we don't like (such as __add__). I can switch the design of this class to the first example proposed in this comment, which will indeed ensure more complete backwards compatibility.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think inheriting from tuple would be the "proper" way to do it. However, I agree that getting tuple's __add__ is a negative so this would need to be overridden. I'd propose subclassing from tuple but then manually overwriting __add__ and __mul__ (and any other unwanted dunder methods) to raise TypeError: + operator is not supported for Inertia or something.

Copy link
Contributor

Choose a reason for hiding this comment

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

The other consideration is whether we should subclass from tuple or typing.NamedTuple. See this related comment on another issue.

Copy link
Contributor

Choose a reason for hiding this comment

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

The fact that you're considering subclassing tuple makes me wonder why there is a class here at all given that the methods are all just boilerplate. Can you not just use a tuple?

Alternatively if you're considering something like namedtuple then it seems like the modern way is frozen dataclasses.

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, I see why you're doing this. Current code returns a tuple and you want to change it to an object with attributes and methods. In that case namedtuple is specifically designed for this situation. Yes, __add__ might not do what you would ideally want but it will continue to function is it always did for anyone who might happen to be using it already. On the other hand if you actually want to change the behaviour of __add__ to do something more useful then you can still override the __add__ method.

Copy link
Member

@sylee957 sylee957 Jan 27, 2023

Choose a reason for hiding this comment

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

It is still not very recommended to override namedtuple for builtin methods like __add__, __mul__ to have inconsistent behavior than tuple (such as vector addition), because you need to be careful you don't use that subclass where tuple + tuple is expected to give juxtaposition result, and it is easy to get this bleed through because isinstance(..., tuple) wouldn't guard it.
If we are unhappy with default addition or multiplication of builtin, we would better raise errors early or leave as is, and define other methods that doesn't exist in base class.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I've reverted the override, while I have to say that I'm quite sure that most problems were guarded by also overwriting the __radd__ and __rmul__ methods. @sylee957 what did you by the way mean with raise errors early? Was currently raising it directly when calling the + or * operation on an Inertia.

Copy link
Member

Choose a reason for hiding this comment

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

I don't have strong opinion about whether this shouldn't be subclassed or not, it can be subclassed if it was originally tuple, but only be careful about overriding __add__ and __mul__ to have different behavior, because that specific part is not compatible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In that case, I'll revert my last commit and block the usage of __add__ and __mul__, because:

  • They'll prevent the misusage of those operations, which is correct from a mechanical point of view.
  • In the future it is easier to switch to supporting those operations in a way which is correct from an mechanical point of view. For example 5 * Inertia(dyadic, point) == Inertia(5 * dyadic, point).

P.S. It is of course still possible to write a class that does support these operations with Inertia as in the example below, but this is not the case for int and tuple (also namedtuple), which are also tested. But even if someone were to be in this position, it would otherwise be supported as well, so trying to block it does not result in any damage.

from sympy.physics.mechanics import ReferenceFrame, Inertia, Point
class Opponent:
    def __init__(self):
        pass
    def __add__(self, other):
        return self
    def __radd__(self, other):
        return self
P = Point('P')
N = ReferenceFrame('N')
I = Inertia(P, N.x | N.x)
I + Opponent()  # Raises an error
Opponent() + I  # Does not raise an error

sympy/physics/mechanics/inertia.py Outdated Show resolved Hide resolved
@github-actions
Copy link

github-actions bot commented Jan 25, 2023

Benchmark results from GitHub Actions

Lower numbers are good, higher numbers are bad. A ratio less than 1
means a speed up and greater than 1 means a slowdown. Green lines
beginning with + are slowdowns (the PR is slower then master or
master is slower than the previous release). Red lines beginning
with - are speedups.

Significantly changed benchmark results (PR vs master)

Significantly changed benchmark results (master vs previous release)

       before           after         ratio
     [41d90958]       [24bc2920]
     <sympy-1.11.1^0>                 
-     1.24±0.01ms         811±20μs     0.65  solve.TimeSparseSystem.time_linear_eq_to_matrix(10)
-     3.55±0.07ms      1.53±0.03ms     0.43  solve.TimeSparseSystem.time_linear_eq_to_matrix(20)
-     7.11±0.09ms      2.21±0.06ms     0.31  solve.TimeSparseSystem.time_linear_eq_to_matrix(30)

Full benchmark results can be found as artifacts in GitHub Actions
(click on checks at the top of the PR).

@brocksam brocksam merged commit 7b1240e into sympy:physics-mechanics-devel Jan 31, 2023
@tjstienstra tjstienstra mentioned this pull request Feb 16, 2023
18 tasks
@tjstienstra tjstienstra deleted the InertiaObject branch March 10, 2023 12:22
@moorepants moorepants added the CZI: Codegen/Biomech Sam Brockie's CZI-funded postdoc work on codegen and biomechanics label Apr 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CZI: Codegen/Biomech Sam Brockie's CZI-funded postdoc work on codegen and biomechanics physics.mechanics
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants