Search code examples
pythonmatplotlibsympypython-3.6fluid-dynamics

plotting streamlines with python


I am trying to plot streamlines and velocity potential for basic potential flows (uniform, source/sink, vortex, etc.)

I am just starting out with python and so I'm a little confused. I am following this guide..

I can plot the streamlines for the flow around a cylinder using this function

def cylinder_stream_function(U=1, R=1):
  r = sympy.sqrt(x**2 + y**2)
  theta = sympy.atan2(y, x)
  return U * (r - R**2 / r) * sympy.sin(theta)

and it works. But when I change the return statement to

return U * r * sympy.cos(theta)

for uniform flow I get the following error

Traceback (most recent call last):
   File "test.py", line 42, in
<module>
    plot_streamlines(ax, u, v)
   File "test.py", line 32, in plot_streamlines
    ax.streamplot(X, Y, u(X, Y), v(X, Y), color='cornflowerblue')
   File "/usr/local/lib/python3.6/site-packages/matplotlib/__init__.py",
line 1710, in inner
    return func(ax, *args, **kwargs)
   File "/usr/local/lib/python3.6/site-packages/matplotlib/axes/_axes.py",
line 4688, in streamplot
    integration_direction=integration_direction)
   File "/usr/local/lib/python3.6/site-packages/matplotlib/streamplot.py",
line 136, in streamplot
    if (u.shape != grid.shape) or (v.shape != grid.shape):
   AttributeError: 'int' object has no attribute 'shape'

I checked the type for the return object and it is <class 'sympy.core.mul.Mul'> with the first return statement and <class 'sympy.core.symbol.Symbol'> with the second one. Maybe this is related to why it doesn't work but I'm not sure how?

I plot the streamlines with the following

import numpy as np
import matplotlib.pyplot as plt
import sympy
from sympy.abc import x, y 

def uniform_flow_stream_function(U=1):
  r = sympy.sqrt(x**2 + y**2)
  theta = sympy.atan2(y, x)
  return U * r * sympy.sin(theta)

def velocity_field(psi):
  u = sympy.lambdify((x, y), psi.diff(y), 'numpy')
  v = sympy.lambdify((x, y), -psi.diff(x), 'numpy')
  return u, v

def plot_streamlines(ax, u, v, xlim=(-4, 4), ylim=(-4, 4)):
    x0, x1 = xlim
    y0, y1 = ylim
    # create a grid of values
    Y, X =  np.ogrid[y0:y1:100j, x0:x1:100j]
    ax.streamplot(X, Y, u(X, Y), v(X, Y), color='cornflowerblue')

psi = uniform_flow_stream_function()
u, v = velocity_field(psi)
fig, ax = plt.subplots(figsize=(5, 5))

plot_streamlines(ax, u, v)
plt.show()

Can someone please help me understand why this doesn't work and how I can get it to work? Thank you!


Solution

  • The reason that this does not work is because of the class difference. Your function U * r * sympy.cos(theta)=y. This means that you are returning a function of only y. Therefore your -psi.diff(x)=0 and you get a integer for v.

    It is impossible to plot streamlines with 1D data. So in order to plot streamlines in 2D you have to have both x and y in your uniform_flow_stream_function.