RuntimeWarning: valor no válido encontrado en división

96

Tengo que hacer un programa usando el método de Euler para el modelo "bola en un resorte"

from pylab import*
from math import*
m=0.1
Lo=1
tt=30
k=200
t=20
g=9.81
dt=0.01
n=int((ceil(t/dt)))
km=k/m
r0=[-5,5*sqrt(3)]
v0=[-5,5*sqrt(3)]
a=zeros((n,2))
r=zeros((n,2))
v=zeros((n,2))
t=zeros((n,2))
r[1,:]=r0
v[1,:]=v0
for i in range(n-1):
    rr=dot(r[i,:],r[i,:])**0.5
    a=-g+km*cos(tt)*(rr-L0)*r[i,:]/rr
    v[i+1,:]=v[i,:]+a*dt
    r[i+1,:]=r[i,:]+v[i+1,:]*dt
    t[i+1]=t[i]+dt

    #print norm(r[i,:])

plot(r[:,0],r[:,1])
xlim(-100,100)
ylim(-100,100)
xlabel('x [m]')
ylabel('y [m]')

show()

Sigo recibiendo este error:

a=-g+km*cos(tt)*(rr-L0)*r[i,:]/rr
RuntimeWarning: invalid value encountered in divide

No puedo entenderlo, ¿qué pasa con el código?

Bogdan Osyka
fuente
imprima lo que está sucediendo en cada uno de los elementos más pequeños en esa línea de código. Esa es la única forma de depurarlo.
CppLearner
2
Tienes nans para rr, que está arrojando ese error. El problema con rrse deriva de r[i,:]que es igual, en algunos casos, a array([ nan, nan]). Como mencionó @CppLearner, la mejor manera de depurar (o escribir) código es probar cada porción más pequeña antes de implementar.
cosmosis

Respuestas:

160

Creo que su código está tratando de "dividir por cero" o "dividir por NaN". Si es consciente de eso y no quiere que le moleste, puede intentar:

import numpy as np
np.seterr(divide='ignore', invalid='ignore')

Para obtener más detalles, consulte:

Yan Zhu
fuente
76
Puede ser útil usarlo with NP.errstate(divide='ignore',invalid='ignore'):si desea suprimir las advertencias para un bloque de código.
GWW
8
¿Por qué querría uno ignorar una división por cero o NaN?
x al cuadrado el
7
@xsquared Cuando haya manejado correctamente el valor usted mismo, después de la división, y esté distribuyendo su código a los usuarios (o esté cansado de ver la advertencia). with np.errstate(...)le permite hacer esto de forma segura solo para el caso manejado.
reve_etrange
2
@reve_etrange Eso me parece mucho más aceptable que ignorar generalmente las divisiones por cero.
x al cuadrado
1
es mejor establecer esto antes de la línea que causa el error y luego restablecer después de la línea al estado normal 'warn'mediante el comandonp.seterr(divide='warn', invalid='warn')
Mohammad ElNesr
15

La indexación de Python comienza en 0 (en lugar de 1), por lo que su asignación "r [1 ,:] = r0" define el segundo elemento (es decir, índice 1) de r y deja el primer elemento (índice 0) como un par de ceros. El primer valor de i en su ciclo for es 0, por lo que rr obtiene la raíz cuadrada del producto escalar de la primera entrada en r consigo mismo (que es 0), y la división por rr en la línea siguiente arroja el error.

Kinch
fuente
10

Para evitar la división por cero, puede preinicializar la salida 'out' donde ocurre el error div0, por ejemplo np.where, no la corta ya que la línea completa se evalúa independientemente de la condición.

ejemplo con preinicialización:

a = np.arange(10).reshape(2,5)
a[1,3] = 0
print(a)    #[[0 1 2 3 4], [5 6 7 0 9]]
a[0]/a[1]   # errors at 3/0
out = np.ones( (5) )  #preinit
np.divide(a[0],a[1], out=out, where=a[1]!=0) #only divide nonzeros else 1
qrtLs
fuente
4

Estás dividiendo por lo rrque puede ser 0.0. Verifica si rres cero y haz algo razonable que no sea usarlo en el denominador.

crayzeewulf
fuente