ghpythonremote icon indicating copy to clipboard operation
ghpythonremote copied to clipboard

GH Python remote with Sympy

Open r-yu52 opened this issue 4 years ago • 3 comments

Hello,

I have a problem while import sympy in the GH Python through GH Python remote. The code is as below:

import rhinoscriptsyntax as rs import scriptcontext as sc import ghpythonremote sp = sc.sticky['sympy']

x = sp.symbols('x') q = sp.symbols('q', cls=Function) Mq = sp.symbols('Mq', cls=Function) Vq = sp.symbols('Vq', cls=Function) diffeqbmq = Eq(Mq(x).diff(x,x), -q) BMq = dsolve(diffeqbmq, Mq(x), ics = {Mq(0):0, Mq(l):0}) SFq = Eq(Vq(x),BMq.rhs.diff(x))

but the functions in Sympy such as Function, Eq, dsolve is not usable in gh python. it shows a warning: name 'Function' is not defined.

Could I ask how to solve it?

r-yu52 avatar Sep 22 '21 10:09 r-yu52

Hi,

Function is a class defined in the top level module sympy. To use it in your script, you either need to do Function = sp.Function, then use the name Function, or use sp.Function everywhere.

That replaces import lines such as from sympy import Function that are normally defined at the top of these scripts.

I'm on mobile and couldn't find exactly where Eq and dsolve are defined in sympy. If you assign those names or use the fully qualified name every time like I wrote for Function, you should be able to run your script.

pilcru avatar Sep 22 '21 12:09 pilcru

Thank you for your quick reply!

I did what you suggest, but it shows another warning:

_Runtime error (Exception): type() argument 1 must be string, not unicode

Traceback:
  line 102, in value, "C:\Users\20204895\AppData\Roaming\McNeel\Rhinoceros\7.0\Plug-ins\IronPython (814d908a-e25c-493d-97e9-ee3861957f49)\settings\lib\rpyc\core\async_.py"
  line 469, in sync_request, "C:\Users\20204895\AppData\Roaming\McNeel\Rhinoceros\7.0\Plug-ins\IronPython (814d908a-e25c-493d-97e9-ee3861957f49)\settings\lib\rpyc\core\protocol.py"
  line 76, in syncreq, "C:\Users\20204895\AppData\Roaming\McNeel\Rhinoceros\7.0\Plug-ins\IronPython (814d908a-e25c-493d-97e9-ee3861957f49)\settings\lib\rpyc\core\netref.py"
  line 253, in __call__, "C:\Users\20204895\AppData\Roaming\McNeel\Rhinoceros\7.0\Plug-ins\IronPython (814d908a-e25c-493d-97e9-ee3861957f49)\settings\lib\rpyc\core\netref.py"
  line 18, in script_

line 18 is : q = sp.symbols('q', cls=Function)

I'm not sure if it's the problem with python 2.7, since it works well with python 3.0

r-yu52 avatar Sep 22 '21 13:09 r-yu52

That looks like a mismatch between what IronPython thinks is a string (unicode) and what Cpython 2 does (bytes). The 'q' string is local to IronPython, so is unicode, and when sympy receives in python 2 it cannot use it as a (bytes) string there.

I'm away until the end of the month and do not have access to a computer to help you with some code to workaround this. You might be able to make it work with some combination of:

  • using bytes strings in IronPython (b'q')
  • using the rpy.deliver utility function to create a string that is local to the Cpython interpreter, if you can find a way to make sure it is bytes and not unicode
  • importing the str type from Cpython and use it to create Cpython strings.

Sorry I can't help much more right now, hope you can make it work

pilcru avatar Sep 23 '21 06:09 pilcru

Hi @r-yu52, sorry it's been a while since you asked for help on this but I've been doing some cleaning around here and just looked at it again today.

From what I can tell, I can properly run sympy functionalities from Grasshopper, as long as all strings sent to it are bytes strings. (And of course, imports need to be properly defined in each of the GHPython scripts you run.) The code below gives the expected result:

import scriptcontext as sc
sp = sc.sticky['sympy']

x = sp.symbols(b'x')
q = sp.symbols(b'q', cls=sp.Function)
Mq = sp.symbols(b'Mq', cls=sp.Function)
Vq = sp.symbols(b'Vq', cls=sp.Function)
l = sp.symbols(b'l')  # Symbol l was not defined

diffeqbmq = sp.Eq(Mq(x).diff(x, x), -q(x))  # -q is not valid, symbolic functions need to be instantiated: -q(x)
BMq = sp.dsolve(diffeqbmq, Mq(x), ics={Mq(0): 0, Mq(l): 0})
SFq = sp.Eq(Vq(x), BMq.rhs.diff(x))

print(BMq, SFq)

Note that your original code had a couple of additional errors that prevented it from working, even outside in regular CPython, see the comments in the code.

pilcru avatar Oct 24 '22 18:10 pilcru