Files
pylib/src/numerical/integration.py

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)