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

Added functionality in the beam module to draw beam diagrams via a draw() function #17240

Closed
wants to merge 2 commits into from

Conversation

@ishanaj
Copy link
Contributor

commented Jul 21, 2019

draw() method makes it possible for the beam module to draw beam diagrams.
Not to be confused with the SFD's, BMD's and other plots. This is a diagram of a beam with loads and supports on it and not a plot.
It uses matplotlib by importing it as an external module.

Matplotlib modules/classes used:

ToDo's:

  • parabolic loads, moment loads
  • tests
  • documentation and examples

Release Notes

  • physics.continuum_mechanics
    • a new method draw() has been added in the beam module which gives functionality to draw the beam diagrams using matplotlib
@sympy-bot

This comment has been minimized.

Copy link

commented Jul 21, 2019

Hi, I am the SymPy bot (v147). 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.continuum_mechanics
    • a new method draw() has been added in the beam module which gives functionality to draw the beam diagrams using matplotlib (#17240 by @ishanaj)

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

Note: This comment will be updated with the latest check if you edit the pull request. You need to reload the page to see it.

Click here to see the pull request description that was parsed.

`draw()` method makes it possible for the beam module to draw beam diagrams.
Not to be confused with the SFD's, BMD's and other plots. This is a diagram of a beam with loads and supports on it and not a plot.
It uses matplotlib by importing it as an external module.

Matplotlib modules/classes used:
- [matplotlib.patches.Rectangle](https://matplotlib.org/api/_as_gen/matplotlib.patches.Rectangle.html) -to draw the beam
- [matplotlib.pyplot.annotate](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.annotate.html) - to draw arrows of load
- [matplotlib.markers](https://matplotlib.org/3.1.1/api/markers_api.html)- to draw supports

### ToDo's:
- [ ] parabolic loads, moment loads
- [ ] tests
- [ ] documentation and examples

### Release Notes

<!-- Write the release notes for this release below. 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.continuum_mechanics
    - a new method `draw()` has been added in the beam module which gives functionality to draw the beam diagrams using matplotlib
<!-- END RELEASE NOTES -->

@ishanaj

This comment has been minimized.

Copy link
Contributor Author

commented Jul 21, 2019

I have tested the following example:

>>> E, I = symbols('E, I')

>>> b1 = Beam(50, E, I)

>>> b1.apply_load(-10, 0, -1)
>>> b1.apply_load(R1, 10, -1)
>>> b1.apply_load(R2, 30, -1)
>>> b1.apply_load(9, 5, 0, 23)
>>> b1.apply_load(9, 30, 1, 50)
>>> b1.apply_support(50, "pin")
>>> b1.apply_support(0, "fixed")
>>> b1.apply_support(20, "roller")
>>> b1.draw()

image

@moorepants

This comment has been minimized.

Copy link
Member

commented Jul 21, 2019

This looks very nice!

Some initial thoughts/comments:

  • What happens if you use symbols for the magnitudes of the loads, etc?
  • There is an apply_support and apply_load with reactions? Why are there both? Is this not redundant?
  • It would be great that if you call Beam.plot_load_results() that it shows this beam diagram as the first of the plots. It should scale such that the length is aligned with the bending moment, shear, slope and deflection plots.
  • The name draw() makes sense, i.e. "draw the beam", but I'm wondering if it should be plot() to be consistent with all the other methods, i.e. plot(), plot_loading_results(), plot_bending_moment(), plot_slope(), etc.
@@ -1521,6 +1528,91 @@ def plot_loading_results(self, subs=None):
return PlotGrid(4, 1, ax1, ax2, ax3, ax4)


def draw(self):

This comment has been minimized.

Copy link
@moorepants

moorepants Jul 21, 2019

Member

Needs docstring.

self._draw_supports(ax)
matplotlib.pyplot.axis("off") # to turn off axis
ax.set_ylim(-0.5, 0.5)
matplotlib.pyplot.show()

This comment has been minimized.

Copy link
@moorepants

moorepants Jul 21, 2019

Member

This method should return ax (standard practice in most packages that use matplotlib, e.g. pandas).

This comment has been minimized.

Copy link
@ishanaj

ishanaj Jul 21, 2019

Author Contributor

Sure will make it return axis.

@moorepants

This comment has been minimized.

Copy link
Member

commented Jul 21, 2019

You may want to think about the fact that sympy.plot(load), where load is a singularity function will plot everything but point and moment loads. If you add the ability to plot the singularity function elements for point and moment to the general sympy plotting module then it can be used as a basis for your plot. All you have to add is the beam and the supports. This would also ensure that SingularityFunctions plot nicely in general. I recommend doing this.

@ishanaj

This comment has been minimized.

Copy link
Contributor Author

commented Jul 21, 2019

What happens if you use symbols for the magnitudes of the loads, etc?

If the magnitude is a symbol then it considers it a negative load and makes an arrow in the upward direction. But if the user specifies the symbol as positive=True it would give a downward arrow.
Also, I have currently not made it compatible to handle a case where the length of the beam is a symbol. But I think we can simply assign a particular value to the length if it is a symbol and I guess that should work.

There is an apply_support and apply_load with reactions? Why are there both? Is this not redundant?

I am not sure but I guess you are referring to the example. I have simply made it up just to check whether all the cases work, it has no prior logic involved.

It would be great that if you call Beam.plot_load_results() that it shows this beam diagram as the first of the plots. It should scale such that the length is aligned with the bending moment, shear, slope and deflection plots.

Sure, I will have to look at it, as the plot_loading_results() uses sympy's PlotGrid and here matplotlib is being used. I will have to see how to merge those two.

The name draw() makes sense, i.e. "draw the beam", but I'm wondering if it should be plot() to be consistent with all the other methods, i.e. plot(), plot_loading_results(), plot_bending_moment(), plot_slope(), etc.

I agree plot() seems to be better. Or should we make it plot_beam()

@codecov

This comment has been minimized.

Copy link

commented Jul 21, 2019

Codecov Report

Merging #17240 into master will increase coverage by 0.069%.
The diff coverage is 13.432%.

@@              Coverage Diff              @@
##            master    #17240       +/-   ##
=============================================
+ Coverage   74.532%   74.602%   +0.069%     
=============================================
  Files          623       627        +4     
  Lines       161580    162840     +1260     
  Branches     37925     38199      +274     
=============================================
+ Hits        120430    121482     +1052     
- Misses       35809     35976      +167     
- Partials      5341      5382       +41
@moorepants

This comment has been minimized.

Copy link
Member

commented Jul 21, 2019

I agree plot() seems to be better. Or should we make it plot_beam()

Beam.plot_beam() is a bit redundant. I think plot() is fine and most obvious that it will show a plot depicting the beam object it is attached to.

@moorepants

This comment has been minimized.

Copy link
Member

commented Jul 26, 2019

@ishanaj Are you still around? I haven't noticed any activity from you in days.

@ishanaj

This comment has been minimized.

Copy link
Contributor Author

commented Jul 26, 2019

Sorry, I was a bit caught up in college-related work.
Also, I had looked into plotting singularity functions using sympy's plot, But I am a bit confused on two points.

  • udl, uvl, parabolic load plots can be made from sympy.plot(), but how will we be adding arrows under those curves using sympy.plot() as needed in our case?
  • For point loads and moment, we require an arrow and an arc with an arrowhead respectively, but what should sympy.plot() plot in general for a singularity function of order -1 or -2?
@moorepants

This comment has been minimized.

Copy link
Member

commented Jul 26, 2019

Sorry, I was a bit caught up in college-related work.

Note that GSoC expects full time work while you are in the program.

udl, uvl, parabolic load plots can be made from sympy.plot(), but how will we be adding arrows under those curves using sympy.plot() as needed in our case?

This could be an option in sympy.plot(), for example sympy.plot(expr, fill=True) or sympy.plot(expr, fill='arrows').

For point loads and moment, we require an arrow and an arc with an arrowhead respectively, but what should sympy.plot() plot in general for a singularity function of order -1 or -2?

You'll have to look in to how sympy.plot() works. I think it converts the singfunc into a piecewise, then lambdifies that, and evaluates it numerically. In the singfunc > piecewise conversion the negative order terms are lost. I recommend asking some questions about this on the mailing list. One issue is that discontinuous point functions (impulse) are not real functions.

@ishanaj

This comment has been minimized.

Copy link
Contributor Author

commented Jul 26, 2019

I figured out the flow.
In the get_segments() function of the plotting module, it converts the SingularityFunction into lambda function via lambdify and further substitutes certain randomly generated values in it to get the segment points.
Since the value of x is being substituted and the singularity function is being evaluated. So I guess it would be somewhere here in the eval() function of singularity_functions.py that we should be making a change for order -1 and -2.

@ishanaj

This comment has been minimized.

Copy link
Contributor Author

commented Jul 27, 2019

This could be an option in sympy.plot(), for example sympy.plot(expr, fill=True) or sympy.plot(expr, fill='arrows')

But I guess fill won't work unless it is a closed area.

@ishanaj

This comment has been minimized.

Copy link
Contributor Author

commented Jul 27, 2019

I have posted a question in the mailing list to initiate discussion on it.

Also issue #16572 mentions some other examples of the problem with plot() in plotting discontinuities.

@ishanaj

This comment has been minimized.

Copy link
Contributor Author

commented Jul 31, 2019

Is there a difference between p.backend and p._backend?

@ishanaj ishanaj referenced this pull request Aug 5, 2019
7 of 7 tasks complete

@jashan498 jashan498 added the GSoC label Aug 13, 2019

@jashan498

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2019

Is this PR still relevant after #17345?

@ishanaj

This comment has been minimized.

Copy link
Contributor Author

commented Aug 14, 2019

PR #17345 was initially an alternative to this PR
But I think we are now good with the former. So I would be closing this.
Thanks everyone!

@ishanaj ishanaj closed this Aug 14, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.