Trying to use Simpson's Law in Python

Question:

I am trying to write a program about Simpson’s Law.What I am trying to do is use as error as shown in this picture:

.

In the code i write the Ih is my f1 and Ih/2 is my f2.If the error doesnt happen then the steps get halved.

However I get this error

Traceback (most recent call last):
  File "C:UsersEgwDesktopAnalyshAskhsh1example.py", line 22, in <module>
    sim2 = simps(f2, x2)
  File "C:UsersEgwDesktopAnalyshAskhsh1venvlibsite-packagesscipyintegrate_quadrature.py", line 436, in simps
    return simpson(y, x=x, dx=dx, axis=axis, even=even)
  File "C:UsersEgwDesktopAnalyshAskhsh1venvlibsite-packagesscipyintegrate_quadrature.py", line 542, in simpson
    last_dx = x[slice1] - x[slice2]
IndexError: index -1 is out of bounds for axis 0 with size 0

Process finished with exit code 1

My code is

import numpy as np
from sympy import *
from scipy.integrate import simps

a = 0
b = np.pi * 2
N = 100
ra = 0.1 # ρα
R = 0.05
fa = 35 * (np.pi/180) # φα
za = 0.4
Q = 10**(-6)
k = 9 * 10**9
aa = sqrt(ra**2 + R**2 + za**2)
error = 5 * 10**(-9)

while True:
    x1 = np.linspace(a, b, N)
    f1 = 1 / ((aa ** 2 - 2 * ra * R * np.cos(x1 - fa)) ** (3 / 2))
    sim1 = simps(f1, x1)
    x2 = np.linspace(a, b, int(N/2))
    f2 = 1 / ((aa ** 2 - 2 * ra * R * np.cos(x2 - fa)) ** (3 / 2))
    sim2 = simps(f2, x2)
    if abs(sim1 - sim2) < error:
        break
    else:
        N = int(N/2)

print(sim1)

I wasnt expecting any error,and basically expecting to calculate correctly.

Asked By: Magnus2211

||

Answers:

When you reduce the grid step by half h -> h/2, the number of grid steps in turn grows N -> 2 * N, so you have to make two changes in your code:

  1. Define x2 to have twice as many elements as x1
   x2 = np.linspace(a, b, 2 * N)
  1. Update N to be twice it was on the previous iteration
        N = 2 * N

The resulting code would be

import numpy as np
from sympy import *
from scipy.integrate import simps

a = 0
b = np.pi * 2
N = 100
ra = 0.1 # ρα
R = 0.05
fa = 35 * (np.pi/180) # φα
za = 0.4
Q = 10**(-6)
k = 9 * 10**9
aa = sqrt(ra**2 + R**2 + za**2)
error = 5 * 10**(-9)

while True:
    x1 = np.linspace(a, b, N)
    f1 = 1 / ((aa ** 2 - 2 * ra * R * np.cos(x1 - fa)) ** (3 / 2))
    sim1 = simps(f1, x1)
    x2 = np.linspace(a, b, 2 * N)
    f2 = 1 / ((aa ** 2 - 2 * ra * R * np.cos(x2 - fa)) ** (3 / 2))
    sim2 = simps(f2, x2)
    if abs(sim1 - sim2) < error:
        break
    else:
        N = 2 * N

print(sim1)

And this prints the value

87.9765411043221

with error consistent with the threshold

abs(sim1 - sim2) = 4.66441463231604e-9
Answered By: Dmitri Chubarov

@DmitriChubarov’s solution is correct. However, your implementation is very inefficient: it does double the work it needs to. Also, simps is deprecated, you should be using proper exponential notation, and your function expression can be simplified. For an equivalent error-free algorithm that still doubles the input array length on each iteration but doesn’t throw away the intermediate result,

import numpy as np
from scipy.integrate import simpson

a = 0
b = 2*np.pi
N = 100
ra = 0.1  # ρα
R = 0.05
fa = np.radians(35)  # φα
za = 0.4
aa = np.linalg.norm((ra, R, za))
error = 5e-9
sim1 = np.nan

while True:
    x = np.linspace(a, b, N)
    f = (aa**2 - 2*ra*R*np.cos(x - fa))**-1.5
    sim2 = simpson(f, x)

    if np.abs(sim1 - sim2) < error:
        break
    sim1 = sim2
    N *= 2

print(sim1)
Answered By: Reinderien

When I modified your code by adding two lines to print(len(x1), len(f1)) and print(len(x2), len(f2)), I got these results:

Output:

length of x1 and f1: 100 100
length of x2 and f2: 50 50 

length of x1 and f1: 50 50
length of x2 and f2: 25 25 

length of x1 and f1: 25 25
length of x2 and f2: 12 12 

length of x1 and f1: 12 12
length of x2 and f2: 6 6 

length of x1 and f1: 6 6
length of x2 and f2: 3 3 

length of x1 and f1: 3 3
length of x2 and f2: 1 1 

length of x1 and f1: 1 1
length of x2 and f2: 0 0 

as you can see the length decreases each loop because N decreases and ends with an empty list length of x2 and f2: 0 0 and this causes the error you have had. To fix the issue of ‘the empty list’ I suggest that you duplicate N; this means using N*2 instead of N/2.

Answered By: Yasser M
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.