slope_field_r1.py

Created by john-c-2021

Created on January 17, 2021

6.19 KB

An updated (Rev 1) of slope_field.py to add a few user selected diffyQs. Note: selecting the max number of points (axes -4 to +4 = 81 points seems to run the Numworks calculator “out of memory” when the diffyQ is: dy/dx = sin(x)/y. No error is thrown but the display is blank. YMMV.


from matplotlib.pyplot import *
from math import *

# The user will input a minimum value for the x axis.
# The user input should be an integer between -4 and -2
# The x and y axes will be set equal to each other at +- this value
# Note: at -4 a 9 point x 9 point slope field is produced.
# Currently, any slope field wih > 81 (9x9) points = out of memory.
# The user will also choose from a selection of predetmined functions
# to use for the display of the slope field,
# By John Cantlin 1-16-2021 with help from Logan Burch.

# obtain and validate user input for the axes
def valid_axis(_a):
  if(-4 <= _a <= -2) and (isinstance(_a,int)):
    return "Good"
  else:
    print("x axis min: int -4 to -2")
    return False  

x_axis_good = False     
x_axis_min = int(input("Enter x axis min -4 to -2: "))
x_axis_good = valid_axis(x_axis_min)

while not x_axis_good:
  x_axis_min = int(input("Enter x axis min  -4 to -2: "))
  x_axis_good = valid_axis(x_axis_min)

# set the x-y axes min/max to equal (symmetric) +- values  
y_axis_min = x_axis_min
x_axis_max = abs(x_axis_min)
y_axis_max = abs(x_axis_min)
print("x-axis: ", x_axis_min, " to ", x_axis_max)
print("y-axis: ", y_axis_min, " to ", y_axis_max)

# create a list of x and corresponding y lattice point coordinates usingaxes max/min
x = list(range(x_axis_min, x_axis_max + 1, 1))  # range(start, stop. step)
y = list(range(x_axis_min, x_axis_max + 1, 1))  # range(start, stop. step)
print("x: ", x)
print("y: ", y)
wait = input("Press Enter to continue.")

# obtain and validate the user selection for the function to display
print("Enter function number:")
print("1: dy/dx=x+y")
print("2: dy/dx=x-y")
print("3: dy/dx=xy")
print("4: dy/dx=x/y")
print("5: dy/dx=sin(x)/y")

# use text labels to echo selection to user and for graph label
# put a dummy string in position 0 so list indices match item selected
dydxstr = ["dummystr", "dy/dx=x+y", "dy/dx=x-y",  "dy/dx=xy", "dy/dx=x/y", "dy/dx=sin(x)/y"]

def valid_selection(_s):
  if(1 <= _s <= 5) and (isinstance(_s,int)):
    return "Good"
  else:
    print("Enter int 1 to 4.")
  return False

fselect_good = False
fselect = int(input("Enter function number: "))
fselect_good = valid_selection(fselect)
    
while not fselect_good:
  fselect = int(input("Enter function number: "))
  fselect_good = valid_selection(fselect)
  
print("Plot ", fselect, ": ", dydxstr[fselect])

# define the selected derivative function of y in terms of x and y 
# that is used for the slope field, include the label used for the graph
if (fselect == 1):
  def dydx(_x,_y):    # define the derivative as a function of x and y
    m = _x + _y   # find slope m for given x and y, do not divide by zero
    return m
elif (fselect == 2):
  def dydx(_x,_y):    # define the derivative as a function of x and y
    m = _x - _y       # find slope m for given x and y, do not divide by zero
    return m
elif (fselect == 3):
  def dydx(_x,_y):    # define the derivative as a function of x and y
    m = _x * _y       # find slope m for given x and y, do not divide by zero
    return m
elif (fselect == 4):
  def dydx(_x,_y):       # define the derivative as a function of x and y
    try:
      m = _x / _y   # define the derivative as a function of x and y
      return m
    except ZeroDivisionError:
      if(_x == 0 and _y == 0):
        m = 0
        return m
      else:
        m = 1000    # cheating a little here since m is actually undefined
        return m
elif (fselect == 5):
  def dydx(_x,_y):       # define the derivative as a function of x and y
    try:
      m = sin(_x) / _y   # define the derivative as a function of x and y
      return m
    except ZeroDivisionError:
      if(_x == 0 and _y == 0):
        m = 1
        return m
      else:
        m = 0
        return m
else:
  pass

# create list of x, y pairs Note: x and y lists are equal length
x_y = [] # initialize empty list of x, y pairs
xm = []  # initialize empty list of x midpoint values
ym = []  # initialize empty list of y midpoint values

# create nested list of lists of all ordered pairs then extract xm and ym lists
for i in range(len(x)):
    for j in range(len(y)):
        x_y.append((x[i], y[j]))

for i in range(len(x_y)):
    xm.append(x_y[i][0]) # select all x midpoint values

for i in range(len(x_y)):
    ym.append(x_y[i][1]) # select all y midpoint values   

wait = input("Press Enter to continue.")

# create x and y axes, extend by 1 in each direction so the slope lines are visible
axis((x_axis_min-1,x_axis_max+1,y_axis_min-1,y_axis_max+1))   # axis(Xmin,Xmax,Ymin,Ymax)
axis("on")                  # mathplotlib: turn axes "on"
grid(False)                 # mathplotlib: turn grid "off"

# mathplotlib: draw arrows(x,y,dx,dy) where (x,y) start and (x + dx, y + dy) is end
# i.e. arrows(xs=xm-dx, ys=ym-dy, 2dx, 2dy)
# where length of arrow is set to 2d where d is set to 1/8 = 0.125
# and dx = 2d/root(1+m^2), dy = m*dx
d  = 0.250 # initial value of half the length of each line segment
xs = []    # initialize empty list of xm starting x coordinate for arrows
ys = []    # initialize empty list of xm starting y coordinate for arrows
m  = []    # initialize empty list of m at each value of xm
dx = []    # initialize empty list of dx at each value of xm
dy = []    # initialize empty list of dy at each value of xm

for i in range(len(xm)):
    m.append(dydx(xm[i],ym[i]))  # call dydx to calculate m for each (xm,ym) ordered pair
for i in range(len(xm)):         # calculate dx for each for each (xm,ym) ordered pair
    dx.append((d)/(sqrt(1 + pow(m[i],2)))) # calculate dx for each xs
for i in range(len(xm)):         #  calculate dy  for each (xm,ym) ordered pair
    dy.append(m[i] * dx[i])      # calculate dy for each xs
for i in range(len(xm)):   
    xs.append(xm[i] - dx[i])     # xs = starting x values of arrows
    ys.append(ym[i] - dy[i])     # ys = starting y values of arrows

print("length of lines: ", 2*d)
print("slope m at each (xm,ym): ", m)
wait = input("Press Enter to continue.")
   
# draw arrows starting at each (xs,ys) ordered pair and moving by 2dx and 2dy
for i in range(len(xs)):   
  arrow(xs[i],ys[i],2*dx[i],2*dy[i],color="red",head_width = 0.05)

text(x_axis_min,y_axis_max,dydxstr[fselect])   # label graph in upper-left with derivative function

show()  # mathplotlib show display

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.