slope_field.py

Created by john-c-2021

Created on January 17, 2021

4.36 KB

Plot a slope field given the derivative of a function in terms of x and or y . The number of points used may be selected to plot the short slope lines at 25, 49, or 81 points. Above 81 points the calculator has issues with memory capacity. The default differential equation used is dy/dx = x + y, this can be changed by editing the function definition in the Python script.


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.
# By John Cantlin 1-15-2021

# obtain and validate user input
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.")

# define the derivative function of y in terms of x and y used for the slope field
# include label with this definition - see end of script
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

# 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   

# uncomment for testing
#print("length x: ",len(x))
#print("length y: ",len(y))
#print("x_y: ", x_y)
#print("length x_y: ",len(x_y))
#print("type x_y: ", type(x_y))
#print("xm: ", xm)
#print("ym: ", ym)
print("length xm: ",len(xm))
print("length ym: ",len(ym))
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,"dy/dx=x+y")   # label graph in upper-left with derivative function

show()  # mathplotlib show display