Programas

Sliding With Friction

« Programas

Un esquiador (una partícula) que se desliza sobre una superficie circular se despega de ella cuando la fuerza normal es cero. Encontrar el ángulo de despegue es un problema típico de mecánica elemental. Nosotros incluímos fricción y además generalizamos a superficies arbitrarias.

FUENTES

Sliding down an arbitrary curve in the presence of friction,
F. González-Cataldo, Gonzalo Gutiérrez and Julio Yáñez.
American Journal of Physics 85, 108 (2017). Available on the arXiv.

EJEMPLOS


Circulo

\vec r(\varphi)=(R\sin\varphi,R\cos\varphi)

\mu=0 , \;\;\;\;\;\; \frac{v_0^2}{gR} = 0.01  , \;\;\;\;\;\; \kappa(\varphi)=\frac{1}{R}.

\mu=0.9 , \;\;\;\;\;\; \frac{v_0^2}{gR} = 0.5  , \;\;\;\;\;\; \kappa(\varphi)=\frac{1}{R}.

\mu=2.685 , \;\;\;\;\;\; \frac{v_0^2}{gR} = 0.9  , \;\;\;\;\;\; \kappa(\varphi)=\frac{1}{R}.

\mu=1.0 , \;\;\;\;\;\; \frac{v_0^2}{gR} = 0.5  , \;\;\;\;\;\; \kappa(\varphi)=\frac{1}{R}.

Elipse

\vec r(\alpha)=(R\gamma\sin\alpha,R\cos\alpha)
\tan\varphi=\frac{1}{\gamma}\tan\alpha

\mu=0.3 , \;\;\;\;\;\; \frac{v_0^2}{gR} = 1.2  , \;\;\;\;\;\; \kappa(\varphi)=\frac{(\gamma^2\sin^2\varphi+\cos\varphi)^{\frac{3}{2}}}{\gamma^2 R}  , \;\;\;\;\;\; \gamma=3.0

\mu=0.3 , \;\;\;\;\;\; \frac{v_0^2}{gR} = 1.2  , \;\;\;\;\;\; \kappa(\varphi)=\frac{(\gamma^2\sin^2\varphi+\cos\varphi)^{\frac{3}{2}}}{\gamma^2 R} , \;\;\;\;\;\; \gamma=0.3

Catenaria

\vec r(\alpha)=(R\alpha,R(2-\cosh\alpha))
\tan\varphi=\sinh\alpha

\mu=0.0 , \;\;\;\;\;\; \frac{v_0^2}{gR} = 0.001  , \;\;\;\;\;\; \kappa(\varphi)=\frac{1}{R}\cos^2\varphi

\mu=0.9 , \;\;\;\;\;\; \frac{v_0^2}{gR} = 0.5  , \;\;\;\;\;\; \kappa(\varphi)=\frac{1}{R}\cos^2\varphi

Parábola

\vec r(\alpha)=(R\gamma\alpha,R(1-\alpha^2)
\tan\varphi=2\alpha/\gamma

\mu=0.1 , \;\;\;\;\;\; \frac{v_0^2}{gR} = 0.1  , \;\;\;\;\;\; \kappa(\varphi)=\frac{2}{\gamma^2 R}\cos^3\varphi  , \;\;\;\;\;\; \gamma=1.2

\mu=1.2 , \;\;\;\;\;\; \frac{v_0^2}{gR} = 0.5  , \;\;\;\;\;\; \kappa(\varphi)=\frac{2}{\gamma^2 R}\cos^3\varphi  , \;\;\;\;\;\; \gamma=1.2

\mu=0.5 , \;\;\;\;\;\; \frac{v_0^2}{gR} = \frac{\gamma^2}{2}  , \;\;\;\;\;\; \kappa(\varphi)=\frac{2}{\gamma^2 R}\cos^3\varphi  , \;\;\;\;\;\; \gamma=1.2

Cicloide

\vec r(\alpha)=\frac R2(\alpha+\sin\alpha,1+\cos\alpha)
\varphi=\frac{1}{2}\alpha

\mu=0.0 , \;\;\;\;\;\; \frac{v_0^2}{gR} = 0.01  , \;\;\;\;\;\; \kappa(\varphi)=\frac{1}{2R}\sec\varphi

\mu=2.999 , \;\;\;\;\;\; \frac{v_0^2}{gR} = 1.8  , \;\;\;\;\;\; \kappa(\varphi)=\frac{1}{2R}\sec\varphi


Código (python)

#****************************************************************#
#*                SLIDING DOWN AN ARBITRARY CURVE               *#
#*                  IN THE PRESENCE OF FRICTION                 *#
#*                                                              *#
#* This program animates a particle sliding on a curved         *#
#* surface with a friction coefficient mu.                      *#
#* More information in:                                         *#
#* F. González-Cataldo et al. Am. J. of Phys. 85, 108 (2017).   *#
#* and https://arxiv.org/abs/1512.00515.                        *#
#****************************************************************#
# AUTHOR: FELIPE GONZALEZ CATALDO, July 2015.


#!/usr/bin/python

from numpy import *
from pylab import *
import scipy.integrate as integrate
from scipy.integrate import quad
import matplotlib.animation as animation

g =  9.8 # acceleration due to gravity, in m/s^2
R = 1.0 # length of pendulum 1 in m
dt = 0.02
tmax = 0.8
xmin, xmax = -5*R, 5*R
ymin, ymax = -5*R, 2*R

# th0 initial angle
case = 'circle'
gamma=1.0
th0 = 0.0
vo2 = 0.09*g*R
mu  = 0.1
alphas = linspace(0,2*pi,100)
if   case=='circle':
 tmax = 1.5
 xmin, xmax = -2*R, 2*R
 ymin, ymax = -2*R, 2*R
 alphas = linspace(0,2*pi,100)
elif   case=='ellipse':
 tmax = 2.0
 gamma=0.3
 L = 2*R if gamma<1 else 2.0*gamma*R
 xmin, xmax = -L, L
 ymin, ymax = -L, L
 alphas = linspace(0,2*pi,100)
elif   case=='parabola':
 tmax = 3.0
 gamma=1.2
 L = 5*R*gamma
 xmin, xmax = -L, L
 ymin, ymax = -4*L, 2*R
 alphas = linspace(-10,10,100)
elif case=='catenary':
 tmax = 3.0
 L = 4*R
 xmin, xmax = -L, L
 ymin, ymax = -4*L, L
 alphas = linspace(-5,5,100)
elif case=='cycloid':
 tmax = 2.2
 L = 3*R
 xmin, xmax = -L, L
 ymin, ymax = -L, L
 alphas = linspace(-4*pi,4*pi,100)


########### PARTICLE POSITION PARAMETRIZATION #############
def r(alpha):
 if case=='circle':
  return R*sin(alpha),  R*cos(alpha)
 elif case=='ellipse':
  return R*gamma*sin(alpha),  R*cos(alpha)
 elif case=='parabola':
  return R*gamma*alpha, R*(1-alpha**2)
 elif case=='catenary':
  return R*alpha, R*(2.0-cosh(alpha))
 elif case=='cycloid':
  return 0.5*R*(alpha+sin(alpha)), 0.5*R*(1.0+cos(alpha))

def alpha(phi):
 if case=='circle':
  return phi
 elif case=='ellipse':
  return arctan(gamma*tan(phi))
 elif case=='parabola':
  return 0.5*gamma*tan(phi)
 elif case=='catenary':
  return arcsinh(tan(phi))
 elif case=='cycloid':
  return 2*phi

def drdp(phi): # dr/dphi = r'(phi)
 drda = 0.0
 drdp = 0.0
 if case=='circle':
  drda = R
  dadp = 1.0
 elif case=='ellipse':
  drda = sqrt( (R*gamma*cos(alpha(phi)))**2 + (R*sin(alpha(phi)))**2 )
  dadp = gamma/(cos(phi)**2+gamma**2*sin(phi)**2)
 elif case=='parabola':
  drda = sqrt( gamma**2 + 4*alpha(phi)**2 )
  dadp = 0.5*gamma/cos(phi)**2
 elif case=='catenary':
  drda = R*cosh(alpha(phi))
  dadp = 1.0/cos(phi)
 elif case=='cycloid':
  drda = R*cos(0.5*alpha(phi))
  dadp = 2.0
 return drda*dadp

def horizon(phi):
 if case=='circle':
  return cos(phi)
 elif case=='ellipse':
  return gamma**2*cos(phi)/(gamma**2*sin(phi)**2+cos(phi)**2)**1.5
 elif case=='parabola':
  return 0.5*gamma**2/cos(phi)**2
 elif case=='catenary':
  return 1.0/cos(phi)
 elif case=='cycloid':
  return 2.0*cos(phi)**2

############### CALCULATE THE VELOCITY ##################
def kappa(phi):
 if case=='circle':
  return 1.0/R
 elif case=='ellipse':
  return (gamma**2*sin(phi)**2+cos(phi)**2)**1.5/(gamma**2*R)
 elif case=='parabola':
  return 2*cos(phi)**3/(gamma**2*R)
 elif case=='catenary':
  return cos(phi)**2/R
 elif case=='cycloid':
  return 1.0/(2*R*cos(phi))
def integrand(phi, mu):
 return (sin(phi)-mu*cos(phi))*exp(-2*mu*phi)/(R*kappa(phi))
def integral(phi,mu):
 return quad(integrand, 0, phi, args=(mu))[0]
def velocity2(phi,mu,vo2):
 return g*R*exp(2*mu*phi)*(vo2/(g*R)+2*integral(phi,mu))
#########################################################



############## SOLVE DIFF. EQUATIONS #####################
def IntegrateODE(state, t):
    # state = ( phi )
    dydx = zeros_like(state)  # dydx = dy/dx = function derivatives
#    dydx[0] = sqrt(velocity2(state[0],mu,vo2))/drdp(state[0])  # dy/dx = dphi/dt = v(phi)/|dr/dphi|

#  SINCE dphi/dt = v(phi)/|dr/dphi| < sqrt(gRH)/|dr/dphi|, the right-hand side limits the values of interest
    vel = velocity2(state[0],mu,vo2) if velocity2(state[0],mu,vo2)>0.0 else 0.0
    value = sqrt(vel)/drdp(state[0])  # dy/dx = dphi/dt = v(phi)/|dr/dphi|
    dydx[0] = value if value<=sqrt(g*R*horizon(state[0]))/drdp(state[0]) else 0.0
    return dydx
# create a time array from 0..100 sampled at 0.05 second steps
t = arange(0.0, tmax, dt)
# initial state
state = array([th0])
# integrate your ODE using scipy.integrate.
y = integrate.odeint(IntegrateODE, state, t)
#########################################################


############## PARAMETRIZE TRAJECTORY ####################
pf = 0
t0 = 0
step = 0
x1 = []
y1 = []
for i in xrange(len(t)):
 p = y[:,0][i] if i<len(y[:,0]) and y[:,0][i]<=0.5*pi else 0.999*pi/2
 if velocity2(p,mu,vo2)/(g*R) <= horizon(p) and step==0:
  x1 += [ r(alpha(p))[0] ]  #[R*gamma*sin(alpha(p))]
  y1 += [ r(alpha(p))[1] ] #[R*cos(alpha(p))]
  t0 = t[i]
#  print "Primer caso: velocity2(p,mu,vo2)/(g*R)=",velocity2(p,mu,vo2)/(g*R),"menor que",horizon(p),"para i=",i,"y=phi(t)=",p*180/pi
 elif velocity2(p,mu,vo2)/(g*R) > horizon(p):
  if step==0:
   step = i
   pf = 0.5*(y[:,0][i] + y[:,0][i-1])
  x1 += [ r(alpha(pf))[0] + sqrt(velocity2(pf,mu,vo2))*cos(pf)*(t[i]-t0) ]
  y1 += [ r(alpha(pf))[1] - sqrt(velocity2(pf,mu,vo2))*sin(pf)*(t[i]-t0) - 0.5*g*(t[i]-t0)**2 ]
#print "Supero horizonte: velocity2(p,mu,vo2)/(g*R)=",velocity2(p,mu,vo2)/(g*R),"mayor que",horizon(p),"para i=",i,"y=phi(t)=",p*180/pi
 elif velocity2(p,mu,vo2)<=0: # If the particle gets stuck
  x1 += [ r(alpha(pf))[0] ]  #[R*gamma*sin(alpha(pf))]
  y1 += [ r(alpha(pf))[1] ]  # [R*cos(alpha(pf))]
 else:
  print "No se cumple ni una en i=",i,"t[i]=",t[i],"phi[i]=",y[i]*180/pi
  print "Porque velocity2(p,mu,vo2)/(g*R)=",velocity2(p,mu,vo2)/(g*R),"no es menor que",horizon(p),"y=phi(t)=",p*180/pi
x1 = array(x1)
y1 = array(y1)
#########################################################


############## DRAW SURFACE ####################
fig = plt.figure()#figsize=(0.7*8,0.7*6))
params = {'legend.fontsize':18, 'text.fontsize':28,'xtick.labelsize':18, 'ytick.labelsize':18, 'xtick.labelsize':18, 'axes.labelsize':19,'xtick.major.size':6,'ytick.major.size':6}
rcParams.update(params)
ax = fig.add_subplot(111, autoscale_on=False, xlim=(xmin, xmax), ylim=(ymin, ymax), aspect='auto')
ax.grid(lw=1)
x_s = r(alphas)[0] #R*gamma*sin(phi)
y_s = r(alphas)[1] #R*cos(phi)
surface, = ax.plot( x_s, y_s, '-', lw=3)
floor,   = ax.plot( linspace(xmin,xmax,100), [0.0]*100, '-k', lw=2)
line1,   = ax.plot([],[], '--b', lw=1)
line2,   = ax.plot([],[], '--g', lw=1)
mass,    = ax.plot([],[], 'ro', ms=15)
#########################################################


################# ANIMATION ############################
time_text = ax.text(0.05, 0.88, '', transform=ax.transAxes,fontsize=18)
t_text    = ax.text(0.05, 0.83, '', transform=ax.transAxes,fontsize=18)
phi_text  = ax.text(0.05, 0.78, '', transform=ax.transAxes,fontsize=18)
def init():
    line1.set_data([], [])
    line2.set_data([], [])
    mass.set_data([], [])
    time_text.set_text('')
    phi_text.set_text('')
    t_text.set_text('')
    return mass, line1, line2, time_text, phi_text, t_text

def animate(i):
    line1x = [(x1[i],xmax) if i<step or step==0 else (x1[step],xmax) ]
    line1y = [(y1[i],y1[i]) if i<step or step==0 else (y1[step],y1[step])]
    line2x = [(x1[i],x1[i]+2*xmax*cos(y[:,0][i])) if i<step or step==0 else (x1[step],x1[step]+2*xmax*cos(y[:,0][step]))]
    line2y = [(y1[i],y1[i]-2*xmax*sin(y[:,0][i])) if i<step or step==0 else (y1[step],y1[step]-2*xmax*sin(y[:,0][step]))]

    line1.set_data(line1x, line1y)
    line2.set_data(line2x, line2y)
    mass.set_data(x1[i], y1[i])
    # TEXT
    my_t = i*dt if i<step else step*dt
    text_phi = (y[:,0][i]*180/pi) if i<step or step==0 else (pf*180/pi)

    time_text.set_text('Time = %.1fs'%(i*dt))
    t_text.set_text('t=%.2f'%my_t)
    phi_text.set_text(r'$\varphi$ = %.2f'%text_phi)

    return mass, line1, line2, time_text, phi_text, t_text

axis('equal')
#ani = animation.FuncAnimation(fig, animate, arange(1, len(t)), interval=50, blit=True, init_func=init)#,repeat_delay=1000)
ani = animation.FuncAnimation(fig, animate, arange(1, len(t)), interval=50, blit=False, init_func=init)#,repeat_delay=1000)

# t_video = Nframes/fps = len(t)/fps
# fps <= Nframes/2  ( or you get bad quality, due to interpolation)
#ani.save('ejemplo.mp4',  fps=0.4*len(t)/2) # Video lasts t_video = len(t)/fps = len(t)/(0.4*len(t)/2) = 2/0.4 = 5 sec


fig = plt.figure(2)
params = {'legend.fontsize':18, 'text.fontsize':18,'xtick.labelsize':18, 'ytick.labelsize':18, 'xtick.labelsize':18, 'axes.labelsize':19,'xtick.major.size':6,'ytick.major.size':6}
rcParams.update(params)
ax = fig.add_subplot(111)
mgr = get_current_fig_manager()
#mgr.window.wm_geometry("+600+55")
ymax = horizon(0)
if horizon(0)<1:
 ymax = 1.0
elif horizon(0)>4:
 ymax = 9.0
xlim(0,0.5*pi)
ylim(0,ymax)
xlabel(r'$\varphi$')
ylabel(r'$v^2(\varphi)/gR$')
xticks( [0,pi/12,2*pi/12,3*pi/12,4*pi/12,5*pi/12,6*pi/12],  [0,15,30,45,60,75,90]  )

phis = [p for p in linspace(0,0.5*pi,100)]
vels = [velocity2(p,mu,vo2)/(g*R) for p in phis ]
j=0
for i in xrange(len(vels)):
 if vels[i]<0: j=i
 if j>0: vels[i]=0.0
horz = [horizon(p) for p in phis]
dashed = linspace(0,horizon(pf))
ax.plot(phis , horz, '-k', lw=2,label='Horizon')
ax.plot(phis , vels, '-r',label=r'$v_0^2/gR=$'+str(vo2/(g*R))+'\n$\mu=$'+str(mu))
ax.plot( [ pf ]*len(dashed) , dashed , '--')
text= ax.text(0.7, 0.6, r'$\varphi=$ %.2f'%(pf*180/pi), transform=ax.transAxes, fontsize=18)
legend(loc=1)

#savefig('ejemplo.pdf')
plt.show()


Ejecutando el programa

Para ejecutar el programa, guarde el código anterior como "sliding-with-friction.py", y ejecute

python sliding-with-friction.py

Esto generará la animación. Si deseas guardar la animacion, quita el comentario '#' en la linea

#savefig('example.pdf')


« Programas