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

Improve apply_support at location defined by decimal value #20404

Open
nopria opened this issue Nov 9, 2020 · 6 comments
Open

Improve apply_support at location defined by decimal value #20404

nopria opened this issue Nov 9, 2020 · 6 comments

Comments

@nopria
Copy link
Contributor

nopria commented Nov 9, 2020

Currently if you add a support to a beam at a location defined by decimal value, such as

b.apply_support(0.2,'fixed') # fixed, pin, roller

and you try to catch the symbols created by the method with

M,R = symbols('M_0.2, R_0.2')

the code fails because method apply_support, when converting numerical value of location to a string in order to create symbols, maintains the trailing zeros. In order to make the code work the user should write something like

M,R = symbols('M_0.200000000, R_0.200000000')

which is clearly counter-intuitive if not incorrect.

Trailing zeros are present because loc variable is converted to string after

loc = sympify(loc)

This behaviour could be fixed either by:

  • converting loc to string before sympify
  • stripping trailing zeros after string conversion
  • by changing the behaviour of sympify function

The second way could be obtained by replacing str(loc) with

str(loc).rstrip('0') if loc > 0 else str(loc)

The following MWE, currently not working, would run correctly with the above fix:

from sympy.physics.continuum_mechanics.beam import Beam
from sympy import symbols
E, I = symbols('E, I')
b = Beam(1, E, I)
b.apply_support(0.2, 'fixed') # fixed, pin, roller
b.apply_load(1, 0, 0)
M, R = symbols('M_0.2, R_0.2')
b.solve_for_reaction_loads(M, R)
b.load
b.reaction_loads
b.plot_loading_results(subs={E: 20E9, I: 3.25E-6})
@moorepants
Copy link
Member

Does:

M, R = symbols('M_{0.2}, R_{0.2}')

work? It is possible SymPy will not support decimals in symbol names.

@nopria
Copy link
Contributor Author

nopria commented Nov 10, 2020

Yes, with the proposed fix it works with decimal too, but without curly brackets.

I used this code to update apply_support after importing Beam:

def apply_support_fix(self, loc, type="fixed"):
    loc = sympify(loc)
    self._applied_supports.append((loc, type))
    strloc = str(loc).rstrip('0') if loc > 0 else str(loc)
    if type == "pin" or type == "roller":
        reaction_load = Symbol('R_'+strloc)
        print(reaction_load)
        self.apply_load(reaction_load, loc, -1)
        self.bc_deflection.append((loc, 0))
    else:
        reaction_load = Symbol('R_'+strloc)
        print(reaction_load)
        reaction_moment = Symbol('M_'+strloc)
        self.apply_load(reaction_load, loc, -1)
        self.apply_load(reaction_moment, loc, -2)
        self.bc_deflection.append((loc, 0))
        self.bc_slope.append((loc, 0))
        self._support_as_loads.append((reaction_moment, loc, -2, None))
    self._support_as_loads.append((reaction_load, loc, -1, None))

Beam.apply_support = apply_support_fix # adds method to Beam class

@moorepants
Copy link
Member

moorepants commented Nov 10, 2020

The arguments to Beam() should be sympifiable objects. If a symbol 'M_{0.2} should work with sympify() and it doesn't then this is an issue with sympify() not Beam().

@nopria
Copy link
Contributor Author

nopria commented Nov 11, 2020

Current code does not work with curly brackets regardless of decimal point. That is:

...
b.apply_support(0, 'fixed') # fixed, pin, roller
...
M, R = symbols('M_{0}, R_{0}')
...

does not work either, giving IndexError: tuple index out of range after b.solve_for_reaction_loads(M, R).

@moorepants
Copy link
Member

I understand now. This line:
https://github.com/sympy/sympy/blob/master/sympy/physics/continuum_mechanics/beam.py#L381
is not well designed. There needs to be a smarter way of creating these arbitrary symbols. Using sympy's numbered_symbols() generator is a good way to get valid symbols. But those symbols should somehow be accessible to the user via an attribute of Beam also. Your fix is a bandaid. I don't think loc should be used at all in the creation of these symbols.

@nopria
Copy link
Contributor Author

nopria commented Nov 11, 2020

I agree.
I would redesign apply_support so that the user can pass the needed symbols as arguments, in the same way it is done with apply_load. This way the code

M, R = symbols('M, R')
b.apply_support([M,R], 0, 'fixed')

would be syntactic sugar for

M, R = symbols('M, R')
b.apply_load(M, 0, -2)
b.apply_load(R, 0, -1)

The purpose of apply_support would be clearer, the usage more uniform to apply_load, it would be more flexible (custom symbols as for apply_load), and loc would NOT be used in the creation of reaction symbols.

The following code would do the job:

def apply_support(self, syms, loc, type="fixed"):
    try:
        reaction_load,reaction_moment = syms
    except:
        try:
            reaction_load, = syms
        except:
            reaction_load = syms
    loc = sympify(loc)
    self._applied_supports.append((loc, type))
    if type == "pin" or type == "roller":
        self.apply_load(reaction_load, loc, -1)
        self.bc_deflection.append((loc, 0))
    else:
        self.apply_load(reaction_load, loc, -1)
        self.apply_load(reaction_moment, loc, -2)
        self.bc_deflection.append((loc, 0))
        self.bc_slope.append((loc, 0))
        self._support_as_loads.append((reaction_moment, loc, -2, None))
    self._support_as_loads.append((reaction_load, loc, -1, None))

If you agree on the redesign I can make a pull request. Should specific tests be added in addition to doctests?

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

3 participants