Code adaptation Fortran for python [Runtimewarning: overflow encountered in double_scalars]

Asked

Viewed 213 times

2

I tried to adapt the following code in Fortran to python:

PROGRAM Escape_tent
IMPLICIT NONE
! Declare local variables
INTEGER :: i,j,tfinal,P,k,rede
Real,dimension(0:2800) :: x,xn
real, external :: f
Real :: sigma,pi,soma,r
pi=4.*atan(1.0)
!
! Parametros e CIs
rede=100
do j=0,75
x(j)=0.3+0.1*sin((j*2*pi)/rede)
enddo
do j=50,rede
x(j)=1.1+0.1*sin((j*2*pi)/rede+pi)
enddo
tfinal=100
sigma=0.38
r=0.32
P=int(rede*r)

!
! Mapa logistico
!
do i=1,tfinal
!atualiza os vetores com o mapa
do j=0,rede
x(j)=f(x(j))
enddo
!
!
! Finite Range Coupling
!
do j=0,rede
soma=0.0
do k=-P,P
soma=soma+x(modulo(j+K,rede+1))-x(j)
enddo
xn(j)=x(j)+(sigma/(2.*P))*soma
enddo
do j = 0,rede
x(j)=xn(j)
enddo
! Write out values of the map
write(1,100) (x(k),k=0,rede)
enddo
END PROGRAM Escape_tent

real function f(x)
    implicit none
    real, intent(in) :: x
    real, parameter :: r=2.78   
f=r*x(1 - x)
end function f

When I adapted for python it was as follows:

import numpy as np
from time import time

# Variáveis do modelo
x, xn = [], []
r = 0.32  # 'raio' de acoplamento r = P/N
pi = np.pi
soma = 0.0

# Parâmetros para condições iniciais
rede = 100  # tamanho da rede
P = int(rede * r)
sigma = 0.38
t = np.arange(0, 1000)  # tempo de iteração

#Condições iniciais da rede
for j in range(0, int(rede / 2)):
    # determina as condições iniciais de metade da rede
    x.insert(j, 0.3 + 0.1 * np.sin((j * 2 * pi) /     (rede)))

for j in range(int(rede / 2), rede):
    # determina as condições iniciais da outra metade da rede
    x.insert(j, 1.1 + 0.1 * np.sin((j * 2 * pi) / (rede + pi)))

# função usada na iteração
def f(x):
    return 3.8 * x * (1 - x)

t1 = time()
#iterando a rede
for i in t:
    for j in range(0, rede):
        x[j] = f(x[j])  # aplica a função em todos os     elementos da rede

    for j in range(0, rede):  # para cada elemento j da rede
        for k in range(0, rede):  # temos um elemento k que esta a uma distância do j
            soma = 0.0
            if k != j:  # k não interage com k
                # calcula a distância do k até o j
                soma = x[k] - x[j]
                xn.insert(j, x[j] + (sigma / 2 * P) * soma)  # add no vetor x

    for j in range(0, rede):
        x[j] = xn[j] % (1.0) #Aqui eu limito o valor de Xn[j] para não tender ao infinito.
    print("T {}\n X :{}".format(i,x))
t2 = time()
print("Tempo decorrido: {}".format(t2 - t1))

After the Ninth iteration occurs the Exception "Runtimewarning: overflow encountered in double_scalars" and "Runtimewarning: invalid value encountered in double_scalars" in the Pycharm terminal and the data added to the vector x is 'Nan'. I would like to know what is happening, because in Fortran runs normally already in python I have this problem. Thank you.

1 answer

3


Not a number (Nan)

Your code is generating nan on the list you name x (I suggest you watch that video), and what is a nan? In a very objective and responsive way, Nan is the acronym for "Not a number", that is, any mathematical operation that results in a value that cannot be expressed in a number, the representation of that result will be nan, usually an exception is generated when trying to perform an operation that results in a nan, for example if you try to make a division by zero, the exception ZeroDivisionError will be raised.

a = 5
b = 0
c = a/b
ZeroDivisionError: division by zero

But not always is the exception raised, unless you treat this, it is difficult to create, purposefully, a nan, but there is an operation with inf which is classic for an example:

a = float('Inf')
b = float('Inf')
c = a - b
print(c)
nan

What happens is that your python code (I won’t compare with the code in Fortran, because I don’t know the language), is generating values nan on the list x, then when Voce sends the value to the function f() the value nan is returned, as any operation involving a nan will result in a nan, the message RuntimeWarning: overflow encountered in double_scalars most of the time is related to operations involving values nan, discover pq these values are being generated and you will solve the problem, I will make some suggestions to debug Voce, but Voce can add more procedures according to your context:

1) Change the function f() to intercept the value nan in x, as follows:

# função usada na iteração
def f(x):
    result =  3.8 * x * (1 - x)
    if np.isnan(result):
        line = '='*22
        print(line,'x recebido na função f: ', x,line, sep='\n')
    return result

2) Comment on the departure of x in the iteration loop, only to make debug output cleaner, also before the procedure that calls the function f() verify that the element j in x that you are sending to the function f is not nan, if the variables involved are displayed, the iteration loop should look like this:

t1 = time()
#iterando a rede
for i in t:
    for j in range(0, rede):

        if np.isnan(x[j]):
            print('valor de j na iteracao, quando x[j] é nan', j)
            print('valor de x na iteracao, quando x[j] é nan', x)

        x[j] = f(x[j])  # aplica a função em todos os elementos da rede

    for j in range(0, rede):  # para cada elemento j da rede
        for k in range(0, rede):  # temos um elemento k que esta a uma distância do j
            soma = 0.0
            if k != j:  # k não interage com k
                # calcula a distância do k até o j
                soma = x[k] - x[j]
                xn.insert(j, x[j] + (sigma / 2 * P) * soma)  # add no vetor x

    for j in range(0, rede):
        x[j] = xn[j]
    # print("T {}\n X :{}".format(i,x))
t2 = time()
print("Tempo decorrido: {}".format(t2 - t1))

After these changes the result should be something close to:

valor de j na iteracao, quando x[j] é nan 0
valor de x na iteracao, quando x[j] é nan [nan, nan, nan,... 1.0350165585196508e+289,... ]
======================
x recebido na função f: 
nan
======================
...

The above output is just a fragment, run the code with the changes to see the actual output, Voce can (and should) use print the variables involved in the calculations to generate the x to find out what is generating the values nan.

  • Excellent answer, thank you very much. I was able to realize my mistake after a while, the fact that I use a logistic function and for some cases it has a chaotic regime so it converges to infinity very fast and I think that’s why it generates an Nan. To correct this error I limited 'Xn[j]' between 0 and 1.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.