152 lines
3.8 KiB
Python
152 lines
3.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Numerical integration, numerical quadrature.
|
|
|
|
de: numerische Integration, numerische Quadratur.
|
|
|
|
:Date: 2015-10-15
|
|
|
|
.. module:: integration
|
|
:platform: *nix, Windows
|
|
:synopsis: Numerical integration.
|
|
|
|
.. moduleauthor:: Daniel Weschke <daniel.weschke@directbox.de>
|
|
"""
|
|
|
|
from __future__ import division
|
|
from numpy import linspace, trapz, zeros
|
|
|
|
def trapez(f, a=0, b=1, N=10, x=None, verbose=False,
|
|
save_values=False):
|
|
r"""
|
|
Integration of :math:`f(x)` using the trapezoidal rule
|
|
(Simpson's rule, Kepler's rule).
|
|
|
|
de: Trapezregel, Simpsonregel (Thomas Simpson), Keplersche
|
|
Fassregel (Johannes Kepler)
|
|
|
|
:param f: function to integrate.
|
|
:type f: function or list
|
|
:param a: lower limit of integration (default = 0).
|
|
:type a: float
|
|
:param b: upper limit of integration (default = 1).
|
|
:type b: float
|
|
:param N: specify the number of subintervals.
|
|
:type N: int
|
|
:param x: variable of integration, necessary if f is a list
|
|
(default = None).
|
|
:type x: list
|
|
:param verbose: print information (default = False)
|
|
:type verbose: bool
|
|
|
|
:returns: the definite integral as approximated by trapezoidal
|
|
rule.
|
|
:rtype: float
|
|
|
|
The trapezoidal rule approximates the integral by the area of a
|
|
trapezoid with base h=b-a and sides equal to the values of the
|
|
integrand at the two end points.
|
|
|
|
.. math::
|
|
f_n(x) = f(a)+\frac{f(b)-f(a)}{b-a}(x-a)
|
|
|
|
.. math::
|
|
I &= \int\limits_a^b f(x) \,\mathrm{d}x \\
|
|
I &\approx \int\limits_a^b f_n(x) \,\mathrm{d}x \\
|
|
&= \int\limits_a^b
|
|
\left( f(a)+\frac{f(b)-f(a)}{b-a}(x-a) \right)
|
|
\mathrm{d}x \\
|
|
&= \left.\left( f(a)-a\frac{f(b)-f(a)}{b-a} \right)
|
|
x \right\vert_a^b +
|
|
\left. \frac{f(b)-f(a)}{b-a} \frac{x^2}{2}
|
|
\right\vert_a^b \\
|
|
&= \frac{b-a}{2}\left[f(a)+f(b)\right]
|
|
|
|
The composite trapezium rule. If the interval is divided into n
|
|
segments (not necessarily equal)
|
|
|
|
.. math::
|
|
a = x_0 \leq x_1 \leq x_2 \leq \ldots \leq x_n = b
|
|
|
|
.. math::
|
|
I &\approx \sum\limits_{i=0}^{n-1} \frac{1}{2} (x_{i+1}-x_i)
|
|
\left[f(x_{i+1})+f(x_i)\right] \\
|
|
|
|
Special Case (Equaliy spaced base points)
|
|
|
|
.. math::
|
|
x_{i+1}-x_i = h \quad \forall i
|
|
|
|
.. math::
|
|
I \approx h \left\{ \frac{1}{2} \left[f(x_0)+f(x_n)\right] +
|
|
\sum\limits_{i=1}^{n-1} f(x_i) \right\}
|
|
|
|
.. rubric:: Example
|
|
|
|
.. math::
|
|
I &= \int\limits_a^b f(x) \,\mathrm{d}x \\
|
|
f(x) &= x^2 \\
|
|
a &= 0 \\
|
|
b &= 1
|
|
|
|
analytical solution
|
|
|
|
.. math::
|
|
I = \int\limits_{0}^{1} x^2 \,\mathrm{d}x
|
|
= \left. \frac{1}{3} x^3 \right\vert_0^1
|
|
= \frac{1}{3}
|
|
|
|
numerical solution
|
|
|
|
>>> f = lambda(x): x**2
|
|
>>> trapez(f, 0, 1, 1)
|
|
0.5
|
|
>>> trapez(f, 0, 1, 10)
|
|
0.3350000000000001
|
|
>>> trapez(f, 0, 1, 100)
|
|
0.33335000000000004
|
|
"""
|
|
N = int(N)
|
|
# f is function or list
|
|
if hasattr(f, '__call__'):
|
|
# h width of each subinterval
|
|
h = (b-a)/N
|
|
|
|
# x variable of integration
|
|
x = linspace(a, b, N+1)
|
|
if save_values:
|
|
# ff contribution from the points
|
|
ff = zeros((N+1))
|
|
for n in linspace(0, N, N+1):
|
|
ff[n] = f(x[n])
|
|
T = (ff[0]/2.+sum(ff[1:N])+ff[N]/2.)*h
|
|
else:
|
|
TL = f(x[0])
|
|
TR = f(x[N])
|
|
TI = 0
|
|
for n in range(1, N):
|
|
TI = TI + f(x[n])
|
|
T = (TL/2.+TI+TR/2.)*h
|
|
else:
|
|
N = len(f)-1
|
|
T = 0
|
|
for n in range(N):
|
|
T = T + (x[n+1]-x[n])/2*(f[n+1]+f[n])
|
|
|
|
if verbose:
|
|
print(T)
|
|
|
|
return T
|
|
|
|
|
|
if __name__ == '__main__':
|
|
func = lambda x: x**2
|
|
trapez(func, 0, 1, 1e6, verbose=True)
|
|
#print(trapz(func, linspace(0,1,10)))
|
|
|
|
trapez([0,1,4,9], x=[0,1,2,3], verbose=True)
|
|
#print(trapz([0,1,4,9]))
|
|
|
|
trapez([2,2], x=[-1,1], verbose=True)
|
|
|
|
trapez([-1,1,1,-1], x=[-1,-1,1,1], verbose=True)
|